数式文字列-A1方式・R1C1方式-変換

Excelでは、セルの参照形式として、A1方式とR1C1方式があります。
A1方式で記述されている数式をR1C1方式の記述に変更するプロシージャと、その逆をするプロシージャを作ってみました。
実は、「条件付き書式の「条件」が数式の場合のカウント」のために作ったものです。

' # 数式文字列変換(A1→R1C1)                               #
'   argFmlA1    :i   数式文字列(A1)
'   argBaseAdls :i   基準セルアドレス
'   argFmlR1C1  :o   数式文字列(R1C1)
Public Function A1ToR1C1(ByVal argFmlA1 As String _
                       , ByVal argBaseAdls As String _
                       , ByRef argFmlR1C1 As String) As Boolean
    Dim aryD As Variant
    Dim wkF As String
    Dim i As Variant
    Dim V As Variant
    Dim j As Long
    Dim wkRowB As Long
    Dim wkColB As Long
    Dim wkExPos As Long
    Dim wkAdlsA As String
    Dim wkSheetA As String
    Dim rngA As Range
    Dim wkRowA As Long
    Dim wkColA As Long

    wkRowB = Range(argBaseAdls).Row
    wkColB = Range(argBaseAdls).Column
    aryD = Array("=", "<", ">", "(", ")", "+", "-", "*", "/", "^", "&", " ", ":", ",")
    wkF = argFmlA1
    For Each i In aryD
        wkF = Replace(wkF, i, vbTab & i & vbTab)
    Next i

    V = Split(wkF, vbTab)
    For j = LBound(V) To UBound(V)
        ' シート参照の場合、シート部分とセル部分に分割する
        wkExPos = InStrRev(V(j), "!")
        If wkExPos = 0 Then
            wkSheetA = ""
            wkAdlsA = V(j)
        Else
            wkSheetA = Left$(V(j), wkExPos)
            wkAdlsA = Mid$(V(j), wkExPos + 1)
        End If
        ' セルかどうか判別する
        Set rngA = Nothing
        On Error Resume Next
        Set rngA = Range(wkAdlsA)
        On Error GoTo 0
        ' セルの場合、R1C1形式に変換する
        If Not rngA Is Nothing Then
            wkRowA = rngA.Row
            wkColA = rngA.Column
            V(j) = "R[" & (wkRowA - wkRowB) _
                 & "]C[" & (wkColA - wkColB) & "]"
            V(j) = wkSheetA & Replace(V(j), "[0]", "")
        End If
    Next j

    argFmlR1C1 = Replace(Join(V, vbTab), vbTab, "")
    A1ToR1C1 = True
End Function

 

' # 数式文字列変換(R1C1→A1)                               #
'   argFmlR1C1  :i   数式文字列(R1C1)
'   argBaseAdls :i   基準セルアドレス
'   argFmlA1    :o   数式文字列(A1)
Public Function R1C1ToA1(ByVal argFmlR1C1 As String _
                       , ByVal argBaseAdls As String _
                       , ByRef argFmlA1 As String) As Boolean
    Dim aryD As Variant
    Dim wkF As String
    Dim i As Variant
    Dim V As Variant
    Dim j As Long
    Dim wkRowB As Long
    Dim wkColB As Long
    Dim wkExPos As Long
    Dim wkAdlsA As String
    Dim wkSheetA As String
    Dim wkTxt As String
    Dim wkAdlsRowFlg As Boolean
    Dim wkAdlsColFlg As Boolean
    Dim wkRowA As Long
    Dim wkColA As Long

    wkRowB = Range(argBaseAdls).Row
    wkColB = Range(argBaseAdls).Column
    aryD = Array("=", "<", ">", "(", ")", "+", "-", "*", "/", "^", "&", " ", ":", ",")
    wkF = argFmlR1C1
    For Each i In aryD
        wkF = Replace(wkF, i, vbTab & i & vbTab)
    Next i
    V = Split(wkF, vbTab)
    For j = LBound(V) + 2 To UBound(V) - 0
        If Right(V(j - 2), 1) = "[" And V(j - 1) = "-" And InStr(1, V(j), "]") > 0 Then
            V(j) = V(j - 2) & V(j - 1) & V(j)
            V(j - 2) = ""
            V(j - 1) = ""
        End If
    Next j

    For j = LBound(V) To UBound(V)
        ' シート参照の場合、シート部分とセル部分に分割する
        wkExPos = InStrRev(V(j), "!")
        If wkExPos = 0 Then
            wkSheetA = ""
            wkAdlsA = V(j)
        Else
            wkSheetA = Left$(V(j), wkExPos)
            wkAdlsA = Mid$(V(j), wkExPos + 1)
        End If
        ' セルかどうか判別し、行・列の番号を求める
        wkAdlsRowFlg = False
        wkAdlsColFlg = False
        If wkAdlsA Like "R*C*" Then
            wkTxt = Mid$(wkAdlsA, 2, InStr(1, wkAdlsA, "C") - 2)
            If wkTxt = "" Then
                wkAdlsRowFlg = True
                wkRowA = wkRowB
            ElseIf IsNumeric(wkTxt) Then
                wkAdlsRowFlg = True
                wkRowA = CLng(wkTxt)
            ElseIf Left(wkTxt, 1) = "[" And Right(wkTxt, 1) = "]" Then
                wkTxt = Mid(wkTxt, 2, Len(wkTxt) - 2)
                If IsNumeric(wkTxt) Then
                    wkAdlsRowFlg = True
                    wkRowA = CLng(wkTxt) + wkRowB
                End If
            End If
            wkTxt = Mid$(wkAdlsA, InStr(1, wkAdlsA, "C") + 1)
            If wkTxt = "" Then
                wkAdlsColFlg = True
                wkColA = wkColB
            ElseIf IsNumeric(wkTxt) Then
                wkAdlsColFlg = True
                wkColA = CLng(wkTxt)
            ElseIf Left(wkTxt, 1) = "[" And Right(wkTxt, 1) = "]" Then
                wkTxt = Mid(wkTxt, 2, Len(wkTxt) - 2)
                If IsNumeric(wkTxt) Then
                    wkAdlsColFlg = True
                    wkColA = CLng(wkTxt) + wkColB
                End If
            End If
        End If
        ' セルの場合、A1形式に変換する
        If wkAdlsRowFlg And wkAdlsColFlg Then
            V(j) = wkSheetA & Cells(wkRowA, wkColA).Address(False, False)
        End If
    Next j

    argFmlA1 = Replace(Join(V, vbTab), vbTab, "")
    R1C1ToA1 = True
End Function

両方ともあまり完成度の高くないコードなので、数式次第では期待した結果を返さない場合があります。
例えば、数式内に文字列があり、それがセルアドレスとaryDで使っている区切りで構成される場合などがそうです。