Display Access form on open & update textbox *while running other code* - vba

Sometimes trying to accomplish the most minor turns into a major headache... I somehow corrupted a database while experimenting to solve this issue. Now I'm really determined to figure this out. (I'll worry about the corrupt DB later!)
End Goal:
When opening .accdb file, automatically:
open form unbound)
run code to:
get Last Update Date from table
display Last Update Date in textbox on form (must be visible to user)
if table data is outdated, run code to:
update data in table
display Update Progress Message(s) in textbox on form (must be visible to user)
when finished:
display Last Update Date in textbox on form (must be visible to user)
The problem is the goal of (must be visible to user).
I can't get the form to display anything until all the code's finished running, regardless of how I run the code (including: set the form to auto-open with File → Options → Display Form; add an AutoExec macro to call code to open the form and run the update; or, run it manually.)
I've been experimenting with the form's opening events to see if I missed something.
According to the Order of Events documentation:
Working with data on a form
Form and control events occur as you move between records in the form and change data. For example, when you first open a form, the following sequence of events occurs:
Open (form) → Load (form) → Resize (form) → Activate (form) → Current (form) → Enter (control) → GotFocus (control)
At no point does the form visibly update. I've tried adding Me.Repaint and even tried Echo=True and DoEvents but obviously they didn't change anything.
My code for testing:
Private Sub Form_Open(Cancel As Integer)
txtTest = "Form_Open()": MsgBox "1. Form_Open"
End Sub
Private Sub Form_Load()
txtTest = "Form_Load()": MsgBox "2. Form_Load"
End Sub
Private Sub Form_Current()
txtTest = "Form_Current()": MsgBox "3. Form_Current"
End Sub
Private Sub txtTest_Enter()
txtTest = "txtTest_Enter()": MsgBox "4. txtTest_Enter"
End Sub
Private Sub txtTest_GotFocus()
Echo True : Repaint : DoEvents
txtTest = "txtTest_GotFocus()": MsgBox "5. txtTest_GotFocus"
End Sub
Private Sub txtTest_Change() : MsgBox "This Does't Run!" : End Sub
Private Sub Form_AfterUpdate() : MsgBox "This Does't Run!" : End Sub
Private Sub txtTest_Change() : MsgBox "This Does't Run!" : End Sub
Private Sub txtTest_BeforeUpdate(Cancel As Integer) : MsgBox "This Does't Run!" : End Sub
Private Sub txtTest_AfterUpdate() : MsgBox "This Does't Run!" : End Sub
The result of opening the form:
(Note that the form's Activate and AfterUpdate events and the control's Change, BeforeEvent and AfterEvent events do not fire at all.)
Theoretically, the form should be visible behind the MsgBox, but neither running the actual update code, nor running a "pause" (loop with DoEvents) doesn't display the form either.
I could swear I've done this in the past without issue but no matter what I do try, the form only displays once all code is finished running.

You can use the Form_Timer event to delay execution until the form fully finishes loading.
Private Sub Form_Load()
Me.TimerInterval = 1 'Trigger 1 millisecond, but asynchronously from other tasks
'Triggers after AutoExec macro has finished
End Sub
Private Sub Form_Timer()
Me.TimerInterval = 0 'Trigger only once
'Your other tasks here
End Sub

Related

Macro Freezes when ListBox is clicked

