When a modeless userform gets loaded, the code in it (except for the Userform_Initialize sub) sometimes does not execute and the main code which calls the userform continues running.
I had it solved, somehow, but this was in the latest update of my program which unfortunately got corrupted.
Sub start() 'shortened drastically, but accurate
'....
If UBound(rs.GetRows(1000000), 2) + 1 < 6 Then
.Close SaveChanges:=False
ThisWorkbook.Sheets("Start").Range("DA1").Value = "1"
ThisWorkbook.Sheets("Start").Range("DA2").Value = MachineNr
UserForm1.Show vbModeless
GoTo ExSub
End If
'...
ExSub:
End Sub
And in the userform module:
Private Sub UserForm_Initialize()
Dim wb As Workbook
If ThisWorkbook.Sheets("Start").Bijwerken = "ja" Then
Me.CommandButton2.Caption = "Cancel"
Me.Label1.Caption = "Select a file to update"
bestand = ""
With Me.ComboBox1
For Each wb In Application.Workbooks
If Not wb.Name = ThisWorkbook.Name Then
For Each sht In wb.Sheets
If sht.Name = "AssetTypeTask" Then
.AddItem wb.Name
Exit For
End If
Next sht
End If
Next wb
End With
Else
bestand = ""
With Me.ComboBox1
For Each wb In Application.Workbooks
If Not wb.Name = ThisWorkbook.Name Then
.AddItem wb.Name
End If
Next wb
End With
End If
End Sub
The code runs through the Userform_Initialize sub without issues, but the userform does not appear at the front of the screen and the code continues at GoTo ExSub which then ends the code execution. The userform stays open but closes as I press one of the commandbuttons on it.
"Code execution will also continue in the background while a modeless
form is shown."
This is what brought me back on my feet. I knew this but had forgotten about it as I firmly believe and still believe that in previous versions of my program I had a modeless UF running that DID interrupt the code.
I ended up solving the issue of the running code by adding a simple loop to check the state of the UF
Do Until Userform1.Visible = False
DoEvents
Loop
This is a slight drawback for the CPU of course, so not ideal, but since this is not a very intensive part of the program, it will do.
The UserForm I use in this instance has to be modeless, because the user needs to be able to scroll through the userform to make sure what they are populating the controls in the UF with is correct. This is not programmable.
If anyone has any other ways of achieving this, please let me know.
Related
First I’m a novice. I’ve been reading, experimenting, and Googling to get this far, but haven’t found anything that helps me understand this.
I’m trying to build a UserForm to collect range data. It’s part of a data centralization effort to add data to “history” workbooks, processing them to track changes and update current interpretations if they’ve changed. The sources vary, but are large and consistent enough to be worth the effort to automate.
Also, I work on am isolated (closed) network so I’ve retyped my code, hopefully (mostly) correctly here.
My UserForm code is:
Private Sub UserForm_Initialize()
Dim wb as Workbook, lastwb as Workbook
For Each wb in Application.workbooks
comboBox1.addItem wb.name
next
ComboBox1 = ActiveWorkbook.name
End sub
Private Sub ComboBox1_Change()
If ComboBox1 <> "" then Application.Workbooks(ComboBox1.Text).Activate
Label1.Caption = "": RefEdit1 = ""
End sub
Private Sub RefEdit1_Change()
Label1.Caption = ""
If RefEdit1.value <> "" then
Label1.Caption = "[" & ComboBox1 & "]" & Replace(refEdit1, "!", "'!")
End sub
I’m calling it with
Private Sub addToHistory()
Dim range1 as range
Dim … 'other variables and code
With New Userform
.Show
range1 = .label
.Hide
Unload Userform1
Debug.Print range1
… 'other code to close/save my workbooks
End Sub
Whenever I try to click on my combo box it vanishes. Even marking every line in the UserForm code for debugging, it simply vanishes leaving me with no clue what happened or how to prevent it.
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.
I have set up a new, empty, modeless userform, to fix my problem with the least amount of code involved.
For when the workbook is opened, the following code is executed to hide Excel and show the userform. It's the only code for the workbook.
Private Sub Workbook_Open()
UserForm1.Show
If Application.Windows.Count <> 1 Then
Application.Windows("test.xlsm").Visible = False
Else
Application.Visible = False
End If
End Sub
I have an empty userform with one single button. The only code for this userform is:
Private Sub CommandButton1_Click()
Application.Windows("test.xlsm").Visible = True
Application.Visible = True
Unload Me
End Sub
The last thing is a button on the first worksheet, to start the same process as when the workbook is opened. Its code:
Sub Button1_Click()
UserForm1.Show
If Application.Windows.Count <> 1 Then
Application.Windows("test.xlsm").Visible = False
Else
Application.Visible = False
End If
End Sub
Now my problem:
When I open the workbook, the userform shows up, but excel and the active window stay visible as well. However, if I click the button on the worksheet, Excel, or the window, are hidden as they should. Also, Excel, not the userform, has focus after loading everything.
The first time I ran this, it worked fine. I suspect changing the ShowModal setting in the editor screwed it up somehow, but that's just me guessing. Anyway, it doesn't work anymore as intended, no matter the modal setting now.
If I just run
Application.Visible = False
instead of the "if"-clause, Excel still stays visible and of course so does the active window.
This is driving me nuts.
What am I missing?
Edit: Link to my test file: Test File on my Dropbox
Might have to start it twice, because when the macros are blocked at startup and only activated after excel has completely loaded, the code works as intended.
Edit: I was able to test this on an excel 2010 pc and there the problem doesn't exist. So it might have something to do with the way newer Office Apps handle stuff.
I found myself having the exact same problem - modeless form opened with Workbook_Open() event that's also supposed to hide excel app (working on Excel 2016, 32bit).
The reason why it's working with UserForm property ShowModal set to True is because: the execution is suspended - it's waiting for user to interact with the UserForm that was shown.
If we change ShowModal to False (or call UserForm.Show vbModeless) then the execution is never suspended and once we reach End Sub of our Workbook_Open(), Excel appears to set Application.Visible = True on its own.
Only solution I've found thus far is this one - basically you suspend the execution by adding an infinite loop so Excel only gets to end of this event once you get rid of (Unload/Hide) the form that was shown previously.
My version looks like this:
Private Sub Workbook_Open()
Dim App As Object
Set App = startMenu
App.Show vbModeless
While App.Visible
DoEvents
Wend
End Sub
Then just to make sure that Excel is closed once that modeless UserForm is closed I've added this:
Private Sub UserForm_Terminate()
CloseApp
End Sub
Public Sub CloseApp()
ThisWorkbook.Saved = True
If Not OtherWorkbooksOpen Then
Application.Quit
Else
ThisWorkbook.Close
End If
End Sub
Public Function OtherWorkbooksOpen()
If Application.Workbooks.Count > 1 Then
OtherWorkbooksOpen = True
Else
OtherWorkbooksOpen = False
End If
End Function
EDIT:
Solution without infinite loop - schedule hiding of Excel:
Private Sub Workbook_Open()
Dim App As Object
Set App = startMenu
App.Show
If Not OtherWorkbooksOpen Then
Application.OnTime Now + TimeValue("00:00:01"), "HideExcel"
End If
End Sub
I think the userform1.show needs to be called after the execution of if statement.
Private Sub Workbook_Open()
If Application.Windows.Count <> 1 Then
Application.Windows("test.xlsm").Visible = False
Else
Application.Visible = False
End If
UserForm1.Show
End Sub
Not an answer, but I can't post this as a comment. This works for me - the user form appears, the application is hidden. I used "<>2" as I have a personal workbook. Can you confirm what happens for you?
Private Sub Workbook_Open()
If Application.Windows.Count <> 2 Then
Application.Windows("test.xlsm").Visible = False
Else
Application.Visible = False
End If
UserForm1.Show False
End Sub
I had the same issue, but I notice the form loads before the excel file. So I put a redundancy calling the application.visible = false, in the form.
Basically after clicking anything in the form, it will call the application.visible = false and the excel window will hide.
As the title say I've been having one particular problem with my userform. When I close it (with a command button) an error pops on Userform.Hide inside the Workbook_Deactivate event.
This is the code on the Userform_initialize event:
All variables in here are global
VBA:
Private Sub Userform_Initialize()
subRemoveCloseButton Me
Set pagina = ThisWorkbook.Worksheets("Ruta")
Set libro = Workbooks.Open(pagina.Range("B4").Value, False, True)
Set pagina2 = libro.Worksheets("GLOBAL")
pasadas = 0
If pagina2.AutoFilterMode Then
If pagina2.FilterMode Then
pagina2.ShowAllData
End If
ElseIf pagina2.FilterMode Then
pagina2.ShowAllData
End If
pagina2.Columns("A:IV").EntireColumn.Hidden = False
lastRow = pagina2.Cells(pagina2.Rows.Count, "B").End(xlUp).Row
Call RemoveDuplicates
With Me.ImagenDatos
.ScrollBars = fmScrollBarsBoth
'Change 8.5 to suit your needs
.ScrollHeight = .InsideHeight * 5
.ScrollWidth = .InsideWidth * 3
End With
End Sub
Then in the CommandButton_Click event I have this:
VBA:
Private Sub BotonCerrar_Click()
Unload Consultas
libro.Saved = True
libro.Close
ThisWorkbook.Close
End Sub
The error, as already commented, comes from this:
VBA:
Private Sub Workbook_Deactivate()
Consultas.Hide
End Sub
If I comment that single line the Userform closes with no problem but I need it so the userform (Consultas) hides when the user switches between workbooks.
The error message says: Object variable or With block variable not set (Error 91)
Anyone have a clue on what's going wrong?
This is my first post and if something else is needed just let me know.
I would appreciate any help on this.
EDIT: I have more code but I think this is pretty much the essential as all I do is open the excel workbook, then the userform shows and then I click the button that closes the userform
So this is how I solved this:
Before trying to hide the userform Consultas on the Workbook_Deactivate event I first checked if the userform was visible with the link provided by #Ralph.
That solved part of the problem but then the error moved to the part where I close libro :
Private Sub BotonCerrar_Click()
Unload Consultas
libro.Saved = True
libro.Close
ThisWorkbook.Close
End Sub
The error persisted even before unloading the userform as suggested by #A.S.H but I fixed it calling Application.Workbooks(libro.Name).Close False instead of libro.close False (If someone could explain this to me I would really appreciated it)
The final code is the following:
Private Sub BotonCerrar_Click()
Dim wb As Workbook
Dim otrolibro As Boolean
otrolibro = False
Application.Workbooks(libro.Name).Close False
Unload Consultas
For Each wb In Workbooks
If wb.Name <> ThisWorkbook.Name Then
otrolibro = True
Exit For
End If
Next wb
If otrolibro = True Then
ThisWorkbook.Close False
Else
ThisWorkbook.Saved = True
Application.Quit
End If
End Sub
The For cicle is to quit the excel application if there is not another Workbook open because if I just close all Workbooks, an Excel window remains open with nothing on it.
Userform1 ComandButton1 code is similar to this (contains more lines of CheckBox checks):
Sub CommandButton1_Click()
Application.DisplayAlerts = False
Set WB = ActiveWorkbook
If CheckBox25.Value = False Then
WB.sheets("PQC 1025").Delete
Else: CheckBox25.Value = True
End If
Unload Me
End
Application.DisplayAlerts = True
End Sub
The second macro will be a Format/Print macro:
Sub Format_Print()
Dim ws As Variant
For Each ws In Workbook
ActiveSheet.PageSetup.LeftFooter = "" & Format(DateTime.Now(), "yyyyMMdd hh:mm:ss")
ActiveSheet.PageSetup.RightFooter = "Page &P of &N"
Next
For Each ws In Workbook
ActiveSheet.PrintOut Copies:=1, Collate:=True
Next
End Sub
I honestly don't know where to start. I'm not a strong coder and it took me a while to get as far as I did.
I would like this macro to automatically happen when Userform1 unloads after use of CommandButton1 (the Okay button). I do not want this second macro to start automatically when CommandButton2 is used to unload Userform1 (the Cancel button).
Any input on how I might try this would be helpful.
I ended up making a new button on the main form to format/print. I fixed a few of the issues I was having with my initial format/print code, removed all of the dimension and setting and simply said "sheets.select" which was the simple fix to object errors.
I had no check that people selected the correct sheets, so I figured this was a safer approach.