6

セル内の特定のExcel数式について、数式に含まれるExcel範囲参照のリストを取得するために数式を解析できるようにしたいと思います。

たとえば、次の数式を含むセルがある場合:

= A + 25 + B  

....数式に含まれるExcel範囲の配列を取得できるようにしたいので、この場合は[A]と[B]が含まれます。

「なぜこれを実行したいのですか?」という質問を聞くことができます。
これを実行したい理由の1つの例は、数式の範囲の「ラベル」を検索することです。 CTRL +〜を実行してシート内の数式を表示する場合、数式内の範囲参照にプログラムでアクセスして、ターゲット範囲の横にあるラベルを検索するオプションが必要です。

したがって、上記の例では、次のような式を書くことができます。

=Offset(CellFormulaRanges('TheAddressMyFormulaIsIn',1),0,-1)
=Offset(CellFormulaRanges('TheAddressMyFormulaIsIn',2),0,-1)

...数式内の1番目と2番目の範囲の左側にラベルが表示されます。

数式パーサーを手書きするのは複雑な作業であるため、これを行うには、Excel自体にすでに含まれているいくつかの機能を呼び出す必要があります。http:
//ewbi.blogs.com/develops/2004/12/excel_formula_p.html

4

3 に答える 3

4

@TimWilliamsと@brettdjが、このトピックに関する以前の議論に正しい方向を示してくれたことに感謝します。自信を持って次のように言うことができます。

いいえ、Excelには構文解析の方法がありません。

ただし、私のかなり最小限の目的のために、機能し、クロスワークシート参照で機能し、UDFから呼び出すことができるものを考え出しました。

しかし、それは非常に壊れやすく、適切に処理されないと確信している完全に正当な式が多数あります。

コードはめちゃくちゃで、大幅に改善される可能性がありますが、とりあえず他の何かに移動しているので、ここにそれを投げたかっただけです。

編集

また、これは非常に興味深いように見えます:
http ://www.dailydoseofexcel.com/archives/2009/12/05/formula-tokenizer/

Public Function CellPrecedents(cell As Range) As Variant()
    Dim resultRanges As New Collection
    If cell.Cells.count <> 1 Then GoTo exit_CellPrecedents
    If cell.HasFormula = False Then GoTo exit_CellPrecedents

    Dim formula As String
    formula = Mid(cell.formula, 2, Len(cell.formula) - 1)

    If IsRange(formula) Then
        resultRanges.Add Range(formula), 1
    Else
        Dim elements() As String
        'Debug.Print formula & " --> "
        formula = Replace(formula, "(", "")
        formula = Replace(formula, ")", "")
        'Debug.Print formula & " --> "
        elements() = SplitMultiDelims(formula, "+-*/\^")
        Dim n As Long, count As Integer
        For n = LBound(elements) To UBound(elements)
            If IsRange(elements(n)) Then
                'ACTUALLY JUST DO A REDIM PRESERVE HERE!!!!
                count = count + 1
                'resultRanges.Add Range(Trim(elements(n)))  '<---  Do **NOT** store as a range, as that gets automatically Eval()'d
                resultRanges.Add Trim(elements(n))
            End If
        Next
    End If

    Dim resultRangeArray() As Variant
    ReDim resultRangeArray(resultRanges.count)
    Dim i As Integer
    For i = 1 To resultRanges.count
        resultRangeArray(i) = CStr(resultRanges(i))  '// have to store as a string so Eval() doesn't get invoked (I think??)
    Next

    CellPrecedents = resultRangeArray

exit_CellPrecedents:
    Exit Function
End Function

Public Function IsRange(var As Variant) As Boolean
    On Error Resume Next
    Dim rng As Range: Set rng = Range(var)
    If err.Number = 0 Then IsRange = True
End Function

(その関数のグーグルSplitMultiDelimsだけ)

于 2012-07-12T18:17:33.383 に答える
1

Tbone、あなたが直接求めたものではないが、代替ソリューションとして機能する可能性のあるもう1つのオプション。

数式を使用して対応するラベルを見つけるのではなく、数式を調整して自分に合ったものを見つけてください。解析しようとした数式に応じて、いくつかのオプションがあります。1.数式がルックアップの場合は、オフセットして左を見ることができます。2.または、両方の数式で「間接」関数を使用して、正しい場所を参照していることを確認することもできます。

于 2015-08-06T18:24:40.097 に答える
0

Use VBA to generate code to reproduce basic calculations on an Excel worksheetつまり、:のサブパートを実行し、関数を使用してn番目のDirectPrecedentsコレクション要素のアドレスまたは名前を返す必要があると思います。

ソース:http ://www.vb-helper.com/howto_vba_excel_formulas.html

ただし、このユースケースは非推奨になりました。Excel 2007の時点で、テーブルははるかに優れたソリューションを可能にします。

于 2012-07-04T21:53:39.657 に答える