I'm using Office Professional Plus 2019. I have a ListBox that sometimes freezes the macro. The UserForm (AffDateSelector) has a ListBox (DateSelectionList) and a Button (Continue). The UserForm is called from the driving Sub with AffDateSelector.show. The code for the form is below:
Option Explicit
Private Sub Continue_Click()
Dim lngCurrItem As Long
'Assign the selected value to the public variable strClassDate.
For lngCurrItem = 0 To DateSelectionList.ListCount - 1
If DateSelectionList.Selected(lngCurrItem) = True Then
strClassDate = DateSelectionList.List(lngCurrItem)
End If
Next lngCurrItem
'Unload the form and return to the calling Sub.
Unload Me
End Sub
Private Sub DateSelectionList_Click()
End Sub
Private Sub UserForm_Click()
End Sub
Private Sub UserForm_initialize()
'Load ListBoxAccounts with the public variable strDateArray
With DateSelectionList
.List = strDateArray
End With
'Default the first row in DateSelectionList to be selected.
DateSelectionList.Selected(0) = True
End Sub
I've been using F8 to step through the code. When the form is shown, the UserForm_initialize() sub is executed and the data display properly. If the user does nothing else except click the Continue button, the Continue_Click() sub gets executed, the variable strClassDate is populated, control is returned to the calling sub and all is well.
The problem comes when the user selects an item other than the one defaulted in the list. Once the user clicks on the ListForm, the sub DateSelectionList_Click() is executed, but there's nothing in that sub, so the macro freezes. If I put in "dummy code" into DateSelectionlist_Click() (e.g. strClassDate = strClassDate) that line is executed and then the macro freezes when the End Sub statement is executed.
How can I allow the user to click on a non-defaulted item in the list, keep the form displayed, and wait for the Continue button to be pressed?
The code was fine. I had a lot of windows open and the pop-up didn't appear I was running the code from the VB editor but the pop-up never appeared. When I pressed Alt + Tab it didn't appear in that list either.

When my Word VBA form opens, why won't my the Open or Load events run

