Using for each to loop through a series of workbooks - vba

I am a VBA newbie trying to figure out how to loop through a series of workbooks and their sheets in an effort to find a specific sheet but are having some trouble with my object variables.
Below is the code I have "written" (glued together might be a more apt description). I have tried various corrections but only seem to be moving the problem from one place to another. Any help will be appreciated!
Sub NestedForEach()
'Create an object variable to represent each worksheet
Dim WS As Worksheet
Dim WB As Workbook
Set WB = ActiveWorkbook
Set WS = Workbook.Sheets
'create a boolen variable to hold the status of whether we found worksheet "D"
Dim IsFound As Boolean
'initialise the IsFound boolean variable
IsFound = False
For Each WB In Application.Workbooks
For Each WS In WB.Worksheets
If WS.Name = "d" Then
IsFound = True
Exit For
End If
Next WS
Next WB
If IsFound Then
MsgBox "sheet D has been found in " & ActiveWorkbook.Name
Else
MsgBox "we could not locate sheet D in any of the open workbooks"
End If
End Sub

Only few changes were necessary in order to make your code work:
Option Explicit
Sub NestedForEach()
'Create a Worksheet variable to represent one worksheet
Dim WS As Worksheet
Dim WB As Workbook
'create a boolen variable to hold the status of whether we found worksheet "D"
Dim IsFound As Boolean
'initialise the IsFound boolean variable
IsFound = False
For Each WB In Application.Workbooks
For Each WS In WB.Worksheets
If WS.Name = "d" Then
IsFound = True
MsgBox "sheet D has been found in " & WB.Name
Exit Sub
End If
Next WS
Next WB
MsgBox "we could not locate sheet D in any of the open workbooks" & _
Chr(10) & "which are open in this instance of Excel" & _
Chr(10) & "(in case multiple Excels are running)"
End Sub
Let me know if you have any question regarding the changes.

