Excel VBA: In a loop, why am I losing my active workbook when I evaluate another sub? - vba

I am modifying a function for looping through all workbooks in a folder and performing an action on each.
In the code below, if I un-comment the Module1.TestSub line, the loop performs TestSub on each file in the chosen folder, as expected.
But I want it to work as a function, taking another sub or function as it's argument and performing that on the loop, so that I could run LoopThroughWorkbooks (Module1.TestSub) and not have to edit LoopThroughWorkbooks every time I want to loop a different action.
If I instead un-comment the Evaluate (myAction) line, it seems to still loop through the intended files doing nothing, and performs Module1.TestSub on the file I had active to begin with.
It seems like the Evaluate (myAction) line is losing track of the workbook opened by the loop in a way that doesn't happen when I just explicitly call Module1.TestSub.
Function LoopThroughWorkbooks(myAction As String)
'PURPOSE: To loop through all xls* files in a user specified folder and perform an action
'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
'Do Action Specified in Argument
'Module1.TestSub <<<<<<<<<<<<<<<< This line works
'Evaluate (myAction) <<<<<<<<<<<<<<<< This line doesn't
'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 "Looping Complete!"
'Reset Macro Optimization Settings
ResetSettings:
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Function
And in case it's helpful, here's Module1.TestSub:
Function TestSub()
Range("A1") = "AAA"
End Function
And here's how I'm calling it:
Sub runtest()
Module2.LoopThroughWorkbooks (Module1.TestSub)
End Sub

Related

Loop through all excel workbooks in a folder and convert all formulas to values

I am looking for a VBA code that would allow me to loop through all the Excel workbooks in a certain folder, and for each workbook will convert the cells in each worksheet from formulas to values.
Use the following code which loops through all the workbooks in a user-specified folder and does the following:
It opens the workbook
It loops within each worksheet in the workbook (including hidden worksheets), and converts to values every cell that contains a formula.
After performing the conversion, it saves and closes the workbook, and moves on to the next workbook in the folder.
See code below:
Sub LoopAllExcelFilesInFolderCancelFormulas()
'Purpose: To loop through all Excel files in a user specified folder and convert all formulas to values
Dim wb As Workbook
Dim ws As Worksheet
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
'Optimize Macro Speed
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Disable Excel Pop-up messages:
Application.DisplayAlerts = False
'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
For Each ws In wb.Sheets
ws.UsedRange.Value = ws.UsedRange.Value
Next
'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.DisplayAlerts = True
End Sub
The code for looping through all workbooks in a certain folder is based on the following code.

Delete multiple columns in multiple Excel files present in a folder

I had tried this code for one excel sheet.
Sub sbVBS_To_Delete_Multiple_Columns ()
Columns("A:C").EntireColumn.Delete
End Sub
This worked well for one excel sheet in the folder, I want to loop through all the excel files in that folder and do it in one go, any help is appreciated.
After adding the logic of traversing through all the files in the folder
​Sub LoopAllExcelFilesInFolder()
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
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
'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
wb.Worksheets(1).Range("A1:Z1").Interior.Color = RGB(51, 98, 174)
wb.Worksheets(1).Columns("A:B").EntireColumn.Delete
'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
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Problem is Compatibility checker, have to disable that.

Copy Entire column into an array in excel vba

I am trying to develop a macro which will open excel files specified by user-prompted location, find a specific column and paste the entire column in the active workbook. So far I have written the code which can loop through the files in the directory, opens the file, search for the column and store the entire column in an array. Now whenever I am trying a Run Time Error saying "Overflow"! Can anyone help me to fix this issue? Also, I want to integrate below item in the macro:
1. Find multiple columns from each file and paste those columns in a sheet. So for multiple files, I should paste the columns in individual worksheet dynamically. How can I do that? Any help is appreciated. Thanks. Below is my code I have written so far:
Sub Test_Template()
'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, myFile As String
Dim myExtension As String
Dim t As Range, rng As Range, rng2 As Range
Dim dblAvg As Single, eng_spd As Single, i As Integer
Dim FldrPicker As FileDialog
Dim rowCtr As Integer
Dim myarray1 As Variant
rowCtr = 2
'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
Execute:
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
'Find "Time" in Row 1
With wb.Worksheets(1).Rows(9)
Set t = .Find("Time", lookat:=xlPart)
'If found, copy the column to Sheet 2, Column A
'If not found, present a message
If Not t Is Nothing Then
'Columns(t.Column).EntireColumn.Copy _
' Destination:=Sheets(3).Range("A1")
Set rng2 = Columns(t.Column)
myarray1 = rng2
Else: MsgBox "Time Not Found"
End If
End With
'Save and Close Workbook
wb.Close 'SaveChanges:=True
'Ensure Workbook has closed before moving on to next line of code
DoEvents
With ActiveSheet
For i = LBound(myarray1) To UBound(myarray1)
Debug.Print myarray1(i, 1)
Next
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
here is your code with clutter, like goto commands, and unused With commands removed
Sub Test_Template()
'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, myFile As String
Dim myExtension As String
Dim t As Range, rng As Range, rng2 As Range
Dim dblAvg As Single, eng_spd As Single, i As Long
Dim FldrPicker As FileDialog
Dim rowCtr As Long
Dim myarray1 As Variant
rowCtr = 2
' 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 = True Then
myPath = .SelectedItems(1) & "\"
End If
End With
myPath = myPath ' In Case of Cancel
If myPath <> "" Then
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) ' Set variable equal to opened workbook
DoEvents ' yield processing time to other events
Set t = wb.Worksheets(1).Rows(9).Find("Time", lookat:=xlPart) ' Find "Time" in Row 1 ????
If Not t Is Nothing Then
' Columns(t.Column).EntireColumn.Copy _
Destination:=Sheets(3).Range("A1")
myarray1 = Columns(t.Column) ' found: copy the column to Sheet 2, Column A
Else
MsgBox "Time Not Found"
End If
wb.Close ' SaveChanges:=True ' Save and Close Workbook
DoEvents ' yield processing time to other events
For i = LBound(myarray1) To UBound(myarray1)
Debug.Print myarray1(i, 1)
Next
myFile = Dir ' Get next file name
Loop
' MsgBox "Task Complete!"
End If
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub

