Search code examples
excelvbaruntime-error

How to fix Run-Time error '91' in custom command bar VBA


I have an excel workbook with multiple sheets and am trying to limit user ability to insert/delete rows within the first worksheet. I currently have VBA code in place that removes (hides) the 'Insert' and 'Delete' buttons in the Row menu, and inserts to new fake insert/delete buttons which both create pop-up boxes instructing the user in how to properly remove/add rows (I have some key-bound macros which simultaneously delete/add rows across multiple select sheets).

This code works SOMETIMES, but most often returns a "Run-time error '91': Object variable or With block variable not set".

From picking through a multitude of similar questions, I've determined that I'm most likely not initializing the command bar object correctly (or something along those lines), but I haven't been able to figure out how to correctly do it. Can anyone assist in correcting the error?

Here is the code within the sheet object:

Private Sub Worksheet_Activate()

'reset to standard context menu before adding new option
Application.CommandBars("Row").Reset

'removes standard Delete and Insert menu bar items
Application.CommandBars("Row").FindControl(ID:=293).Visible = False
Application.CommandBars("Row").FindControl(ID:=296).Visible = False
        
'add custom row deletion call
With Application.CommandBars("Row").Controls.Add
    .Caption = "Delete Row"
    .Style = msoButtonCaption
    .OnAction = "DeleteRow"
End With
With Application.CommandBars("Row").Controls.Add
    .Caption = "Insert Row"
    .Style = msoButtonCaption
    .OnAction = "InsertRow"
End With

End Sub

Private Sub Worksheet_Deactivate()
'get rid of the customization when you're done with this sheet
Application.CommandBars("Row").Reset

End Sub

Here is the code within the workbook object:

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Source As Range)
'resets menu bars when workbook sheets are changed
Application.CommandBars("Row").Reset
End Sub

Private Sub Workbook_Deactivate()
    'Resets menu bars when workbook is deactivated
    Application.CommandBars("Row").Reset
End Sub

Here is are the modules for the added buttons -

Module 1:

Public Sub DeleteRow()

    MsgBox "Manually deleting rows from this Estimate will disconnect linked sheets. Please use CTRL-Q to delete rows.", vbOKOnly, "WARNING: Delete Rows"

End Sub

Module 2:

Public Sub InsertRow()

    MsgBox "Manually inserting rows into this Estimate will disconnect linked sheets. Please use CTRL-A to add rows.", vbOKOnly, "WARNING: Insert Row"

End Sub

Solution

  • Setting these controls visibility to false appears to be modifying the collection, removing the ID you're looking for.

    Code to see IDs:

    Sub test()
        Dim ctl As Object
        
        For Each ctl In Application.CommandBars("Row").Controls
            Debug.Print ctl.ID, ctl.Caption, ctl.TooltipText
        Next
        Debug.Print vbNewLine, vbNewLine
    End Sub
    

    If I run this before modifying:

    ID Caption Tooltip
    21 Cu&t Cu&t
    19 &Copy &Copy
    22 &Paste &Paste
    21437 Paste &Special... Paste &Special...
    3624 &Paste Table &Paste Table
    32713 Data T&ype
    296 &Rows Insert Rows
    293 &Delete &Delete
    3125 Clear Co&ntents Clear Co&ntents
    855 &Format Cells... &Format Cells...
    541 &Row Height... &Row Height...
    883 &Hide &Hide (Ctrl+9)
    884 &Unhide &Unhide (Ctrl+Shift+( )
    3626 &Remove Hyperlinks &Remove Hyperlinks

    Running it as you have it with ID:=293 first:

    ID Caption Tooltip
    21 Cu&t Cu&t
    19 &Copy &Copy
    22 &Paste &Paste
    21437 Paste &Special... Paste &Special...
    3624 &Paste Table &Paste Table
    32713 Data T&ype
    3183 &Insert Insert Cells
    293 &Delete &Delete
    3125 Clear Co&ntents Clear Co&ntents
    855 &Format Cells... &Format Cells...
    541 &Row Height... &Row Height...
    883 &Hide &Hide (Ctrl+9)
    884 &Unhide &Unhide (Ctrl+Shift+( )
    3626 &Remove Hyperlinks &Remove Hyperlinks

    You can see that ID 296 is gone from the list and 3183 is now present. Testing manually it does the same thing, adds a row.

    After swapping the lines and successfully running your script:

    ID Caption Tooltip
    21 Cu&t Cu&t
    19 &Copy &Copy
    22 &Paste &Paste
    21437 Paste &Special... Paste &Special...
    3624 &Paste Table &Paste Table
    32713 Data T&ype
    3183 &Insert Insert Cells
    293 &Delete &Delete
    3125 Clear Co&ntents Clear Co&ntents
    855 &Format Cells... &Format Cells...
    541 &Row Height... &Row Height...
    883 &Hide &Hide (Ctrl+9)
    884 &Unhide &Unhide (Ctrl+Shift+( )
    3626 &Remove Hyperlinks &Remove Hyperlinks
    1 Delete Row Delete Row
    1 Insert Row Insert Row

    No matter what 296 seems to be replaced while 293 sticks around. I can't reproduce it now but while testing I saw ID 3181 instead of 3183 so I wouldn't rely on that value.

    I have no clue why it would do this.