Read a file and creat a table - excel

I'm looking for a help in a difficult mission.
I have more then 30.000 files in a especific folder (*\backup) in xl?? format and need to read the cell B4. I thought the better idea is use the VBA in Excel to read this specific cell for each file and write on a table A:B.

I believe the following should help you, just remember to amend the declaration for the destination Worksheet name and the full path to the folder where the Workbooks you want to read reside.
The code below will loop through your desired Directory/Folder and read all the files with an .xls* extension, get the value from the first Worksheet in cell B4 and pass this value to the destination worksheet.
Sub LoopAllExcelFilesInFolder()
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim wsDestination As Worksheet: Set wsDestination = ThisWorkbook.Worksheets("Sheet1")
'declare and set the worksheet where you want to aggregate the data.
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Application.CutCopyMode = False
myPath = "C:\backup\"
'set the full path to the folder you want to utilize, remember to add the last \
Last = wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp).Row
If Last >= 2 Then wsDestination.Range("A2:B" & Last).ClearContents
'clear the destination worksheet ready to aggregate again
myExtension = "*.xls*"
'Target File Extension (must include wildcard "*")
myFile = Dir(myPath & myExtension)
'Target Path with Ending Extention
Do While myFile <> ""
'Loop through each Excel file in folder
Set wb = Workbooks.Open(Filename:=myPath & myFile)
DoEvents
'Ensure Workbook has opened before moving on to next line of code
wsDestination.Cells(1, "A").Value = "Filename"
wsDestination.Cells(1, "B").Value = "Value From Cell B4"
NextRow = wsDestination.Cells(wsDestination.Rows.Count, "A").End(xlUp).Offset(1, 0).Row
wsDestination.Cells(NextRow, "A").Value = myFile
wsDestination.Cells(NextRow, "B").Value = wb.Worksheets(1).Range("B4").Value
wb.Close SaveChanges:=False
'Close Workbook without Saving
DoEvents
'Ensure Workbook has closed before moving on to next line of code
myFile = Dir
'Next File
Loop
MsgBox "Transfer of Data Completed!", vbInformation, "Info"
'Message Box when tasks are completed
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub

Related

Loop Through Files to Find Specific Files

I am trying to set up a macro where you can open certain files with a certain name without having to go through the files I have already filtered through.
In the code before this macro, it loops through an entire folder, and opens all of the files that meet a criteria, pull a number from there, pastes into the new workbook, closes that workbook, and goes to the next file.
I have the criteria in a range in the current workbook, and I want to use that criteria when determining which workbooks to open in the folder.
I'm wondering if there is a way to start looping through the folder starting with the last file that was opened using the macro before.
EDIT: The following code is what I have so far.
Sub LoopThroughFilesInFolder()
'=============================================================================
'Looping through all of the files in the folder, and grabbing the last value
'=============================================================================
Dim wb As Workbook
Dim MyPath As String
Dim MyFile As String
Dim myExtension As String
Dim FolderPicker As FileDialog
Application.ScreenUpdating = False
'Retrieve Target Folder Path From User
Set FolderPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FolderPicker
.Title = "Select a Target Folder"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
MyPath = .SelectedItems(1) & "\"
End With
'In case of cancel
NextCode:
MyPath = MyPath
If MyPath = "" Then GoTo ResetSettings
'Target File Extension
myExtension = "*1*9 Restraint*.xls*"
'Target Path with Ending Extension
MyFile = Dir(MyPath & myExtension)
'Loop through each Excel file in folder
LastRow = Sheets("Sheet Name").Cells(Rows.Count, 1).End(xlUp).Row
i = LastRow - 1
Do While MyFile <> ""
If MyFile Like Cells(LastRow, 1).Value Then
Set wb = Workbooks.Open(Filename:=MyPath & MyFile, ReadOnly:=True)
'Ensure Workbook has opened before moving on
DoEvents
'Find last row
LastRow = ActiveSheet.Cells(Rows.Count, 2).End(xlUp).Row
'Grab value next to last row
LastValue = ActiveSheet.Cells(LastRow, 2).Value
If WorksheetFunction.IsNumber(LastValue) = False Then
LastValue = ActiveSheet.Cells(LastRow, 3).Value
End If
'Go back to graph workbook
Workbooks("Workbook Name").Sheets("Sheet Name").Cells(i, 2).Value = MyFile
Workbooks("Workbook Name").Sheets("Sheet Name").Cells(i, 3).Value = LastValue
i = i + 1
wb.Close savechanges:=False
DoEvents
MyFile = Dir
End If
Loop
'Reset Macro Optimization Settings
ResetSettings:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
This is looping through the entire folder (there are about 1000 files). My question above assumes that we have already done this macro, and the macro I am trying to currently write will only open the most recent files matching a certain criteria, still from the same folder though (but without having to loop through the files that were already opened from the previous macro).
Dir$() without a new file pattern retrieves the next matching file (Win32 FindNextFile), whereas Dir$(file pattern) starts the search over again, even if the pattern is the same as the previous one (Win32 FindFirstFile).
That being said, maybe do something like
Static bolBeenHere As Boolean
If bolBeenHere = False Then
' First search, use the file search pattern
' Target Path with Ending Extension
MyFile = Dir(MyPath & myExtension)
bolBeenHere = True
Else
' Retrieve the next matching file
MyFile = Dir$()
End If
' Stuff
Do While MyFile <> ""
...
Loop
A small performance advice. Use
Do While Len(MyFile) > 0
instead of
Do While MyFile <> ""
A string comparison "costs" more than a numeric comparison.