VBA Looping through excel files in selected directory - Copy data and paste in different sheets

I'm looking to select a directory and then loop through each xlsm file within that directory. For each loop it should open the file, copy a range and paste into the current workbook under a specific sheet.
I.e. the first file will paste into sheet1 the second opened file will past into sheet 2, and so on.
I have some code, now I need help to get it to paste the rang into a sheets.count? or something like that. At the moment it just pastes into sheet 1 because that is static.
Sub Test()
Dim wb As Workbook, wb1 As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Set wb1 = Workbooks(ThisWorkbook.Name)
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 = "*.xlsm"
'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
'Copy data from opened workbook
wb.Sheets("HI Sub-segment split").Range("A1:Z1").Copy
'Paste data into destination workbook
wb1.Sheet(1).Range("A1:Z1").PasteSpecial xlPasteValues
'Close Workbook
wb.Close
'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 "Import Complete!"
ResetSettings:
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Worked with this...
Sub Testing()
'
'
'
Dim wb As Workbook, wb1 As Workbook
Dim myPath As String
Dim myFile As String
Dim myExtension As String
Dim FldrPicker As FileDialog
Dim loop_ctr As Integer
Set wb1 = Workbooks(ThisWorkbook.Name)
loop_ctr = 1
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
'Copy data from opened workbook
wb.Sheets("Sheet1").Range("A1:B2").Copy
'Paste data into destination workbook
wb1.Sheets(loop_ctr).Range("A1:B2").PasteSpecial xlPasteValues
'Close Workbook
wb.Close
'Ensure Workbook has closed before moving on to next line of code
DoEvents
'Get next file name
myFile = Dir
'Update loop_ctr value
loop_ctr = loop_ctr + 1
Loop
'Message Box when tasks are completed
MsgBox "Import Complete!"
ResetSettings:
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub

Need to modify my VBA code to include subfolders as well

I have created a VBA code that loops through all excel workbooks in a given folder , opens then, refreshes the sheet, pauses for 10 seconds, closes and saves and moves on to the next. The issue I am facing is that it wont do it for the excel workbooks in the subfolder, Please can someone assist.
The code is as per below:
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
'Change First Worksheet's Background Fill Blue
Application.Calculate
ActiveWorkbook.RefreshAll
Application.Wait (Now + TimeValue("0:00:10"))
'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
Its probably an old question indeed, but still, I enjoyed writing it somehow. And in my solution, you get some nice printing in the console. Here you go:
Option Explicit
Function GetFiles(ByVal Folder As String) As Collection
Dim strFile As String
Set GetFiles = New Collection
strFile = Dir(Folder & "\*")
Do While strFile <> ""
GetFiles.Add strFile
strFile = Dir
Loop
End Function
Function GetFolders(ByVal Folder As String) As Collection
Dim strFile As String
Set GetFolders = New Collection
strFile = Dir(Folder & "\*", vbDirectory)
Do While strFile <> ""
If GetAttr(Folder & "\" & strFile) And vbDirectory Then GetFolders.Add strFile
strFile = Dir
Loop
End Function
Sub LoopThroughSubfoldersAsWell()
Dim colFoFi As Collection
Dim varEl01 As Variant
Dim varEl02 As Variant
Dim varEl03 As Variant
Dim strLine As String: strLine = "--------------------------"
Dim strAddress As String: strAddress = "C:\Users\UserName\Desktop\Testing01\"
Debug.Print strAddress
Set colFoFi = GetFiles(strAddress)
For Each varEl01 In colFoFi
Debug.Print varEl01
Next varEl01
Debug.Print strLine
Set colFoFi = GetFolders(strAddress)
For Each varEl01 In colFoFi
If Len(varEl01) > 2 Then 'to avoid some hidden stuff
Set varEl02 = GetFiles(strAddress & varEl01)
Debug.Print (strAddress & varEl01)
For Each varEl03 In varEl02
Debug.Print varEl03
Next varEl03
Debug.Print strLine
End If
Next varEl01
End Sub