我需要一些代码来测试一个单元格是否包含一个引用另一个单元格的公式。
我找到了答案Find all used references in Excel formula,但解决方案也错误地匹配了表格列引用的公式:
=SearchValInCol2(Tabella1[articolo];[@articolo];Tabella1[b])
然后,我使用 Like 运算符编写了以下VBA代码,但是使用正则表达式的解决方案肯定会更加可靠(我认为以下代码在许多情况下都不起作用)。
Private Function TestIfCellContainsAFormula(cellToTest As Variant) As Boolean
Dim result As Object
Dim r As Range
Dim testExpression As String
Dim objRegEx As Object
Set r = cellToTest ' INPUT THE CELL HERE , e.g. RANGE("A1")
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.IgnoreCase = True
objRegEx.Global = True
objRegEx.Pattern = """.*?""" ' remove expressions
testExpression = CStr(r.FormulaR1C1)
' search for pattern "=R[-3]C+4"
If testExpression Like "*R[[]*[]]*C*" Then
TestIfCellContainsAFormula2 = True
Exit Function
End If
' search for pattern "=RC[2]"
If testExpression Like "*R*C[[]*[]]*" Then
'If InStr(1, testExpression, "C[", vbTextCompare) <> 0 Then
TestIfCellContainsAFormula2 = True
Exit Function
End If
TestIfCellContainsAFormula2 = False
End Function
答案 0 :(得分:0)
要匹配R1C1样式引用,您可以使用this regex:
R(\[-?\d+\])C(\[-?\d+\])|R(\[-?\d+\])C|RC(\[-?\d+\])
有关直观说明,请参阅railroad图表:
核心是&#39;偏移&#39; -?\d+
是可选的-
,后跟一个或多个数字。括号([]
)中的此序列位于\[-?\d+\]
。然后正则表达式允许组合:
R[offset]C[offset]
R[offset]C
或(|
)RC[offset]
或(|
)上面的正则表达式不匹配R
,C
或RC
。它将与R[0]
,C[0]
,R[0]C
,RC[0]
和R[0]C[0]
相匹配。要消除这些匹配,您可以使用this regex:
R(\[-?[1-9][0-9]*\])C(\[-?[1-9][0-9]*\])|R(\[-?[1-9][0-9]*\])C|RC(\[-?[1-9][0-9]*\])
但似乎在我的Excel(v2013)中输入R[0]
,C[0]
和R[0]C[0]
会将其转换为R
,C
和RC
无论如何 - 如果这不是一个问题,你可以避免额外的复杂性。
如果您想允许R
,C
和RC
,您可以使用更简单的正则表达式:
R(\[-?\d+\])?C(\[-?\d+\])?
这使用选项1。
Option Explicit
Sub Test()
Dim varTests As Variant
Dim varTest As Variant
Dim varMatches As Variant
Dim varMatch As Variant
varTests = Array("RC", _
"R[1]C", _
"RC[1]", _
"R[1]C[1]", _
"R[-1]C", _
"RC[-1]", _
"R[-1]C[-1]", _
"=SUM(A1:B2)", _
"RC[1]+R[-1]C+R[2]C[-99]", _
"R[-1]C-R[1]C[-44]-RC[999]+R[0]C[0]", _
"SearchValInCol2(Tabella1[articolo];[@articolo];Tabella1[b])")
For Each varTest In varTests
varMatches = FormulaContainsR1C1Reference(CStr(varTest))
Debug.Print "Input: " & CStr(varTest)
Debug.Print VBA.String(Len(CStr(varTest)) + 7, "-")
If IsEmpty(varMatches) Then
Debug.Print "No matches"
Else
Debug.Print UBound(varMatches) & " matches"
For Each varMatch In varMatches
Debug.Print varMatch
Next varMatch
End If
Debug.Print vbCrLf
Next varTest
End Sub
Function FormulaContainsR1C1Reference(ByVal strFormula As String) As Variant
Dim objRegex As Object
Dim strPattern As String
Dim objMatches As Object
Dim varMatches As Variant
Dim lngCounter As Long
Set objRegex = CreateObject("VBScript.RegExp")
With objRegex
' setup regex
.Global = True
.IgnoreCase = False
.Pattern = "R(\[-?\d+\])C(\[-?\d+\])|R(\[-?\d+\])C|RC(\[-?\d+\])"
' get matches
Set objMatches = .Execute(strFormula)
' iterate matches
If objMatches.Count > 0 Then
ReDim varMatches(1 To objMatches.Count)
For lngCounter = 1 To objMatches.Count
varMatches(lngCounter) = objMatches.Item(lngCounter - 1)
Next lngCounter
Else
varMatches = Empty
End If
End With
FormulaContainsR1C1Reference = varMatches
End Function
我为A1样式引用发布了一个正则表达式here:
^(?:[A-Z]|[A-Z][A-Z]|[A-X][A-F][A-D])(?:[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9][0-9]|10[0-3][0-9][0-9][0-9][0-9]|104[0-7][0-9][0-9][0-9]|1048[0-4][0-9][0-9]|10485[0-6][0-9]|104857[0-6])$