Passing VBA execution to another workbook - vba

I though there would be many answers to this question, but didn't find any obvious one.
Is it possible to pass VBA execution to another workbook ?
What I'd like to do is : pass execution from ThisWorbook (WbA) to another workbook (WbB, ie make WbB the new ThisWorkook), then close Wb A.
Edit
What I'm actually trying to do...
I'm looking for a way to update a workbook I'm distributing to a few people and which contains 20 sheets + 10 code modules + 10 userforms.
My current solution
Every time the workbook (WbA) is open, the code will first check if a newer version is available on a network directory. If so, the macro propose to the user to automatically download/save the new workbook (WbB) and export user data from WbA.
But, after that, I'm forced to tell the user it can now closed WbA and open WbB and import the data back in WbB.
I'd rather automate the close WbA / open WbB / import data back too.

You can do this by using Application.OnTime:
Code in WbA.xlsm:
Sub Macro1()
Application.OnTime Now(), "WbB.xlsm!Macro2"
ThisWorkbook.Close
End Sub
Code in WbB.xlsm:
Sub Macro2()
MsgBox ThisWorkbook.Name & " says hello"
End Sub
Because Macro2 is being called by the Application via a scheduled task, it no longer needs WbA to be open.
Note: WbB.xlsm does not even need to be open when Macro1 is run, providing you fully qualify the workbook name:
Code in WbA.xlsm:
Sub Macro1()
Application.OnTime Now(), "'C:\Temp\SO_Test\WbB.xlsm'!Macro2"
ThisWorkbook.Close
End Sub
Code in WbB.xlsm:
Sub Macro2()
MsgBox ThisWorkbook.Name & " says hello"
End Sub
Assuming WbA.xlsm was the only workbook open in Excel when Macro1 was run, you might actually see an empty Excel for a very short time before WbB.xlsm is opened and execution continues.

You just have to leave workbook A open while the code runs, the last line of code you need to execute should be
WorkbookA.Close

Related

How to run a macro from a different workbook in a shared network?

