How do I implement an event properly in a VBA Context-Menu? - vba

I try to call an Function via an CommandBarButton-Event.
The Code looks finde so far, I also get no Error, but nothing happens. What am I doing wrong?
My Code looks like this:
Private Sub Main()
ContextMenu1
CommandBars("MyListControlContextMenu").ShowPopup
End Sub
Private Sub ContextMenu1()
Dim MenuItem As CommandBarPopup
On Error Resume
NextCommandBars("MyListControlContextMenu").Delete
On Error GoTo 0
With CommandBars.Add(Name:="MyListControlContextMenu", Position:=msoBarPopup, MenuBar:=False, Temporary:=True)
Set MenuItem = .Controls.Add(Type:=msoControlPopup)
With MenuItem
.Caption = "main"
Dim MenuButton As CommandBarButton
Set MenuButton = MenuItem.Controls.Add(Type:=msoControlButton)
With MenuButton
.Caption = "sub"
.OnAction = "Test1"
End With
End With
End With
End Sub
Private Sub Test1()
MsgBox "test", vbOKOnly, "test"
End Sub

It seems like the correct syntax for MS-Access 2010 VBA when implementing an event inside a contextmenu looks like this:
Sub MyContextMenuConstructor()
...
With MenuButton
.Caption = "myCaption"
.OnAction = "=MyFunction('" & myParameter & "')"
End With
...
End Sub
Private Function MyEvent(myInputParameter As String)
MsgBox myInputVariable, vbOKOnly
End Function
Remember:
- What ever called by the Event, needs to be a Function, no Sub;
- It needs to be called with brackets, even if you do not pas a parameter;
- When you call the Function, you must have an '=' before its name and you have to have an apostrophe before and after your Parameter. Also allways place a Whitespace between '&' and '"', since VBA doesn't seem to be that clever.

Related

How can I fix a run-time error when capturing text from a textbox in a form?

I am trying to capture the value entered into the text box of a form instance which was created using the following module code:
Public myForm As Form_Form1
'Dim myForm As Form_Form1 ' tried this
Sub test()
'Dim myForm As New Form_Form1 ' tried this
Set myForm = New Form_Form1
With myForm
.Visible = True
' .SetFocus ' tried this
' .Modal = True ' tried this
If .IsCancelled Then
Exit Sub
End If
Debug.Print .RptDt
End With
The form is very basic with an OK and Cancel button and a single text box named Text7. The form code-behind is:
Private cancelling As Boolean
Public Property Get RptDt() As String
RptDt = Text7.Text
End Property
Public Property Get IsCancelled() As Boolean
IsCancelled = cancelling
End Property
Private Sub Command2_Click()
'DoCmd.Close acForm, Me.Name
Me.Visible = False
'Me.Visible
End Sub
Private Sub Command4_Click()
cancelling = True
'DoCmd.Close acForm, Me.Name
'MsgBox Me.Name
'MsgBox Me.OpenArgs
'Me.Hide
Me.Visible False
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
cancelling = True
Me.Visible = False
End If
End Sub
When I run the code as is I get:
"Run-time error '2185' You can't reference a property or method for a control unless the control has the focus"
I have also tried:
Public Property Get RptDt() As String
RptDt = Text7.Value
End Property
I then get Run-time error '94' Invalid use of null. The code above was modified from a comparable Excel VBA code which uses the Userform Show method (only works in Excel) in the Sub Test() instead of .Visible = True.
Just a side point, but on the Command4_Click event change the below line to add an equals:
Me.Visible = False
This can change the syntax and is a different function to the one intended.
The .Text property can only be called when a Control has the focus. Similarly, a null exception will be called if you use .Value in it's place when the textbox is empty.
There are two ways around this:
Option 1 - Handling the NULL value
Public Property Get RptDt() As String
If IsNull(Text7.Text) = True Then
RptDt = "EmptyString" 'Or whatever string you want to set this to
Else
RptDt = Text7.Text
End if
End Property
Option 2 - Setting the focus
Public Property Get RptDt() As String
Text7.SetFocus
RptDt = Text7.Text
End Property

How to create dynamic naming for each controls on userform in sub routine?

I want to create a routine that when called will perform the function base on the control names dynamically. Here's my code:
Private Sub myControl(counter as string)
If mySecondControl & counter.Value = "Y" Then
myThirdControl & counter.Caption = "Do Something Here" 'Error syntax
End If
End Sub
Private Sub doThis_Change()
myControl("1")
myControl("2")
End Sub
You need to get the Control you want from the form's Controls collection:
If Controls("mySecondControl" & counter).Value = "Y" Then
Controls("myThirdControl" & counter).Caption = "Do Something Here"
End If

Excel VBA: Compile Error: Method or data member not found

