How can I automate the addition from WorkbookConnections with VBA? - vba

I want to connect csv files with excels power pivot with a VBA code by using WorkbookConnection.AddfromFile
My question:
I want to connect numerous csv file. To do so I have to click for hours through the Text Import Wizard. I haven't found out yet how to automatize this! I imagine to do it in a similar way like I did it with the FileDialog in the upper part of my code. Below the part of my code where I want to implement it.
For LoopCounter = 1 To fd.SelectedItems.count
ActiveWorkbook.Connections.AddFromFile _
fd.SelectedItems(LoopCounter), True, False
Next LoopCounter
Below the code I have already written. With this code I have to click through the TextImportWizard manually.
Sub csv()
Dim fd As FileDialog
Dim ActionClicked As Boolean
Dim LoopCounter As Long
Set fd = Application.FileDialog(msoFileDialogFilePicker)
fd.InitialFileName = "C:\temp"
fd.AllowMultiSelect = True
fd.Title = "Open your data"
fd.ButtonName = "GO"
ActionClicked = fd.Show
If ActionClicked Then
For LoopCounter = 1 To fd.SelectedItems.count
ActiveWorkbook.Connections.AddFromFile _
fd.SelectedItems(LoopCounter), True, False
Next LoopCounter
Else
MsgBox "You didn't choose anything"
Exit Sub
End If
End Sub

The faster way to import CSV or text files is with the following
Dim InputStringCSV As String
Dim CSVFile As Variant
Dim ArrayStringCSV() As String
CSVFile = Application.GetOpenFilename("CSV Files,*.CSV", Title:="MyData")
If CSVFile = False Then "No input!", vbCritical: End
Open CSVFile For Input As #1
Do Until EOF(1)
Line Input #1, InputStringCSV
ArrayStringCSV = Split(InputStringCSV, Chr(10))
For CounterArray = LBound(ArrayStringCSV) To UBound(ArrayStringCSV)
'Defaults: Row 1 is the beginnning for the sheet
Sheets(Sheet_CSV).Cells(1 + CounterArray, 1).NumberFormat = "#"
Sheets(Sheet_CSV).Cells(1 + CounterArray, 1) = ArrayStringCSV(CounterArray)
Next CounterArray
Loop
Close #1
If you want to automate it for all the CSV files in a folder, I'd suggest that you loop through archives -looking for .csv ones-, here's a sample on how to get you started:
Set oFSO = CreateObject("Scripting.FileSystemObject")
oStartFolder = "C:/Documents"
Set oFolder = oFSO.GetFolder(oStartFolder)
oFSO.GetFolder (oFolder)
For Each FileItem In oFolder.Files
if Instr(FileItem,".csv") Then Call ImportCSV(FileName) 'you would change the above code to don't ask folder and set the argument so each time you call it would be the file csv in the folder
Next FileItem