So, I've done a lot of research on this and my code isn't working still. As per the title, the problem is this:
I pull a data report off of a website, this report is downloaded as an .xlsx file. I created a macro on the ribbon so I when I click it, it will then open another workbook and run that macro. The code I'm using is as below:
Option Explicit
Sub NotHardAtAll()
Dim ws As Worksheet,
Dim wb As Workbook
Set wb = ActiveWorkbook
Set ws = ActiveSheet
Workbooks.Open Filename:="C:\Users\a0c27n\Desktop\Projects\incident_extended_report1.xlsm"
'With Sheets("Sheet4").Activate '*Not sure if this is enter code here
necessary...at all*
Application.Run "!ADDHMKRFID"
'End With
End Sub
I've tried putting the path before the macro (i.e. Application.Run"'incident_extended_report1.xlsm!ADDHMKRFID") but it doesn't work either*
I'm aware, at least form the research I've done, that I should be able to just use the 'Application.Run' Method, however I couldn't get it to access the correct sheet.
When I run the Macro, it pulls a Run-time error '1004' error, a '400', or the it pulls the most is: "Cannot run the macro '!ADDHMKRFID'. The macro may not be available in this workbook or all macros may be disable."
The file that I'm trying to pull the macro from is below:
Workbook name: incident_extended_report1.xlsm
Worksheet name: Sheet4 (TEST MACRO)
Macro Name:
Sub ADDHMKRFID()
End Sub
I understand that the C:\ is not a shared network, the one I will be working out of will be the S:\, however I'm not sure how much information I can post due to confidentiality.
Please ask for any clarification or questions you may have. I've been stuck for a bit and am not sure what I'm doing wrong. Thanks in advance!
The string you need to pass to Application.Run depends on whether the workbook containing the macro is active, and if it isn't, the filename of the macro-containing workbook (IE: what's in the workbook.Name property).
if the macro is supposed to be run while the data report workbook is active, you want:
dim wb_data as Workbook: set wb_data = ActiveWorkbook
dim ws_data as Worksheet: set ws_data = ActiveSheet
dim wb_macro as Workbook
set wb_macro = Workbooks.Open(Filename:="C:\Users\a0c27n\Desktop\Projects\incident_extended_report1.xlsm")
ws_data.Activate
Application.Run wb_macro.Name & "!ADDHMKRFID"
This will guarantee that the correct string is supplied, even if you change the name of the macro file.
Otherwise, if the macro workbook is supposed to be active, skip activating the data worksheet, as the last opened workbook will be active by default, then use "ADDHMKRFID" as your string. Note that the "!" is missing. You need that only if you are specifying a macro in another workbook. It's the same kind of notation used when referring to data in other worksheets.
First of all, I solved my own problem. I would, however, be grateful if someone might explain to me why it worked the way it did.
I saved the original macro on the shared network, but I had to save it as a module (in this case Module1). I also saved the 2nd macro (to run the original one) in a different workbook (though it shouldn't matter, as long it is not a .xlsx file).
The Code I wrote was:
Sub Test() 'Name doesn't matter
Application.Run "'S:\xxxx\xxxx\xxxx\incident_extended_report.xlsm'!module1.ADDHMKRFID"
End Sub
Then I saved this macro to the ribbon so I could run it on the data report.xlsx file I have to download. Now, anytime I want to run the original macro, I just click the Test Macro, and it'll run the other one!
I'm guessing if you want to close the other workbook that you opened, you can just add a
Workbooks (“S:\xxxx\xxxx\xxxx\incident_extended_report.xlsm").Close Savechanges:=False
Good Luck!

How to make vba code to run auto-close only on active workbook?

Here's the scenario. I have multiple excel workbooks that copy and paste data among each other. So the macro works to open.copy.close from one workbook then open.paste.close to another. I am working on creating a function to auto run macro when file is closed.
Here's the issue, when I click macro button in workbook 1, it is supposed to open.copy.close from workbook 2. However, because of the auto run when file is closed function in workbook 2, an error will occur (2 macros cannot run at the same time)Any solution for this? I am looking for a solution to only auto run macro when file is closed IF IT IS AN ACTIVE WORKBOOK. Here is what I have now:
Workbook 1
Sub workbook_beforeclose(cancel As Boolean)
Application.Run "Sheet1.UpdateYellowTabs_Click"
End Sub
Workbook 2
Sub Workbook_BeforeClose(Cancel As Boolean)
Workbook.BeforeClose
Application.Run "Sheet12.UpdateGreen_Click"
End Sub
How do I code it in the workbook code to only make this run only when it's active/closed by a human user and not when open/close by macro?
Thanks!
Well I am not sure to understand your final goal from this, but I can answer the "technical" question. Technically, if you want to check if a given workbook is active: If Application.ActiveWorkbook Is Me,
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Not Application.ActiveWorkbook Is Me Then Exit Sub ' <-- add this test
''''''''''''''''''''''''''
' Whatever code goes here
''''''''''''''''''''''''''
End Sub
EDIT
But problem is that invoking wb2.close will make the workbook wb2 the "active" one during the execution of the macro. So this method won't work. Another method is to disable events before closing the workbook; so that the event Workbook_BeforeClose will not fire. After that, you can enable events back if needed. The code looks like this:
' ... open wb2 and do the work with it
Application.EnableEvents = False
wb2.Close False
Application.EnableEvents = True
notice, if you had already disabled events at the beginning of the current macro, which is usually recommended, then this additional code wouldn't be needed.

Close a workbook at a specific time

I have looked everywhere to get an answer to this and can't figure it out. I'm looking for a way to close and save a workbook automatically at midnight every night because it has important information that people keep losing because they don't save it. I've got the closing and saving part down, if I manually click the X to close Excel, but I can't get it to do it at a predetermined time. I've used Application.OnTime without any success. Here is the code that I'm using to close and save the workbook. I just need the code to have it run at midnight if the workbook is still open.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Sheet1.Activate
Sheet1.Range("AB18:AD18").Select
Selection.ClearContents
ActiveWorkbook.Save
End Sub
I had trouble referencing the Worksheet .CodeName property but not with the Worksheet .Name property.
Module1 code sheet
Option Explicit
Sub ScheduleClose()
Application.OnTime Now + TimeSerial(0, 0, 4), "Kamikaze"
End Sub
Sub Kamikaze()
Debug.Print "boom"
Application.DisplayAlerts = False
With ThisWorkbook
.Worksheets("Sheet1").Activate
.Worksheets("Sheet1").Range("AB18:AD18").ClearContents
.Save
.Close savechanges:=False
End With
End Sub
Of course, the workbook must be already saved (i.e. not Book1) since no name is provided but a Workbook.SaveAs method could be used if the workbook habitually is not already saved.
This will also leave 'orphaned' VBA projects within the Excel application 'instance'. VBA cannot kill itself as it has to be running to complete the command.

Shared Excel Document

I've got a Excel documents with macros with input and update forms for information, the document is used as a monthly database where you can run reports from as well.
The issue is that when using the document sometimes the input and update options are used at the same time causing information loss. Both the input and output save at the end of the macro to minimise the losses, but I was wondering if there is anyway of checking at runtime if there is a macro being use by another user and if so delay the next macro run until the other user is finished?
There is one way I can think of. Logically it should work. However I have not tested it.
Create a temp sheet and hide it
When anyone runs a macro, check if cell A1 of that sheet is empty or not
If it is empty then run the macro
Before running the macro, write to that cell and once the macro is run, clear the contents of the other cell
Sandwich your macro code as mentioned below
Code
Sub Sample()
Dim ws As Worksheet
ThisWorkbook.Save
Doevents
Set ws = ThisWorkbook.Sheets("HiddenSheetName")
If Len(Trim(ws.Range("A1").Value)) = 0 Then
ws.Range("A1").Value = "Macro Starts"
ThisWorkbook.Save
Doevents
'
'~~> Rest of your code goes here
'
ws.Range("A1").ClearContents
ThisWorkbook.Save
Doevents
Else
MsgBox "Please try after some time. There is a macro running... Blah Blah"
End If
End Sub
CAUTION: Once the code runs, you cannot undo the changes since the code save the file programatically. The changes are permanent. In a file which is not shared, you can undo by closing the file without saving and re-opening it.

VBA Select a sheet when the workbook is opened

The following program doesn't work when I open my workbook. What are the possible reasons?
' Select the first sheet when the workbook is opened.
Private Sub Workbook_Open()
Sheet4.Select
Sheet4.Range("B1").Select
End Sub
If you hit alt+F11 to go to the VBA code editor. On the left side, under the file name you will see the different sheets, and whatever modules you might have in there. If you go under the ThisWorkbook module
and place your code there, it will automatically run when you start up the Excel File.
you are using the "Select" Method without an Activating a Sheet First!
Yes, when you have closed your workbook last time, the current sheet will remain in the memory index and when you will again open the same workbook, the pointer search for the most recent sheet used based on the index no.
'Here is the code
Private Sub Workbook_Open()
Sheet4.Activate
Sheet4.Select
Sheet4.Range("B1").Select
End Sub
using "Select Method" without Activating the Parent Object is a Crime. lol
Hope this will help you.