Just 1 week ago I wrote a script to go to a specified folder (the user chooses) and list all Excel files and sheet names in that folder.
Public Sub LoopAllExcelFilesInFolder()
Dim WB As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim sht As Worksheet
Dim LastRow As Long
Application.DisplayAlerts = False
Sheets("ListFilesInFolder").Select
Set sht = ThisWorkbook.Worksheets("ListFilesInFolder")
sht.Activate
Rows("2:2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.ClearContents
Range("A1").Select
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 = "*.xl*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
Do While myFile <> ""
Set WB = Workbooks.Open(Filename:=myPath & myFile)
With Application
.AskToUpdateLinks = False
End With
For Each Sheet In Workbooks(myFile).Worksheets
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row + 1
Workbooks("Questionaire-Mock-Up.xlsb").Worksheets("ListFilesInFolder").Cells(LastRow, 1).Value = myPath & myFile
Workbooks("Questionaire-Mock-Up.xlsb").Worksheets("ListFilesInFolder").Cells(LastRow, 2).Value = myFile
Workbooks("Questionaire-Mock-Up.xlsb").Worksheets("ListFilesInFolder").Cells(LastRow, 3).Value = Sheet.Name
File = InStr(myFile, ".xl") - 1
LeftName = Left(myFile, File)
Workbooks("Questionaire-Mock-Up.xlsb").Worksheets("ListFilesInFolder").Cells(LastRow, 4).Value = LeftName
LastRow = LastRow + 1
Next Sheet
Workbooks(myFile).Close SaveChanges:=False
myFile = Dir
Loop
ResetSettings:
Application.DisplayAlerts = True
End Sub

Related

Loop through worksheets and save key-info to rows in new sheet

I would like to make a piece of code which opens up a bunch of workbooks, pulls out some key data and pastes it into a sort of 'overview' spreadsheet so I can load it in to Access.
Example:
I have 3 documents Book1, Book2 and Book3.
I would like Cell A1,B2,B4,D6 from sheet1 and B2,B5,E9 from sheet2 and A1:C3 from sheet3 from Book1 to be pasted into row 1 in a new document.
Cell A1,B2,B4,D6 from sheet1 and B2,B5,E9 from sheet2 and A1:C3 from sheet3 from Book2 to be pasted into row 2 in the new document.
And the same from Book3 to be pasted in to row 3 in the new document.
Ect.
I found this code which loops through all worksheets in a folder:
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 = "*.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
'SOME SMART CODE SHOULD BE HERE
'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
I also found this code which Copy from one workbook and paste into another, but I have a hard time combining those two and get it to work.
Please help!
'SOURCE https://stackoverflow.com/questions/19351832/copy-from-one-workbook-
'and-paste-into-another
Dim x As Workbook, y As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Set x = Workbooks.Open("path to copying book")
Set y = Workbooks.Open("path to pasting book")
Set ws1 = x.Sheets("Sheet you want to copy from")
Set ws2 = y.Sheets("Sheet you want to copy to")
ws1.Cells.Copy ws2.cells
y.Close True
x.Close False
This is extremely literal, based on the problem statement you outlined, but with a little tweaking based on things you know about your actual content, you can probably add in some variables to make this a little less hard-coded.
That said, notionally, I think this is along the lines of what you want:
Dim wb, newWorkbook As Workbook
Dim ws, newWorksheet As Worksheet
Dim idx, row, col As Integer
Dim cell As Range
Set newWorkbook = Workbooks.Add
Set newWorksheet = newWorkbook.Sheets(1)
row = 1
For Each wb In Workbooks
If wb.Name <> newWorkbook.Name Then
Set ws = wb.Sheets("Sheet1")
newWorksheet.Cells(row, 1).Value = ws.Range("A1").Value
newWorksheet.Cells(row, 2).Value = ws.Range("B2").Value
newWorksheet.Cells(row, 3).Value = ws.Range("B4").Value
newWorksheet.Cells(row, 4).Value = ws.Range("D6").Value
Set ws = wb.Sheets("Sheet2")
newWorksheet.Cells(row, 5).Value = ws.Range("B2").Value
newWorksheet.Cells(row, 6).Value = ws.Range("B5").Value
newWorksheet.Cells(row, 7).Value = ws.Range("E9").Value
Set ws = wb.Sheets("Sheet3")
col = 8
For Each cell In ws.Range("A1:C3")
newWorksheet.Cells(row, 7).Value = cell.Value
col = col + 1
Next cell
row = row + 1
End If
Next wb

VBA to import and transpose multiple sheets data

I have been working on the below code, however I am looking to edit this further:
1) Instead of setting 'Set Range1' via an input box, this should always be the cell range of 'B2:P65' when looping through the sheets in the folder.
2) When pasting the data I want this to fill starting at column B of the 'Database' tab in the workbook and then subsequently C, D, E etc.. for the rest of the workbooks in the folder loop.
Sub LoopFileUpload_base()
Dim wb As Workbook
Dim myPath As String
Dim myfile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim Range1 As Range, Range2 As Range, Rng As Range
Dim rowIndex As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
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
NextCode:
myPath = myPath
If myPath = "" Then GoTo ResetSettings
myExtension = "*.xlsx"
myfile = Dir(myPath & myExtension)
Do While myfile <> ""
Set wb = Workbooks.Open(fileName:=myPath & myfile)
'CHANGE CODE BELOW HERE
xTitleId = "Range"
Set Range1 = Application.Selection
Set Range1 = Application.InputBox("Source Ranges:", xTitleId, Range1.Address, Type:=8)
Set Range2 = Application.InputBox("Convert to (single cell):", xTitleId, Type:=8)
rowIndex = 0
For Each Rng In Range1.Rows
Rng.Copy
Range2.Offset(rowIndex, 0).PasteSpecial Paste:=xlPasteValues, Transpose:=True
rowIndex = rowIndex + Rng.Columns.Count
Next
'CHANGE CODE ABOVE HERE
wb.Close SaveChanges:=True
myfile = Dir
Loop
MsgBox "Task Complete!"
ResetSettings:
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Consider the following macro where you loop through .xlsx workbooks in a folder and iteratively copy cells in specified range to current sheet row by row. Then, after each workbook move to next column:
Sub TransposeWorkbooks()
Dim strfile As String
Dim sourcewb As Workbook
Dim i As Integer, j As Integer
Dim cell As Range
strfile = Dir("C:\Path\To\Workbooks\*.xlsx")
ThisWorkbook.Sheets("Database").Activate
ThisWorkbook.Sheets("Database").Range("A2").Activate
Do While Len(strfile) > 0
' OPEN SOURCE WORKBOOK
Set sourcewb = Workbooks.Open("C:\Path\To\Workbooks\" & strfile)
ThisWorkbook.Activate
ActiveCell.Offset(0, 1).Activate ' MOVE TO NEXT COLUMN
ActiveCell = strfile
' ITERATE THROUGH EACH CELL ACROSS RANGE
j = 1
For Each cell In sourcewb.Sheets(1).Range("B2:P65")
ActiveCell.Offset(j, 0).Value = cell.Value ' MOVE TO NEXT ROW
j = j + 1
Next cell
' CLOSE WORKBOOK
sourcewb.Close False
strfile = Dir
Loop
End Sub
It sounds like you got your task solved. For future reference, please try the AddIn from the link below. I think you will find so many uses for this tool.
http://www.rondebruin.nl/win/addins/rdbmerge.htm

How to add up two-dimensional arrays?

My code runs trough dozens of excel documents, selects range and gives the range to an array. I would like to add up the arrays to get a summarized data then paste the result to an existing worksheet.
The formula should be something like this:
rangeVar = oNewBook.Worksheets(1).Range("A1:D4").Value
sumRange = sumRange + rangeVar
Important! Some cells in the range is empty (I don't know is this matters). Also I would like to add up the values separately like sumRange(1,1)+rangeVar(1,1) ; sumRange(2,2)+rangeVar(2,2) , etc... How to do this?
You can check the code here:
Sub LoopAllExcelFilesInFolder()
Dim OutputWs As Worksheet
Dim oNewBook As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim Lastrow As Long
Dim i As Integer, j As Integer
Dim summaryVar() As Variant
Dim rangeVar() As Variant
'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
myExtension = "*.xlsx"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
'set output worksheet
Set OutputWs = ThisWorkbook.Worksheets("Teszt")
'Loop through each Excel file in folder
Do While myFile <> ""
Set oNewBook = Workbooks.Open(myPath & myFile)
rangeVar = oNewBook.Worksheets(1).Range("A1:D4").Value
oNewBook.Close
'Copy selected items
With OutputWs
Lastrow = .Cells(.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
OutputWs.Range("A" & Lastrow & ":" & "D" & Lastrow) = Application.WorksheetFunction.Sum(rangeVar) 'summaryVar
Paste:=xlPasteAll, operation:=xlPasteSpecialOperationAdd, skipBlanks:=False
Application.CutCopyMode = False
End With
'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
S. Meaden answers this question wonderfully in How to add arrays?. Instead of trying to add the two arrays together, he makes use of Excel's pasteSpecial Addvalues function to add the original range's values to another range. Based on his code, something like the below should work.
Set tempWS = Sheets.Add
Do While myFile <> ""
Set oNewBook = Workbooks.Open(myPath & myFile)
oNewBook.Worksheets(1).Range("A1:D4").Copy
tempWS.Range("A1:D4").PasteSpecial Paste:=xlPasteAll, operation:=xlPasteSpecialOperationAdd
oNewBook.Close
Standard Excel Worksheet Functions will work on 1 and 2 dimensional arras.
Sub Test()
Dim array2(25, 25) As Double
Dim i As Integer, j As Integer
For i = 0 To UBound(array2, 1)
For j = 0 To UBound(array2, 1)
array2(i, j) = Int((Rnd * 100) + 1)
Next
Next
MsgBox WorksheetFunction.Sum(array2)
End Sub

How can I copy Excel sheets based on their name using VBA?

The background:
I have a directory containing multiple workbooks.
Each workbook contains multiple sheets, both hidden and visible.
I would like to copy one particular sheet from each workbook into an existing master workbook.
The problem:
At the moment, my code copies the first sheet in each source workbook.
I require the code to copy only the sheet called "[current month] Summary", which is most often not the first sheet in the source workbooks.
Because the [current month] will change, it needs to copy the sheet where the last seven letters of the name are "Summary".
My code as it stands:
Dim wbDst As Workbook
Dim wbSrc As Workbook
Dim wsSrc As Worksheet
Dim MyPath As String
Dim strFilename As String
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Application.EnableEvents = False
Application.ScreenUpdating = False
MyPath = InputBox("Please copy and paste the path to the folder containing the source documents")
Set wbDst = ActiveWorkbook
strFilename = Dir(MyPath & "\*.xls", vbNormal)
If Len(strFilename) = 0 Then Exit Sub
Do Until strFilename = ""
Set wbSrc = Workbooks.Open(Filename:=MyPath & "\" & strFilename)
Set wsSrc = wbSrc.Worksheets(1)
wsSrc.Copy After:=wbDst.Worksheets(wbDst.Worksheets.Count)
wbSrc.Close False
strFilename = Dir()
Loop
Replace this line
Set wsSrc = wbSrc.Worksheets(1)
With
Set wsSrc = wbSrc.Worksheets("[current month] Summary")
Edit:
Replace your current Do Until Code with the below one :)
Do Until strFilename = ""
Set wbSrc = Workbooks.Open(Filename:=MyPath & "\" & strFilename)
For Each ws In wbSrc.Worksheets
If InStr(1, ws.Name, "summary", vbTextCompare) Then
Set wsSrc = ws
End If
Next ws
wsSrc.Copy After:=wbDst.Worksheets(wbDst.Worksheets.Count)
wbSrc.Close False
strFilename = Dir()
Loop
Following code will get the current month and after checking the name in workbooks will give you the desired result:
Dim currMonth As String
currMonth = MonthName(Month(Now))
Do Until strFilename = ""
Set wbSrc = Workbooks.Open(Filename:=MyPath & "\" & strFilename)
For Each ws In wbSrc.Worksheets
If ws.Name = currMonth & "Summary" Then
Debug.Print ws.Name
Set wsSrc = ws
wsSrc.Copy After:=wbDst.Worksheets(wbDst.Worksheets.Count)
Exit For
End If
Next
wbSrc.Close False
strFilename = Dir()
Loop

Code to pick a folder path to save multiple spreadsheets in a workbook?

I have a workbook with multiple spreadsheets and am looking to save them as individual csv files (retaining the file name from their respective spreadsheets) in a folder of my choosing.
The following code seems to let me choose a path, but errors out with the following message:
Error code 9
Subscript out of range on this line
For Each ws In Sheets(Array("01 - Currencies", "...., "14 - User Defined
Fields"))
What am I missing?
Sub SaveOnlyCSVsThatAreNeeded()
Dim ws As Worksheet, newWb As Workbook
Dim pathh As Variant
Dim FolderName As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show = -1 Then
FolderName = .SelectedItems(1)
End If
End With
pathh = FolderName
Application.ScreenUpdating = False
For Each ws In Sheets(Array("01 - Currencies", "...., "14 - User Defined
Fields"))
ws.Copy
Set newWb = ActiveWorkbook
With newWb
.SaveAs pathh.path & "\" & ws.Name, xlCSV
.Close (False)
End With
Next ws
Application.ScreenUpdating = True
End Sub
Beyond the question of each worksheet's parent workbook, there was a problem with pathh.Path. FolderName is already the full path of the folder selected; you do not need to find its .Path. This would produce:
Runtime error 424: Object required.
Sub SaveOnlyCSVsThatAreNeeded()
Dim ws As Worksheet, wb As Workbook
Dim pathh As Variant
Set wb = ActiveWorkbook
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
If .Show = -1 Then 'a folder was picked
pathh = .SelectedItems(1)
End If
End With
If pathh = False Then Exit Sub 'no folder picked; pathh is false
Application.ScreenUpdating = False
For Each ws In wb.Sheets(Array("Sheet1", "Sheet2", "Sheet4"))
ws.Copy
With ActiveWorkbook
'Application.DisplayAlerts = False 'to avoid overwrite warnings
' pathh is a string (variant) of the path of the folder; does not need pathh.Path
.SaveAs pathh & "\" & ws.Name, xlCSV
.Close SaveChanges:=False
End With
Next ws
Application.ScreenUpdating = True
End Sub
Don't forget to double-check the worksheets names in the array for typos.
Maybe...
For Each ws In ActiveWorkbook.Worksheets
Or
For Each ws In Sheets(Array("01 - Currencies", "14 - User Defined Fields"))