There are lots of ways to import text files. See the link below.
http://www.rondebruin.nl/win/s3/win022.htm
This AddIn will do the work for you.
http://www.rondebruin.nl/win/addins/rdbmerge.htm
Also, you can merge all your text files in a folder into one worksheet.
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#Else
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#End If
Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103
Public Sub ShellAndWait(ByVal PathName As String, Optional WindowState)
Dim hProg As Long
Dim hProcess As Long, ExitCode As Long
'fill in the missing parameter and execute the program
If IsMissing(WindowState) Then WindowState = 1
hProg = Shell(PathName, WindowState)
'hProg is a "process ID under Win32. To get the process handle:
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, hProg)
Do
'populate Exitcode variable
GetExitCodeProcess hProcess, ExitCode
DoEvents
Loop While ExitCode = STILL_ACTIVE
End Sub
Sub Merge_CSV_Files()
Dim BatFileName As String
Dim TXTFileName As String
Dim XLSFileName As String
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim DefPath As String
Dim Wb As Workbook
Dim oApp As Object
Dim oFolder
Dim foldername
'Create two temporary file names
BatFileName = Environ("Temp") & _
"\CollectCSVData" & Format(Now, "dd-mm-yy-h-mm-ss") & ".bat"
TXTFileName = Environ("Temp") & _
"\AllCSV" & Format(Now, "dd-mm-yy-h-mm-ss") & ".txt"
'Folder where you want to save the Excel file
DefPath = Application.DefaultFilePath
If Right(DefPath, 1) <> "\" Then
DefPath = DefPath & "\"
End If
'Set the extension and file format
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007 or higher
FileExtStr = ".xlsx": FileFormatNum = 51
'If you want to save as xls(97-2003 format) in 2007 use
'FileExtStr = ".xls": FileFormatNum = 56
End If
'Name of the Excel file with a date/time stamp
XLSFileName = DefPath & "MasterCSV " & _
Format(Now, "dd-mmm-yyyy h-mm-ss") & FileExtStr
'Browse to the folder with CSV files
Set oApp = CreateObject("Shell.Application")
Set oFolder = oApp.BrowseForFolder(0, "Select folder with CSV files", 512)
If Not oFolder Is Nothing Then
foldername = oFolder.Self.Path
If Right(foldername, 1) <> "\" Then
foldername = foldername & "\"
End If
'Create the bat file
Open BatFileName For Output As #1
Print #1, "Copy " & Chr(34) & foldername & "*.csv" _
& Chr(34) & " " & TXTFileName
Close #1
'Run the Bat file to collect all data from the CSV files into a TXT file
ShellAndWait BatFileName, 0
If Dir(TXTFileName) = "" Then
MsgBox "There are no csv files in this folder"
Kill BatFileName
Exit Sub
End If
'Open the TXT file in Excel
Application.ScreenUpdating = False
Workbooks.OpenText Filename:=TXTFileName, Origin:=xlWindows, StartRow _
:=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True, _
Space:=False, Other:=False
'Save text file as a Excel file
Set Wb = ActiveWorkbook
Application.DisplayAlerts = False
Wb.SaveAs Filename:=XLSFileName, FileFormat:=FileFormatNum
Application.DisplayAlerts = True
Wb.Close savechanges:=False
MsgBox "You find the Excel file here: " & vbNewLine & XLSFileName
'Delete the bat and text file you temporary used
Kill BatFileName
Kill TXTFileName
Application.ScreenUpdating = True
End If
End Sub
You'll find more info here.
http://www.rondebruin.nl/win/s3/win021.htm

