Auto Open used to execute another macro with VBA - excel

I have an excel book titled Can Opener that is opened by my task scheduler. It opens another workbook on a shared drive that my task scheduler cannot access, and then closes itself.. Can Opener works fine. The problem I am having is that the other workbook has code that, upon open, if it is 7pm system time executes an update macro to get new data from the servers. Once this is done the file saves and closes. The data workbook opens, but no update is occurring, and it does not automatically save and close. I have tied breaking the code down so it would at least update, and this is not working either. I have checked several forums and other locations and I still cannot figure out what the problem is. Can I get a little help?
Sub DataBook_Open()
Application.EnableCancelKey = xlDisabled
If Hour(Now) = 7 And Weekday(Now, vbSunday) < 7 Then
Run_Update
Me.Save
Application.Quit
Else: Me.Save
Application.Quit
End If
End Sub
Run_Update is the name of the macro in my module that merely executes that other macros in the module that create the server connection and run the SQL's. This works fine if manually ran, or run with a button, so I know the error is not here. Also I am trying to run this code every night at 7pm.
I really appreciate any help I can get guys.

Are you sure DataBook_Open() executes at all?
It might not unless you're calling it from Auto_Open() or Workbook_Open().
Try this minimal test files. Replacing the paths with your actual folders.
--can_opener.xlsm--
Sub OpenOtherWorkbook()
Dim sWbkPath As String
sWbkPath = ThisWorkbook.Path & "\" & "test_data.xlsm"
Dim wbkData As Workbook
Set wbkData = Workbooks.Open(sWbkPath)
End Sub
--test_data.xlsm-- in the ThisWorkbook Object
Private Sub Workbook_Open()
If Hour(Now) = 9 Then 'replace with your condition
UpdateData
ThisWorkbook.Save
DoEvents
Else
DoEvents
End If
ThisWorkbook.Close
'Application.Quit
End Sub
Sub UpdateData()
ThisWorkbook.Sheets(1).Range("A1").Value = Format(Now, "yyyy-mm-dd:hh\hmm")
End Sub

Related

How to show only the userform and completely hide the excel window?