I must be missing something basic (no pun intended), but I can't figure this out.
I have a MS Word VBA form called frmChooseMacros. I want to execute a subroutine on an Open or Load event for that form before the user interacts with the form.
From this topic https://learn.microsoft.com/en-us/office/vba/api/access.form.open, I came up with this code as a test and added it to the code window for frmChooseMacros:
Private Sub Form_Open(Cancel As Integer)
MsgBox "Running open event"
End Sub
But it never executes when the form loads.
From this topic, https://learn.microsoft.com/en-us/office/vba/api/access.form.load, I also tried the Load event, like this, but still no joy:
Private Sub Form_Load()
MsgBox "Running open event"
End Sub
I'm running the form through this sub-routine...
Sub DocFix_00_RunMultipleMacros()
frmChooseMacros.Show
End Sub
...which executes when a button tied is clicked on the menu.
This image may help provide additional context:
Any help is appreciated. Thank you!
(Credit goes to #braX for helping me find the answer here.)
For Word, you have to use the UserForm_Initialize or UserForm_Activate events. There is no Form_Load or Form_Open events for Word.
I was able to solve this by first defining a UserForm object and setting it to my frmChooseMacros user form:
Sub DocFix_00_RunMultipleMacros()
Dim oForm As UserForm
Set oForm = New frmChooseMacros
frmChooseMacros.Show
End Sub
Then I use the UserForm_Activate event here:
Private Sub UserForm_Activate()
MsgBox "Form has activated."
End Sub

VBA issue when reopening a form

I am creating a user interface with VBA and have an issue when I close a form with the X button.
A main window has several buttons; one of them call a form for the user to identify. The code, very simple, is below:
Private Sub CommandButton3_Click()
Main_Form.Hide
Identification_Form.Show
End Sub
Then the Identification form opens; It has a textbox in which the user enters his name and a OK button to validate and follow the process.
Yet I want the user to be able to close this window with the X button and go back to the main form.
The code is below:
Public how_closing As Integer
Private Sub UserForm_Terminate()
If how_closing = 0 Then
Main_Form.Show
End If
End Sub
Private Sub UserForm_Activate()
how_closing = 0
End Sub
Private Sub OK_Id_Click()
If TextBox1.Text = "" Then
MsgBox "Please enter your name."
Exit Sub
End If
user_name = TextBox1.Text
how_closing = 1
Unload Identification_Form
Third_Form.Show
End Sub
The how_closing variable is used to know if the unloading of the form is due to the press of the OK button or the X button (the behaviour should not be the same of course).
My issue is the following:
If I launch the identification a first time, everything works fine. But if I close it (X button) and then relaunch it, nothing works; the OK button doesn't react, neither does the X button. All I can do is stop all the macros.
Have you ever seen this kind of bug ?
There are two options :
Answer 1 (the quick way) - Just add this to your code and live further:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
End
End Sub
Answer 2 (the tough way, which would need about 2 months to learn some OOP basics):
Read about OOP
Rebuild the form, following the good practices, defining the form as an object and not working with the default instance:
https://codereview.stackexchange.com/questions/154401/handling-dialog-closure-in-a-vba-user-form
http://www.vitoshacademy.com/vba-the-perfect-userform-in-vba/ (disclaimer - my site)
Enjoy

VBA - UserForm Button (Macro) to Continue running the sub

I have a sub called as sub1() which activates the userform1 through the command userform1.show()
This userform1 has a button called as continue. On clicking that button continue - A Macro called as Private Sub continuebutton() gets activated.
I want to program in such a way that it redirects to the line after userform1.show() in sub1().
Is it something that can be done?
Theoretically, what you want is possible, if you do it like this:
In the UserForm:
Private Sub btnContinue_Click()
flag = True
Debug.Print "I continue ..."
sub1
End Sub
In a module:
Public flag As Boolean
Public Sub sub1()
If flag Then
Debug.Print "sub 1 continues here..."
Else
flag = False
UserForm1.Show
Exit Sub
End If
End Sub
It will work exactly as intended, BUT it is not a good practice to work this way. (Some people may throw stones at you for using public variables at all in VBA.) Here are two articles, that give better ideas:
https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/
Disclaimer - this one is mine:
http://www.vitoshacademy.com/vba-the-perfect-userform-in-vba/
On the form properties for userform1, set its "Modal" property to true.
When the form opens, it will have exclusive focus, and the code in sub1 will not continue running until after it closes. This may be the solution you need.
In the code below, the msgbox will only appear once userform1 closes:
sub sub1()
userform1.show()
msgbox "Now continuing with sub1"
end sub
No way as long as you show the form.
If you show the form modal, the calling routine continues if (and only if) the form is closed.
If you show the form non-modal, the code continues to run directly after the show - so it's already done.
So either you have to close the form when the user clicks the "continue..." button to let the calling macro continue or you have to split your code into two routines and call the second on button-click.
You can change your Sub1 as follows:
Sub sub1(Optional Continue As Boolean)
If Continue = True Then
DoSomeStuff
Exit Sub
End If
userform1.show
End sub
And then, you can call your sub1 using:
Private Sub continuebutton()
Call sub1(True)
End Sub
Hope it helps
If you don't want to go with the 'Modal Form' solution, you could add a subroutine to your main module, and call it when required. So, in userform1, you have:
sub sub1()
userform1.show()
end sub
public sub sub2()
msgbox "Now continuing..."
end sub
And then in userform1, set some code on its onClose event:
Private Sub continuebutton()
Call sub2()
end sub

Can you set events within Tab Control for MS Access?

I have been searching the internet for this all day. But no luck.
Can you setup events for when you enter/leave a tab.
I.E.
OnExit(Tab1)
Do something
Thanks
Depending on your program flow, you might try:
Private Sub Combo3_Exit(Cancel As Integer)
If IsNull(Me.Combo3) Then
MsgBox "No exit"
Cancel = True
End If
End Sub
Private Sub Form_Current()
Me.Combo3.SetFocus
''Or to refer to a subform from the main form
Me.subformcontrolname.Form.Combo3.SetFocus
End Sub
Does the tab contain a subform or only controls from the main form?
A subform has an Exit event, so if you are only concerned that once you have entered the subform you should not leave without completing data, you could:
Private Sub subformcontrolname_Exit(Cancel As Integer)
If IsNull(Me.subformcontrolname.Form.Combo3) Then
Me.subformcontrolname.Form.Combo3.SetFocus
MsgBox "No exit"
Cancel = True
End If
End Sub
While this is not exactly what you want, you could instead of handling the exit simply prevent the user from clicking somewhere else. To do this, attach some code to your combobox1 that bascially set .Enabled=Xfor all elements outside your tab view - where X is determined by the state of the combobox...