PSLine2000Documentation/Modules/MacroModule.md

15 KiB

MacroModule

Analysis generated on: 4/1/2025 5:16:54 PM

VBA Code

Attribute VB_Name = "MacroModule"
Option Compare Database
Option Explicit

' Subroutine to analyze Macros and document them
Public Sub AnalyzeMacrosForObsidianVault()
    Dim txtFile As Object
    Dim filePath As String
    Dim macrosPath As String
    Dim fso As Object
    Dim overviewFile As Object
    Dim overviewPath As String
    Dim vaultPath As String
    
    On Error GoTo ErrorHandler
    
    ' Set up the FileSystemObject
    Debug.Print "Creating FileSystemObject"
    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso Is Nothing Then
        Debug.Print "Failed to create FileSystemObject"
        MsgBox "Failed to create FileSystemObject. Error: " & Err.Description, vbCritical
        Exit Sub
    End If
    Debug.Print "FileSystemObject created successfully"
    
    ' Create the vault folder and subfolders
    vaultPath = CurrentProject.Path & "\ObsidianVault"
    macrosPath = vaultPath & "\Macros"
    
    Debug.Print "Checking/creating vault folder: " & vaultPath
    If Not fso.FolderExists(vaultPath) Then
        fso.CreateFolder vaultPath
        If Err.Number <> 0 Then
            Debug.Print "Failed to create vault folder: " & vaultPath & ". Error: " & Err.Description
            MsgBox "Failed to create vault folder: " & vaultPath & ". Error: " & Err.Description, vbCritical
            Exit Sub
        End If
    End If
    
    Debug.Print "Checking/creating macros folder: " & macrosPath
    If Not fso.FolderExists(macrosPath) Then
        fso.CreateFolder macrosPath
        If Err.Number <> 0 Then
            Debug.Print "Failed to create macros folder: " & macrosPath & ". Error: " & Err.Description
            MsgBox "Failed to create macros folder: " & macrosPath & ". Error: " & Err.Description, vbCritical
            Exit Sub
        End If
    End If
    
    ' Set up the overview file
    overviewPath = vaultPath & "\Overview.md"
    Debug.Print "Creating overview file: " & overviewPath
    Set overviewFile = fso.CreateTextFile(overviewPath, True)
    If overviewFile Is Nothing Then
        Debug.Print "Failed to create Overview.md"
        MsgBox "Failed to create Overview.md. Error: " & Err.Description, vbCritical
        Exit Sub
    End If
    Debug.Print "Overview file created successfully"
    
    overviewFile.WriteLine "# Overview"
    overviewFile.WriteLine "Generated on: " & Now
    overviewFile.WriteLine "## Macros"
    
    ' --- Analyze Macros ---
    Dim macroVar As Object
    Dim macroCount As Long
    macroCount = 0
    For Each macroVar In CurrentProject.AllMacros
        macroCount = macroCount + 1
        Dim safeMacroName As String
        safeMacroName = SanitizeFileName(macroVar.name)
        filePath = macrosPath & "\" & safeMacroName & ".md"
        Debug.Print "Creating text file for macro: " & macroVar.name & " at " & filePath
        Set txtFile = fso.CreateTextFile(filePath, True)
        If txtFile Is Nothing Then
            Debug.Print "Failed to create file for macro: " & macroVar.name
            overviewFile.WriteLine "- [[Macros/" & safeMacroName & "]] (Error: Failed to create file - " & Err.Description & ")"
            Err.Clear
            GoTo NextMacro
        End If
        Debug.Print "Text file created successfully for macro: " & macroVar.name
        
        overviewFile.WriteLine "- [[Macros/" & safeMacroName & "]]"
        
        txtFile.WriteLine "# " & safeMacroName
        txtFile.WriteLine "Analysis generated on: " & Now
        txtFile.WriteLine "---"
        
        ' Export the macro to a temporary file in XML format
        On Error Resume Next
        Dim tempFilePath As String
        tempFilePath = fso.GetSpecialFolder(2) & "\" & macroVar.name & ".txt" ' Temporary folder
        Debug.Print "Exporting macro " & macroVar.name & " to " & tempFilePath
        Application.SaveAsText acMacro, macroVar.name, tempFilePath
        If Err.Number <> 0 Then
            txtFile.WriteLine "## Error"
            txtFile.WriteLine "- *Failed to export macro: " & Err.Description & "*"
            txtFile.Close
            Set txtFile = Nothing
            Err.Clear
            GoTo NextMacro
        End If
        
        ' Add a small delay to ensure the file is fully written
        Dim waitStart As Double
        waitStart = Timer
        Do While Timer - waitStart < 0.5 ' Wait 0.5 seconds
            DoEvents
        Loop
        
        ' Read the macro definition from the temporary file
        Dim macroText As String
        If fso.FileExists(tempFilePath) Then
            Dim tempFile As Object
            Debug.Print "Opening temporary file: " & tempFilePath
            Set tempFile = fso.OpenTextFile(tempFilePath, 1) ' 1 = ForReading
            If tempFile Is Nothing Then
                Debug.Print "Failed to open temporary file: " & tempFilePath
                macroText = "*Failed to open temporary file for reading*"
            Else
                macroText = tempFile.ReadAll
                Debug.Print "Read macro text from temp file for " & macroVar.name & ": Length=" & Len(macroText)
                tempFile.Close
                Set tempFile = Nothing
            End If
            ' Delete the temporary file
            fso.DeleteFile tempFilePath
            If Err.Number <> 0 Then
                Debug.Print "Failed to delete temporary file: " & tempFilePath & ". Error: " & Err.Description
                Err.Clear
            End If
        Else
            macroText = "*Failed to export macro: Temporary file not found*"
            Debug.Print "Temporary file not found for " & macroVar.name
        End If
        On Error GoTo ErrorHandler
        
        ' Parse the macro text to extract actions, arguments, and conditions
        txtFile.WriteLine "## Macro Definition"
        If InStr(1, macroText, "Failed", vbTextCompare) = 0 Then
            Dim macroDetails As Collection
            Set macroDetails = ParseMacroXML(macroText)
            
            If macroDetails.Count > 0 Then
                txtFile.WriteLine "| Action | Arguments | Condition |"
                txtFile.WriteLine "|--------|-----------|-----------|"
                Dim actionDetail As Variant
                For Each actionDetail In macroDetails
                    Dim actionLine As String
                    actionLine = "| " & actionDetail("Action") & " | "
                    actionLine = actionLine & IIf(Len(actionDetail("Arguments")) > 0, actionDetail("Arguments"), "-") & " | "
                    actionLine = actionLine & IIf(Len(actionDetail("Condition")) > 0, actionDetail("Condition"), "-") & " |"
                    txtFile.WriteLine actionLine
                Next actionDetail
                
                ' Add the "What it does" section
                txtFile.WriteLine "## What it does"
                For Each actionDetail In macroDetails
                    Dim actionDescription As String
                    Select Case LCase(actionDetail("Action"))
                        Case "copyobject"
                            actionDescription = "Copies an object (e.g., a table, query, or form) to a new name or location."
                        Case "setwarnings"
                            actionDescription = "Enables or disables system warnings (e.g., confirmation dialogs for actions)."
                        Case "openform"
                            actionDescription = "Opens a specified form in the database."
                        Case "close"
                            actionDescription = "Closes a specified object (e.g., a form, report, or query)."
                        Case "openquery"
                            actionDescription = "Runs a specified query in the database."
                        Case "openreport"
                            actionDescription = "Opens a specified report in the database."
                        Case Else
                            actionDescription = "Performs an action: " & actionDetail("Action") & "."
                    End Select
                    txtFile.WriteLine "- **" & actionDetail("Action") & "**: " & actionDescription
                    If Len(actionDetail("Arguments")) > 0 Then
                        txtFile.WriteLine "  - **Arguments**: " & actionDetail("Arguments")
                    End If
                    If Len(actionDetail("Condition")) > 0 Then
                        txtFile.WriteLine "  - **Condition**: " & actionDetail("Condition")
                    End If
                Next actionDetail
            Else
                txtFile.WriteLine "- *No actions found or failed to parse macro definition*"
                txtFile.WriteLine "## What it does"
                txtFile.WriteLine "- *No actions to describe due to parsing failure*"
            End If
        Else
            txtFile.WriteLine "- *Failed to export macro definition*"
            txtFile.WriteLine "## What it does"
            txtFile.WriteLine "- *No actions to describe due to export failure*"
        End If
        
        Debug.Print "Closing text file for macro: " & macroVar.name
        txtFile.Close
        Set txtFile = Nothing
