我有一个VBA源代码,其中包含许多对单元格的硬编码引用。代码是Worksheet_Change
sub的一部分,所以我想硬编码范围引用是必要的,你会看到许多赋值语句,如下所示:
Set cell = Range("B7")
If Not Application.Intersect(cell, Range(Target.Address)) Is Nothing Then
我想在工作表的顶部插入2行,所以基本上所有行引用都会移动2行。例如,上述赋值语句将更改为Set cell = Range("B9")
。
鉴于代码中存在大量硬编码行引用,我想到使用Regex将所有行引用增加2.所以我开发了以下代码。
Sub UpdateVBACode()
'*********************Read Text File Containing VBA code and assign content to string variable*************************
Dim str As String
Dim strFile As String: strFile = "F:\Preprocessed_code.txt"
Open strFile For Input As #1
str = Input$(LOF(1), 1)
Close #1
'*********************Split string variables to lines******************************************************************
Dim vStr As Variant: vStr = Split(str, vbCrLf)
'*********************Regex work***************************************************************************************
Dim rex As New RegExp
rex.Global = True
Dim i As Long
Dim mtch As Object
rex.Pattern = "(""\w)([0-9][0-9])("")" ' 3 capturing groups to reconstruct the replacement string
For i = 0 To UBound(vStr, 1)
If rex.Test(vStr(i)) Then
For Each mtch In rex.Execute(vStr(i))
vStr(i) = rex.Replace(vStr(i), mtch.SubMatches(0) & IncrementString(mtch.SubMatches(1)) & mtch.SubMatches(2))
Next
End If
Next i
'********************Reconstruct String*********************************************************************************
str = ""
For i = 0 To UBound(vStr, 1)
str = str & vbCrLf & vStr(i)
Next i
'********************Write string to text file******************************************************************************
Dim myFile As String
myFile = "F:\Processed_code.txt"
Open myFile For Output As #2
Print #2, str
Close #2
'
End Sub
Function IncrementString(rowNum As String) As String '
Dim num As Integer
num = CInt(rowNum) + 2
IncrementString = CStr(num)
End Function
上面的VBA代码有效,但如果同一行中有两个行引用则失败,例如,如果我们有If Range("B15").Value <> Range("B12").Value Then
,则在处理该行后,我得到If Range("B14").Value <> Range("B14").Value Then
而不是{ {1}}。问题出在If Range("B17").Value <> Range("B14").Value Then
语句中,因为如果一行超过Regex匹配,它会被多次调用。
有什么想法吗?提前致谢
答案 0 :(得分:2)
我认为你想要做的是一个坏主意,原因有两个:
"123"
,"_12"
和"A00"
),并且还会遗漏许多硬编码的单元格引用(例如"A1"
和Cell(3,7)
)。这可能对您的特定代码无关紧要,但确保其有效的唯一方法是手动检查每个引用。这是恕我直言,而不是重构(例如,用命名范围替换)。根据我的经验,你不会修复正则表达式,只是让问题更加微妙。那说,既然你问过......
<cthulu>
使用RegExp.Replace()
时只有两种选择 - 替换第一场比赛或替换所有匹配(分别对应于RegExp.Global
或False
设置)。你没有比那更精细的控制,所以你的逻辑必须改变。您可以使用True
对象的Replace()
属性和VBA的字符串函数来编写自己的替换代码,而不是使用FirstIndex
来隔离相关的部分。字符串:
Match
请注意,我仍然没有解决正则表达式模式的问题。我建议您只使用命名范围...
哎呀,差点忘了 - Dim rex As Object
Set rex = CreateObject("VBScript.RegExp")
rex.Global = True
Dim i As Long
Dim mtch As Object
Dim newLineText As String
Dim currMatchIndex As Long, prevPosition As Long
rex.Pattern = "(""\w)([0-9][0-9])("")" ' 3 capturing groups to reconstruct the replacement string
For i = 0 To UBound(vStr, 1)
If rex.Test(vStr(i)) Then
currMatchIndex = 0: prevPosition = 1
newLineText = ""
For Each mtch In rex.Execute(vStr(i))
'Note that VBA string functions are indexed from 1 but Match.FirstIndex starts from 0
currMatchIndex = mtch.FirstIndex
newLineText = newLineText & Mid(vStr(i), prevPosition, currMatchIndex - prevPosition + 1) & _
mtch.SubMatches(0) & IncrementString(mtch.SubMatches(1)) & mtch.SubMatches(2)
prevPosition = currMatchIndex + Len(mtch.Value) + 1
Next
vStr(i) = newLineText & Right(vStr(i), Len(vStr(i)) - prevPosition + 1)
End If
Next i