Search code examples
vbams-access-2016

CommandBarControl executing .OnAction before click on button


The code in my question in inspired by the solution in the answer provided by this question:
How to add a menu item to the default right click context menu

I have a ListBox object on a form showing a list of Actions. I want the user to be able to right click an item of this list to show a contextual menu where he can either :

  1. open a new form where he can view and edit the action (corresponds to the execution of a double click event on the list item)
  2. delete the item from the list

    Private Sub List_actions_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single
    
        'set up commandBar
        Dim combo As CommandBarControl
    
        'Since it may have been defined in the past, it should be deleted,
        'or if it has not been defined in the past, the error should be ignored
        On Error Resume Next
        CommandBars("RCActionContextMenu").Delete
        On Error GoTo 0
    
        'Make this menu a popup menu
        With CommandBars.Add(Name:="RCActionContextMenu", Position:=msoBarPopup)
            Set combo = .Controls.Add(Type:=msoControlButton)
                combo.BeginGroup = True
                combo.Caption = "View action"              ' Add label the user will see
                combo.OnAction = "List_actions_DblClick"    'Add the name of a function to call
    
            Set combo = .Controls.Add(Type:=msoControlButton)
                combo.Caption = "Delete action"
                combo.OnAction = DelAction()
        End With
    
        If Button = acRightButton Then
            DoCmd.CancelEvent
            CommandBars("RCActionContextMenu").ShowPopup
        End If
    End Sub
    
    Public Function DelAction()
        If Not IsNull(Me.Controls("RCActionContextMenu").Column(0)) Then
            CurrentDb.Execute "DELETE * FROM T_ACTIONS " & _
                      "WHERE ID = " & List_actions.Column(9) & ";"
            MsgBox "Action supprimée", vbInformation, "Information"
        End If
    End Function
    
    Private Sub List_actions_DblClick(Cancel As Integer)
        Dim vStatus As String
    
        'Get the record's index of the action
        rowNumber = Me.List_actions.ListIndex + 1
    
        id_action = List_actions.Column(9, rowNumber)
        vStatus = List_actions.Column(5, rowNumber)
    
        'Open the action
        DoCmd.OpenForm "F_ACTIONS", , , "[ID] = " & List_actions.Column(9)
    
        Form_F_ACTIONS.Effective_date.Visible = Effdatefunction(vStatus)
    
    End Sub
    

The problem i get is that the DelAction() function is executed before the pop-up is shown and i get a run-time error 2465 stating "Microsoft Access can't find the field 'RCActionContextMenu' referred to in your expression."
I've tried repalcing the row combo.OnAction = DelAction() by combo.OnAction = "DelAction". It results in the conextual menu showing itself but nothing happens when i click on either button.


Solution

  • There are a few problems here.

            combo.OnAction = DelAction()
    

    This will call the function, as you have seen. You need to set a string here.

            combo.OnAction = "DelAction()"
    

    This still won't work, since DelAction() is in your form module.
    Either move the function to a public module, with parameters, or hardcoding the object names there,

    combo.OnAction = "DelAction(""MyFormName"", ""List_actions"")"
    

    or try (not sure if this works):

            combo.OnAction = "Form_YourFormName_DelAction()"
    

    It's the same with "List_actions_DblClick" - the function needs to be called "from the outside", like from the Immediate window.


    If Not IsNull(Me.Controls("RCActionContextMenu").Column(0)) Then
    

    You context menu command bar isn't a control, what you want is the list box:

    If Not IsNull(Me.Controls("List_actions").Column(0)) Then
    

    or simply

    If Not IsNull(Me!List_actions.Column(0)) Then
    

    After deleting an action, you need to requery the listbox.

    CurrentDb.Execute "DELETE * FROM T_ACTIONS " ...
    Me!List_actions.Requery