How can I paste data from one spreadsheet to the last column of another?

Im trying to copy data from a whole bunch of different workbooks into one master sheet, pasting just the values in the next blank column. It all seems to be functional but always fails when it attempts to paste into the master sheet. I've tried looking at similar problems elsewhere but i cant seem to get them to work with what I am trying to do.
I have grabbed the bulk of this code off somewhere else and modified to suit, as you may be able to tell from some of the left over comments
Sub LoopAllExcelFilesInFolder()
'PURPOSE: To loop through all Excel files in a user specified folder and perform a set task on them
'SOURCE: www.TheSpreadsheetGuru.com
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim colDest As Long
Dim Dest As Worksheet
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FldrPicker
.Title = "Select A Target Folder"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myPath = .SelectedItems(1) & "\"
End With
'In Case of Cancel
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.xls*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Set wb = Workbooks.Open(fileName:=myPath & myFile)
'Ensure Workbook has opened before moving on to next line of code
DoEvents
'Change First Worksheet's Background Fill Blue this is where the work occurs
Set Dest = Workbooks("Master.xlsm").Worksheets(1)
colDest = Dest.Cells(1, Dest.Columns.Count).End(xlToRight).Column
wb.Worksheets(1).Range("b3:u83").Copy
Dest.Range(1, colDest).PasteSpecial Paste:=xlPasteValues
'Save and Close Workbook
wb.Close SaveChanges:=True
'Ensure Workbook has closed before moving on to next line of code
DoEvents
'Get next file name
myFile = Dir
Loop
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
EDIT: Error occurs on this line:
Dest.Range(1, colDest).PasteSpecial Paste:=xlPasteValues
Run-time error '1004':
Method 'Range' of object '_Worksheet' failed.
EDIT2: Changing the attempt to Paste with an attempt to write a value to the cell ie:
Dest.Cells(1, colDest) = "Test"
Correctly types "Test" into the next available column on the master sheet for every workbook that was opened from the directory.
Apparently changing 'Range' to 'Cells' works, which i thought i tried yesterday but was throwing a different error complaining i wasn't selecting the correct size cell
Try this basically what you need to do is add 1 to the colDest to give you the next empty column.
Sub LoopAllExcelFilesInFolder()
'PURPOSE: To loop through all Excel files in a user specified folder and perform a set task on them
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim colDest As Long
Dim Dest As Worksheet
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FldrPicker
.Title = "Select A Target Folder"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myPath = .SelectedItems(1) & "\"
End With
'In Case of Cancel
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.xls*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Set wb = Workbooks.Open(fileName:=myPath & myFile)
'Ensure Workbook has opened before moving on to next line of code
DoEvents
'Change First Worksheet's Background Fill Blue this is where the work occurs
Set Dest = Workbooks("Master.xlsm").Worksheets(1)
colDest = Dest.Cells(1, Dest.Columns.Count).End(xlToLeft).Column + 1
wb.Worksheets(1).Range("b3:u83").Copy
Dest.Range(1, colDest).PasteSpecial Paste:=xlPasteValues
'Save and Close Workbook
wb.Close SaveChanges:=True
'Ensure Workbook has closed before moving on to next line of code
DoEvents
'Get next file name
myFile = Dir
Loop
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Below are some guidelines on how to find last column an import value after last column.
Option Explicit
Sub Test()
Dim LastColumn As Long
With ThisWorkbook.Worksheets("Sheet1")
'Last Column using UsedRange (NOT A GOOD IDEA)
LastColumn = .UsedRange.Columns(.UsedRange.Columns.Count).Column
'Last Column using specific row 7
LastColumn = .Cells(7, .Columns.Count).End(xlToLeft).Column
'Add a value in row 5 & after last column
.Cells(5, LastColumn + 1).Value = ""
End With
End Sub
Set Dest = Workbooks("Master.xlsm").Worksheets(1)
colDest = Dest.Cells(1, Dest.Columns.Count).End(xlToLeft).Column + 1
wb.Worksheets(1).Range("b3:u83").Copy
Dest.Cells(1, colDest).PasteSpecial Paste:=xlPasteValues
Correctly inputs the Data where I need it, the 'ToLeft' made a difference but 'Range' wouldn't allow me to paste where 'Cells' does

