MS Access – Find Embedded Macros

Most people already know that I do not favor Embedded Macros in any capacity. Unlike VBA, Macros are more complicated to program, are not searchable making it hard to perform database updates.

Long story short, I was working on a project a short while ago where I need to do a major cleanup of object names, control names, … and was needing to identify where object were being used so I could update them. Then I decided, even better, let’s find all the Embedded Macros so I can simply convert them over to plain VBA and then this problem would not occur again in the future.

As such, I put together the following procedure which goes through all the database Forms and Reports and their respective controls to identify those that use Embedded Macros. Hopefully it can help someone else.

'---------------------------------------------------------------------------------------
' Procedure : FindEmbeddedMacros
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Search Forms & Reports to locate any Embedded Macros
'             The search results are printed to the immediate window
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' None
'
' Usage:
' ~~~~~~
' ?FindEmbeddedMacros
' Call FindEmbeddedMacros
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2017-01-07              Initial Release
' 2         2018-05-24              Copyright updated
'---------------------------------------------------------------------------------------
Public Sub FindEmbeddedMacros()
    On Error GoTo Error_Handler
    Dim oFrm                  As Object
    Dim frm                   As Access.Form
    Dim oRpt                  As Object
    Dim rpt                   As Access.Report
    Dim ctl                   As Access.Control
    Dim prp                   As DAO.Property

    Access.Application.Echo False
    Debug.Print "Search Results"
    Debug.Print "Object Type", "Object Name", "Control Name", "Event Name"
    Debug.Print String(80, "-")

    'Search the forms
    For Each oFrm In Application.CurrentProject.AllForms
        DoCmd.OpenForm oFrm.Name, acDesign
        Set frm = Forms(oFrm.Name).Form
        With frm
            For Each prp In .Properties
                'Form Properties
                If InStr(prp.Name, "EMMacro") > 0 Then
                    If Len(prp.value) > 0 Then
                        Debug.Print "Form", frm.Name, , Replace(prp.Name, "EmMacro", "")
                    End If
                End If
            Next prp
            'Form Control Properties
            For Each ctl In frm.Controls
                For Each prp In ctl.Properties
                    If InStr(prp.Name, "EMMacro") > 0 Then
                        If Len(prp.value) > 0 Then
                            Debug.Print "Form", frm.Name, ctl.Name, Replace(prp.Name, "EmMacro", "")
                        End If
                    End If
                Next prp
            Next ctl
        End With
        DoCmd.Close acForm, oFrm.Name, acSaveNo
    Next oFrm

    'Search the Reports
    For Each oRpt In Application.CurrentProject.AllReports
        DoCmd.OpenReport oRpt.Name, acDesign
        Set rpt = Reports(oRpt.Name).Report
        With rpt
            'Report Properties
            For Each prp In .Properties
                If InStr(prp.Name, "EmMacro") > 0 Then
                    If Len(prp.value) > 0 Then
                        Debug.Print "Report", rpt.Name, , Replace(prp.Name, "EmMacro", "")
                    End If
                End If
            Next prp
            'Report Control Properties
            For Each ctl In rpt.Controls
                For Each prp In ctl.Properties
                    If InStr(prp.Name, "EMMacro") > 0 Then
                        If Len(prp.value) > 0 Then
                            Debug.Print "Report", rpt.Name, ctl.Name, Replace(prp.Name, "EmMacro", "")
                        End If
                    End If
                Next prp
            Next ctl
        End With
        DoCmd.Close acReport, oRpt.Name, acSaveNo
    Next oRpt
    
    Debug.Print String(80, "-")
    Debug.Print "Search Completed"

Error_Handler_Exit:
    On Error Resume Next
    Access.Application.Echo True
    If Not prp Is Nothing Then Set prp = Nothing
    If Not ctl Is Nothing Then Set ctl = Nothing
    If Not rpt Is Nothing Then Set rpt = Nothing
    If Not oRpt Is Nothing Then Set oRpt = Nothing
    If Not frm Is Nothing Then Set frm = Nothing
    If Not oFrm Is Nothing Then Set oFrm = Nothing
    Exit Sub

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: FindEmbeddedMacros" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Sub

12 responses on “MS Access – Find Embedded Macros

  1. Alexandros Avgoustiniatos

    Thank you, thank you, thank you. You saved me a lot of time. I have been searching for a lost embeded macro for days and I couldn’ find it.
    In 2 minutes I found it and fixed it.
    I will be using it often to find mistakes.

  2. Climent

    Thank you, thank you, thank you. You saved me a lot of time. I have been searching for a lost embeded macro for days and I couldn’ find it.
    In 2 minutes I found it and fixed it.
    I will be using it often to find mistakes.

    Yes, I know: I copied it. But it’s exactly what I’m feeling right now.
    Again: Thank-you, thank-you, thank-you

  3. Simon

    I am still learning and have a MS template with data macros. I can’t get this to work. I have saved it in a module and when I run it, it seems to work but I don’t see any output/report .. I’m not sure what I’m missing?

    1. Daniel Pineault Post author

      This function uses Debug.Print to output the results to the immediate window in the VBE. So you need to ensure you have the Immediate window open (in the visual basic editor – VBE- press Ctrl+G).

  4. Marcus

    This is so great THANK YOU!
    But why in the world would Access spit out an error and not tell you where the error occurred???

  5. Borge Hansen

    When running some maintenance code to get the name of all the Form Properties I came across that many of the event properties have a second one with the suffix of “EmMacro” – which let me to a search ending up on this webpage. Again excellent informative website! Thumbs up!
    Question: What syntax (i.e. Sublime Text > View > Syntax as an example) do you use to get the nice colored syntax highlighting of the vba code presented on the web page?? As you can see I use Sublime Text a lot to archive VBA modules but I have found not Syntax selector that gives me such nice color highlighting. Thanks!

  6. Andy Whitton

    An excellent solution that saved me hours of manually looking. I did find one enhancement was useful which was to look through all the forms and close them first else you get an error when it tries to open a particular form. Whilst trivial to close them manually it was nice to solve programatically.
    ‘Close any open forms
    For Each oFrm In Application.CurrentProject.AllForms
    If oFrm.IsLoaded Then DoCmd.Close acForm, oFrm.Name, acSavePrompt
    Next