Combined multiple CSV files to single worksheet maintaining date time formatting - vba

So I have been going around in circles trying to find an answer to what should be a basic file combination.
I have a weeks worth of CSV files generated.
I need to combine the files into a single worksheet with the data stacked
Original file has 2 of the columns that are date and time combined (d/mm/yyyy h:mm:ss)
I have my VBA code combining the data as required but the time formatting is screwed in the master file (d/mm/yyyy h:mm)
Can someone help please with my code :(
Option Explicit
Sub ImportCSVsWithReference()
'Summary: Import all CSV files from a folder into a single sheet
' adding a field in column A listing the CSV filenames
Dim wbCSV As Workbook
Dim wsMstr As Worksheet: Set wsMstr = ThisWorkbook.Sheets("MasterCSV")
Dim fCSV As String
Dim fList As String
Dim fName As String
Dim fd As FileDialog
Dim FileChosen As Integer
Dim FileName As String
Dim i As Integer
Dim wbCSVDisplayOrder As Long
Dim M As Long
'Select the correct files for merge
Set fd = Application.FileDialog(msoFileDialogFilePicker)
'use the standard title and filters, but change the
'initial folder
fd.InitialFileName = "C:\RTVis\OT"
fd.InitialView = msoFileDialogViewList
'allow multiple file selection
fd.AllowMultiSelect = True
FileChosen = fd.Show
If FileChosen = -1 Then
'open each of the files chosen
For i = 1 To fd.SelectedItems.Count
Workbooks.Open fd.SelectedItems(i)
Next i
End If
'clear master page of previous data
If MsgBox("Clear the existing MasterCSV sheet before importing?", vbYesNo, "Clear?") _
= vbYes Then wsMstr.UsedRange.Clear
Application.ScreenUpdating = False 'speed up macro
'Combine files
'start the CSV file listing
fCSV = Dir(fName & "*.csv")
Do While Len(fCSV) > 0
'open a CSV file
Set wbCSV = Workbooks.Open(fName & fCSV)
'copy date into master sheet and close source file
ActiveSheet.UsedRange.Copy wsMstr.Range("A" & Rows.Count).End(xlUp).Offset(0)
wbCSV.Close False
'ready next CSV
fCSV = Dir
Loop
Application.ScreenUpdating = True
End Sub

If I understand you correctly, your problem is with the date/time formatting being munged by Excel when you open the file, but the parsing works properly otherwise.
When Excel sees what looks like a date, it will try to interpret it in accord with your Windows Regional Settings. So if the date in the file is DMY, and your settings at MDY, the dates will not be interpreted properly.
Workaround 1: Change your windows regional settings to match those in the CSV file
Workaround 2: Use the QueryTables method. You can get the VBA equivalent by using the macro recorder and executing, from native Excel, Data ► Get External Data ► From Text Files This will allow specification of the date format. But you must be careful about not adding them multiple times but by refreshing them instead or first deleting them and then adding them again.
Workaround 3: Write your own parsing routine to parse the raw data. Probably should use the FileSystemObject if doing this.
Workaround 4: Change the file suffix to something other than .csv, and then use the OpenText method. This requires the least changes to your existing code. You create a new file; import that; then delete it. The code below demonstrates that process, but does NOT do the other things that you want.
If you use 4, you should add some error handling in case the file copy / delete process goes awry. My favorite options would be 2 or 3.
Sample Code
Option Explicit
Sub foo()
Dim WB As Workbook, wbCSV As Workbook, swbCSV As String
Dim sFN As String, sCopyFN
Dim FD As FileDialog
Set WB = ThisWorkbook
Set FD = Application.FileDialog(msoFileDialogFilePicker)
With FD
.AllowMultiSelect = False
.Filters.Add "Text or CSV", "*.txt, *.csv", 1
.Show
sFN = .SelectedItems(1)
End With
'If CSV, remove suffix
sCopyFN = ""
If sFN Like "*.csv" Then
sCopyFN = Left(sFN, Len(sFN) - 4)
FileCopy sFN, sCopyFN
sFN = sCopyFN
End If
Workbooks.OpenText Filename:=sFN, DataType:=xlDelimited, origin:=437, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=True, Other:=False, _
FieldInfo:=Array(Array(1, xlDMYFormat), Array(2, xlGeneralFormat))
Set wbCSV = ActiveWorkbook
'Get path as string since it will not be available after closing the file
swbCSV = wbCSV.FullName
'Move the data into this workbook
Dim rCopy As Range, rDest As Range
With WB.Worksheets("sheet1")
Set rDest = .Cells(.Rows.Count, 1).End(xlUp)
End With
Set rCopy = wbCSV.Sheets(1).UsedRange
rCopy.Copy rDest
'must close the file before deleting it
wbCSV.Close False
Kill swbCSV
End Sub

Related

Compile many csv files into a single, new csv sheet

I am working on copying the contents of several CSV files into a single, new CSV file, and am having trouble with my vba code. I am aware of the CMD tool to copy .csv files, but this does not work for me, as my directory is stored on the network and I can't path to it from the CMD window (I get an error about using a UNC address). My boss would prefer for the code to have zero human interaction, so moving the files to a directory on the computer, running the CMD, and then moving the results back is not an option.
Per my boss's request, the code needs to do the following:
"Every time the macro is run, the new master file should be saved over when it's run so the report pulls the same file each time."
A logical consequence of this is that the macro should catch a particular string in the resulting file name and "skip over" that file when making a new version. Also, every .csv file has headings, so my ranges are set up to avoid copying them.
Below is the code I have written thus far. When I try to run the macro, I get a few errors to come up with the line:
Set WorkBk = Workbooks.Open(FolderPath & FileName)
They're always 1004 messages, and they either say my created file is either read-only/encrypted, or they tell me that Method 'Open' of object 'Workbooks' failed.
What do I need to change or do to get the below code to work? I am confident in this code because I slightly modified it from code I wrote yesterday to do a similar task with .xlsx files. Any help is greatly appreciated, thank you.
Sub CSV_Aggregate()
'
'
'
'
Dim CSVAggregation As Worksheet
Dim SummarySheet As Worksheet
Dim FolderPath As String
Dim NRow As Long
Dim FileName As String
Dim WorkBk As Workbook
Dim SourceRange As Range
Dim DestRange As Range
' Points the macro to the proper data source (UPDATE THIS LINE TO YOUR DATA SOURCE!!!)
FolderPath = "\\usilsvr01\lin#mktg\Analytical Services\DIA\Offers Data Question to Exclude"
' Creates a blank workbook to host the aggregation, and names the first worksheet appropriately.
Set CSVAggregation = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
Sheets(1).Name = "DIA Aggregation"
' Heads the worksheet with the relevant fields to be aggregated.
CSVAggregation.Range("A1:C1") = Array("Manufacturer Number", "Offer Code", "Data Question")
' Incrementer to keep track of where new rows should be appended.
NRow = 2
Dim LastRow As Long
' Call Dir the first time, pointing it to all Excel files in the folder path.
FileName = Dir(FolderPath & "*.csv")
' Loop until all .csv files in the source folder have been read.
Do While FileName <> ""
' Macro should skip over the previous version of the aggregate file
If InStr(1, FileName, "Aggregate") > 0 Then
FileName = Dir()
End If
' Open a workbook in the folder.
Set WorkBk = Workbooks.Open(FolderPath & FileName)
' Loop through data sheets to collect data.
Sheets(1).Activate ' Make the sheet active, find where the data is, and select the data.
LastRow = WorkBk.Worksheets(1).Cells.Find(What:="*", _
After:=WorkBk.Worksheets(1).Cells.Range("A1"), _
SearchDirection:=xlPrevious, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows).Row
Set SourceRange = WorkBk.Worksheets(1).Range("A2:C" & LastRow)
' Set the destination range to start at column A and
' be the same size as the source range.
Set DestRange = DIAAggregation.Range("A" & NRow)
Set DestRange = DestRange.Resize(SourceRange.Rows.Count, SourceRange.Columns.Count)
' Copy over the values from the source to the destination.
DestRange.Value = SourceRange.Value
' Increment NRow so that data is not overwritten.
NRow = NRow + DestRange.Rows.Count
' Close the source workbook without saving changes.
WorkBk.Close savechanges:=False
' Use Dir to get the next file name.
FileName = Dir()
Loop
' Call AutoFit on the destination sheet so that all data is readable.
CSVAggregation.Columns.AutoFit
CSVAggregation.Rows.AutoFit
' Places cursor on the first sell so document doesn't open highlighted or anywhere besides the top.
CSVAggregation.Range("A1").Select
' Creates variable to hold SaveAs name for Aggregation Report.
Dim workbook_Name As String
workbook_Name = "CSV Aggregate"
' Saves the workbook in the folder that the data is found in (BE SURE TO CHECK TAHT YOU HAVE THE FOLDER/FILES WITH WHICH YOU SHOULD BE WORKING!!!!)
ActiveWorkbook.SaveAs FileName:=(FolderPath & workbook_Name), FileFormat:=6
End Sub
Okay, I was able to make a few changes to get my code to work.
Here is the final code:
Sub CSV_Aggregate()
'
'
'
'
Dim CSVAggregation As Worksheet
Dim SummarySheet As Worksheet
Dim FolderPath As String
Dim NRow As Long
Dim FileName As String
Dim WorkBk As Workbook
Dim SourceRange As Range
Dim DestRange As Range
' Points the macro to the proper data source (UPDATE THIS LINE TO YOUR DATA SOURCE!!!)
FolderPath = "\\usilsvr01\lin#mktg\Analytical Services\DIA\Offers Data Question to Exclude\"
' Creates a blank workbook to host the aggregation, and names the first worksheet appropriately.
Set CSVAggregation = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
Sheets(1).Name = "DIA Aggregation"
' Heads the worksheet with the relevant fields to be aggregated.
CSVAggregation.Range("A1:C1") = Array("Manufacturer Number", "Offer Code", "Data Question")
' Incrementer to keep track of where new rows should be appended.
NRow = 2
Dim LastRow As Long
' Call Dir the first time, pointing it to all Excel files in the folder path.
FileName = Dir(FolderPath & "*.csv")
' Loop until all .csv files in the source folder have been read.
Do While FileName <> ""
' Macro should skip over the previous version of the aggregate file
If InStr(1, FileName, "Aggregate") > 0 Then
FileName = Dir()
End If
' Open a workbook in the folder.
Set WorkBk = Workbooks.Open(FolderPath & FileName, , True)
' Loop through data sheets to collect data.
Sheets(1).Activate ' Make the sheet active, find where the data is, and select the data.
LastRow = WorkBk.Worksheets(1).Cells.Find(What:="*", _
After:=WorkBk.Worksheets(1).Cells.Range("A1"), _
SearchDirection:=xlPrevious, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows).Row
Set SourceRange = WorkBk.Worksheets(1).Range("A2:C" & LastRow)
' Set the destination range to start at column A and
' be the same size as the source range.
Set DestRange = CSVAggregation.Range("A" & NRow)
Set DestRange = DestRange.Resize(SourceRange.Rows.Count, SourceRange.Columns.Count)
' Copy over the values from the source to the destination.
DestRange.Value = SourceRange.Value
' Increment NRow so that data is not overwritten.
NRow = NRow + DestRange.Rows.Count
' Close the source workbook without saving changes.
WorkBk.Close savechanges:=False
' Use Dir to get the next file name.
FileName = Dir()
Loop
' Call AutoFit on the destination sheet so that all data is readable.
CSVAggregation.Columns.AutoFit
CSVAggregation.Rows.AutoFit
' Places cursor on the first sell so document doesn't open highlighted or anywhere besides the top.
CSVAggregation.Range("A1").Select
' Creates variable to hold SaveAs name for Aggregation Report.
Dim workbook_Name As String
workbook_Name = "CSV Aggregate"
' Saves the workbook in the folder that the data is found in (BE SURE TO CHECK TAHT YOU HAVE THE FOLDER/FILES WITH WHICH YOU SHOULD BE WORKING!!!!)
ActiveWorkbook.SaveAs FileName:=(FolderPath & workbook_Name), FileFormat:=6
End Sub
I added a final "\" at the FilePath declaration.
I also rewrote the set WorkBk line as:
Set WorkBk = Workbooks.Open(FolderPath & FileName, , True)
This resolved the "read only" error I was getting.
You can use the pushd command to get around the UNC/network folder issue in cmd. It assigns a temporary drive letter to the network folder and allows you to continue as normal.

Copying data from many workbooks to a summary workbook with Excel-VBA. Run time errors

I have files in a folder and I want to copy data from these files and paste them into another Master workbook sheet.
I keep getting a runtime error ‘1004’: Sorry we couldn’t find C:\Users\jjordan\Desktop\Test Dir\MASTER`, It is possible it was moved, renamed or deleted.
The error is highlighted on this line of code: Workbooks.Open SumPath & SumName
I have seen other questions similar to this on the web, I have tried making various changes. But still without success. Please advise.
Dir for source files: C:\Users\ jjordan \Desktop\Test Dir\GA Test\
Dir for Master file: C:\Users\ jjordan \Desktop\Test Dir\MASTER\
Source filenames differ, but all end in "*.xlsx."
Master filename: " MASTER – Data List - 2016.xlsm " ‘macro file
Source worksheet name = "Supplier_Comments"
Master worksheet name = "Sheet5"
Option Explicit
Sub GetDataFromMaster()
Dim MyPath As String
Dim SumPath As String
Dim MyName As String
Dim SumName As String
Dim MyTemplate As String
Dim SumTemplate As String
Dim myWS As Worksheet
Dim sumWS As Worksheet
'Define folders and filenames
MyPath = "C:\Users\jjordan\Desktop\Test Dir\GA Test\"
SumPath = "C:\Users\jjordan\Desktop\Test Dir\MASTER\"
MyTemplate = "*.xlsx" 'Set the template.
SumTemplate = "MASTER – Data List - 2016.xlsm"
'Open the template file and get the Worksheet to put the data into
SumName = Dir(SumPath & SumTemplate)
Workbooks.Open SumPath & SumName
Set sumWS = ActiveWorkbook.Worksheets("Sheet5")
'Open each source file, copying the data from each into the template file
MyName = Dir(MyPath & MyTemplate) 'Retrieve the first file
Do While MyName <> ""
'Open the source file and get the worksheet with the data we want.
Workbooks.Open MyPath & MyName
Set myWS = ActiveWorkbook.Worksheets("Suppliers_Comment")
'Copy the data from the source and paste at the end of sheet 5
myWS.Range("A2:N100").Copy
sumWS.Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
'Close the current sourcefile and get the next
Workbooks(MyName).Close SaveChanges:=False 'close
MyName = Dir 'Get next file
Loop
'Now all sourcefiles are copied into the Template file. Close and save it
Workbooks(SumName).Close SaveChanges:=True
End Sub
Here is a template for what you'd like done. NOTE that forward slashes can cause run time error b/c vba handles them in an annoying way.
Sub DougsLoop()
Dim wbk As Workbook
Dim Filename As String
Dim path As String
Dim rCell As Range
Dim rRng As Range
Dim wsO As Worksheet
Dim StartTime As Double
Dim SecondsElapsed As Double
Dim sheet As Worksheet
Application.ScreenUpdating = False 'these three statements help performance by disabling the self titled in each, remeber to re-enable at end of code
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
StartTime = Timer 'Starts timer to see how long code takes to execute. I like having this in macors that loop through files
path = "C:\Users\jjordan\Desktop\Test Dir\GA Test" & "\" 'pay attention to this line of code********
Filename = Dir(path & "*.xl??")
Set wsO = ThisWorkbook.Sheets("Sheet5")
Do While Len(Filename) > 0 'this tells the code to stop when there are no more files in the destination folder
DoEvents
Set wbk = Workbooks.Open(path & Filename, True, True)
For Each sheet In ActiveWorkbook.Worksheets
Set rRng = sheet.Range("a2:n100")
For Each rCell In rRng.Cells
wsO.Cells(wsO.Rows.count, 1).End(xlUp).Offset(1, 0).Value = rCell
Next rCell
Next
wbk.Close False
Filename = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
End Sub
alter to this to your needs and you'll find it works perfectly :)
EDIT: Also in your code you make use of COPY & PASTE a lot. Try avoid doing this in the future. Try doing something:
ThisWorkbook.Sheets("Sheet1").Range("a1").Value = OtherWork.Sheets("Sheet1").Range("a1").Value
This is more efficient and wont bog down your code as much.
here is some offset logic
wsO.Cells(wsO.Rows.count, 1).End(xlUp).Offset(1, 0).Value =
wsO.Cells(wsO.Rows.count, 1).End(xlUp).Offset(0, 1).Value =
wsO.Cells(wsO.Rows.count, 1).End(xlUp).Offset(0, 2).Value =
notice the Offset(x,y) value? Essentially x is down and y is right. this is of course referencing the original position. So to get a value to go in the same row but three columns over you would use "Offset(0,3)" etc etc
Ill let you alter your code to do this. :)
I guess actually trying to piece it together was a struggle? Here this version assumes the macro is in the master workbook(and that youre running it form the master). If you want to change go ahead, but this is as far as I go. At some point, you'll have to experiment on your own.

Excel VBA: Error in file format when saved using VBA

I am trying to format the contents of an Excel file, and automatically save it in a specified location with a specified name via a dialog box. I have the codes below, but I am experiencing issues with the file format after I save the file. This is the issue that Excel prompts me:
This code allows me to format my excel file to the format I require, and then automatically shows the location and file name that I want to save it in. This codes allows me to save me excel file successfully. However, when I try to open it, it tells me that the file is corrupted, or that the extension is wrong.
Does anyone know why am I experiencing this error? Thanks!
Code:
Option Explicit
Sub externalRatingChangeFile()
'Declare the data type of the variables
Dim wks As Worksheet
Dim lastCol As Integer
Dim lastRow As Long
Dim iCol As Integer
Dim iRow As Long
Dim sFilename As String
Dim fdlg As FileDialog
Dim xlsxFileFormat As XlFileFormat
'Set wks to the current active worksheet
Set wks = ActiveWorkbook.ActiveSheet
Set fdlg = Application.FileDialog(msoFileDialogFilePicker)
'Set the location to save the file to a variable
sFilename = "H:\Testing File\Rating Change - " + Format(Date, "YYYYMMDD")
'xlsxFileFormat = XlFileFormat.xlOpenXMLWorkbook
'Within the current active worksheet, identify the last interested row and column of data
'Any values such as 'a', '1' or '%' are considered as values. Spaces (Spacebars) are not considered as values.
With wks
With .Cells(1, 1).CurrentRegion
lastCol = .Columns.Count
lastRow = .Rows.Count
End With
'Select the interested cells and insert borders around the interested fields
.UsedRange.Borders.LineStyle = xlContinuous
.UsedRange.Columns.AutoFit
End With
'Inserting a Row at the top to input Date
Range("A1").EntireRow.Insert
'Input today's Date
wks.Range("A1").Value = "Date: " + Format(Date, "DD MMMM YYYY")
'Save as .xlsx file in the specific location stated earlier
Set fdlg = Application.FileDialog(msoFileDialogSaveAs)
With fdlg
.InitialFileName = sFilename
.Show
'If there are errors in the code, set wks to nothing and end the process
On Error GoTo err_handler
wks.SaveAs (fdlg.SelectedItems(1))
End With
'System to/not display alerts to notify Users that they are replacing an existing file.
Application.DisplayAlerts = True
err_handler:
'Set wks to its default value
Set wks = Nothing
End Sub
I assume your are starting with a CSV or other non excel format (text file etc...)
If you change the line that actually saves the file to
wks.SaveAs (fdlg.SelectedItems(1)) , FileFormat:=xlOpenXMLWorkbook
that will force the VBA to save the file in the "correct" format. It would be better to actually pick up the format selected in the dialogue but I dont think it is returned except in the file extension. You could detect that and then choose the matching format but if you are always saving as XLSX then you could just use the above method.

Manipulate/copy .CSV data, without opening the file?

I'm trying to optimize some code that takes some test data stored in CSV files does some analysis and copies their data into an excel sheet. This code is often run on hundreds of tests at a time, and its taking about 4.5 seconds per test so it can take hours to complete at times.
I looked up some optimization techniques and cut it down by about .25 seconds per test but I think the bulk of the time is being taken up by excel having to "open" the individual files before it can do anything with them. Is there a way to do this more efficiently?
I am open to answers that involve using another language to compile the files into one big file if that would make things quicker.
I would open them as text rather than workbooks:
Sub ReadCSV()
Dim MyString As String
Open "C:\path\text.csv" For Input As #1 ' Open file for input.
Do While Not EOF(1) ' Loop until end of file.
Line Input #1, MyString ' Read a line into variable
Debug.Print MyString ' Print data to the Immediate window.
Loop
Close #1 ' Close file.
End Sub
This will be much faster than opening as a workbook
I have this function working greate handling lot of CSV files. You need to indicate in cell "D11" the name of folder containing all the CSV files and will combine them into one single file. I handle over 200 files and make it quick. Hope it helps.
Sub CombineAllFilesInADirectory()
Dim Path As String 'string variable to hold the path to look through
Dim FileName As String 'temporary filename string variable
Dim tWB As Workbook 'temporary workbook (each in directory)
Dim tWS As Worksheet 'temporary worksheet variable
Dim aWS As Worksheet 'active sheet in master workbook
Dim RowCount As Long 'Rows used on master sheet
Dim uRange As Range 'usedrange for each temporary sheet
Dim mWB_comb As Workbook 'master workbook exclusivo de esta funcion
Path = Sheets("CombineFiles").Range("D11").Value
Application.EnableEvents = False 'turn off events
Application.ScreenUpdating = False 'turn off screen updating
Set mWB_comb = Workbooks.Add(1) 'create a new one-worksheet workbook
Set aWS = mWB_comb.ActiveSheet 'set active sheet variable to only sheet in mWB
If Right(Path, 1) <> Application.PathSeparator Then 'if path doesnt end in "\"
Path = Path & Application.PathSeparator 'add "\"
End If
FileName = Dir(Path & "*.csv", vbNormal) 'set first file's name to filename variable
Application.StatusBar = "reading files, please wait."
Do Until FileName = "" 'loop until all files have been parsed
If Path <> ThisWorkbook.Path Or FileName <> ThisWorkbook.Name Then
Set tWB = Workbooks.Open(FileName:=Path & FileName) 'open file, set to tWB variable
For Each tWS In tWB.Worksheets 'loop through each sheet
Set uRange = tWS.Range("A4", tWS.Cells(tWS.UsedRange.Row + tWS.UsedRange.Rows.count - 1, _
tWS.UsedRange.Column + tWS.UsedRange.Columns.count - 1)) 'set used range
If RowCount + uRange.Rows.count > 65536 Then 'if the used range wont fit on the sheet
aWS.Columns.AutoFit 'autofit mostly-used worksheet's columns
Set aWS = mWB_comb.Sheets.Add(After:=aWS) 'add a new sheet that will accommodate data
RowCount = 0 'reset RowCount variable
End If
If RowCount = 0 Then 'if working with a new sheet
aWS.Range("A1", aWS.Cells(3, uRange.Columns.count)).Value = tWS.Range("A1", _
tWS.Cells(3, uRange.Columns.count)).Value 'copy headers from tWS
RowCount = 3 'add one to rowcount
End If
aWS.Range("A" & RowCount + 1).Resize(uRange.Rows.count, _
uRange.Columns.count).Value = uRange.Value 'move data from temp sheet to data sheet
RowCount = RowCount + uRange.Rows.count 'increase rowcount accordingly
Next 'tWS
tWB.Close False 'close temporary workbook without saving
End If
FileName = Dir() 'set next file's name to FileName variable
Loop
Application.StatusBar = "Ready"
mWB_comb.Sheets(1).Select 'select first data sheet on master workbook
Application.EnableEvents = True 're-enable events
Application.ScreenUpdating = True 'turn screen updating back on
'Clear memory of the object variables
Set tWB = Nothing
Set tWS = Nothing
Set mWB_comb = Nothing
Set aWS = Nothing
Set uRange = Nothing
End Sub

Copy data from another Workbook through VBA

I want to collect data from different files and insert it into a workbook doing something like this.
Do While THAT_DIFFERENT_FILE_SOMEWHERE_ON_MY_HDD.Cells(Rand, 1).Value <> "" And Rand < 65536
then 'I will search if the last row in my main worksheet is in this file...
End Loop
If the last row from my main worksheet is in the file, I'll quit the While Loop. If not, I'll copy everything. I'm having trouble finding the right algorithm for this.
My problem is that I don't know how to access different workbooks.
The best (and easiest) way to copy data from a workbook to another is to use the object model of Excel.
Option Explicit
Sub test()
Dim wb As Workbook, wb2 As Workbook
Dim ws As Worksheet
Dim vFile As Variant
'Set source workbook
Set wb = ActiveWorkbook
'Open the target workbook
vFile = Application.GetOpenFilename("Excel-files,*.xls", _
1, "Select One File To Open", , False)
'if the user didn't select a file, exit sub
If TypeName(vFile) = "Boolean" Then Exit Sub
Workbooks.Open vFile
'Set targetworkbook
Set wb2 = ActiveWorkbook
'For instance, copy data from a range in the first workbook to another range in the other workbook
wb2.Worksheets("Sheet2").Range("C3:D4").Value = wb.Worksheets("Sheet1").Range("A1:B2").Value
End Sub
You might like the function GetInfoFromClosedFile()
Edit: Since the above link does not seem to work anymore, I am adding alternate link 1 and alternate link 2 + code:
Private Function GetInfoFromClosedFile(ByVal wbPath As String, _
wbName As String, wsName As String, cellRef As String) As Variant
Dim arg As String
GetInfoFromClosedFile = ""
If Right(wbPath, 1) <> "" Then wbPath = wbPath & ""
If Dir(wbPath & "" & wbName) = "" Then Exit Function
arg = "'" & wbPath & "[" & wbName & "]" & _
wsName & "'!" & Range(cellRef).Address(True, True, xlR1C1)
On Error Resume Next
GetInfoFromClosedFile = ExecuteExcel4Macro(arg)
End Function
Are you looking for the syntax to open them:
Dim wkbk As Workbook
Set wkbk = Workbooks.Open("C:\MyDirectory\mysheet.xlsx")
Then, you can use wkbk.Sheets(1).Range("3:3") (or whatever you need)
There's very little reason not to open multiple workbooks in Excel. Key lines of code are:
Application.EnableEvents = False
Application.ScreenUpdating = False
...then you won't see anything whilst the code runs, and no code will run that is associated with the opening of the second workbook. Then there are...
Application.DisplayAlerts = False
Application.Calculation = xlManual
...so as to stop you getting pop-up messages associated with the content of the second file, and to avoid any slow re-calculations. Ensure you set back to True/xlAutomatic at end of your programming
If opening the second workbook is not going to cause performance issues, you may as well do it. In fact, having the second workbook open will make it very beneficial when attempting to debug your code if some of the secondary files do not conform to the expected format
Here is some expert guidance on using multiple Excel files that gives an overview of the different methods available for referencing data
An extension question would be how to cycle through multiple files contained in the same folder. You can use the Windows folder picker using:
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
If .Selected.Items.Count = 1 the InputFolder = .SelectedItems(1)
End With
FName = VBA.Dir(InputFolder)
Do While FName <> ""
'''Do function here
FName = VBA.Dir()
Loop
Hopefully some of the above will be of use
I had the same question but applying the provided solutions changed the file to write in. Once I selected the new excel file, I was also writing in that file and not in my original file. My solution for this issue is below:
Sub GetData()
Dim excelapp As Application
Dim source As Workbook
Dim srcSH1 As Worksheet
Dim sh As Worksheet
Dim path As String
Dim nmr As Long
Dim i As Long
nmr = 20
Set excelapp = New Application
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
.Show
path = .SelectedItems.Item(1)
End With
Set source = excelapp.Workbooks.Open(path)
Set srcSH1 = source.Worksheets("Sheet1")
Set sh = Sheets("Sheet1")
For i = 1 To nmr
sh.Cells(i, "A").Value = srcSH1.Cells(i, "A").Value
Next i
End Sub
With excelapp a new application will be called. The with block sets the path for the external file. Finally, I set the external Workbook with source and srcSH1 as a Worksheet within the external sheet.