EDIT: To clarify, the code seen below is within a module and the UserForm is all contained within its own code.
I have the following code. When I go to run it, Excel throws me a compile error: Method or data member not found and highlights the following piece of code: .showInputsDialog. I have no idea how to resolve this error.
To give more information, the sub sportUserForm is supposed to call up a UserForm sportsUsrFrm. Any help with this issue is greatly appreciated.
Option Explicit
Sub sportUserForm()
Dim sSport As String, sPreference As String
If sportsUsrFrm.showInputsDialog(sSport, sPreference) Then
MsgBox "Your favorite sport is " & sSport & ", and you usually " _
& sPreference & "."
Else
MsgBox "Sorry you don't want to play."
End If
End Sub
Public Function showInputsDialog(sSports As String, sPreference As String) As Boolean
Call Initialize
Me.Show
If Not cancel Then
If optBaseball.Value Then sSport = "Baseball"
ElseIf optBasketball.Value Then sSport = "Basketball"
Elss sSport = "Football"
End If
If optTV.Value Then sPreference = "watch on TV" _
Else: sPreference = "go to games"
End If
showInputsDialog = Not cancel
Unload Me
End Function
UserForm code for sportUsrFrm
Option Explicit
Private Sub cmdCnl_Click()
Me.Hide
cancel = True
End Sub
Private Sub cmdOK_Click()
If Valid Then Me.Hide
cancel = False
End Sub
You're getting the error because showInputsDialog isn't a member of the form, it's a member of the module you're calling it from. You should also be getting compiler errors on these two lines...
Call Initialize
Me.Show
...because you seem to be getting the module and form code mixed up.
That said, you're overthinking this. A UserForm is a class module, and it can be stored in a variable (or in this case, in a With block), and can have properties. I'd add a Cancelled property to the form:
'In sportsUsrFrm
Option Explicit
Private mCancel As Boolean
Public Property Get Cancelled() As Boolean
Cancelled = mCancel
End Property
Private Sub cmdCnl_Click()
Me.Hide
mCancel = True
End Sub
Private Sub cmdOK_Click()
If Valid Then Me.Hide '<-- You still need to implement `Valid`
End Sub
And then call it like this:
Sub sportUserForm()
With New sportsUsrFrm
.Show
Dim sSport As String, sPreference As String
If Not .Cancelled Then
If .optBaseball.Value Then
sSport = "Baseball"
ElseIf .optBasketball.Value Then
sSport = "Basketball"
Else
sSport = "Football"
End If
If .optTV.Value Then
sPreference = "watch on TV"
Else
sPreference = "go to games"
End If
MsgBox "Your favorite sport is " & sSport & ", and you usually " _
& sPreference & "."
Else
MsgBox "Sorry you don't want to play."
End If
End With
End Sub

VBA for Access 2010: Dynamically creating a control and linking event handlers

