'***************************************************************************************
' Name : VBIDE
' Purpose : For reporting on or editing a VB Project
' Updated : 20141118
' Notes : Dev use only. Remove from end user version.
'
'
' Requirements/Dependencies:
' Reference Library = Microsoft Visual Basic for Applications Extensibility 5.3
' Modules =
' t_Arrays_1_ReadWrite ( Write1or2DArrToNewWB )
' t_Arrays_3_Edit ( fnavarSafeTranspose )
'***************************************************************************************
Option Explicit
Option Private Module
Private Const mstrcVBIDE_GUID As String = "{0002E157-0000-0000-C000-000000000046}"
Private mstrRangeAddress As String
Public Sub ListMacrosUsedInTWB()
Dim VBComp As VBIDE.VBComponent
Dim VBCodeMod As VBIDE.CodeModule
Dim lngModLineNo As Long
Dim strModName As String
Dim strProcName As String
Dim avarOutput As Variant
Dim lngArrCnt As Long
Dim strThisModule As String
Dim wbkOutput As Excel.Workbook
If fnblnRefCheck(mstrcVBIDE_GUID) = False Then
Call MsgBEnableVBIDE
Exit Sub
End If
'get name of this module - we dont want to check this
strThisModule = Application.VBE.ActiveCodePane.CodeModule
ReDim avarOutput(1 To 2, 1 To 1)
lngArrCnt = 0
For Each VBComp In ThisWorkbook.VBProject.VBComponents
strModName = vbNullString
strModName = VBComp.Name
If strModName = strThisModule Then
'skip
Else
Set VBCodeMod = ThisWorkbook.VBProject.VBComponents(strModName).CodeModule
With VBCodeMod
lngModLineNo = .CountOfDeclarationLines + 1
Do Until lngModLineNo >= .CountOfLines
strProcName = vbNullString
strProcName = .ProcOfLine(lngModLineNo, vbext_pk_Proc)
'expand array then write to last record
lngArrCnt = lngArrCnt + 1
ReDim Preserve avarOutput(1 To 2, 1 To lngArrCnt)
avarOutput(1, lngArrCnt) = strModName
avarOutput(2, lngArrCnt) = strProcName
lngModLineNo = lngModLineNo + .ProcCountLines(strProcName, vbext_pk_Proc)
Loop
End With
Set VBCodeMod = Nothing
End If
Next VBComp
'output array to new workbook
avarOutput = fnavarSafeTranspose(avarOutput)
Call Write1or2DArrToNewWB(avarOutput, False, True, 2, 1, wbkOutput)
With wbkOutput.Worksheets(1)
.Name = "Macros"
.Range("A1:B1").Value = Array("ModName", "ProcName")
.UsedRange.Columns.AutoFit
End With
End Sub
Public Sub ListNamesUsedInTWB()
'/ Credits: adapted from code by JosephP
'/ Useful function to run on a WB that has large accumulation of names
'/ You can filter the output to see which names are obselete.
Dim wbName As Name
Dim strWhere As String
Dim strName As String
Dim avarOutput As Variant
Dim lngArrCnt As Long: lngArrCnt = 0
Dim strThisModule As String
Dim wbkOutput As Excel.Workbook
If fnblnRefCheck(mstrcVBIDE_GUID) = False Then
Call MsgBEnableVBIDE
Exit Sub
End If
Application.ScreenUpdating = False
ReDim avarOutput(1 To 6, 1 To 1)
'get name of this module - we dont want to check this
strThisModule = Application.VBE.ActiveCodePane.CodeModule
For Each wbName In ThisWorkbook.Names
strWhere = vbNullString
strName = wbName.Name
'for sheet-level names remove the sheet name
If InStr(strName, "!") > 0 Then
strName = Mid$(strName, InStr(strName, "!") + 1)
End If
'skip sheet print areas from output
If Not strName = "Print_Area" Then
lngArrCnt = lngArrCnt + 1
ReDim Preserve avarOutput(1 To 6, 1 To lngArrCnt)
avarOutput(1, lngArrCnt) = strName
'check VBA for name usage
Select Case fnblnIsNameInUseInVBA(strThisModule, strName, ActiveWorkbook.VBProject, strWhere)
Case True
avarOutput(2, lngArrCnt) = True
avarOutput(4, lngArrCnt) = strWhere
Case False
avarOutput(2, lngArrCnt) = False
End Select
'check WS formulas for name usage
Select Case fnblnIsNameInUseInWS(strName, strWhere)
Case True
avarOutput(3, lngArrCnt) = True
avarOutput(5, lngArrCnt) = strWhere
avarOutput(6, lngArrCnt) = mstrRangeAddress
Case False
avarOutput(3, lngArrCnt) = False
End Select
strName = vbNullString
End If
Next wbName
'output array to new workbook
avarOutput = fnavarSafeTranspose(avarOutput)
Call Write1or2DArrToNewWB(avarOutput, False, True, 2, 1, wbkOutput)
With wbkOutput.Worksheets(1)
.Name = "NamesInUse"
.Range("A1:F1").Value = Array("Name", "In VBA?", "In WS?", "Module", "Sheet", "rngCell")
.UsedRange.Columns.AutoFit
End With
Application.ScreenUpdating = True
End Sub
Private Function fnblnIsNameInUseInVBA(ByRef strThisModule As String, ByRef strName As String, ByVal vbp As _
VBProject, ByRef strModule As String) As Boolean
'/ Credits: adapted from code by JosephP
Dim vbc As VBIDE.VBComponent
Dim lngStartLine As Long: lngStartLine = 1
Dim lngStartColumn As Long: lngStartColumn = 1
For Each vbc In vbp.VBComponents
If Not vbc.Name = strThisModule Then
If vbc.CodeModule.Find(target:=strName, StartLine:=lngStartLine, _
startcolumn:=lngStartColumn, endline:=-1, endcolumn:=-1, wholeword:=True) Then
fnblnIsNameInUseInVBA = True
strModule = vbc.Name
Exit For
End If
End If
Next vbc
End Function
Private Function fnblnIsNameInUseInWS(ByRef strName As String, ByRef strSheetName As String) As Boolean
Dim wsSheet As Excel.Worksheet
Dim rngCell As Excel.Range
For Each wsSheet In Worksheets
wsSheet.Activate
If fnblnFoundOnPage(strName, wsSheet.Name) Then
fnblnIsNameInUseInWS = True
strSheetName = wsSheet.Name
Exit For
End If
If fnblnIsNameInUseInWS Then
Exit For
End If
Next wsSheet
End Function
Private Function fnblnFoundOnPage(ByVal strFindString As String, ByVal strSheetName As String) As Boolean
'/ adapted from code by Ron de Bruin http://www.rondebruin.nl/win/s9/win006.htm
Dim Rng As Excel.Range
If Trim(strFindString) <> "" Then
With Sheets(strSheetName).UsedRange
Set Rng = .Find(What:=strFindString, after:=.Cells(.Cells.Count), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
If Not Rng Is Nothing Then
fnblnFoundOnPage = True
mstrRangeAddress = Rng.Address
Else
fnblnFoundOnPage = False
End If
End With
End If
End Function
Private Sub MsgBEnableVBIDE()
Dim Answer As Integer
Dim Msg As String
Msg = "This procedure can not continue. You need to enable the Microsoft VBA extensibility reference set." & vbNewLine & _
" 1. In the VBA Editor, choose References from the Tools menu." & vbNewLine & _
" 2. Scroll through list of Available References " & _
"and make sure the Microsoft Visual Basic for Applications Extensibility check box is selected." & _
vbNewLine & " 3. Close the dialog box."
Answer = MsgBox(Msg, vbCritical)
End Sub
Private Function fnblnRefCheck(ByVal strGUID As String) As Boolean
Dim lngRefCnt As Long
With ThisWorkbook.VBProject.References
For lngRefCnt = 1 To .Count
If .Item(lngRefCnt).GUID = strGUID Then
fnblnRefCheck = True
Exit Function
End If
Next lngRefCnt
End With
End Function
Bookmarks