VBA Code to paste multiple cells from one worksheet into another with the filenames

I am new on doing the VBA codes. So not familiar with coding as such. Just copied few code snippets. However, not getting the desired output.
What I have done need is looped through excel files in a folder and pasted the desired data from the worksheets into the master worksheet.
Sub LoopAllExcelFilesInFolder()
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim lRow As Long
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Dim y As Workbook
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FldrPicker
.Title = "C:\Users\check"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myPath = .SelectedItems(1) & "\"
End With
'In Case of Cancel
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.xls*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
Set y = Workbooks.Open("C:\Users\Super\Desktop\Master")
Set ws2 = y.Sheets("Conso P-L")
Set ws3 = y.Sheets("Conso Expenses")
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Set wb = Workbooks.Open(Filename:=myPath & myFile)
With wb.Sheets("Profit-Loss")
lRow = .Range("A" & Rows.Count).End(xlUp).Row
.Range("A2:M" & lRow).Copy ws2.Range("A" & Rows.Count).End(xlUp)(2)
End With
Application.CutCopyMode = False
With wb.Sheets("Expenses")
lRow = .Range("A" & Rows.Count).End(xlUp).Row
.Range("A2:M" & lRow).Copy ws3.Range("A" & Rows.Count).End(xlUp)(2)
End With
Application.CutCopyMode = False
wb.Close SaveChanges:=True
'Get next file name
myFile = Dir
Loop
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
However, the problem is I need to add a column in the master worksheets to get the filenames of the source data (excluding the .xls or .xlsx), I am not able to figure out where to tweak the code!!
Added a screenshot below for the desired output I require. the filename is required in Column A of both the worksheets of the master workbook.
Appreciate if anybody can help please..
In your code to copy replace the A with a B for the paste range.
With wb.Sheets("Profit-Loss")
lRow = .Range("A" & Rows.Count).End(xlUp).Row
.Range("A2:M" & lRow).Copy ws2.Range("B" & Rows.Count).End(xlUp)(2)
End With
Now your data gets pasted from column B onwards.
To get the name of the file you copied from you can use myFile.name. You want to paste that on the same rows you just copied your data to, so lets make use of the things you calculated to determine what to copy (lRow), together with the last empty row in column A.
Dim lRowA as Long
Dim PasteRows as Long
lRowA = ws2.Range("A" & Rows.Count).End(xlUp)
PasteRows = lRowA + lRow -1 ' the -1 is to compensate for the fact that your copy area starts on row 2.
ws2.Range(ws2.Cells(lRowA,1),ws2.Cells(PasteRows,1)).value = myFile.name
You can use above code to fill column A with the filename. Place it directly after your end with (twice) and change the appropriate ws names (ws2/ws3) to match the code in your with statement.

