Two different Private Sub statements same code - ms-access

I have received code for Access 2010 in VBA and there are two separate sub statements that contain the same code which is as follows:
Private Sub Test_Type_AfterUpdate()
If Not IsNull(Me.Test_Type.Value) Then
Me.TestNameID.Value = frmTestNameIDSmallToBigUpdate
Me.Test.Value = frmTestSmallToMedUpdate
End If
End Sub
Private Sub Test_Type_Change()
If Not IsNull(Me.Test_Type.Value) Then
Me.TestNameID.Value = frmTestNameIDSmallToBigUpdate
Me.Test.Value = frmTestSmallToMedUpdate
End If
End Sub
Also other Private Sub statements contain the same coding but a different variable after If Not IsNull. I am new at VBA but have experience programming in Python and C#, is there a way to combine these statements into one statement.
Thanks

Yes. Create a third private sub to handle Test_Type's events.
Private Sub HandleTestTypeEvent(object)
If Not IsNull(object.Value) Then
Me.TestNameID.Value = frmTestNameIDSmallToBigUpdate
Me.Test.Value = frmTestSmallToMedUpdate
End If
End Sub
And call it from your existing event procedures.
Private Sub Test_Type_AfterUpdate()
HandleTestTypeEvent Me.TestType
End Sub
Private Sub Test_Type_Change()
HandleTestTypeEvent Me.TestType
End Sub
Make sure properly type the parameter and give it a meaningful name.
If you're feeling really froggy, you can have a look at this.
Overriding all Access form control AfterUpdate methods

For better maintainability, refactor that code into a single sub that is called from both event subs, like this:
Private Sub Set_Test_NameID_and_Value
If Not IsNull(Me.Test_Type.Value) Then
Me.TestNameID.Value = frmTestNameIDSmallToBigUpdate
Me.Test.Value = frmTestSmallToMedUpdate
End If
End Sub
Private Sub Test_Type_AfterUpdate()
Call Set_Test_NameID_and_Value()
End Sub
Private Sub Test_Type_Change()
Call Set_Test_NameID_and_Value()
End Sub

Related

Is it possible to incorporate a private sub into a function in VBA access?

Basically I would like to use a function or sub to "paste" code so that I don't have to paste the same thing over and over again. I'm kinda new with VBA so I'm not sure if there's an easier way to handle this. I have many rows of combo boxes that will be determined by their corresponding text box in front of them. I would like to just place a function/subroutine with a number to designate the combo box.
Function cboAfterUpdate (x as Variant)
Private Sub cboOperation &x& _AfterUpdate()
'some other function that uses x'
End Sub
End Funcion
I'm hoping it'll end like this...
cboAfterUpdate(5)
Will show..
Private Sub cboOperation5_AfterUpdate()
'some other function that uses 5'
End Sub
In other words I'd like to do this
Private Sub cboOperation1_AfterUpdate()
Call SqlDes(1)
End Sub
Private Sub cboOperation2_AfterUpdate()
Call SqlDes(2)
End Sub
Private Sub cboOperation3_AfterUpdate()
Call SqlDes(3)
End Sub
up to 20 times since I have cboOperation(1-20) combo boxes. How can I do that in one function without having to have to copy/paste/type 20 private sub events?
I'd probably suffix my comboboxes with a number and use use their Caller property to provide the parameter you want via their string name. E.G. create 3 comboboxes and call them cbo_1, cbo_2, and cbo_3. Then assign a single sub to them:
Sub CboHasChanged()
Dim cboNumber As Integer
Msgbox Application.Caller & " is about to call the sub SqlDes!", vbinformation
cboNumber = CInt(Right(Application.Caller, 1))
SqlDes cboNumber
End Sub
You can make the string manipulation more complicated of course, to account for numbers with double digits and so on but I hope you get the idea - use the name of the combobox to provide the required value.
By the way, you don't need to Call your sub like that, just put the sub name then any parameters without brackets, as I've done in the example.
If you really want to write code with code it is possible in VBA but is an advanced topic.

Ms-Access - IF checkbox = true THEN (Compile error)

A Compile error occurs when i try this code allow a button to be pressed if the check boxes are true
Option Compare Database
Function CheckMyButton()
Me.Command414.Enabled = (Me.chk1 And Me.chk2 And Me.check4 And Me.chk3)
End Function
Private Sub chk1_AfterUpdate()
=CheckMyButton()
End Function
Private Sub chk2_AfterUpdate()
=CheckMyButton()
End Sub
Private Sub check4_AfterUpdate()
=CheckMyButton()
End Sub
Private Sub chk3_AfterUpdate()
=CheckMyButton()
End Sub
=CheckMyButton() doesn't go into the body of event procedures (in there you would use Call CheckMyButton() ).
=CheckMyButton() goes directly into the AfterUpdate property - in the property window of the form.
The point is to not have multiple event procedures that all do the same thing.
German Access here:

Access Listbox AfterUpdate Not Firing when Selected = True

I have an Access form with a listbox and a combo box.
Private Sub Form_Open(Cancel As Integer)
'... misc code
me.comboBox.RowSource = "sql statement"
call comboBox_AfterUpdate
End Sub
Private Sub comboBox_AfterUpdate()
listbox.Selected(0) = true
End Sub
Private Sub listbox_AFterUpdate()
'.... important code that updates the form
End Sub
On the form load/open, the the code runs as
Form_Open > comboBox_AfterUpdate > listbox_AfterUpdate
However after the form has already loaded, when the combo box is changed and the comboBox_AfterUpdate is triggered, the listbox_AfterUpdate() is NOT triggered.
I would move the code in the listbox_AfterUpdate() to a separate sub-routine, but that would call the code to run twice when the form loads. Any ideas on why this happens?
Similar issue here:
http://www.tek-tips.com/viewthread.cfm?qid=1395160
You could use two custom functions and use optional parameters to know the context in which it is called. That way you have full control over when which function does which.
E.g.
Public Sub MyFunc1 (Optional CalledFromLoad As Boolean)
Public Sub MyFunc2 (Optional CalledFromLoad As Boolean)
Private Sub comboBox_AfterUpdate()
Call MyFunc1 False
End Sub
Private Sub listbox_AFterUpdate()
Call MyFunc2 False
End Sub
Private Sub Form_Open(Cancel As Integer)
Call MyFunc1 True
End Sub
Moving all your code gives you a greater degree of customization, and can help you avoid calling the same code twice.
You could possibly set a global variable in MyFunc1, then trigger MyFunc2 by changing the listbox, and then reset that global variable again. Numerous solutions are possible.

