I'm trying to trigger the button that will handle the extraction of the selected document once the user double click the document listed in the form like the screen shot below
So I went in the properties and configured:
Private Sub ParamName_DblClick(Cancel As Integer)
call Forms!FormName.Extract_Click
End Sub
With no success , I also tried :
Private Sub ParamName_DblClick(Cancel As Integer)
Forms!FormName.Extract_Click
End Sub
Inside the form , the sub is declared as below :
Private Sub Extract_Click()
Dim dbs As DAO.Database
//.... //do work
end sub
What I am doing wrong ?
Short answer: You can't, and even if you could (or in contexts where you can), you shouldn't.
Longer answer: don't implement any logic directly in event handlers. Invoke the logic from the handlers:
Private Sub SomeControl_SomeEvent()
DoTheThing
End Sub
Public Sub DoTheThing()
'do stuff
End Sub
That Public member can live in a standard module, and thus can be invoked by anything anywhere - from a button on some form, or from another button on another form, or whatever you need to invoke it from.
But don't invoke event handler procedures yourself. Event handlers handle events, they're invoked by the VBA runtime: leave it that way and live prosper.
Related
In an Access application, I'd like to programmatically set up a dynamic key handler to execute a VBA function when this key is pressed.
I was able to manually create a macro that calls the function and another AutoKeys macro that "calls" the first macro when a specific key is pressed.
Now, I'd like to be able to create these macros with VBA only. Is this somehow possible?
Of course, if there are other ways to achieve what I want, I am open to suggestions.
You could do something like this, create a class called clsCustomForm, containing this code
Option Compare Database
Option Explicit
Private WithEvents frmCustomForm As Form
Public Function INIT(frmFormToMakeCustom As Form)
Set frmCustomForm = frmFormToMakeCustom
frmCustomForm.OnKeyDown = "[Event Procedure]"
End Function
Private Sub frmCustomForm_KeyDown(KeyCode As Integer, Shift As Integer)
MsgBox "Hello"
End Sub
Then in a module, you will need to have a public collection, which you add a class for each form opened and removed when each form closed, I'd suggest a dictionary, with the key as the form name and the item as the class, for example, just testing (limited time) I've used the following code in 1 form, hope this helps, i'll have a bit more time later to show the dictionary if needed.
Option Compare Database
Option Explicit
Public CUSTOM_FORM As clsCustomForm
Private Sub Form_Load()
Set CUSTOM_FORM = New clsCustomForm
CUSTOM_FORM.INIT Me
End Sub
I have some code in Before_Update event of Subform. Can I Cancel this code when I click on another control in Main form, like a Cmdbutton ? I tried with this, but It's not working:
Public CnclEvnt As Boolean
Private Sub Form_BeforeUpdate(Cancel As Integer)
If CnclEvnt=True Then
Cancel=True
End if
End sub
Private Sub cmdButton1_Click()
CnclEvnt=True
End Sub
No. The update happens before the click event or any other event like the OnExit of the subform control.
The only method I can see is to always cancel the update and then have a button to actively save the record. However, if you have several records in the subform, this would be very cumbersome.
I am sure this is really simple but i just cant make it work. I have a form with three sub forms. The main form loads and finds the requested record fine and if i run the below from a button on the main form it works fine. What i want to do is have it run after form loads requested record and with out user interaction. I have tried on load and on current but as the form is not yet on screen there are no values to populate the variables and the msgboxes are blank. But like i said fired from a button on the main it works fine.
any help would be greatly appreciated.
actCount = [ActMovDelete].Form![Text93].Value
PlaCount = [PalnMovDelete].Form![Text91].Value
noCount = [NotesDelete].Form![Text50].Value
MsgBox actCount
MsgBox PlaCount
MsgBox noCount
I'm not sure if I understand your question, but if you are you trying to active the code upon initialize, then just
Private Sub UserForm_Initialize()
[your code here...]
End Sub
If however, you are trying to populate variables of forms that are not loaded, then a better approach might be to store the variables as public variables in the forms. This should give you access to the variables even when they are not loaded. Just as an example of how this might work:
In the form from where you want to get the variable (named UserForm1):
Public strFromTheForm As String
Private Sub UserForm_Activate()
TextBox1.Value = strFromTheForm
End Sub
From another form or a module, you can include the code:
Public Sub Test2()
Dim strTest As String
strTest = UserForm1.strFromTheForm
If strTest = "" Then
UserForm1.strFromTheForm = "Test"
End If
UserForm1.Show
End Sub
I have a form with some fields on it. Form was created from the table in question.
I've tried to use the button wizard to create a save button, I've tried to use the following:
Private Sub saveRecord_Click()
DoCmd.RunCommand acCmdSaveRecord
End Sub
Nothing works, any method I try to save the info doesn't work. I've made sure the form is bound, as far as I can tell it is, it was created off that table.
I have this line when the form loads to make sure the form is on a new record:
Me.Recordset.AddNew
From my limited understanding of the language, setting the form to a new record and then doing a save command should work?
RunCommand acCmdSaveRecord will only do a save if there is something to save. Simply adding a record to the form's recordset doesn't give you anything to save.
Make this change to saveRecord_Click() to confirm whether that is the explanation:
Private Sub saveRecord_Click()
If Me.Dirty = True Then
DoCmd.RunCommand acCmdSaveRecord
Else
MsgBox "nothing to save"
End If
End Sub
Some other suggestions ...
Since you want to go to the new record when the form loads, use GoToRecord instead of Me.Recordset.AddNew:
Private Sub Form_Load()
DoCmd.GoToRecord Record:=acNewRec
End Sub
The version of saveRecord_Click() I suggested earlier was only to explore the problem. But for routine use, it doesn't make sense to allow the user to click a saveRecord button and then tell them there is nothing to save. It is better to only make the button clickable when there is something to save.
So you can disable the command button in the form's On Current event and enable it in the On Dirty event (which means there is something to save).
Private Sub Form_Current()
Me.saveRecord.Enabled = False
End Sub
Private Sub Form_Dirty(Cancel As Integer)
Me.saveRecord.Enabled = True
End Sub
Also, as the last step of saveRecord_Click(), you may wish to SetFocus on another control and disable the command button.
I've made a graphical navigation system so the user can easily find the record he/she wants to. I'm using this on multiple forms now, and since I'm going to use it on another form, I want to standarize the code into a class instead of copy-pasting the VBA code. This way I can improve the code in one place, instead of doing the same change on all the forms.
This is how it works right now:
Dim v As New clsNav
Set v.button1 = Me.button1
Set v.button2 = Me.button2
v.init
And in v.init, I want to set up all the events like click. So when the user clicks button1, it should run a specified method.
How can I do that?
The events for the button clicks will look like this
Private Sub Button1_Click()
' Your code
End Sub
And they are located within the code found behind the respective forms. To be able to reuse code you simply write a sub in a separate module and then call it in the event.
Private Sub Button1_Click()
call MySub()
End Sub
' This is in a module
Private Sub MySub()
' Your code
End Sub
Now this works as long as the code you have to run doesn't use controls specific to that form. If you do need to write code like that, its simply a matter of passing a control to the sub, instead of calling it by its Name
Example. Lets say when we click our buttons it updates a TextBox with today's date. The textboxes have different names on each form. txtDate1 on Form1 and txtDate2 on Form2. So how that will look is
'Form 1 Button
Private Sub Button1_Click()
call MySub(txtDate1)
End Sub
'Form 2 Button
Private Sub Button2_Click()
call MySub(txtDate2)
End Sub
' This is in a module
Private Sub MySub(t as TextBox)
t.Text = Date()
End Sub
If you're trying to do this during run time
How to add events to Controls created at runtime in Excel with VBA
seems like a good place to start. I can't imagine a situation where this would be worth the effort.
I have a generic class I use called frmCtrl, which has WithEvents pointers set up for different control types, with the corresponding events (click, dbl-click, etc...). I then have a function on that class to "set up" the object, so I pass the control in, and the function assigns it to the object pointer of the correct type. This routine also has a parameter for what function to call on which object, so it knows how to respond to the event.
So when I build a form that uses dynamically-added controls, I just create one of these objects for each of the controls, and set it up to call code within the form. The code in the form takes an argument of just the frmCtrl object, so it can easily see which control fired the code, and go from there. I work in Visio, so I'm able to also call a function by module and function name, so the class can handle that too. You'd have to work in how to make such a call using Access, though.
This approach can be used when your controls have been added via the VBIDE, but it may not be worth the effort to set this class up for that, when you can just use the method in the other answer here.