Reputation: 733
I want to get all the names of the subs in a workbook to execute if their name contains something. However I can't find the right class for doing such thing. Do you know what I should use to do something like :
Dim mdl As Module
Dim macro As macro
For Each mdl In ThisWorkbook
For Each macro In mdl
If Left(macro.Name, 11) = "FilterChart" Then
Run macro
.Chart.Export ....
End If
Next mdl
That's the spirit of what I want to do however I don't know what to put in my loops. Does anyone know if what I want to achieve is even possible? Thank you in advance!
Upvotes: 0
Views: 903
Reputation: 4714
In order to be able to programatically read details of the Visual Basic code in a worksheet you need to set the workbook to allow access to the vb code. File,Options,Advanced,Trust Center, Trust Center Settings,Macro Settings and tick "Trust Access to the VBA project model"
Then in the vb editor you need to set a reference to "Microsoft Visual Basic for Applications Extensibility" (The version number will differ depending on your installation)
You can then run this to dump the names to the immediate window (you can modify to suit)
Sub getnames()
Dim p As VBProject
Dim m As VBComponent
Dim l As Long
Dim s As String
Set p = ThisWorkbook.VBProject
For Each m In p.VBComponents
With m.CodeModule
If .CountOfLines > 2 Then
For l = 2 To .CountOfLines
s = .Lines(l, 1)
If Left(s, 4) = "Sub " Then
Debug.Print Replace(s, "Sub ", "")
End If
Next l
End If
End With
Next m
End Sub
Upvotes: 1
Reputation: 6664
This Piece of code does that exactly.
Sub GetProcedures()
' Declare variables to access the Excel workbook.
Dim app As Excel.Application
Dim wb As Excel.Workbook
Dim wsOutput As Excel.Worksheet
Dim sOutput() As String
Dim sFileName As String
' Declare variables to access the macros in the workbook.
Dim vbProj As VBIDE.VBProject
Dim vbComp As VBIDE.VBComponent
Dim vbMod As VBIDE.CodeModule
' Declare other miscellaneous variables.
Dim iRow As Long
Dim iCol As Long
Dim iLine As Integer
Dim sProcName As String
Dim pk As vbext_ProcKind
Set app = Excel.Application
' create new workbook for output
Set wsOutput = app.Workbooks.Add.Worksheets(1)
'For Each wb In app.Workbooks
For Each vbProj In app.VBE.VBProjects
' Get the project details in the workbook.
On Error Resume Next
sFileName = vbProj.fileName
If Err.Number <> 0 Then sFileName = "file not saved"
On Error GoTo 0
' initialize output array
ReDim sOutput(1 To 2)
sOutput(1) = sFileName
sOutput(2) = vbProj.Name
iRow = 0
' check for protected project
On Error Resume Next
Set vbComp = vbProj.VBComponents(1)
On Error GoTo 0
If Not vbComp Is Nothing Then
' Iterate through each component in the project.
For Each vbComp In vbProj.VBComponents
' Find the code module for the project.
Set vbMod = vbComp.CodeModule
' Scan through the code module, looking for procedures.
iLine = 1
Do While iLine < vbMod.CountOfLines
sProcName = vbMod.ProcOfLine(iLine, pk)
If sProcName <> "" Then
iRow = iRow + 1
ReDim Preserve sOutput(1 To 2 + iRow)
sOutput(2 + iRow) = vbComp.Name & ": " & sProcName
iLine = iLine + vbMod.ProcCountLines(sProcName, pk)
Else
' This line has no procedure, so go to the next line.
iLine = iLine + 1
End If
Loop
' clean up
Set vbMod = Nothing
Set vbComp = Nothing
Next
Else
ReDim Preserve sOutput(1 To 3)
sOutput(3) = "Project protected"
End If
If UBound(sOutput) = 2 Then
ReDim Preserve sOutput(1 To 3)
sOutput(3) = "No code in project"
End If
' define output location and dump output
If Len(wsOutput.Range("A1").Value) = 0 Then
iCol = 1
Else
iCol = wsOutput.Cells(1, wsOutput.Columns.Count).End(xlToLeft).Column + 1
End If
wsOutput.Cells(1, iCol).Resize(UBound(sOutput) + 1 - LBound(sOutput)).Value = _
WorksheetFunction.Transpose(sOutput)
' clean up
Set vbProj = Nothing
Next
' clean up
wsOutput.UsedRange.Columns.AutoFit
End Sub
I found it somewhere on a Site couple of months ago.
Upvotes: 1