Conoscere il nome della routine attiva

di il
15 risposte

Conoscere il nome della routine attiva

Ciao a tutti, vorrei sapere se è possibile ricavare il nome della routine attiva, chiaramente dall'interno della stessa routine.

Mi servirebbe per tracciare il flusso di esecuzione di molte routine in un DB Access che dal 2014 si è "ingrassato" e contiene parecchio codice non più utilizzato, vedendo cosa attualmente è utile.

Grazie

15 Risposte

  • Re: Conoscere il nome della routine attiva

    Se è codice VBA per Access perché posti nella sezione VB6?

  • Re: Conoscere il nome della routine attiva

    25/04/2025 - oregon ha scritto:

    Se è codice VBA per Access perché posti nella sezione VB6?

    scusate se ho sbagliato ma nella descrizione del sub forums è descritto come :
    Visual Basic 6.0 - Forum di discussioni sul linguaggio Visual Basic 6.0, VBScript e VBA

  • Re: Conoscere il nome della routine attiva

    Giusto, ma dati che la questione era mirata al VBA di Access, era meglio quella sezione (che del testo hai già usato). Ma non importa.

    In realtà non c'è nulla che nativamente ti può essere utile, non è previsto un modo per farlo.

    Alla fine forse potresti inserire una linea all'inizio di ogni Sub/Function che chiami una funzione che scrive un log passando il nome della procedura scritta da te.

    Forse esiste qualche tool che può essere utilizzato (MZTool?l) ma avrai migliori risposte da @Alex

  • Re: Conoscere il nome della routine attiva

    25/04/2025 - darioV ha scritto:

    Mi servirebbe per tracciare il flusso di esecuzione di molte routine in un DB Access

    Ciao,

    puoi utilizzare la libreria Microsoft Visual Basic for Applications Extensibility 5.3

    Con essa puoi accedere ai moduli, routine, etc.. del VBA MsAccess, e quindi per esempio:

    • Realizzare una lista di moduli, sub, fuction,etc... etc..
    • Ogni volta che viene utilizzato un metodo, aggiornare la lista per esempio con un contatore e/o altro atto a definire se talune routine vengono richiamate o meno

    .
    Molto semplicee veloce da realizzare, anche in maniere del tutto automatica e dinamica.

  • Re: Conoscere il nome della routine attiva

    25/04/2025 - By65Franco ha scritto:

    Ogni volta che viene utilizzato un metodo, aggiornare la lista per esempio con un contatore e/o altro atto a definire se talune routine vengono richiamate o meno

    molto interessante, puoi darmi suggerimenti se c'è già qualche post da guardare per prendere spunto  e adattarlo alle mie esigenze?

  • Re: Conoscere il nome della routine attiva

    26/04/2025 - darioV ha scritto:

    molto interessante, puoi darmi suggerimenti se c'è già qualche post da guardare per prendere spunto  e adattarlo alle mie esigenze?

    Ciao, 

    ma se hai guardato Microsoft Visual Basic for Applications Extensibility 5.3 risulta semplice implementare il codice necessario allo scopo.

    Io prima di proporti di guardare tale libreria avevo già scritto il codice che sfrutta la libreira per assolvere quanto da te richiesto. 
    Una volta che ho visto che era una strada percorribile allora ti ho consigliato di prendere spunto da tale libreria.

    Adesso non so se sei in grado o meno di sviluppare e il grado di conoscenze che hai di VBA... 
    Se devo descriverti i vari passaggi perchè tu li possa replicare con seuccesso e non hai sufficienti conoscenze in merito al linguaggio, allora penso che si debba passare ad un semplice copia incolla.

    Fai sapere come vorresti procedere.

  • Re: Conoscere il nome della routine attiva

    Ok, nel frattempo che ci pensi, ti propongo questa traccia.

    Questa è una piccola analisi di come impostare ed eseguire un tracciamento per le routine invocate nel/dal progetto. 
    Solo un semplice esempio per far vedere una delle tante possibili soluzioni per tracciare tali eventi e analizzarli a proprio piacimento.
    Eventualmente implementare controlli e attività che possono essere ulteriormente eseguite.
    Si raccomanda di testare e "prova a provare" ;-)  se soddisfa le tue esigenze.

    ATTENZIONE !!!  prima di apportare le modifiche, eseguire sempre le copie di riserva/salvataggio/backup delprogetto. (mi raccomando)

    In Sintesi….

    Tracing of the invoked routines :

    1. Si crea un modulo code di nome MyTraceDataAnalysis per inizializzare e impostare la fase di tracciamento e analisi
    2. Si imposta nel progetto  il riferimento alla libreria:
      1. Microsoft Visual Basic for Applications Extensibility 5.3
    3. Per iniziare il tracciamento si richiama la Sub MyTableDataTrace
      1. Per ogni routine in tutti i moduli VBA, viene scritta (aggiunta) una nuova riga di codice subito dopo la dichiarazione delle varie Sub e Function, atta al tracciamento delle routine invocate durante l’esecuzione del progetto
    4. Eseguire il progetto in tutte le sue parti, se necessario anche per alcuni giorni
      1. In questa fase viene implementato il tracciamento per tutte le routine che verranno invocate
    5. A fine della fase 4. eseguire l’analisi del tracciamento
      1. Tramite delle query, report, etc… che possono essere create a proprio piacimento interrogando la tabella MyTableDataTrace
    6. Ripristino codice VBA del progetto
      1. Al termine della propria analisi sarà possibile richiamare la MyRemoveUpdateTraceCalls  per ripristinare il codice VBA originale senza l’esecuzione del tracciamento

    .
    Analisi Dettagliata :

    MyTableDataTrace

    • Inizializzazione Trace :
      • Elimina e ricrea la tabella di trace MyTableTrace
      • Legge tutti i moduli e routine presenti nel VBA
      • Inserisce nella tabella di trace tutte le routine presenti nel VBA
      • Crea in una collection la lista con tutti i moduli e routine da tracciare

    .
    MyUpdateProceduresWithTrace

    • Viene richiamata dalla Sub MyTableDataTrace :
      • Legge tutta la trace collection
      • Inserisce in ogni routine il richiamo di MyUpdateTraceNumber per il tracciamento

    .
    MySaveAndCloseObgjFormAndReport

    • Viene richiamata alla fine della Sub MyTableDataTrace :
      • Salva e Chiude tutte le finestre di progettazione

    .
    A questo punto troviamo in tutte le routine del progetto, il richiamo della Sub MyUpdateTraceNumber che traccerà quante volte la routine viene invocata.

    MyUpdateTraceNumber

    • Aggiorna la tabella di trace MyTableTrace incrementato il contatore di utilizzo per ogni routine invocata nel progetto.

    .
    Esempio di come vengono modificate le routine presenti nei vari moduli del progetto: (evidenziato in giallo la riga di codice che viene aggiunta nelle varie routine)

    .
    Analisi tabella di trace MyTableTrace

    • Eseguire una query sulla tabella
      • È possibile determinare le routine che non vengono utilizzate, selezionando solo i records dove “TraceNumber” risulta essere = 0
      • ESEMPIO Tabella tracciamento :

    La query per esempio può essere impostata :

    In questo caso si elencano tutte le routine non ancora richiamate in fase di esecuzione del progetto. Vedere la colonna TraceNumber come illustrato nell'analisi

    .
    MyRemoveUpdateTraceCalls

    • Al termine dell’anali può essere richiamata questa routine che permette di rimuovere da tutte le routine del progetto, la call di tracciamento MyUpdateTraceNumber

    .

    Infine....

    Questo il Codice di esempio: (creare il Modulo MyTraceDataAnalysis ed inserire il codice)

    Ho cercato di commentare le righe di codice il più possibile per una migliore comprensione. 

    Prova a provare ;-) e fai sapere se fa al caso tuo.

    Option Compare Database
    Option Explicit
    
    ' Inizialize trace const string - VBA code modules to be excluded from Trace
    Public Const modCodeTrace As String = "MyTraceDataAnalysis"
    
    
    ' INITIALIZE NEW TRACE TABLE
    Sub MyTableDataTrace()
        ' Set reference VBIDE
        Dim vbComp As VBIDE.VBComponent
        Dim vbModule As VBIDE.codeModule
        Dim vbKind As VBIDE.vbext_ProcKind
        Dim vbModuleName As String
        Dim vbTotalLineModule As Long
        
        ' Set procedure variables
        Dim procedureName As String
        Dim procedureType As String
        Dim procedureAccess As String
        Dim procedureTraceRoutine As String
        
        ' Set count variables
        Dim i As Long
        Dim countLine As Long
        Dim startLine As Long
        Dim numberLine As Long
        Dim procLine As String
        Dim procLCaseLine As String
    
        ' Array to store procedure data for later update
        Dim proceduresToUpdate As Collection
        Set proceduresToUpdate = New Collection
    
        ' Set error handler
        On Error GoTo ErrorHandler
        
        ' set ado current db
        Dim db As DAO.Database
        Set db = CurrentDb
        ' Check if the table exists and remove
        If DCount("*", "MSysObjects", "Name='MyTableTrace' AND Type=1") > 0 Then db.Execute "DROP TABLE MyTableTrace"
        ' Create trace table
        db.Execute "CREATE TABLE MyTableTrace (TraceID AUTOINCREMENT PRIMARY KEY, TraceModule TEXT(255), TraceRoutine TEXT(255), TraceNumber LONG)"
        
        ' Read all module
        For Each vbComp In Application.VBE.ActiveVBProject.VBComponents
            ' Retrieve module name
            vbModuleName = vbComp.Name
            ' Retrieve total line number in the module
            Set vbModule = vbComp.codeModule
            vbTotalLineModule = vbModule.CountOfLines
            
            ' Skip the MyTraceDataAnalysis module and form
            If vbModuleName <> modCodeTrace Then
            
                countLine = 1
                ' Read module line
                Do While countLine <= vbTotalLineModule
                    procedureName = vbModule.ProcOfLine(countLine, vbKind)
                    
                    ' Check and normalize procedure name and type
                    If procedureName <> "" Then
                        ' Retrieve starting line and length
                        startLine = vbModule.procStartLine(procedureName, vbKind)
                        numberLine = vbModule.ProcCountLines(procedureName, vbKind)
                        
                        ' Scan until we find the first non empty, non comment line
                        procLine = ""
                        For i = 0 To numberLine - 1
                            procLCaseLine = LCase(Trim(vbModule.Lines(startLine + i, 1)))
                            If procLCaseLine <> "" And Left(procLCaseLine, 1) <> "'" Then
                                procLine = procLCaseLine
                                Exit For
                            End If
                        Next i
                        ' Normalize access type
                        If InStr(procLine, "public") > 0 Then
                            procedureAccess = "Public"
                        ElseIf InStr(procLine, "private") > 0 Then
                            procedureAccess = "Private"
                        Else
                            procedureAccess = ""
                        End If
                        ' Normalize procedure type
                        If InStr(procLine, "sub") > 0 Then
                            procedureType = "Sub"
                        ElseIf InStr(procLine, "function") > 0 Then
                            procedureType = "Function"
                        ElseIf InStr(procLine, "property") > 0 Then
                            procedureType = "Property"
                        Else
                            procedureType = "Unknown"
                        End If
                        
                        ' Retrieve full procedure description
                        procedureTraceRoutine = IIf(procedureAccess <> "", procedureAccess & " ", "") & procedureType & " " & procedureName
                        ' Insert into table
                        db.Execute "INSERT INTO MyTableTrace (TraceModule, TraceRoutine, TraceNumber) " & _
                                   "VALUES ('" & vbModuleName & "', '" & procedureTraceRoutine & "', 0)"
                        ' Add procedure info to collection for later update
                        proceduresToUpdate.Add Array(procedureTraceRoutine, vbModuleName, procedureName)
                        
                        'Increase line count
                        countLine = startLine + numberLine
                    Else
                        countLine = countLine + 1
                    End If
                Loop
            End If
        Next vbComp
        
        ' Insert the MyUpdateTraceNumber Sub line for each procedure
        Call MyUpdateProceduresWithTrace(proceduresToUpdate)
        
        ' Close connection
        Set db = Nothing
        ' Message show
        MsgBox "Initialization of the completed routine Trace", vbInformation, "Info"
        'Exit sub
        Exit Sub
        
    ' Error handler display
    ErrorHandler:
        MsgBox "Errore: " & Err.Description, vbCritical
        ' Check connection is closed
        If Not db Is Nothing Then Set db = Nothing
    End Sub
    
    
    ' INSERT NEW COMMAND LINE PROCEDURE TRACE AND SAVE/EXIT MODULES
    Sub MyUpdateProceduresWithTrace(procedures As Collection)
        Dim procData As Variant
        Dim procedureTraceRoutine As String
        Dim vbModuleName As String
        Dim procedureName As String
        Dim vbModule As VBIDE.codeModule
    
        ' Read all procedures and insert new command line
        For Each procData In procedures
            ' retrieve collection values
            procedureTraceRoutine = procData(0)
            vbModuleName = procData(1)
            procedureName = procData(2)
    
            ' Set module
            Set vbModule = Application.VBE.ActiveVBProject.VBComponents(vbModuleName).codeModule
            
            ' Search module and insert newline
            Dim i As Long
            For i = 1 To vbModule.CountOfLines
                If Left(Trim(vbModule.Lines(i, 1)), Len(procedureTraceRoutine)) = procedureTraceRoutine Then
                    ' Insert the MyUpdateTraceNumber call right after the routine declaration
                    vbModule.InsertLines i + 1, "    MyUpdateTraceNumber """ & procedureTraceRoutine & """, """ & vbModuleName & """"
                    ' Exit for
                    Exit For
                End If
            Next i
        Next procData
    
        ' Save and close all objects
        MySaveAndCloseObgjFormAndReport
    
    End Sub
    
    
    'SAVE AND CLOSE ALL OBJECTS FORMS AND REPORTS
    Sub MySaveAndCloseObgjFormAndReport()
        ' Set object db application
        Dim obj As AccessObject
        Dim db As Object
        Set db = Application.CurrentProject
        ' Save and Close all forms objects
        For Each obj In db.AllForms
            If obj.IsLoaded Then
                ' Check if open structure
                If Forms(obj.Name).CurrentView = 0 Then
                    ' Save and close
                    DoCmd.Save acForm, obj.Name
                    DoCmd.Close acForm, obj.Name
                End If
            End If
        Next obj
        ' Save and Close all reports objects
        For Each obj In db.AllReports
            If obj.IsLoaded Then
                ' Check if open structure
                If Reports(obj.Name).CurrentView = 0 Then
                    ' Save and close
                    DoCmd.Save acReport, obj.Name
                    DoCmd.Close acReport, obj.Name
                End If
            End If
        Next obj
        ' Close connection
        Set db = Nothing
    End Sub
    
    
    ' UPDATE COUNTER INVOKE PROCEDURE
    Sub MyUpdateTraceNumber(procedureName As String, traceModule As String)
        On Error Resume Next
        Dim db As DAO.Database
        Set db = CurrentDb
        ' Increase TraceNumber
        db.Execute "UPDATE MyTableTrace SET TraceNumber = TraceNumber + 1 " & _
                   "WHERE TraceModule = '" & traceModule & "' AND TraceRoutine = '" & procedureName & "'"
        ' Close
        Set db = Nothing
    End Sub
    
    
    ' REMOVE ALL TRACE CALLS INTO ROUTINES
    Sub MyRemoveUpdateTraceCalls()
        Dim vbComp As VBIDE.VBComponent
        Dim vbModule As VBIDE.codeModule
        Dim i As Long
        Dim totalLines As Long
        Dim currentLine As String
        
        ' Read all modules in the project
        For Each vbComp In Application.VBE.ActiveVBProject.VBComponents
            ' Skip the MyTraceDataAnalysis module
            If vbComp.Name <> modCodeTrace Then
                ' Only process if the component has code
                If vbComp.Type = vbext_ct_StdModule Or _
                   vbComp.Type = vbext_ct_ClassModule Or _
                   vbComp.Type = vbext_ct_MSForm Or _
                   vbComp.Type = vbext_ct_Document Then
                    
                    ' Set module obj
                    Set vbModule = vbComp.codeModule
                    totalLines = vbModule.CountOfLines
                    
                    ' Read and search from bottom to top
                    For i = totalLines To 1 Step -1
                        currentLine = vbModule.Lines(i, 1)
                        ' Check if the line contains MyUpdateTraceNumber
                        If InStr(1, currentLine, "MyUpdateTraceNumber", vbTextCompare) > 0 Then
                            ' Delete line
                            vbModule.DeleteLines i
                        End If
                    Next i
                End If
            End If
        Next vbComp
        
        ' Save and close all objects
        MySaveAndCloseObgjFormAndReport
        ' Message show
        MsgBox "Removed all Trace activities in the VBA code", vbInformation, "Info"
    End Sub
    

    .
    Chiedo venia in quanto l'ho buttato giù un pò velocemente e spero sia comprensibile e privo di errori marchiani ;-)) ma comunque si parla di un codice molto molto banale e semplice e di facile realizzazione... pertanto si raccomanda di fare i dovuti test e validazioni del caso.

     
    In sintesi è venuto fuori un post un pò lungo, ma da leggere attentamente e approfondire metodi e tecniche che possono essere implementate, migliorate, etc....
    Del resto non saprei come meglio descrivere un processo di questo tipo, ma sono a completa disposizioni per eventuali spiegazioni, approfondimenti, etc...

  • Re: Conoscere il nome della routine attiva

    Ciao, 

    Come ulteriore spunto ho rifinito la mia demo con una form dove gestire :

    • Display attuale stato di tracciamento (se attivo oppure no)
    • Avvio / Inizializzazione del tracciamento routine invoke (aggiunge una nuova riga di codice su tutte le routine vba del progetto)
    • Analisi del tracciamento (visualizza il risultato di una query sulla tabella di tracciamento)
    • Rimozione del tracciamento (rimuove tutte le righe di codice aggiunto alle routine per eseguire il tracciamento)

    Nel codice della form ho inserito il metodo per testare se il Trace delle routine è già attivo oppure no. 
    Questo evita di rilanciare i metodi sopra descritti quando non serve....

    Per esempio il codice della form è:

    Option Compare Database
    Option Explicit
    
    ' LOAD FORM
    Private Sub Form_Load()
        ' Set label trace status
        MySetLabelStatusTrace
    End Sub
    
    ' START TRACE
    Private Sub ButtonStartTrace_Click()
        ' Check if Trace activated
        If MyCheckTrace Then
            MsgBox "Trace already running"
        Else
            MyTableDataTrace
        End If
    
        ' Set label trace status
        MySetLabelStatusTrace
    End Sub
    
    ' TRACE ANALYSIS
    Private Sub ButtonTraceAnalysis_Click()
        DoCmd.OpenQuery "QueryMyTrace"
    End Sub
    
    ' REMOVE TRACE
    Private Sub ButtonRemoveTrace_Click()
        ' Check if Trace activated
        If Not MyCheckTrace Then
            MsgBox "Trace is not currently running"
        Else
            MyRemoveUpdateTraceCalls
        End If
    
        ' Set label trace status
        MySetLabelStatusTrace
    End Sub
    
    ' SET LABEL TRACE STATUS
    Private Sub MySetLabelStatusTrace()
        ' Check if trace activated
        If MyCheckTrace Then
            Me.LabelTraceStatus.Caption = "Trace in Execution"
            Me.LabelTraceStatus.ForeColor = vbRed
            Me.LabelTraceStatus.BorderColor = vbRed
        Else
            Me.LabelTraceStatus.Caption = "Not Active Trace"
            Me.LabelTraceStatus.ForeColor = vbBlue
            Me.LabelTraceStatus.BorderColor = vbBlue
        End If
        
        ' Load trace summary info
        LoadTraceSummaryInfo
    End Sub
    
    ' CHECK TRACE IF EXISTS EXCLUDING COMMENTS AND ONLY AT LINE START
    Private Function MyCheckTrace() As Boolean
        Dim vbComp As VBIDE.VBComponent
        Dim vbModule As VBIDE.codeModule
        Dim i As Long
        Dim totalLines As Long
        Dim currentLine As String
        Dim trimmedLine As String
        
        ' Default return no trace calls
        MyCheckTrace = False
        
        ' Loop through all components in the project
        For Each vbComp In Application.VBE.ActiveVBProject.VBComponents
            ' Only consider Forms and Reports
            If vbComp.Type = vbext_ct_MSForm Or vbComp.Type = vbext_ct_Document Then
                ' Skip if it is the MyTraceDataAnalysis module or the current form module
                If vbComp.Name <> modCodeTrace And vbComp.Name <> modFormTrace Then
                    Set vbModule = vbComp.codeModule
                    totalLines = vbModule.CountOfLines
                    
                    ' Search lines
                    For i = 1 To totalLines
                        currentLine = vbModule.Lines(i, 1)
                        trimmedLine = LTrim(currentLine) ' remove leading spaces
                        
                        ' Skip empty lines or comment lines
                        If Len(trimmedLine) > 0 Then
                            If Left(trimmedLine, 1) <> "'" Then
                                If Left(trimmedLine, Len("MyUpdateTraceNumber")) = "MyUpdateTraceNumber" Then
                                    ' Return function value and exit
                                    MyCheckTrace = True
                                    Exit Function
                                End If
                            End If
                        End If
                    Next i
                End If
            End If
        Next vbComp
    End Function
    
    ' LOAD TRACE SUMMARY INFO
    Private Sub LoadTraceSummaryInfo()
        Dim db As DAO.Database
        Dim rst As DAO.Recordset
        Dim totalModules As Long
        Dim totalRoutines As Long
        Dim totalTraceNumber As Long
        Dim totalUntraced As Long
        
        On Error GoTo errorsExit
    
        ' Set db
        Set db = CurrentDb
    
        ' Calculate total module number
        Set rst = db.OpenRecordset("SELECT Count(*) AS totalCount FROM (SELECT DISTINCT TraceModule FROM MyTableTrace)")
        If Not rst.EOF Then totalModules = Nz(rst!totalCount, 0)
        rst.Close
    
        ' Calculate total routine number
        Set rst = db.OpenRecordset("SELECT Count(*) AS totalCount FROM MyTableTrace")
        If Not rst.EOF Then totalRoutines = Nz(rst!totalCount, 0)
        rst.Close
    
        ' Calculate total trace number sum
        Set rst = db.OpenRecordset("SELECT Sum(TraceNumber) AS totalCount FROM MyTableTrace")
        If Not rst.EOF Then totalTraceNumber = Nz(rst!totalCount, 0)
        rst.Close
    
        ' Calculate total untraced
        Set rst = db.OpenRecordset("SELECT Count(*) AS totalCount FROM MyTableTrace WHERE TraceNumber = 0")
        If Not rst.EOF Then totalUntraced = Nz(rst!totalCount, 0)
        rst.Close
    
    errorsExit:
        ' Close
        Set rst = Nothing
        Set db = Nothing
        
        ' Set label info trace
        Me.LabelInfo1.Caption = "Total Trace number :  " & Format(totalTraceNumber, "#,##0")
        Me.LabelInfo2.Caption = "Total Module number :  " & Format(totalModules, "#,##0")
        Me.LabelInfo3.Caption = "Total Routine number :  " & Format(totalRoutines, "#,##0")
        Me.LabelInfo4.Caption = "Total Number of Untraced Routines :  " & Format(totalUntraced, "#,##0")
    End Sub
    
    

    In questo caso è necessario modificare il codice del modulo MyTraceDataAnalysis in questo modo:

    Option Compare Database
    Option Explicit
    
    ' Inizialize trace const string - VBA code modules to be excluded from Trace
    Public Const modCodeTrace As String = "MyTraceDataAnalysis"
    Public Const modFormTrace As String = "Form_FormTraceAllRoutineInvoke"
    
    ' INITIALIZE NEW TRACE TABLE
    Sub MyTableDataTrace()
        ' Set reference VBIDE
        Dim vbComp As VBIDE.VBComponent
        Dim vbModule As VBIDE.codeModule
        Dim vbKind As VBIDE.vbext_ProcKind
        Dim vbModuleName As String
        Dim vbTotalLineModule As Long
        
        ' Set procedure variables
        Dim procedureName As String
        Dim procedureType As String
        Dim procedureAccess As String
        Dim procedureTraceRoutine As String
        
        ' Set count variables
        Dim i As Long
        Dim countLine As Long
        Dim startLine As Long
        Dim numberLine As Long
        Dim procLine As String
        Dim procLCaseLine As String
    
        ' Array to store procedure data for later update
        Dim proceduresToUpdate As Collection
        Set proceduresToUpdate = New Collection
    
        ' Set error handler
        On Error GoTo ErrorHandler
        
        ' set ado current db
        Dim db As DAO.Database
        Set db = CurrentDb
        ' Check if the table exists and remove
        If DCount("*", "MSysObjects", "Name='MyTableTrace' AND Type=1") > 0 Then db.Execute "DROP TABLE MyTableTrace"
        ' Create trace table
        db.Execute "CREATE TABLE MyTableTrace (TraceID AUTOINCREMENT PRIMARY KEY, TraceModule TEXT(255), TraceRoutine TEXT(255), TraceNumber LONG)"
        
        ' Read all module
        For Each vbComp In Application.VBE.ActiveVBProject.VBComponents
            ' Retrieve module name
            vbModuleName = vbComp.Name
            ' Retrieve total line number in the module
            Set vbModule = vbComp.codeModule
            vbTotalLineModule = vbModule.CountOfLines
            
            ' Skip the MyTraceDataAnalysis module and form
            If vbModuleName <> modCodeTrace And vbModuleName <> modFormTrace Then
            
                countLine = 1
                ' Read module line
                Do While countLine <= vbTotalLineModule
                    procedureName = vbModule.ProcOfLine(countLine, vbKind)
                    
                    ' Check and normalize procedure name and type
                    If procedureName <> "" Then
                        ' Retrieve starting line and length
                        startLine = vbModule.procStartLine(procedureName, vbKind)
                        numberLine = vbModule.ProcCountLines(procedureName, vbKind)
                        
                        ' Scan until we find the first non empty, non comment line
                        procLine = ""
                        For i = 0 To numberLine - 1
                            procLCaseLine = LCase(Trim(vbModule.Lines(startLine + i, 1)))
                            If procLCaseLine <> "" And Left(procLCaseLine, 1) <> "'" Then
                                procLine = procLCaseLine
                                Exit For
                            End If
                        Next i
                        ' Normalize access type
                        If InStr(procLine, "public") > 0 Then
                            procedureAccess = "Public"
                        ElseIf InStr(procLine, "private") > 0 Then
                            procedureAccess = "Private"
                        Else
                            procedureAccess = ""
                        End If
                        ' Normalize procedure type
                        If InStr(procLine, "sub") > 0 Then
                            procedureType = "Sub"
                        ElseIf InStr(procLine, "function") > 0 Then
                            procedureType = "Function"
                        ElseIf InStr(procLine, "property") > 0 Then
                            procedureType = "Property"
                        Else
                            procedureType = "Unknown"
                        End If
                        
                        ' Retrieve full procedure description
                        procedureTraceRoutine = IIf(procedureAccess <> "", procedureAccess & " ", "") & procedureType & " " & procedureName
                        ' Insert into table
                        db.Execute "INSERT INTO MyTableTrace (TraceModule, TraceRoutine, TraceNumber) " & _
                                   "VALUES ('" & vbModuleName & "', '" & procedureTraceRoutine & "', 0)"
                        ' Add procedure info to collection for later update
                        proceduresToUpdate.Add Array(procedureTraceRoutine, vbModuleName, procedureName)
                        
                        'Increase line count
                        countLine = startLine + numberLine
                    Else
                        countLine = countLine + 1
                    End If
                Loop
            End If
        Next vbComp
        
        ' Insert the MyUpdateTraceNumber Sub line for each procedure
        Call MyUpdateProceduresWithTrace(proceduresToUpdate)
        
        ' Close connection
        Set db = Nothing
        ' Message show
        MsgBox "Initialization of the completed routine Trace", vbInformation, "Info"
        'Exit sub
        Exit Sub
        
    ' Error handler display
    ErrorHandler:
        MsgBox "Errore: " & Err.Description, vbCritical
        ' Check connection is closed
        If Not db Is Nothing Then Set db = Nothing
    End Sub
    
    
    ' INSERT NEW COMMAND LINE PROCEDURE TRACE AND SAVE/EXIT MODULES
    Sub MyUpdateProceduresWithTrace(procedures As Collection)
        Dim procData As Variant
        Dim procedureTraceRoutine As String
        Dim vbModuleName As String
        Dim procedureName As String
        Dim vbModule As VBIDE.codeModule
    
        ' Read all procedures and insert new command line
        For Each procData In procedures
            ' retrieve collection values
            procedureTraceRoutine = procData(0)
            vbModuleName = procData(1)
            procedureName = procData(2)
    
            ' Set module
            Set vbModule = Application.VBE.ActiveVBProject.VBComponents(vbModuleName).codeModule
            
            ' Search module and insert newline
            Dim i As Long
            For i = 1 To vbModule.CountOfLines
                If Left(Trim(vbModule.Lines(i, 1)), Len(procedureTraceRoutine)) = procedureTraceRoutine Then
                    ' Insert the MyUpdateTraceNumber call right after the routine declaration
                    vbModule.InsertLines i + 1, "    MyUpdateTraceNumber """ & procedureTraceRoutine & """, """ & vbModuleName & """"
                    ' Exit for
                    Exit For
                End If
            Next i
        Next procData
    
        ' Save and close all objects
        MySaveAndCloseObgjFormAndReport
    
    End Sub
    
    
    'SAVE AND CLOSE ALL OBJECTS FORMS AND REPORTS
    Sub MySaveAndCloseObgjFormAndReport()
        ' Set object db application
        Dim obj As AccessObject
        Dim db As Object
        Set db = Application.CurrentProject
        ' Save and Close all forms objects
        For Each obj In db.AllForms
            If obj.IsLoaded Then
                ' Check if open structure
                If Forms(obj.Name).CurrentView = 0 Then
                    ' Save and close
                    DoCmd.Save acForm, obj.Name
                    DoCmd.Close acForm, obj.Name
                End If
            End If
        Next obj
        ' Save and Close all reports objects
        For Each obj In db.AllReports
            If obj.IsLoaded Then
                ' Check if open structure
                If Reports(obj.Name).CurrentView = 0 Then
                    ' Save and close
                    DoCmd.Save acReport, obj.Name
                    DoCmd.Close acReport, obj.Name
                End If
            End If
        Next obj
        ' Close connection
        Set db = Nothing
    End Sub
    
    
    ' UPDATE COUNTER INVOKE PROCEDURE
    Sub MyUpdateTraceNumber(procedureName As String, traceModule As String)
        On Error Resume Next
        Dim db As DAO.Database
        Set db = CurrentDb
        ' Increase TraceNumber
        db.Execute "UPDATE MyTableTrace SET TraceNumber = TraceNumber + 1 " & _
                   "WHERE TraceModule = '" & traceModule & "' AND TraceRoutine = '" & procedureName & "'"
        ' Close
        Set db = Nothing
    End Sub
    
    
    ' REMOVE ALL TRACE CALLS INTO ROUTINES
    Sub MyRemoveUpdateTraceCalls()
        Dim vbComp As VBIDE.VBComponent
        Dim vbModule As VBIDE.codeModule
        Dim i As Long
        Dim totalLines As Long
        Dim currentLine As String
        
        ' Read all modules in the project
        For Each vbComp In Application.VBE.ActiveVBProject.VBComponents
            ' Skip the MyTraceDataAnalysis module
            If vbComp.Name <> modCodeTrace And vbComp.Name <> modFormTrace Then
                ' Only process if the component has code
                If vbComp.Type = vbext_ct_StdModule Or _
                   vbComp.Type = vbext_ct_ClassModule Or _
                   vbComp.Type = vbext_ct_MSForm Or _
                   vbComp.Type = vbext_ct_Document Then
                    
                    ' Set module obj
                    Set vbModule = vbComp.codeModule
                    totalLines = vbModule.CountOfLines
                    
                    ' Read and search from bottom to top
                    For i = totalLines To 1 Step -1
                        currentLine = vbModule.Lines(i, 1)
                        ' Check if the line contains MyUpdateTraceNumber
                        If InStr(1, currentLine, "MyUpdateTraceNumber", vbTextCompare) > 0 Then
                            ' Delete line
                            vbModule.DeleteLines i
                        End If
                    Next i
                End If
            End If
        Next vbComp
        
        ' Save and close all objects
        MySaveAndCloseObgjFormAndReport
        ' Message show
        MsgBox "Removed all Trace activities in the VBA code", vbInformation, "Info"
    End Sub
    

    .
    Il codice è stato aggiornato nelle parti in cui è necessario escludere il modulo di questa form di gestione Trace dai vari cicli di  lettura dei moduli Vba da analizzare/modificare/rimuovere.
    Altrimenti vale la versione rilasciata in precedenza e in quel caso si eseguono le varie attività lanciandole manualmente.

  • Re: Conoscere il nome della routine attiva

    Alla faccia di qualche suggerimento!  Mi hai servito antipasto, primo , secondo , contorno, frutta, dolce, caffè e ammazzacaffè!

    Martedì mi metterò a guardare bene tutto quello che mi hai dato per vedere se servono adattamenti e utilizzarlo

    Per il momento grazie

  • Re: Conoscere il nome della routine attiva

    27/04/2025 - darioV ha scritto:

    Martedì mi metterò a guardare bene tutto quello che mi hai dato per vedere se servono adattamenti e utilizzarlo

    Ciao, mi son divertito a farlo... no problem ;-)     (più tempo per scrivere la documentazione che il codice e relativi test)

    Metto a disposizione un database di demo https://1drv.ms/u/c/46aacde0762d4e68/EX3oPhJSsLxPuM3-tU6_AEEBBZ2SbNbjxo3pQoa1plVExQ?e=PJcRy2
    che puoi scaricare  in modo tu possa avere un riscontro immediato prima di modificare il tuo progetto.
    In questa Demo puoi fare tutte le modifiche e i test che ritieni opportuno prima di instarlarlo nel tuo database e magari rischiare di rovinare qualcosa.

    Una volta scaricata la Demo e dopo aver estratto il Database dal file Zip, ricordarsi di verificare nelle proprietà del file se l'opzione "Annulla Blocco" è attiva.
    In tal caso porre il  "Flag" , premere "Applica" e premere "OK":

    Rimuovere il Blocco

    Avviare il Database

    Installare la demo in una qualsiasi cartella a proprio piacimento

    1. All'avvio della demo si apre la Form Main dove si trovano :
      1. Buttons per avviare delle Forms e Reports
      2. Button Management Trace Analysis
    2. Selezionare il Button Management Trace Analysis per accedere alla Form

    • Button Start Trace - per attivare l'attività di tracciamento
    • Button Trace Analysis - per visualizzare una query per analizzare l'andamento e i risultati del tracciamento
    • Button Remove Trace - per rimuove il tracciamento e ripristinare il codice Vba alle condizioni originali

    .
    Start Trace :
    Quando si esegue questa funzione viene creata una nuova riga all'interno di ogni routine che permetterà il tracciamento 

    Prima del Tracciamento

    Durante il Tracciamento... evidenziato in giallo le righe di codice aggiunte nelle varie routine che verranno tracciate

    Remove Trace :
    Quando si esegue questa funzione le righe di codice aggiunte alle varie  routine, viene rimossa e il tracciamento viene interrotto

    Trace Analysis :
    Quando si esegue questa funzione viene aperta una query per analizzare il tracciamento.
    Su questa sarà possibile impostare i filtri e/o i criteri per selezionare i records desiderati.

    Esempio:

    Esempio dopo o durante il tracciamento delle routine richiamate dal progetto:

    • Aprire e chiudere le varie Form presenti nella demo in modo che le routine possono essere tracciate
    • Nella colonna TraceNumber viene riportato il numero di volte che le varie routine sono state richiamate
      Le routine che hanno valore = 0 significa che non sono state ancora mai richiamate 

    [Note]

    • Quando si esegue il "Remove Trace", i dati di tracciamento sono sempre visibili e disponibili.
    • Il tracciamento si azzera al successivo riavvio del Trace "Start Trace".
    • Il Database può essere chiuso e riaperto tutte le volte che si vuole e se il tracciamento è attivo rimarrà attivo fino a quando non viene rimosso.
    • Per visualizzare/verificare se il tracciamento è attivo oppure no, sarà sufficiente aprire la Form "Management Trace Analysis" e  leggere nell'etichetta "Status Trace" l'attuale status.

    .
    Installazione delle funzioni nel proprio database
    Per esequire il tracciamento nel proprio database sarà necessario importare alcuni oggetti ed eseguire alcune azioni preliminari:

    1. Eseguire copie di riserva/backup del proprio progetto prima di proseguire.
    2. Inserire nei riferimenti del progetto la libreria "Microsoft Visual Basic for Applications Extensibility 5.3"
    3. Importare il modulo di codice : MyTraceDataAnalysis
    4. Importare la query : QueryMyTrace
    5. Importare la Form : FormSearch
    6. Non è necessario importare la Tabella MyTableTrace di tracciamento in quando verrà creata in automatico al primo avvio della funzione di tracciamento

    .
    Avvio tracciamento
    Per richiamare le funzioni di tracciamento eseguire la Form FormSearch e seguire le istruzioni come descritto per la Demo di cui sopra.

    .
    Mi sembra che ci sia più o meno tutto... se hai bisogno di ulteriori istruzioni e/o chiarimenti, chiedi pure e ti sarà dato ....
    Prova a provare ;-)  e vedi se può andare bene al tuo scopo.

  • Re: Conoscere il nome della routine attiva

    Ciao, 
    Per chiudere l'analisi del precedente post, non so se ci hai fatto caso... nella Demo, dopo aver utilizzato tutte le form, report e funzioni varie, troviamo (volutamente) due routine che non vengono richiamate e pertanto risultano "Inutilizzate".
    Infatti ho inserito volutamente queste due routine che non hanno niente a che fare all'interno del Database e sono del tutto inutili. 

    Troviamo una Function nel modulo di una form e una Sub in un modulo code che non vengono mai richiamate...

    Esempio dell'analisi Trace: queste due routine, nella query di analisi tracciamento, le troviamo con valore = 0 nella colonna "TraceNumber" :

    Questo è il risultato finale del tracciamento che ha lo scopo di individuare quale routine sono in disuso e/o in eccesso all'interno del proprio progetto e abbiamo:

    • In quale modulo del codice Vba si trovano
    • Il nome e il tipo di routine
  • Re: Conoscere il nome della routine attiva

    Ciao,

    Attenzione!!! Riscaricare la nuova versione della Demo dove ho sistemato alcuni controlli e altre piccole cose...

    Si può scaricare anche da questo link la nuova versione senza tornare nei post precedenti a ricercarla:
    https://1drv.ms/u/c/46aacde0762d4e68/EX3oPhJSsLxPuM3-tU6_AEEBBZ2SbNbjxo3pQoa1plVExQ?e=PJcRy2

  • Re: Conoscere il nome della routine attiva

    26/04/2025 - By65Franco ha scritto:

    Solo un semplice esempio

    Ah... XD

  • Re: Conoscere il nome della routine attiva

    28/04/2025 - Sgrubak ha scritto:

    26/04/2025 - By65Franco ha scritto:

    Solo un semplice esempio

    Ah... XD

    Daiiii... è semplice ;-))  ... purtroppo spiegarlo solo a parole sarebbe stato, anche se il processo è semplice, molto faticoso e lungoooooo... 

    Ma visto che è semplice semplice ho preferito fare una piccola demo per fare prima... poi uno prende ciò che gli occorre e l'adatta a proprio piacimento nel suo progetto,... oppure non ne fa nulla  ;-) 

Devi accedere o registrarti per scrivere nel forum
15 risposte