I have created a userform to add data in order to generate a report and multiple users will have access to the file containing the userform.However my problem is that everytime i open the ".xlsm" file there are instances where the excel workbook in the background is visible.Also i'm having problems when the userform initiates.I looked for the solution to this on the internet and got a lot many ideas.However,i still did not get what i was looking for and thus am asking the question.
I have tried the following code;
Private Sub Workbook_Open()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.WindowState = xlMinimized
ActiveWindow.WindowState = xlMinimized
'Also tried the following
'1 'Application.Visible = False(Have error running the code if i use this.
It worked fine in excel 2007 but in 2013 and 2016 and higher versions the code won't work properly.No idea why.)
'2 ' With Application (This was basically to hide the visible excel application window behind the userform)`
' .WindowState = xlNormal
' .Height = 500
' .Width = 300
' End With
'do stuff (Cells.ClearContents)
userform1.show
End Sub
I also tried creating and running a ".vbs" file but, it seems to avoid only the excel startup splash screen.
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = false
Set objWorkbook = objExcel.Workbooks.Open("C:\Users\filepath\filename.xlsm")
Following are a few screenshots that might help you understand the problem better.
1: On startup the userform always opens up behind my current window.Is there a way to fix this?
2: Because of the first problem the user usually tends to click on the excel application icon on the task bar.
3: Thus making the workbook/worksheet visible in the background like so.I want to avoid this from happening.No matter what i want the user to see only the userform .Is there something i'm doing wrong?
PS. 1: I also saw that one can put a background image of one's choice to avoid showing the excel worksheet.But since i'm fairly new to vba i really don't know if that would be the best option and haven't tried it yet.I'd prefer tweaking the current code i have (if possible) to get the desired result.
In Excel 2019, the following worked for me:
Attached the following to the Workbook_Open event:
Private Sub Workbook_Open()
Application.Visible = False
UserForm1.Show
End Sub
Created a UserForm with a CommandButton where I did put the following:
Private Sub CommandButton1_Click()
Application.Visible = True
Unload Me
End Sub
Obviously you can use these codes at many more places, but this was just for test purposes:
Edit:
If this does not automatically bring Excel to the forefront, you might want to consider using:
AppActivate Application.Caption
Put that as a first line. Testing this threw an "error 5" to me but looking around the net this is definately not the case to all users. While this is a rare occurence, you can tackle that problem (if you have it) by implementing a waiting time (as that helped me):
Dim HoldOn As Date
HoldOn = DateAdd("s", 10, Now())
Do While Now < HoldOn
Loop
Lower the waiting time if you can as 10 seconds might be a bit much. The whole thing then looks like:
Private Sub Workbook_Open()
Dim HoldOn As Date
HoldOn = DateAdd("s", 10, Now())
Do While Now < HoldOn
Loop
AppActivate Application.Caption
Application.Visible = False
UserForm1.Show
End Sub

Closing different workbook ends code execution of current workbook

I am trying to run foo in Book1.xlsm that runs another sub, bar, in Book2.xlsm. Following is the code for both:
In Book1:
Sub foo()
Dim oldBook As Workbook: Set oldBook = ActiveWorkbook
Dim newBook As Workbook: Set newBook = Workbooks("Book2.xlsm")
Application.Run "'Book2.xlsm'!Module1.bar", oldBook
End Sub
In Book2:
Sub bar(book As Workbook)
book.Close False
Debug.Print "Closed Workbook!"
MsgBox "Closed workbook!"
End Sub
The execution of foo runs perfectly fine and the control is passed onto bar in Book2.xlsm. The line book.Close false runs perfectly fine (closes Book1.xlsm), but code execution stops immediately without any warning (no messages in console or popup). Shouldn't both lines be executed in Book2.xlsm since the control was passed to bar?
I tried this by calling bar workbooks(1) (workbooks(1) = Book1.xlsm) and the entirety of the code runs perfectly fine, as expected. Shouldn't the same happen
How do I preserve code execution in the first scenario, i.e. foo runs bar, change workbooks, close Book1.xlsm and continue execution of bar?
Reconsider who's responsible for what. It's not normal that a workbook is just given any random Workbook object and proceeds to Close it.
Sure you can hack around the fact that you're essentially closing the owner of the call stack, but the root of the problem is, when you have WorkbookA responsible for doing something, and that something involves opening or creating WorkbookB, then it's WorkbookA's responsibility to close WorkbookB when it's done.
Book2 has no business closing anything. Assuming the real macro actually does something more than just closing it, then it should do its thing and then let the caller decide whether to close the workbook or leave it open; Book2!Bar is given a resource that it doesn't own: it's beyond its responsibility to close that resource.
Maybe this can serve as a simple illustration:
Public Sub DoSomething()
Set t = New Thing
UseTheThing t
t.SomeMethod ' error 91: object reference is gone!
End Sub
Private Sub UseTheThing(ByRef t As Thing)
t.Foobar 42
Set t = Nothing ' not your job!
End Sub
Working around the natural order of things (caller -> callee -> back to caller) is neither recommended nor useful. Something is broken in the bigger picture - take a step back and fix the higher level instead of fighting the entire paradigm.
You can use Application.OnTime to accomplish this task.
Book2.xlsm
Public wb As Workbook
Public Sub bar(book As Workbook)
'set the variable for the workbook we want to close - We do this because we cannot pass a workbook object
Set wb = book
'set it to call 1 second from now
Application.OnTime DateTime.DateAdd("s", 1, DateTime.Now), "CloseIt"
End Sub
Sub CloseIt()
wb.Close False
Debug.Print "Closed Workbook!"
MsgBox "Closed workbook!"
End Sub
Even if you use an add-in you may face this problem. I found using the below function very useful in handling such problems. Your call stack root won't be in Book1:
Application.OnTime Now + TimeValue("00:00:01"), "'Book2.xlsm'!Module1.bar", oldBook

Msgbox not closing when WSH.Popup waits for certain time

I have an Excel file that opens automatically with Windows Scheduler. Also I have an Auto_Open sub to run a macro immediately. To avoid that every time it opens it starts running without a chance to modify it, I set up a msgbox that let me choose if the macro runs or not. However, I want Excel to automatically choose "Yes" after 10 seconds have passed, and I'm not able to get it. This is my code:
I have tried to place the seconds directly without a variable, I have also tried Case -1 alone, yet nothing works.
Sub Auto_Open()
Set WSH = CreateObject("WScript.Shell")
'cTime = 10
BtnCode = WSH.Popup("¿Desea generar la consulta de vacaciones?", cTime, "Consulta", vbYesNo)
Select Case BtnCode
Case vbYes
Call consulta
Case vbNo
Case 1, -1
Call consulta
End Select
End Sub
It might be easier to use a userform in combination with a module to run this. The UserForm would need to replace whatever you're doing with Msgbox. The code you'll need would look something like this:
USERFORM clode
Private Sub CommandButton2_Click()
'Run code for yes
'then
Unload Me
End Sub
Private Sub CommandButton1_Click()
'run code for "no".
'then
Unload Me
End Sub
Private Sub UserForm_Activate()
Application.OnTime Now + TimeValue("00:00:10"), "KeepItGoing"
End Sub
Then you can have it interact with an external module:
Sub launchSOMETHING()
'Run this first
UserForm1.Show
End Sub
Sub KeepItGoing()
If UserForm1.Visible = True Then
MsgBox "BOOOOMO"
Unload UserForm1
End If
End Sub
You can see an example in this file here.
UPDATED: It appears that all macros will pause while Msgbox is open. In the below two procedures, you'll note that the second one won't be triggered until after the box is closed, even though it was supposed to run in 5 seconds.
Sub TestWhatMsgBoxDoes()
Application.OnTime Now + TimeValue("00:00:5"), "someOtherMacro"
MsgBox "Everything is on hold?"
End Sub
Sub someOtherMacro()
Application.StatusBar = "The Second Macro has run at" & Now()
End Sub
I think has to do with the "Call consulta" procedure, try use megbox to test it.
Ok, so after a lot of research I managed to do what I want without a lot of issues.
First, I created a scrip (.vbs file) that contains the following:
Dim objExcel
Dim objWB
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True
Set objWB = objExcel.Workbooks.Open("R:path\file.xlsm")
objExcel.Run "MyMacroName"
objWB.Save
objWB.Close False
objExcel.Quit
Now every time I run the script, the macro would run automatically. I have also set up a Windows Scheduler Event so it will run by itself with the script. In that way, I don't need a Popup to ask me if I want to run something, and the script would only run when the Event is triggered by the conditions set.
On the other hand, the Excel file itself is free from autorun when the workbook is opened, so any user can modify it without any problem.
Thanks to the people that helped me through this.

How do I make VBA complete it's previous command (Refreshing using Bex analyser 7) before moving on to the next one?

I am attempting to create a macro which opens up a file refreshs a query and will then save and close. Currently the macro initiates the refresh however it moves on to the Save and close command before it has finished and therefore nothing changes. I have seen that there are ways off 'pausing' or 'sleeping' for a period of time to allow the command to be completed however I wish to expand this macro to opening multiple workbooks with queries which take differing times to refresh so therefore that would be a last resort. What I have currently utilizes DoEvents however this doesn't seem to be working either.
Note: The refresh works through SAP Bex analyser 7.
My code:
Sub OpenAndRefresh()
Workbooks.Open "QueryRefresh.xls", UpdateLinks:=False
Workbooks("QueryRefresh.xls").Activate
Run "BExAnalyzer.XLA!SAPBEXrefresh", True
DoEvents
Workbooks("QueryRefresh.xls").Close SaveChanges:=False
End Sub
Any help or guidance would be greatly appreciated.
I have a macro for this purpose, and I've never had this issue:
Public Sub Refresh_All()
Dim filepathstr As String
Dim filename As String
Dim wbk As Workbook
filepathstr = Sheet1.Range("filepath").Value
For Each cell In Sheet1.Range("workbooks")
If Not cell.Value = "" Then
filename = cell.Value
Set wbk = Workbooks.Open(filepathstr & filename)
''''**REFRESH**''''''
SAPBexrefresh (True)
Application.DisplayAlerts = False
wbk.Save
wbk.Close False
Application.DisplayAlerts = True
End If
Next cell
End Sub
The main difference here code-wise is that I'm calling the refresh macro directly rather than using the Run command.
EDIT: To make this work you also need to add the "BExAnalyzer" Reference in your project. If you're not familiar with adding references, you need to go into Tools --> References, then click on "BExAnalyzer" out of the long list of available references.
I'm not sure why this would make any difference but as I say, I've always found that my macro finishes refreshing (even when this takes up to 15 minutes) before continuing. I'm also using BEx 7

App_WorkbookOpen not responding when opening XLS workbooks

I'm writing a simple macro to solve a common problem for people who use XLS with multiple monitors. Often, a workbook is saved in the second window and will not appear in the main window when re-opened.
To get around this, I have attempted to use the App_WorkbookOpen function and have encountered several problems.
This code only runs when opening a fresh instance of XLS.
This code opens the workbook, but does not display it in the windows menu.
This code interacts only with the personal.xls template.
I've included several lines of code to test what the macro is interacting with.
The code resides in ThisWorkbook section of my personal template.
The core code works if placed in an individual worbook, but I'd like it to run in all Wb_open situations.
Option Explicit
Public WithEvents App As Application
Private Sub Workbook_Open()
Set App = Application
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
On Error Resume Next 'error handling, remove when final
Application.ScreenUpdating = False
If ActiveWindow.Left > Application.UsableWidth Then
ActiveWindow.Left = 15
ActiveWindow.Top = 10
End If
MsgBox "New Workbook:" & Wb.Name 'what wkbook?, remove when final
If Error Then End
End Sub
Any thoughts?

Resources