If you want to maintain the data connections, like I do, then you need to first make a query using Power Query M formula. Then you can add your connection to that query. This is what Excel does when you use the Get Data wizards.
Use this procedure in your loop and it will make a new sheet for each CSV file:
'#Description("Create a new worksheet with a table that is connected to a CSV file as a data source.")
Public Sub GetDataFromCSV(ByVal name As String, ByVal fileName As String)
On Error GoTo errorHandler
' The Power Query points to the CSV file, if your data contains headers you need the Promoted Headers
Dim csvFormula As String
csvFormula = "let" & vbNewLine & _
" Source = Csv.Document(File.Contents(""" & fileName & """),null,null,null,1252)," & vbNewLine & _
" #""Promoted Headers"" = Table.PromoteHeaders(Source, [PromoteAllScalars=true])" & vbNewLine & _
"in" & vbNewLine & _
" #""Promoted Headers"""
ThisWorkbook.Queries.Add name:=name, Formula:=csvFormula
' The workbook connects to that query
Dim newConnection As WorkbookConnection
Set newConnection = ThisWorkbook.Connections.Add2("Query - " & name, _
"Connection to the '" & name & "' query in the workbook.", _
"OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" & name & ";Extended Properties="""";", """" & name & """", 6, True, False)
' I always want one table per sheet that begins at A1
Dim newSheet As Worksheet
Set newSheet = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
newSheet.name = name
' Only once you have the connection backed by the query can you link it to a Table
With newSheet.ListObjects.Add(SourceType:=xlSrcModel, Source:=newConnection, LinkSource:=True, XlListObjectHasHeaders:=xlYes, Destination:=newSheet.Range("$A$1")).TableObject
.RowNumbers = False
.PreserveFormatting = True
.RefreshStyle = 1
.AdjustColumnWidth = True
' I get errors when there are hyphens in the DisplayName, the default behavior of the wizard replaces them with underscors
.ListObject.DisplayName = Replace(name, "-", "_")
.Refresh
End With
Exit Sub
errorHandler:
If Err.Number = -2147024809 Then
' Query already exists, we delete it so we can recreate it
ThisWorkbook.Queries.Item(name).Delete
Resume
Else
Debug.Print "ERROR " & Err.Number & " : " & Err.Description
End If
End Sub

Related

How to download multiple files from same link in Sharepoint

I have the following code to download a single file from a share point site:
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" _ Alias "URLDownloadToFileA" (ByVal pCaller As Long, _
ByVal szURL As String, ByVal szFileName As String, _
ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Dim Ret As Long
Sub Report_download()
Dim strURL As String
Dim strPath As String
Dim strFile As String
strFile = "report.Denial." & Format(sDate, "yyyymmdd") & ".xlsx"
strURL = "https://sharepoint.com/HumanResources/Shared%20Documents/report.Denial.xlsx"
strPath = sPATH & strFile
Ret = URLDownloadToFile(0, strURL, strPath, 0, 0)
If Ret = 0 Then
' MsgBox "File successfully downloaded"
Else
MsgBox "Returncode:" & Ret & " Unable to download"
End If
End Sub
My question is this. I have 3 files to download from the same site. Links are the same, except of course, the report name. Is there a way that this code can be rewritten as loop to download the 3 files I need from this URL?
thank you
This should do what you want.
Option Explicit
Sub btnSharePointFolder()
Dim sht As Worksheet
Set sht = ThisWorkbook.Sheets("SharePoint Download")
If sht.Range("SharePointPath") = "" Then
MsgBox "Please enter a sharepoint path first", vbCritical
Exit Sub
End If
If Right(sht.Range("SharePointPath"), 1) <> "/" Then
'SharePointPath: http://testdrive.sharepoint.ckannan.blogspot.com/teams/YourTeam/
sht.Range("SharePointPath") = sht.Range("SharePointPath") & "/"
End If
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = sht.Range("SharePointPath")
.Title = "Please select a location of input files"
.Show
If Not .SelectedItems.Count = 0 Then
sht.Range("SharepointFolder") = .SelectedItems(1)
Else
Exit Sub
End If
End With
' 'To Remove Drive
' Shell "net use Q: /delete"
If Dir("Q:\", vbDirectory) = "" Then
Shell "net use Q: " & sht.Range("SharePointPath").Value '/user:MyDomain\MyUserName MyPassword
End If
End Sub
'_________________________________________________________________________________
Sub MapNetworkDrive()
If Dir("Q:\", vbDirectory) = "" Then
'SharePointPath: http://testdrive.sharepoint.ckannan.blogspot.com/teams/YourTeam/
Shell "net use Q: " & ThisWorkbook.Sheets("SharePoint Download").Range("SharePointPath").Value '/user:MyDomain\MyUserName MyPassword
MsgBox "The sharepoint path is mapped as network drive.", vbInformation
Else
MsgBox "The mapped network drive already exists.", vbInformation
End If
End Sub
'_________________________________________________________________________________
Sub DownloadFiles()
Dim Directory As String
Dim file As String
Dim i As Long
Dim fso As FileSystemObject
Application.ScreenUpdating = False
If Dir("Q:\", vbDirectory) = "" Then
MsgBox "There is no mapped network drive", vbCritical
Exit Sub
End If
'DownloadFolder: http://testdrive.sharepoint.ckannan.blogspot.com/teams/YourTeam/Shared Documents/PDW Status
Directory = "Q:\" & ThisWorkbook.Sheets("SharePoint Download").Range("DownloadFolder").Value & "\"
Set fso = CreateObject("Scripting.FileSystemObject")
' Get first file
file = Dir(Directory, vbReadOnly + vbHidden + vbSystem)
If file = "" Then
MsgBox "No files found in the sharepoint folder.", vbCritical
Exit Sub
End If
Do While file <> ""
fso.CopyFile Directory & file, "C:\", True
file = Dir()
Loop
Application.StatusBar = False
MsgBox "Downloaded all files to the local folder.", vbInformation
End Sub
'_________________________________________________________________________________
Sub btnLocalFolder_Click()
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = "C:\"
.Title = "Please select a location to download files"
.Show
If Not .SelectedItems.Count = 0 Then
ThisWorkbook.Sheets("SharePoint Download").Range("LocalFolder") = .SelectedItems(1)
End If
End With
End Sub

Create A Folder Directory in Excel using Visual Basic

I am extremely new to Visual Basic
I am currently trying to create a calculator within excel that I can export the data within to a PDF. I have been able to export the excel document however it is only going to my "D:\".
How do I create a folder within D:\ called something like Excel_Calculator where I can have all the PDF's created be saved directly into that folder & If there already is a folder called "Excel_Calculator" to use that folder instead of overwriting the existing folder.
The code I have for saving the PDF is listed here:
Sub GetFilenameForPDF()
Dim strFileName As String, strB1 As String, strWorksheet As String
strB1 = Range("B1").Value
strWorksheet = ActiveSheet.Name
strFileName = strB1 & " " & strWorksheet & " " & Format(Date, "DD-MM-YYYY")
Sub SaveToPDF()
Dim strFileName As String, strC3 As String, strWorksheet As String
strB1 = Range("B1").Value
strWorksheet = ActiveSheet.Name
strFileName = strB1 & " " & strWorksheet & " " & Format(Date, "DD-MM-YYYY")
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"D:\" & strFileName & ".pdf", _
Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=True
End Sub
** EDIT: Or is there a way I can create or redirect the files to a temporary location so that the folder isn't clogged up and the user can print/save the PDF when needed?**
I prefer using the FileSystemObject
In your VBA project, click Toos->References and add "Microsoft Scripting Runtime".
Then, in your code, do something like:
Dim fso as FileSystemObject
Dim folderName as String
Set fso = new FileSystemObject
folderName = "D:\MyFolder"
If fso.FolderExists(folderName) = false then
fso.CreateFolder folderName
End If
Dim strFileName As String, strC3 As String, strWorksheet As String
strB1 = Range("B1").Value
strWorksheet = ActiveSheet.Name
strFileName = folderName + "\" + strB1 & " " & strWorksheet & " " & Format(Date, "DD-MM-YYYY")
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"D:\" & strFileName & ".pdf", _
Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=True
You can use the function below to create a single folder or a tree of subfolders. The function uses the (VBA.FileSystem) MkDir function.
Public Function CreateFolderTree(ByVal mainFolder As String, ParamArray args() As Variant) As String
On Error GoTo ErrProc
Dim path As String
path = mainFolder & IIf(Right(mainFolder, 1) <> "\", "\", vbNullString)
Dim idx As Long
For idx = LBound(args) To UBound(args)
If Len(Dir(path & args(idx), vbDirectory)) = 0 Then MkDir path & args(idx)
path = path & args(idx) & "\"
Next idx
CreateFolderTree = path
Leave:
On Error GoTo 0
Exit Function
ErrProc:
MsgBox Err.Description, vbCritical
Resume Leave
End Function
To call it:
Sub T()
Dim path_ As String
path_ = CreateFolderTree("C:\My folder", "Subfolder 1", "Subfolder 2")
Debug.Print path_
'C:\My folder\Subfolder 1\Subfolder 2\
End Sub
I usually use this:
Private Declare Function MakeSureDirectoryPathExists Lib "imagehlp.dll" (ByVal lpPath As String) As Long
Public Sub MakeFullDir(strPath As String)
If Right(strPath, 1) <> "\" Then strPath = strPath & "\" 'Optional depending upon intent
MakeSureDirectoryPathExists strPath
End Sub
If the path doesn't already exists, it creates it, even if there are multiple layer of non-existing folders.
E.g: C:\aFolder\bFolder\cFolder\ if only aFolder exists this will make bFolder and cFolder.

Formatting data imported from csv files to excel spreadsheet

I'm working on writing a script that will import the csv file outputs from a scanning electron microscope to a master spreadsheet organized by date and sample number. Having never used vba before and with little programming experience before now, this has been quite a challenge. There are a few thousand files organized by sample and image number. Right now what I have is able to read in the csv files and copy them to a single spreadsheet. The csv files look something like this
Atomic number,Element symbol,Element name,Concentration percentage,Certainty
8,O,Oxygen,57.5,0.99
14,Si,Silicon,15.5,0.99
26,Fe,Iron,13.6,0.97
13,Al,Aluminium,8.4,0.98
19,K,Potassium,3.3,0.97
22,Ti,Titanium,0.9,0.89
65,Tb,Terbium,0.7,0.53
When I run the code I have, the above data is copied from each file and pasted into the master spreadsheet. What I would like to do is have it format this data. Here is what I have so far to actually write the data to a spreadsheet.
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#Else
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#End If
Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103
Public Sub ShellAndWait(ByVal PathName As String, Optional WindowState)
Dim hProg As Long
Dim hProcess As Long, ExitCode As Long
If IsMissing(WindowState) Then WindowState = 1
hProg = Shell(PathName, WindowState)
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, hProg)
Do
GetExitCodeProcess hProcess, ExitCode
DoEvents
Loop While ExitCode = STILL_ACTIVE
End Sub
Sub Merge_CSV_Files()
Dim BatFileName As String
Dim TXTFileName As String
Dim XLSFileName As String
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim DefPath As String
Dim Wb As Workbook
Dim oApp As Object
Dim oFolder
Dim foldername
BatFileName = Environ("Temp") & _
"\CollectCSVData" & Format(Now, "dd-mm-yy-h-mm-ss") & ".bat"
TXTFileName = Environ("Temp") & _
"\AllCSV" & Format(Now, "dd-mm-yy-h-mm-ss") & ".txt"
DefPath = Application.DefaultFilePath
If Right(DefPath, 1) <> "\" Then
DefPath = DefPath & "\"
End If
If Val(Application.Version) < 12 Then
FileExtStr = ".xls": FileFormatNum = -4143
Else
FileExtStr = ".xlsx": FileFormatNum = 51
'FileExtStr = ".xls": FileFormatNum = 56
End If
XLSFileName = DefPath & "SEM Master File" & _
Format(Now, "dd-mmm-yyyy h-mm-ss") & FileExtStr
Set oApp = CreateObject("Shell.Application")
Set oFolder = oApp.BrowseForFolder(0, "Select folder with CSV files", 512)
If Not oFolder Is Nothing Then
foldername = oFolder.Self.Path
If Right(foldername, 1) <> "\" Then
foldername = foldername & "\"
End If
Open BatFileName For Output As #1
Print #1, "Copy " & Chr(34) & foldername & "*.csv" _
& Chr(34) & " " & TXTFileName
Close #1
ShellAndWait BatFileName, 0
If Dir(TXTFileName) = "" Then
MsgBox "There are no csv files in this folder"
Kill BatFileName
Exit Sub
End If
Application.ScreenUpdating = False
Workbooks.OpenText Filename:=TXTFileName, Origin:=xlWindows, StartRow _
:=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True, _
Space:=False, Other:=False, AdjustColumnWidth = True
Set Wb = ActiveWorkbook
Application.DisplayAlerts = False
Wb.SaveAs Filename:=XLSFileName, FileFormat:=FileFormatNum
Application.DisplayAlerts = True
Wb.Close savechanges:=False
MsgBox "You will find the Excel file here: " & vbNewLine & XLSFileName
Kill BatFileName
Kill TXTFileName
Application.ScreenUpdating = True
End If
End Sub
The name of each file is its sample/image number and date. What I need is for this to ignore the first row of data in each csv file (Atomic number,Element symbol, etc.), create a single protected row at the top of the sheet that has those labels, and record the name of each file in a column next to each row of data from that file. With this information recorded I think I will be able to organize the data the way I want.
check out this approach using ADO. Adapted from: https://msdn.microsoft.com/en-us/library/ms974559.aspx
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H0001
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")
strPathtoTextFile = "C:\Databases\"
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strPathtoTextFile & ";" & _
"Extended Properties=""text;HDR=YES;FMT=Delimited"""
objRecordset.Open "SELECT * FROM MyCSV.csv where [Atomic number] <> "Atomic number"", _
objConnection, adOpenStatic, adLockOptimistic, adCmdText
Range("A2").CopyFromRecordset objRecordset
objRecordset.close
objConnection.close

VBA Macro for importing text files into separate Excel workbooks

I have a macro that imports all the text files in one folder onto one Excel sheet. What I want now is that the macro should import all the files into the folder, but into separate Excel workbooks (separate Excel files).
I am attaching the macro here, please help!
P.S. : This macro is not written by me. I found it online, and made some necessary changes to suit my needs.
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#Else
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
#End If
Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103
Public Sub ShellAndWait(ByVal PathName As String, Optional WindowState)
Dim hProg As Long
Dim hProcess As Long, ExitCode As Long
'fill in the missing parameter and execute the program
If IsMissing(WindowState) Then WindowState = 1
hProg = Shell(PathName, WindowState)
'hProg is a "process ID under Win32. To get the process handle:
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, hProg)
Do
'populate Exitcode variable
GetExitCodeProcess hProcess, ExitCode
DoEvents
Loop While ExitCode = STILL_ACTIVE
End Sub
Sub Merge_CSV_Files()
Dim BatFileName As String
Dim TXTFileName As String
Dim XLSFileName As String
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim DefPath As String
Dim Wb As Workbook
Dim oApp As Object
Dim oFolder
Dim foldername
'Create two temporary file names
BatFileName = Environ("Temp") & _
"\CollectCSVData" & Format(Now, "dd-mm-yy-h-mm-ss") & ".bat"
TXTFileName = Environ("Temp") & _
"\AllCSV" & Format(Now, "dd-mm-yy-h-mm-ss") & ".txt"
'Folder where you want to save the Excel file
'DefPath = Application.DefaultFilePath
DefPath = ThisWorkbook.Path
If Right(DefPath, 1) <> "\" Then
DefPath = DefPath & "\"
End If
'Set the extension and file format
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007 or higher
FileExtStr = ".xlsx": FileFormatNum = 51
'If you want to save as xls(97-2003 format) in 2007 use
'FileExtStr = ".xls": FileFormatNum = 56
End If
'Name of the Excel file with a date/time stamp
XLSFileName = DefPath & "MetaData Collated " & _
Format(Now, "dd-mmm-yyyy h-mm-ss") & FileExtStr
'Browse to the folder with CSV files
Set oApp = CreateObject("Shell.Application")
Set oFolder = oApp.BrowseForFolder(0, "Select folder with CSV files", 512)
If Not oFolder Is Nothing Then
foldername = oFolder.Self.Path
If Right(foldername, 1) <> "\" Then
foldername = foldername & "\"
End If
'Create the bat file
Open BatFileName For Output As #1
Print #1, "Copy " & Chr(34) & foldername & "*.txt" _
& Chr(34) & " " & TXTFileName
Close #1
'Run the Bat file to collect all data from the CSV files into a TXT file
ShellAndWait BatFileName, 0
If Dir(TXTFileName) = "" Then
MsgBox "There are no csv files in this folder"
Kill BatFileName
Exit Sub
End If
'Open the TXT file in Excel
Application.ScreenUpdating = False
Workbooks.OpenText Filename:=TXTFileName, Origin:=xlWindows, StartRow _
:=1, DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, Tab:=False, Semicolon:=False, Comma:=True, _
Space:=False, Other:=True, OtherChar:="|"
'Save text file as a Excel file
Set Wb = ActiveWorkbook
Wb.SaveAs FileFormat:=FileFormatNum
Wb.SaveAs Filename:=XLSFileName, FileFormat:=FileFormatNum
Application.DisplayAlerts = True
Wb.Close savechanges:=False
MsgBox "You find the Excel file here: " & vbNewLine & XLSFileName
'Delete the bat and text file you temporary used
Kill BatFileName
Kill TXTFileName
Application.ScreenUpdating = True
End If
End Sub
The following works (tested on .csv files):
Sub test()
Convert "C:\"
End Sub
Sub Convert(strPath As String)
Dim wbI As Workbook, wbO As Workbook
Dim wsI As Worksheet
Dim filename, newname
Dim fldr As FileDialog
Dim sItem As String
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = strPath
If .Show <> -1 Then Exit Sub
sItem = .SelectedItems(1)
End With
Set fldr = Nothing
filename = Dir(sItem & "\*.*")
While (filename <> "")
Set wbO = Workbooks.Open(sItem & "\" & filename)
If (wbO Is Nothing) Then Exit Sub
pos = InStrRev(filename, ".")
newname = Mid(filename, 1, pos) + "xlsx"
Set wbI = Workbooks.Add
Set wsI = wbI.Sheets("Sheet1")
wbO.Sheets(1).Cells.Copy wsI.Cells
wbO.Close SaveChanges:=False
wbI.SaveAs sItem & "\" & newname
wbI.Close
filename = Dir
Wend
End Sub

Using FileSystemObject (VBA) with filter

With my code I have to write a file name to search : "test.txt" . It works fine, returns as many as test.txt exist in the selected path.
I want it to work searching : "txt" and get all the .txt files in the selected path.
My code :
Option Explicit
Dim fso As New FileSystemObject
Dim fld As Folder
Private Sub Command1_Click()
Dim nDirs As Long, nFiles As Long, lSize As Currency
Dim sDir As String, sSrchString As String
sDir = InputBox("Type the directory that you want to search for", _
"FileSystemObjects example", "C:\")
sSrchString = InputBox("Type the file name that you want to search for", _
"FileSystemObjects example", "")
' MousePointer = vbHourglass
' Label1.Caption = "Searching " & vbCrLf & UCase(sDir) & "..."
lSize = FindFile(sDir, sSrchString, nDirs, nFiles)
' MousePointer = vbDefault
MsgBox Str(nFiles) & " files found in" & Str(nDirs) & _
" directories", vbInformation
MsgBox "Total Size = " & lSize & " bytes"
End Sub
Private Function FindFile(ByVal sFol As String, sFile As String, _
nDirs As Long, nFiles As Long) As Currency
Dim tFld As Folder, tFil As File, FileName As String
On Error GoTo Catch
Set fld = fso.GetFolder(sFol)
FileName = Dir(fso.BuildPath(fld.path, sFile), vbNormal Or _
vbHidden Or vbSystem Or vbReadOnly)
While Len(FileName) <> 0
FindFile = FindFile + FileLen(fso.BuildPath(fld.path, _
FileName))
nFiles = nFiles + 1
' List1.AddItem fso.BuildPath(fld.Path, FileName) ' Load ListBox
FileName = Dir() ' Get next file
DoEvents
Wend
' Label1 = "Searching " & vbCrLf & fld.Path & "..."
nDirs = nDirs + 1
If fld.SubFolders.Count > 0 Then
For Each tFld In fld.SubFolders
DoEvents
FindFile = FindFile + FindFile(tFld.Path, sFile, nDirs, nFiles)
Next
End If
Exit Function
Catch: FileName = ""
Resume Next
End Function
and a tip, I've found something like :
For Each file In files
If Right(file, 3) = "pdf" Then
myMailItem.Attachments.Add CStr(file)
found = True
End If
But I couldn't get it working in my code.
Thanks!