Access VBA - TreeView Control - AfterLabelEdit Event

I've got a treeview control in my form. I would like to be able to edit the node in the tree and push the change to Access DB. However, I'm having trouble finding an appropriate event. MSDN treeview events reference page advices AfterLabelEdit, but I am not able to get it to work. Is anyone aware of any workaround/solution?
Snippet of the code I use (I've added onClick and onDblClick for comparison, as they work):
Private Sub xMyTreeview_Click() 'OK
testit
End Sub
Private Sub xMyTreeview_DblClick() 'OK
EditLabel
End Sub
Private Sub xMyTreeview_AfterLabelEdit() 'Problem
AfterLabel
End Sub
Sub EditLabel()
Me.xMyTreeview.StartLabelEdit
End Sub
Sub AfterLabel()
MsgBox prompt, vbOKOnly, "afterlabel"
End Sub
Sub testit()
Dim nodSelected As MSComctlLib.Node ' a variable for the currently selected node
Set nodSelected = Me.xMyTreeview.SelectedItem ' get the currently selected node
NodesStrLength = Len(nodSelected.Key)
Dim NodeStr As String
Dim StrToChange As String
StrToChange = nodSelected.Key
NodeStr = Mid(StrToChange, 2, NodesStrLength - 1)
Me.txtNodeID = NodeStr
Me.sfrmDOCNODE.Visible = True
End Sub
Your link is to the .net Windows Form Treeview but MSComctlLib is the older Visual Basic Common Controls: http://msdn.microsoft.com/en-us/library/aa443023(v=vs.60).aspx
Note the event prototype is different; if you don't declare it with the correct arguments it will never get raised;
Private Sub object_AfterLabelEdit(cancel As Integer, newstring As String)

Access 2007 ReportEvents class is not firing events

I'm having an issue with report events that I haven't
encountered before in Access prior to Access 2007.
I'm using using Access 2007 for a Front-end to a SQL Back-end.
I have a Class, ReportEvents, that I use for the reports.
In a report's Report_Open event I instantiate and then use this class to
handle events like activate, Close, NoData and I also put common code
such as exporting data to excel instead of a report.
This code was working fine in a previous Access 2003 application (mdb) I was using,
but it isn't working as expected in 2007 (accdb). In my tests the call to a non event public sub, ProvideXLOption works like a charm, but none of the events are being fired
from the ReportEvents class. I didn't change the code I just imported it into the
project. I set up break points but they aren't being hit. I changed all of them to
public events and then called them within the test reports event and they worked fine.
I set up another report in Access 2007 with the same results. I've checked
the startup settings in Access and they are fine. I even removed and re-added
the database location from the trusted locations without any luck.
Has Microsoft modified the Events Code or is this just a simple code error on my part that I'm not seeing? It's gotta be something simple. My brain is just toast (my son decided to stay awake after last night's feeding).
Class ReportEvents Code:
Option Compare Database
Option Explicit
Private WithEvents rpt As Access.Report
Const strEventKey As String = "[Event Procedure]"
Public Property Set Report(Rept As Access.Report)
Set rpt = Rept
With rpt
.OnActivate = strEventKey
.OnClose = strEventKey
If LenB(.OnNoData) = 0 Then
.OnNoData = strEventKey
End If
End With
End Property
Public Sub Terminate()
On Error Resume Next
Set rpt = Nothing
End Sub
Private Sub rpt_Activate()
LoadPrintRibbon
End Sub
Private Sub rpt_Close()
Me.Terminate
End Sub
Private Sub rpt_NoData(Cancel As Integer)
Dim strMsg As String
strMsg = "No Records were found that match your criteria."
MsgBox strMsg, vbInformation, rpt.Name & _
": No Match. Report Cancelled"
Cancel = True
End Sub
Private Sub LoadPrintRibbon()
#If AccessVersion >= 12 Then
If rpt.RibbonName <> "PrintPreview" Then
rpt.RibbonName = "PrintPreview"
End If
#End If
End Sub
';;Provides user with option to send data to Excel instead of a report
Public Sub ProvideXLOption(Cancel As Integer)
'... some XLOption Code
End Sub
In the Test Report Code:
Private Sub Report_Open(Cancel As Integer)
Dim rptEvts As ReportEvents
Set rptEvts = New ReportEvents
Set rptEvts.Report = Me
';;Let User User Choose to Export Data to Excel or Display the report
rptEvts.ProvideXLOption Cancel
End Sub
I figured it out. It was a scope issue The ReportEvents class variable rptEvts, was inside the Report_Open sub. Because of this it wouldn't exist when the other events happened. It should be at the module level and not within the procedure.
Dim rptEvts As ReportEvents
Private Sub Report_Open(Cancel As Integer)
Set rptEvts = New ReportEvents
Set rptEvts.Report = Me
';;Let User User Choose to Export Data to Excel or Display the report
rptEvts.ProvideXLOption Cancel End Sub
End Sub
It's amazing what a little rest will do for you.