提问人:Noam Brand 提问时间:11/14/2023 最后编辑:GSergNoam Brand 更新时间:11/15/2023 访问量:142
在 MsgBox 中查找带有 VBA 正则表达式的字符串文字的文本行
Find line of text in MsgBox with a string literal with VBA regex
问:
我想知道工作簿的模块中是否存在某种格式的代码行,在本例中为 VBA 正则表达式的带有字符串文字的 MsgBox。
已找到,但即使它存在于模块中也找不到。pattern1
pattern2
Pattern1
将 MsgBox 与字符串文字匹配,并带有左括号和右括号( ),例如:
testString = MsgBox("Do you want to open our product page?", vbInformation + vbYesNoCancel, "myMessageBox")
testString = MsgBox("Do you want to open our product page?", vbYesNoCancel, "myMessageBox")
testString = MsgBox("Do you want to open our product page?", vbYesNoCancel)
testString = MsgBox("Do you want to open our product page?")
Pattern2
将 MsgBox 与字符串文字匹配,不带左括号和右括号( ),例如:
MsgBox "Do you want to open our product page?", vbInformation + vbYesNoCancel, "myMessageBox"
MsgBox "Do you want to open our product page?", vbInformation + vbYesNoCancel
MsgBox "Do you want to open our product page?"
' Matches strings in all VBA modules of the specified workbook
' Add a reference to "Microsoft VBScript Regular Expressions 5.5" for early binding
Public Sub FindStringsInModules(ByVal objWorkbookToObfuscate As Workbook)
Dim vbComp As Object
Dim lineNum As Long
Dim lineText As String
Dim newLineText As String
' Iterate over all VBA modules in the provided workbook
For Each vbComp In objWorkbookToObfuscate.VBProject.VBComponents
' Process each line in the module
Dim lineCount As Long
lineCount = vbComp.codeModule.CountOfLines
For lineNum = 1 To lineCount
lineText = vbComp.codeModule.Lines(lineNum, 1)
newLineText = MatchLine(lineText)
vbComp.codeModule.ReplaceLine lineNum, newLineText
Next lineNum
Next vbComp
End Sub
Function MatchLine(ByVal lineText As String) As String
Dim regex As RegExp
Set regex = New RegExp
Dim pattern1 As String
Dim pattern2 As String
Dim pattern3 As String
' Pattern 1: Matches MsgBox with string literals, with opening and closing parenthesis ( )
pattern1 = "(?:[a-zA-Z0-9]+\s*=\s*)?MsgBox\s*\(\s*(""[^""]*"")(?:\s*,\s*[^,)]+(?:\s*\+\s*[^,)]+)*)?(?:\s*,\s*""[^""]*"")?\s*\)"
' Pattern 2: Matches MsgBox without parentheses, including additional parameters and concatenations
pattern2 = "MsgBox\s+""""[^""""]*""""(?:\s*&\s*""""[^""""]*""""|[^""""])*(?:\s*,\s*[^,""""]+)*"
pattern3 = "MsgBox\(""[^""]*""\)\s*"
' Combine patterns using alternation operator
regex.Pattern = pattern1 & "|" & pattern2 & "|" & pattern3
regex.Global = True
regex.MultiLine = True
Dim matches As MatchCollection
Set matches = regex.Execute(lineText)
' Process each match for potential transformation
If matches.Count > 0 Then
Dim match As match
For Each match In matches
Dim literal As String
literal = match.SubMatches(0)
If literal = "" Then
Debug.Print "lineText not catched:" & lineText
'Stop
End If
Next match
End If
MatchLine = lineText
End Function
match.SubMatches(0)
即使 .literal = ""
matches.Count > 0
P.S. 在 VBA 中针对字符串文字进行测试时,MsgBox 行
需要用双引号括起来,内部双引号加倍,例如 .
针对一行 VBA 代码(而不是字符串文本)进行测试时,MsgBox 行将显示为直接写入代码,例如 .testString = "MsgBox ""Do you want to open our product page?"""
MsgBox "Do you want to open our product page?"
答:
Regex.Test(Text)
如果存在匹配项,则返回 true。以下是我如何重构代码:
Sub ExampleUsage()
Const Pattern1 As String = "(?:[a-zA-Z0-9]+\s*=\s*)?MsgBox\s*\(\s*(""[^""]*"")(?:\s*,\s*[^,)]+(?:\s*\+\s*[^,)]+)*)?(?:\s*,\s*""[^""]*"")?\s*\)"
Const Pattern2 As String = "MsgBox\s+""""[^""""]*""""(?:\s*&\s*""""[^""""]*""""|[^""""])*(?:\s*,\s*[^,""""]+)*"
Const Pattern3 As String = "MsgBox\(""[^""]*""\)\s*"
Dim MasterPattern As String
MasterPattern = Join(Pattern1, Pattern2, Pattern3)
Const NewText As String = "MsgBox(""Sample Text"")"
Dim Patterns() As Variant
Patterns = Array(Pattern1, Pattern2, Pattern3)
ReplaceMatchesInModule ThisWorkbook, NewText, MasterPattern
End Sub
Public Sub ReplaceMatchesInModule(ByVal objWorkbookToObfuscate As Workbook, NewText As String, Pattern As String)
Rem Requires the reference to "Microsoft Visual Basic for Applications Extensibility #.#" library
Dim Component As VBComponent
Dim CodeModule As CodeModule
Dim lineNum As Long
Dim lineText As String
' Iterate over all VBA modules in the provided workbook
For Each vbComp In objWorkbookToObfuscate.VBProject.VBComponents
' Process each line in the module
Dim lineCount As Long
lineCount = Component.CodeModule.CountOfLines
For lineNum = 1 To lineCount
Set CodeModule = Component.CodeModule
lineText = CodeModule.Lines(lineNum, 1)
If RegExMatch(Pattern) Then
CodeModule.ReplaceLine lineNum, NewText
End If
Next lineNum
Next vbComp
End Sub
Public Function RegExMatch(Text As String, GlobalMatch As Boolean, Multiline As Boolean, ByRef Patterns() As Variant)
Rem Requires the reference to "Microsoft VBScript Regular Expressions 5.5" library
Dim Regex As New RegExp
Regex.Global = GlobalMatch
Regex.Multiline = Multiline
Dim Pattern As Variant
For Each Pattern In Patterns
If Regex.Test(Text) Then
RegExMatch = True
Exit Function
End If
Next
End Function
测试正则表达式很乏味。regex101.com 是一个受欢迎的测试网站。
表达:
(?:[a-zA-Z0-9]+\s*=\s*)?MsgBox\s*(\s*(“[^”]“)(?:\s,\s*[^,)]+(?:\s*+\s*[^,)]+))?(?:\s,\s*“[^”]“)?\s)|MsgBox\s+“”[^“”]“”(?:\s&\s*“”[^“”]“”|[^“”])(?:\s*,\s*[^,“”]+)|MsgBox(“[^”]“)\s*
评论
match.Value
match.Value
match.SubMatches(0)