絶対参照、相対参照、および外部参照を含む、Excel 数式の任意の参照に一致する正規表現パターンを作成しようとしています。ワークシートとワークブック名を含む参照全体を返す必要があります。
Excel の A1 表記法に関する完全なドキュメントを見つけることはできませんでしたが、多くのテストを行った結果、次のことがわかりました。
- 式の前に等号「=」を付ける
- 数式内の文字列は二重引用符で囲まれており、実際の参照を探す前に削除する必要があります。そうしないと、
=A1&"A1"
正規表現が壊れます - ワークシート名は、\ / ? を除き、最大 31 文字です。* [ ] :
- 外部参照内のワークシート名は bang で終わる必要があります
=Sheet1!A1
- 外部参照のワークブック名は角かっこで囲む必要があります
=[Book1.xlsx]Sheet1!A1
- 参照が閉じたブック内の範囲への参照である場合に Excel が追加するブック パスは、常に一重引用符で囲まれ、ブック名の角かっこの左側にあります。
'C:\[Book1.xlsx]Sheet1'!A1
- 一部の文字 (区切りのないスペースなど) により、Excel はブックとワークシートの名前を単一引用符で囲んだ外部参照を作成しますが、どの文字が具体的にわかりません。
='[Book 1.xlsx]Sheet 1'!A1
- R1C1 表記が有効になっている場合
Range.Formula
でも、参照は A1 表記で返されます。Range.FormulaR1C1
参照を R1C1 表記で返します。 - 3D 参照スタイルにより、1 つのワークブックでさまざまなシート名を使用できます
=SUM([Book5]Sheet1:Sheet3!A1)
- 名前付き範囲は数式で指定できます。
- 名前の最初の文字は、文字、アンダースコア (_)、またはバックスラッシュ (\) でなければなりません。名前の残りの文字は、文字、数字、ピリオド、およびアンダースコア文字にすることができます。
- 大文字と小文字の "C"、"c"、"R"、または "r" を定義名として使用することはできません。これらはすべて、現在選択されているセルの行または列を選択する際の省略形として使用されるためです。それらを [名前] または [移動先] テキスト ボックスに入力します。
- 名前は、Z$100 や R1C1 などのセル参照と同じにすることはできません。
- 名前の一部としてスペースを使用することはできません。
- 名前の長さは最大 255 文字です。
- 名前には大文字と小文字を含めることができます。Excel では、名前の大文字と小文字が区別されません。
これが、テスト用の VBA プロシージャにラップされた、私が思いついたものです。名前も処理するようにコードを更新しました。
Sub ReturnFormulaReferences()
Dim objRegExp As New VBScript_RegExp_55.RegExp
Dim objCell As Range
Dim objStringMatches As Object
Dim objReferenceMatches As Object
Dim objMatch As Object
Dim intReferenceCount As Integer
Dim intIndex As Integer
Dim booIsReference As Boolean
Dim objName As Name
Dim booNameFound As Boolean
With objRegExp
.MultiLine = True
.Global = True
.IgnoreCase = True
End With
For Each objCell In Selection.Cells
If Left(objCell.Formula, 1) = "=" Then
objRegExp.Pattern = "\"".*\"""
Set objStringMatches = objRegExp.Execute(objCell.Formula)
objRegExp.Pattern = "(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _
& "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)?" _
& "(\$?[a-z]{1,3}\$?[0-9]{1,7}(\:\$?[a-z]{1,3}\$?[0-9]{1,7})?" _
& "|\$[a-z]{1,3}\:\$[a-z]{1,3}" _
& "|[a-z]{1,3}\:[a-z]{1,3}" _
& "|\$[0-9]{1,7}\:\$[0-9]{1,7}" _
& "|[0-9]{1,7}\:[0-9]{1,7}" _
& "|[a-z_\\][a-z0-9_\.]{0,254})"
Set objReferenceMatches = objRegExp.Execute(objCell.Formula)
intReferenceCount = 0
For Each objMatch In objReferenceMatches
intReferenceCount = intReferenceCount + 1
Next
Debug.Print objCell.Formula
For intIndex = intReferenceCount - 1 To 0 Step -1
booIsReference = True
For Each objMatch In objStringMatches
If objReferenceMatches(intIndex).FirstIndex > objMatch.FirstIndex _
And objReferenceMatches(intIndex).FirstIndex < objMatch.FirstIndex + objMatch.Length Then
booIsReference = False
Exit For
End If
Next
If booIsReference Then
objRegExp.Pattern = "(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _
& "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)?" _
& "(\$?[a-z]{1,3}\$?[0-9]{1,7}(\:\$?[a-z]{1,3}\$?[0-9]{1,7})?" _
& "|\$[a-z]{1,3}\:\$[a-z]{1,3}" _
& "|[a-z]{1,3}\:[a-z]{1,3}" _
& "|\$[0-9]{1,7}\:\$[0-9]{1,7}" _
& "|[0-9]{1,7}\:[0-9]{1,7})"
If Not objRegExp.Test(objReferenceMatches(intIndex).Value) Then 'reference is not A1
objRegExp.Pattern = "^(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _
& "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)" _
& "[a-z_\\][a-z0-9_\.]{0,254}$"
If Not objRegExp.Test(objReferenceMatches(intIndex).Value) Then 'name is not external
booNameFound = False
For Each objName In objCell.Worksheet.Parent.Names
If objReferenceMatches(intIndex).Value = objName.Name Then
booNameFound = True
Exit For
End If
Next
If Not booNameFound Then
objRegExp.Pattern = "^(\'.*(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\'\!" _
& "|(\[.*\])?([^\:\\\/\?\*\[\]]{1,31}\:)?[^\:\\\/\?\*\[\]]{1,31}\!)"
For Each objName In objCell.Worksheet.Names
If objReferenceMatches(intIndex).Value = objRegExp.Replace(objName.Name, "") Then
booNameFound = True
Exit For
End If
Next
End If
booIsReference = booNameFound
End If
End If
End If
If booIsReference Then
Debug.Print " " & objReferenceMatches(intIndex).Value _
& " (" & objReferenceMatches(intIndex).FirstIndex & ", " _
& objReferenceMatches(intIndex).Length & ")"
End If
Next intIndex
Debug.Print
End If
Next
Set objRegExp = Nothing
Set objStringMatches = Nothing
Set objReferenceMatches = Nothing
Set objMatch = Nothing
Set objCell = Nothing
Set objName = Nothing
End Sub
誰かがこれを壊したり改善したりできますか? Excel の数式構文に関する完全なドキュメントがなければ、これが正しいかどうかを知ることは困難です。
ありがとう!