NextMacro:
    Next macroVar
    
    ' If no macros were found, add a note to the overview
    If macroCount = 0 Then
        overviewFile.WriteLine "- *No macros found in the database*"
    End If
    
    ' Finalize and clean up
    Debug.Print "Closing overview file"
    overviewFile.WriteLine "---"
    overviewFile.WriteLine "## Analysis Complete"
    overviewFile.Close
    Set overviewFile = Nothing
    Set fso = Nothing
    
    MsgBox "Macro analysis complete. Files saved to: " & macrosPath, vbInformation
    Exit Sub

ErrorHandler:
    Debug.Print "Error in AnalyzeMacrosForObsidianVault: " & Err.Number & ": " & Err.Description & " at " & Now
    ' Ensure objects are properly closed and set to Nothing
    On Error Resume Next
    If Not txtFile Is Nothing Then
        Debug.Print "Closing txtFile in error handler"
        txtFile.Close
        Set txtFile = Nothing
    End If
    If Not overviewFile Is Nothing Then
        Debug.Print "Closing overviewFile in error handler"
        overviewFile.Close
        Set overviewFile = Nothing
    End If
    Set fso = Nothing
    On Error GoTo 0
    MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical
    Exit Sub
End Sub

' Helper function to sanitize filenames
Private Function SanitizeFileName(fileName As String) As String
    Dim invalidChars As String
    Dim i As Integer
    invalidChars = "\/:*?""<>|#" ' Added # to the list of invalid characters
    SanitizeFileName = fileName
    For i = 1 To Len(invalidChars)
        SanitizeFileName = Replace(SanitizeFileName, Mid(invalidChars, i, 1), "_")
    Next i