In Microsoft Access 2010, I am trying to dynamically create a form and then add a commandbutton to it. However, I can't figure out how to assign an event handler to that button's click (or onclick) event?
From reading extracts on the internet, I have created the following vba module code:
Option Compare Database
Option Explicit
Public Sub ProduceForm()
Dim aForm As Form
Dim aButton As CustomButton
Set aForm = CreateAForm("Table1")
Set aButton = CreateAButton(aForm, "Click me!")
DoCmd.Restore
End Sub
Private Function CreateAForm(table As String) As Form
Set CreateAForm = CreateForm(, table)
With CreateAForm
.Caption = CreateAForm.Name
End With
End Function
Private Function CreateAButton(aForm As Form, text As String) As CustomButton
Set CreateAButton = New CustomButton
Set CreateAButton.btn = CreateControl(aForm.Name, acCommandButton)
CreateAButton.SetupButton text
End Function
In accordance with the internet advice, I have then added the following class module (that I've called "CustomButton" and is referred to above):
Option Compare Database
Public WithEvents btn As CommandButton
Public Sub SetupButton(text As String)
If IsNull(btn) = False Then
With btn
.Caption = text
.OnClick = "[Event Procedure]"
End With
End If
End Sub
Public Sub btn_OnClick() ' or should this method just be called btn_Click()?
MsgBox "Happy days"
End Sub
However, when I run this code and then click the button (when in form view) nothing happens?
I notice that explanations given for similar problems, but for excel 2010, give an alternative solution by writing code as a string in a "CodeModule", which I think is linked to the "vbComponents" object. This solution should work for me but I can't find this functionality in Access 2010?
Anyway, any help on this issue would be greatly appreciated.
Thanks
EDIT - my original answer had assumed that Access behaved something like excel, which doesn't seem to be the case...
You don't need a custom class to handle events - you just pass a string to the OnClick property of your button.
This works for me - maybe needs tidying up a bit though.
Public Sub ProduceForm()
Dim aForm As Form, strName As String
Dim btn As CommandButton
Set aForm = CreateAForm("Table1")
Set btn = CreateAButton(aForm, "Click me!", "=SayHello()")
btn.Top = 100
btn.Left = 100
Set btn = CreateAButton(aForm, "Click me too!", "=SayHello('World')")
btn.Top = 1000
btn.Left = 100
DoCmd.OpenForm aForm.Name, , , , , acDialog
DoCmd.Restore
End Sub
Private Function CreateAForm(table As String) As Form
Set CreateAForm = CreateForm(, table)
With CreateAForm
.Caption = CreateAForm.Name
End With
End Function
Private Function CreateAButton(aForm As Form, txt As String, proc As String) As CommandButton
Dim btn As CommandButton
Set btn = CreateControl(aForm.Name, acCommandButton)
btn.OnClick = proc
btn.Caption = txt
Set CreateAButton = btn
End Function
'has to be a Function not a Sub
Public Function SayHello(Optional arg As String = "")
MsgBox "Hello " & arg
End Function

Cannot Run Macro Created with Add-in in Excel

I have create an xla (excel add-in) that have a function to protect the document (so that user could protect the document without knowing the password). This xla is added in every excel file that need this functionality.
when the xla is installed or added to excel, the protect button will be added in last menu. but when i click the button, an error occur show that
"Cannot run the macro Pivot Add-In 0.2'!protectSheet'". The macro may not be available in this workbook or all macros may be disabled."
The code that event handler onclicked is protectSheet, please see the source below:
Could anyone pointed my why this problem occur?
on ThisWorkbook
'main function'
Public Sub protectSheet()
ActiveWorkbook.ActiveSheet.protect Password:="password", AllowUsingPivotTables:=True
End Sub
Public Sub ShowToolbar()
' Assumes toolbar not already loaded '
Application.CommandBars.Add Module1.TOOLBARNAME
AddButton "Proteksi Sheet", "Memproteksi Pivot", 3817, "protectSheet"
' call AddButton more times for more buttons '
With Application.CommandBars(Module1.TOOLBARNAME)
.Visible = True
.Position = msoBarTop
End With
End Sub
Public Sub AddButton(caption As String, tooltip As String, faceId As Long, methodName As String)
Dim Btn As CommandBarButton
Set Btn = Application.CommandBars(Module1.TOOLBARNAME).Controls.Add
With Btn
.Style = msoButtonIcon
.faceId = faceId ' choose from a world of possible images in Excel: see http://www.ozgrid.com/forum/showthread.php?t=39992 '
.OnAction = methodName
.TooltipText = tooltip
End With
End Sub
Public Sub DeleteCommandBar()
Application.CommandBars(TOOLBARNAME).Delete
End Sub
'called when add-in installed
Private Sub Workbook_AddinInstall()
Call ShowToolbar
End Sub
'called when add-in uninstalled
Private Sub Workbook_AddinUninstall()
Call DeleteCommandBar
End Sub
On module1
Public Const TOOLBARNAME = "PivotTools"
After moving all function to module1 , then retain caller function on ThisWorkbook the error now gone. Seem that i have to define all functionality that call/ use constant (Public Const TOOLBARNAME = "PivotTools") in the same file (in my case in module1)
on module1 file
Public Const TOOLBARNAME = "PivotTools"
'caller method'
Public Sub protectDoc()
On Error GoTo errorInfo
protectSheet
'if success, show msg box'
MsgBox ("Report berhasil diproteksi")
Exit Sub
errorInfo:
MsgBox Err.Description & vbCrLf & Err.Number
End Sub
Public Sub protectSheet()
ActiveWorkbook.ActiveSheet.protect Password:="password", AllowUsingPivotTables:=True
End Sub
Public Sub refreshDoc()
On Error GoTo errorInfo
refreshConnection
protectSheet
'if success, show msg box'
MsgBox ("Report berhasil diperbaharui")
Exit Sub
errorInfo:
MsgBox Err.Description & vbCrLf & Err.Number
End Sub
Private Sub refreshConnection()
ActiveWorkbook.ActiveSheet.Unprotect Password:="password"
ActiveWorkbook.RefreshAll
End Sub
Public Sub ShowToolbar()
' Assumes toolbar not already loaded '
Application.CommandBars.Add TOOLBARNAME
AddButton "Proteksi Sheet", "Memproteksi Pivot", 225, "protectDoc"
AddButton "Refresh Data", "Refresh Pivot", 459, "refreshDoc"
' call AddButton more times for more buttons '
With Application.CommandBars(TOOLBARNAME)
.Visible = True
.Position = msoBarTop
End With
End Sub
Public Sub AddButton(caption As String, tooltip As String, faceId As Long, methodName As String)
Dim Btn As CommandBarButton
Set Btn = Application.CommandBars(TOOLBARNAME).Controls.Add
With Btn
.Style = msoButtonIcon
.faceId = faceId
' choose from a world of possible images in Excel: see http://www.ozgrid.com/forum/showthread.php?t=39992 '
.OnAction = methodName
.TooltipText = tooltip
End With
End Sub
Public Sub DeleteCommandBar()
Application.CommandBars(TOOLBARNAME).Delete
End Sub
on ThisWorkbook
'called when add-in installed
Private Sub Workbook_AddinInstall()
Call Module1.ShowToolbar
End Sub
'called when add-in uninstalled
Private Sub Workbook_AddinUninstall()
Call Module1.DeleteCommandBar
End Sub
I had this issue, but found that I had my module named the same as my sub (e.g. module named as "InsertLineID" and the sub was "InsertLineID").
Changing the module name to "LineID" and leaving the sub as "InsertLineID" worked a treat for me!