我正在尝试在VBA中创建代码,该代码将通过模块进行搜索,找到特定的文本,然后在该文本之前在同一行中添加一个字符串。例如,每次在模块中说“ yo”时,我都希望将其改为“ Add This yo”。
下面的代码成功地找到了在模块中说“ yo”的实例,但是没有在我想要的地方添加文本。而是在模块的最顶部(甚至不在子内部)添加文本。我如何在“ yo”之前添加此文本?
Public Sub Edit()
Dim vb As VBComponent
Dim i As Long
Dim intFoundLine As Integer
Dim strSearchPhrase As String
Set vb = ThisWorkbook.VBProject.VBComponents("Module2")
strSearchPhrase = "yo"
intLinesNr = vb.CodeModule.CountOfLines
For i = 1 To intLinesNr
If vb.CodeModule.Find(strSearchPhrase, i, 1, -1, -1) Then
intFoundLine = i
MsgBox "Found at " & intFoundLine
vb.CodeModule.AddFromString ("Add This")
End If
Next
End Sub
答案 0 :(得分:3)
用新文本替换行:
vb.CodeModule.ReplaceLine i, "Add This" & vb.CodeModule.Lines(i, 1)
根据Mathieu Guindon的回答,这是我将如何处理搜索短语的所有实例:
Do While vb.CodeModule.Find(strSearchPhrase, i, 1, -1, -1)
vb.CodeModule.ReplaceLine i, "Add This" & vb.CodeModule.Lines(i, 1)
i = i + 1
Loop
'
答案 1 :(得分:2)
迭代模块的所有行似乎对Find
方法的使用不佳,该方法能够在模块中的任何位置查找文本,并接受ByRef
自变量,如果函数返回{{1} },其中将包含找到的文本的确切位置-对于用户定义的True
,这是一个很好的用例:
Type
现在您拥有要重写的编辑器内的行号,请使用Option Explicit
Private Type CodeStringLocation
StartLine As Long
EndLine As Long
StartColumn As Long
EndColumn As Long
End Type
Sub test()
Dim module As CodeModule
Set module = ThisWorkbook.VBProject.VBComponents("Module1").CodeModule
Dim foundAt As CodeStringLocation
If module.Find("test", foundAt.StartLine, foundAt.StartColumn, foundAt.EndLine, foundAt.EndColumn) Then
'L9C5-L9C9
Debug.Print "L" & foundAt.StartLine & "C" & foundAt.StartColumn & "-L" & foundAt.EndLine & "C" & foundAt.EndColumn
End If
End Sub
进行重写-例如,用以下内容替换上面的CodeModule.ReplaceLine
语句:
Debug.Print
如果您需要替换模块中所有出现的搜索文本,只需运行搜索,直到Dim newLine As String
newLine = Replace(module.Lines(foundAt.StartLine, 1), "test", "Renamed")
module.ReplaceLine foundAt.StartLine, newLine
返回CodeModule.Find
-像这样:
False
关键是除搜索文本外,所有内容均为 output 参数;通过对这些参数中的任何一个进行硬编码,您将失去对它们返回值的引用。如果要将搜索限制为特定范围或行范围,则正确的方法是在运行搜索之前配置Dim foundAt As CodeStringLocation
Do While module.Find("test", foundAt.StartLine, foundAt.StartColumn, foundAt.EndLine, foundAt.EndColumn)
Dim newLine As String
newLine = Replace(module.Lines(foundAt.StartLine, 1), "test", "Renamed")
module.ReplaceLine foundAt.StartLine, newLine
Loop
值。
foundAt
这样,您就可以利用参数的实际双向特性,而不会丢失对输出值的引用-并且无需在不需要时迭代多达1万行代码。
请注意,这完全是基于文本的搜索,并且绝对采用零语法考虑:API不会在意是否在标识符,注释,字符串文字或关键字中找到搜索字符串。