VBA looping through each file in folder

I know similar questions have been asked, but I've tried all the solution codes with no success. I'm a beginner in VBA and What I'm trying to accomplish is:
Copy files from sfol to dfol
For each file now in dfol, if "summary" tab exists, change cell I3
For each file in dfol, if "sheet2" tab exists, change pivot filter
The code runs and the changes are complete for the first file in dfol, but it doesn't even open each of the rest of the files. I need it to open every file. Also as a side note, the final msgbox at the end does not pop-up, so I'm thinking the code doesn't even run its full course.
Sub GenerateReports()
'Generate Seed Run Validation Reports Macro
Dim wb As Workbook
Dim MainFile, dfol, sfol As String
Dim vDate, Fname, myExtension As String
Dim wsCount As Integer
Dim fso
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'Confirm the user wants to proceed
If MsgBox("Compile?", vbYesNo) = vbNo Then Exit Sub
'Define current workbook
MainFile = ThisWorkbook.Name
'Define Dates
vDate = "Potato"
'Set file path
sfol = "I:\ABCFolder"
dfol = "I:\DEFFolder"
'Copy all files from source folder
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CopyFolder sfol, dfol
'Target Path with extension
myExtension = "*.xls*"
dfol = dfol & "\"
Fname = Dir(dfol & myExtension)
'Loop through files in folder
Do While Fname <> ""
Set wb = Workbooks.Open(fileName:=dfol & Fname)
'Ensure workbook opened
DoEvents
wsCount = wb.Worksheets.Count
For i = 1 To wsCount
'Update Date on Summary tab
If wb.Worksheets(i).Name = "Summary" Then
wb.Worksheets(i).Range("I3") = vDate
End If
Next i
'save changes and close
wb.Close SaveChanges:=True
'Ensure workbook closed
DoEvents
'Get next file name
Fname = Dir
Loop
'***************************** End of Macro ***************************
Application.ScreenUpdating = True
Application.DisplayAlerts = True
MsgBox ("Assumptions Compiled!")
End Sub
Additional problems:
Every time a file is opened, I get asked if I want to update the links. I need it just not update.
I will also need to rename all the files in the folder starting with "2017..." to be, say, "2018..."
Any help is greatly appreciated!
You can specify not to update links when opening.
Set wb = Workbooks.Open(fileName:=dfol & Fname, UpdateLinks:=false)
Use SaveAs to change the name of the open workbook.
wb.saveas FileName:=replace(wb.name, "2017", "2018")
After the SaveAs, wb will be the new copy of the original.
Use on error resume next for a more direct route to changing data on the Summary worksheet.
on error resume next
with wb.worksheets("summary")
.Range("I3") = vDate
end with
on error goto 0

Open multiple CSV files, sort and filter the data from each one, place in master spreadsheet Macro/VBA

