I have an excel macro saved in a blank workbook and multiple data workbooks.
I currently open the macro file and each data file individually, running the macro on each one with a keyboard shortcut.
Is there a way to run the macro on all the data workbooks without opening them, either with
a batch file,
VBA/VBScript,
powershell,
or something similar?
One way to do this is to add your macro's to the file PERSONAL.XLSB. This file will be loaded in the background every time you start Excel. Initially the PERSONAL.XLSB file will NOT be there.
To automatically create this file, just start recording a "dummy" macro (with the record button on the left-bottom of a spreadsheet) and select "Personal Macro Workbook" to store it in. After recording your macro, you can open the VBA editor with [Alt]+[F10] and you will see the PERSONAL.XLSB file with the "dummy" macro.
I use this file to store loads of general macro's which are always available. I have added these macro's to my own menu ribbon.
One disadvantage of this common macro file is that if you launch more than one instance of Excel, you will get an error message that the PERSONAL.XLSB file is already in use by Excel instance Nr. 1. This is no problem as long as you do not add new macro's at this moment.
Two potential solutions below,
vbscript which can be run directly as a vbs file
A vba solution to be run from within Excel (as per Tim Williams suggestion)
vbscript solution
Dim objFSO
Dim objFolder
Dim objFil
Dim objXl
Dim objWb
Dim objExcel
Set objExcel = CreateObject("Excel.Application")
Set objFSO = CreateObject("scripting.filesystemobject")
Set objFolder = objFSO.getfolder("c:\temp")
For Each objFil In objFolder.Files
If InStr(objFil.Type, "Excel") > 0 Then
Set Wb = objExcel.Workbooks.Open(objFil.Path)
wscript.echo Wb.name
Wb.Close False
End If
Next
vba solution
Sub OpenFilesVBA()
Dim Wb As Workbook
Dim strFolder As String
Dim strFil As String
strFolder = "c:\Temp"
strFil = Dir(strFolder & "\*.xls*")
Do While strFil <> vbNullString
Set Wb = Workbooks.Open(strFolder & "\" & strFil)
Wb.Close False
strFil = Dir
Loop
End Sub
I sort of stumbled across your post just now, maybe very late, but for all future searches.
It is possible to launch your Macro by creating a .vbs file.
To do this, open notepad and add the following:
objExcel = CreateObject("Excel.Application")
objExcel.Application.Run <insert macro workbook file path, module and macro name here>
objExcel.DisplayAlerts = False
objExcel.Application.Save
objExcel.Application.Quit
Set objExcel = Nothing
save the file as follows ("your filename".vbs)
By double clicking (opening) the saved .vbs file, it will launch your macro without you having to open your excel file at all.
Hope this helps.
You could keep the macro in your personal.xls, or a masterfile, and loop through the workbooks with vba, and activate them before running your macro. As far as I know, you still have to open them with vba though.
You could use something like this:
sub LoopFiles
Dim sFiles(1 to 10) as string 'You could also read this from a range in a masterfile
sFiles(1) = "Filename1.xls"
.
.
sFiles(10) = "Filename10.xls"
Dim wb as Workbook
Dim iCount as integer
iCount = ubound(sFiles)
Dim iCount2 as integer
For iCount2 = 1 to iCount
Workbooks(sFiles(iCount2)).open
Workbooks(sFiles(iCount2)).activate
Call YourMacro
Workbooks(sFiles(iCount2)).close
next iCount2
end sub
Other way,
Sub LoopAllWorkbooksOpened()
Dim wb As Workbook
For Each wb In Application.Workbooks
Call YourMacroWithWorkbookParam(wb)
Next wb
End Sub
Sub YourMacroWithWorkbookParam(wb As Workbook)
MsgBox wb.FullName
End Sub
Related
I have a macro in one XLSM workbook's module that refreshes all the external data, then saves and closes that workbook.
ActiveWorkbook.RefreshAll
ActiveWorkbook.Save
ActiveWorkbook.Close
Application.Quit
I use a VBScript file to run that macro as part of a scheduled task
objExcel.Workbooks.Open(fname)
objExcel.Visible = True
On error resume next
objExcel.Run "RefreshAllData"
Question: How can I reuse the existing macro in the existing workbook to refresh all the data of multiple other workbooks? (ie. I'm looking for the necessary modifications to the VBScript file, I want to minimise changes to the macro itself. The filenames will be contained in the VBScript file) TIA.
I'd recommend against re-using a trivial macro like that. Instead incorporate the refresh functionality in the VBScript:
Set fso = CreateObject("Scripting.FileSystemObject")
Set xl = CreateObject("Excel.Application")
xl.Visible = True
For Each f In fso.GetFolder("C:\some\folder").Files
If LCase(fso.GetExtensionName(f.Name)) = "xlsx" Then
Set wb = xl.Workbooks.Open(f.Path)
wb.RefreshAll
wb.Save
wb.Close
End If
Next
xl.Quit
I suppose you can do something like this.
Find all the excel file in the given folder
Select Each Excel file and activate
call refreshdata function
code snippet to support this
Sub RefreshAllExcelInFolder()
Dim fso
Dim ObjFolder
Dim ObjFiles
Dim ObjFile
Dim objExcel
'Creating File System Object
Set fso = CreateObject("Scripting.FileSystemObject")
'Getting the Folder Object
Set ObjFolder = fso.GetFolder("<<C:folder path>>")
'Getting the list of Files
Set ObjFiles = ObjFolder.Files
'On Error Resume Next
For Each ObjFile In ObjFiles
If LCase(Right(ObjFile.Name, 5)) = ".xlsx" Or LCase(Right(ObjFile.Name, 4)) = ".xls" Then
Workbooks.Open(ObjFile).Activate
RefreshAllData
End If
Next
End Sub
Sub RefreshAllData()
ActiveWorkbook.RefreshAll
ActiveWorkbook.Save
ActiveWorkbook.Close
MsgBox ("Going back In")
End Sub
Hope this will help
If you don't change the macro at all you will have to keep reloading excel, then open the macro workbook followed by the target workbook and then run the macro. If you can remove:
Application.quit
then you can at least keep excel open and just keep opening target workbooks before running the macro each time. Seems to me it'd be simpler to put the macro code into the vbs file though
I have a macro in one XLSM workbook's module that refreshes all the external data, then saves and closes that workbook.
ActiveWorkbook.RefreshAll
ActiveWorkbook.Save
ActiveWorkbook.Close
Application.Quit
I use a VBScript file to run that macro as part of a scheduled task
objExcel.Workbooks.Open(fname)
objExcel.Visible = True
On error resume next
objExcel.Run "RefreshAllData"
Question: How can I reuse the existing macro in the existing workbook to refresh all the data of multiple other workbooks? (ie. I'm looking for the necessary modifications to the VBScript file, I want to minimise changes to the macro itself. The filenames will be contained in the VBScript file) TIA.
I'd recommend against re-using a trivial macro like that. Instead incorporate the refresh functionality in the VBScript:
Set fso = CreateObject("Scripting.FileSystemObject")
Set xl = CreateObject("Excel.Application")
xl.Visible = True
For Each f In fso.GetFolder("C:\some\folder").Files
If LCase(fso.GetExtensionName(f.Name)) = "xlsx" Then
Set wb = xl.Workbooks.Open(f.Path)
wb.RefreshAll
wb.Save
wb.Close
End If
Next
xl.Quit
I suppose you can do something like this.
Find all the excel file in the given folder
Select Each Excel file and activate
call refreshdata function
code snippet to support this
Sub RefreshAllExcelInFolder()
Dim fso
Dim ObjFolder
Dim ObjFiles
Dim ObjFile
Dim objExcel
'Creating File System Object
Set fso = CreateObject("Scripting.FileSystemObject")
'Getting the Folder Object
Set ObjFolder = fso.GetFolder("<<C:folder path>>")
'Getting the list of Files
Set ObjFiles = ObjFolder.Files
'On Error Resume Next
For Each ObjFile In ObjFiles
If LCase(Right(ObjFile.Name, 5)) = ".xlsx" Or LCase(Right(ObjFile.Name, 4)) = ".xls" Then
Workbooks.Open(ObjFile).Activate
RefreshAllData
End If
Next
End Sub
Sub RefreshAllData()
ActiveWorkbook.RefreshAll
ActiveWorkbook.Save
ActiveWorkbook.Close
MsgBox ("Going back In")
End Sub
Hope this will help
If you don't change the macro at all you will have to keep reloading excel, then open the macro workbook followed by the target workbook and then run the macro. If you can remove:
Application.quit
then you can at least keep excel open and just keep opening target workbooks before running the macro each time. Seems to me it'd be simpler to put the macro code into the vbs file though
I am still relatively new to VBA and not too experienced with the Application.OnTime method. I have been looking at multiple resources, and I cannot see a clear way to automatically run a macro daily without opening any workbooks (assuming I run the macro first in my workbook).
Is this possible? I would like to be more efficient instead of running multiple macros every morning.
Let me know if you need more info but my code would simply be a copy/paste process:
Sub MyMacro()
Application.ScreenUpdating = False
Dim OH As Workbook
Dim PO As Workbook
Set OH = Workbooks.Open("filepath")
Set PO = Workbooks.Open("filepath2")
'clear sheet
ThisWorkbook.Sheets("OH").Range("A2:O10000").ClearContents
'clear other sheet
ThisWorkbook.Sheets("OP").Range("A2:AG10000").ClearContents
'Paste new data
OH.Sheets("OH").Range("B3:P10000").Copy
Destination:=ThisWorkbook.Sheets("OH").Range("A2")
PO.Sheets("OP").Range("A3:AG20000").Copy
Destination:=ThisWorkbook.Sheets("OP").Range("A2")
OH.Close savechanges:=False
PO.Close savechanges:=False
'Refresh all pivot tables
Dim PT As PivotTable
Dim WST As Worksheet
For Each WST In ThisWorkbook.Worksheets
For Each PT In WST.PivotTables
PT.RefreshTable
Next PT
Next WST
'Clear last sheet
ThisWorkbook.Sheets("Pivot1 paste").Range("A6:E10000").ClearContents
ThisWorkbook.Sheets("Pivot1").Range("A6:D10000").Copy
Destination:=ThisWorkbook.Sheets("Pivot1 paste").Range("A6")
'Paste variable column to last sheet
Dim cell As Range
For Each cell In ThisWorkbook.Sheets("Pivot1").Range("E3:AZ6")
If cell.Value = "Out" Then cell.EntireColumn.Copy
Destination:=ThisWorkbook.Sheets("Pivot1 paste").Columns(5)
Next
'Save with current date and close
ThisWorkbook.SaveAs ("TargetFilepath")
& ".xlsm")
ThisWorkbook.Close
Application.ScreenUpdating = True
End Sub
VBA is made to work within Microsoft Office, but you can leverage VB Script to open a workbook and run a macro.
Place the following in a .vbs file. You will create a schedule to call and execute this file. Make sure to set the correct path and edit "test.xlsm!mymacro" to the name of your workbook and the macro you wish to call.
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("C:\path\to\test.xlsm")
objExcel.Application.Run "test.xlsm!mymacro"
objExcel.ActiveWorkbook.Close
objExcel.Application.Quit
WScript.Echo "Finished."
WScript.Quit
To test this, I created a quick macro in test.xlsm to create a text file in the same directory and verified that it was there after I ran the VB Script. There is nothing special about the macro below, you can call whatever macro you desire. This will save you from having to manually open the workbook and run the macro.
Sub mymacro()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim oFile As Object
Set oFile = fso.CreateTextFile("C:\Users\bcohan\Downloads\testing.txt")
oFile.WriteLine "test"
oFile.Close
Set fso = Nothing
Set oFile = Nothing
End Sub
Once you have the above working, you should be able to create a scheduled task in windows to run your script.
I want to copy a range of cells in my .csv file into a template.csv (named "pp"). Then I would like to save the template as "name of the original .csv file_2", without closing the original template as I would need it to do this procedure in loop for all the files in my folder. I have come up with this code that doesn't work:
Sub LoopThroughDirectory()
Dim MyFile As String
Dim pp As Workbook ' Workbook to receive the copied data
Dim ppSht As Worksheet ' Worksheet where copied data will be inserted
Dim Wkb As Workbook ' Temporary workbook for the Loop
Dim Sht As Worksheet ' Temporary worksheet variable for the loop
MyFile = Dir("R:\COMT study\Silvia\Cognitive data\COMT 1\Tasks\CPT*.csv*")
Set pp = Workbooks("pp.csv")
Set ppSht = pp.Sheets("Sheet1")
Do While MyFile <> ""
Set Wkb = Workbook.Open("R:\COMT study\Silvia\Cognitive data\COMT 1\Tasks\CPT" & MyFile)
Set Sht = Wkb.Worksheets("sheet1")
Sht.Range("A1:G113").Copy
With ppSht
.Range("A1:G113").PasteSpecial xlPasteFormulas
End With
pp.SaveCopyAs Filename = MyFile_2.csv
Wkb.Close True
MyFile = Dir
Loop
End Sub
I am new to the vba coding and I am not sure what I am doing wrong as I don't get any error messages, the code simply doesn't run. Do you have any suggestion?
First of all I would like to recommend you how to use a CSV file (Comma-separated values). By this a csv file does not have any sheets. Therefore you can reach the worksheet with the following, there wb is the workbook. Another good advice is to use Option Explicit that enables some error codes, example if you get to initialize a variable.
Dim pp As Workbook
pp.Worksheets (1)
Do While MyFile <> ""
Set wb = Workbooks.Open("R:\COMT study\Silvia\Cognitive data\COMT 1\Tasks\CPT" & MyFile)
With wb.Worksheets(1)
Range(A1,G113).copy
End With
With ppSht
.Range(A1,G113).PasteSpecial xlPasteFormulas
End With
pp.SaveCopyAs Filename = "MyFile_2.csv"
'Remove the wb.Close if you want the sheet to stay open (Not recommended if there are many files)
wb.Close
MyFile = Dir
loop
Try using some of this (Haven't tried it so just use it as a template). See if you can get any errors or at least if you can collect the data from the file into a array.
I have a macro in one XLSM workbook's module that refreshes all the external data, then saves and closes that workbook.
ActiveWorkbook.RefreshAll
ActiveWorkbook.Save
ActiveWorkbook.Close
Application.Quit
I use a VBScript file to run that macro as part of a scheduled task
objExcel.Workbooks.Open(fname)
objExcel.Visible = True
On error resume next
objExcel.Run "RefreshAllData"
Question: How can I reuse the existing macro in the existing workbook to refresh all the data of multiple other workbooks? (ie. I'm looking for the necessary modifications to the VBScript file, I want to minimise changes to the macro itself. The filenames will be contained in the VBScript file) TIA.
I'd recommend against re-using a trivial macro like that. Instead incorporate the refresh functionality in the VBScript:
Set fso = CreateObject("Scripting.FileSystemObject")
Set xl = CreateObject("Excel.Application")
xl.Visible = True
For Each f In fso.GetFolder("C:\some\folder").Files
If LCase(fso.GetExtensionName(f.Name)) = "xlsx" Then
Set wb = xl.Workbooks.Open(f.Path)
wb.RefreshAll
wb.Save
wb.Close
End If
Next
xl.Quit
I suppose you can do something like this.
Find all the excel file in the given folder
Select Each Excel file and activate
call refreshdata function
code snippet to support this
Sub RefreshAllExcelInFolder()
Dim fso
Dim ObjFolder
Dim ObjFiles
Dim ObjFile
Dim objExcel
'Creating File System Object
Set fso = CreateObject("Scripting.FileSystemObject")
'Getting the Folder Object
Set ObjFolder = fso.GetFolder("<<C:folder path>>")
'Getting the list of Files
Set ObjFiles = ObjFolder.Files
'On Error Resume Next
For Each ObjFile In ObjFiles
If LCase(Right(ObjFile.Name, 5)) = ".xlsx" Or LCase(Right(ObjFile.Name, 4)) = ".xls" Then
Workbooks.Open(ObjFile).Activate
RefreshAllData
End If
Next
End Sub
Sub RefreshAllData()
ActiveWorkbook.RefreshAll
ActiveWorkbook.Save
ActiveWorkbook.Close
MsgBox ("Going back In")
End Sub
Hope this will help
If you don't change the macro at all you will have to keep reloading excel, then open the macro workbook followed by the target workbook and then run the macro. If you can remove:
Application.quit
then you can at least keep excel open and just keep opening target workbooks before running the macro each time. Seems to me it'd be simpler to put the macro code into the vbs file though