End Function

' Helper function to parse macro (legacy format) and extract actions, arguments, and conditions
Private Function ParseMacroXML(macroText As String) As Collection
    Dim actions As New Collection
    Dim lines() As String
    Dim i As Long
    Dim inActionBlock As Boolean
    Dim currentAction As String
    Dim currentArguments As String
    Dim currentCondition As String
    
    ' Split the macro text into lines
    lines = Split(macroText, vbCrLf)
    inActionBlock = False
    currentAction = ""
    currentArguments = ""
    currentCondition = ""
    
    Debug.Print "ParseMacroXML: Total lines in macro: " & UBound(lines) - LBound(lines) + 1
    
    For i = LBound(lines) To UBound(lines)
        Dim line As String
        line = Trim(lines(i))
        
        Debug.Print "ParseMacroXML: Processing line " & i & ": " & Left(line, 100) & IIf(Len(line) > 100, "...", "")
        
        ' Skip empty lines
        If Len(line) = 0 Then
            Debug.Print "ParseMacroXML: Skipping empty line " & i
            GoTo nextLine
        End If
        
        ' Check for the start of an action block
        If InStr(1, line, "Begin", vbTextCompare) > 0 Then
            Debug.Print "ParseMacroXML: Found start of action block on line " & i
            inActionBlock = True
            currentAction = ""
            currentArguments = ""
            currentCondition = ""
        ElseIf InStr(1, line, "End", vbTextCompare) > 0 And inActionBlock Then
            Debug.Print "ParseMacroXML: Found end of action block on line " & i
            If currentAction <> "" Then
                ' Save the current action
                Debug.Print "ParseMacroXML: Saving action: " & currentAction
                Dim actionDetail As Object
                Set actionDetail = CreateObject("Scripting.Dictionary")
                actionDetail("Action") = currentAction
                actionDetail("Arguments") = currentArguments
                actionDetail("Condition") = currentCondition
                actions.Add actionDetail
            End If
            inActionBlock = False
            currentAction = ""
            currentArguments = ""
            currentCondition = ""
        ElseIf inActionBlock Then
            ' Check for action, arguments, or conditions
            If InStr(1, line, "Action =", vbTextCompare) > 0 Then
                Debug.Print "ParseMacroXML: Found action on line " & i
                ' Extract the action name
                Dim startPos As Long
                Dim endPos As Long
                startPos = InStr(1, line, """") + 1
                endPos = InStrRev(line, """")
                If startPos > 1 And endPos > startPos Then
                    currentAction = Mid(line, startPos, endPos - startPos)
                    Debug.Print "ParseMacroXML: Action name extracted: " & currentAction
                Else
                    Debug.Print "ParseMacroXML: Failed to extract action name on line " & i
                    currentAction = "UnknownAction"
                End If
            ElseIf InStr(1, line, "Argument =", vbTextCompare) > 0 Then
                Debug.Print "ParseMacroXML: Found argument on line " & i
                ' Extract the argument value
                Dim argValue As String
                startPos = InStr(1, line, """") + 1
                endPos = InStrRev(line, """")
                If startPos > 1 And endPos > startPos Then
                    argValue = Mid(line, startPos, endPos - startPos)
                    currentArguments = currentArguments & IIf(currentArguments = "", "", "; ") & argValue
                    Debug.Print "ParseMacroXML: Argument extracted: " & argValue
                Else
                    Debug.Print "ParseMacroXML: Failed to extract argument on line " & i
                End If
            ElseIf InStr(1, line, "Condition =", vbTextCompare) > 0 Then
                Debug.Print "ParseMacroXML: Found condition on line " & i
                ' Extract the condition
                startPos = InStr(1, line, """") + 1
                endPos = InStrRev(line, """")
                If startPos > 1 And endPos > startPos Then
                    currentCondition = Mid(line, startPos, endPos - startPos)
                    Debug.Print "ParseMacroXML: Condition extracted: " & currentCondition
                Else
                    Debug.Print "ParseMacroXML: Failed to extract condition on line " & i
                End If
            End If
        End If
nextLine:
    Next i
    
    Debug.Print "ParseMacroXML: Total actions parsed: " & actions.Count
    Set ParseMacroXML = actions
End Function

What it does

No VBA code to document due to export failure