I am trying to:
open up spreadsheets from a folder of 50
sort and filter the first sheet on each one (the name will be unknown of this sheet)
filtering needs to find each row that has a certain value in column J - this value is 'No'
All rows that meet the criteria (row J contains 'no') need to be then placed onto a master spreadsheet
Each csv should close each time it's been processed
I have spent hours & hours on forums and have some code which I have been tinkering with, but can't get it running together:
Sub LoopAllExcelFilesInFolder()
'PURPOSE: To loop through all Excel files in a user specified folder and perform a set task on them
'SOURCE: www.TheSpreadsheetGuru.com
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Retrieve Target Folder Path From User
Set FldrPicker = Application.FileDialog(msoFileDialogFolderPicker)
With FldrPicker
.Title = "Select A Target Folder"
.AllowMultiSelect = False
If .Show <> -1 Then GoTo NextCode
myPath = .SelectedItems(1) & "\"
End With
'In Case of Cancel
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.csv*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Set wb = Workbooks.Open(Filename:=myPath & myFile)
'Ensure Workbook has opened before moving on to next line of code
DoEvents
Range("A1:AC3100").Select
Selection.AutoFilter
ActiveWindow.LargeScroll ToRight:=1
Range("Y2").Select
ActiveSheet.Range("$A$1:$AC$3110").AutoFilter Field:=25, Criteria1:="No"
Range("A1:AC3100").Select
Range("Y2").Activate
Selection.Copy
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Windows("Book1").Activate
Rows("1:1").Select
Selection.Insert Shift:=xlDown
'Save and Close Workbook
wb.Close SaveChanges:=True
'Ensure Workbook has closed before moving on to next line of code
DoEvents
'Get next file name
myFile = Dir
Loop
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
The spreadsheet data has variable lengths do I made the selection the maximum:
Range("A1:AC3100")
I would assume there is a better way than this too.
Your criterion is a bit too vague to give a perfect response, but I'll take a crack at it. Some parts of your code seem extraneous or convoluted so I'm doing this based on your end goal (all rows where the value in column J for the first sheet in each workbook that contain 'no' are copied into a master spreadsheet).
If all of your worksheets are always in the same folder you can make the myPath static rather than attempting to use the msoFileDialogFolderPicker. When I attempted to run your code on my machine it gave me an "Out of Memory" error, if you have this issue as well I recommend a static string for myPath.
Option Explicit
Sub PutInMasterFile()
Dim wb As Workbook
Dim masterWB As Workbook
Dim rowNum As Integer
Dim copyRange As Range
Dim pasteRange As Range
Dim myPath As String
Dim myFile As String
Dim FirstAddress As String
Dim x As Variant
Dim c As Variant
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
I would advise against disabling Events until you have confirmed your code is running correctly. Worry about getting working code before thinking about optimization.
x = 1
Set masterWB = Workbooks("NAMEOFWORKBOOK")
Set pasteRange = masterWB.Sheets(1).Range("A" & x)
myPath = "C:\EXAMPLE\MOREEXAMPLE\*.csv"
myFile = Dir(myPath)
myPath can be set to search directly for .csv files in the string.
Do While myFile <> vbNullString
Workbooks.Open (myFile)
With Workbooks(myFile).Sheets(1)
Set c = .Range("J:J").Find("No", LookIn:=xlValues, lookat:=xlWhole)
Using .find in vba is preferential to trying to get a filter and then grabbing everything that the filter displays.
If Not c Is Nothing Then
FirstAddress = c.Address
Do
rowNum = c.Row
Set copyRange = .Range(rowNum & ":" & rowNum)
copyRange.Copy
pasteRange.PasteSpecial
x = x + 1
Set pasteRange = masterWB.Sheets(1).Range("A" & x)
Copies in the row into your master sheet. The x = x + 1 guarantees you paste new data onto a new row to avoid overwriting anything.
Set c = .Range("J:J").FindNext(c)
Loop While Not c Is Nothing And FirstAddress <> c.Address
End If
End With
Workbooks(myFile).Close
myFile = Dir()
Closes your first file and gets the next one set up
Set pasteRange = masterWB.Sheets(1).Range("A" & x)
Sets the paste range in the master wb outside of the inner loop, otherwise it will overwrite the values starting at A1 again with the next file.
Loop
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
I would also recommend you read up on VBA best practices for any future code you work on such as using Option Explicit and avoiding use of GoTo or .Select wherever possible.

Resources