Разобрать строку формулы Excel в предыдущую строку, функцию, аргументы и строку после функции в VBA - PullRequest
0 голосов
/ 14 ноября 2018

Для данной функции Excel (например, VLOOKUP) мне нужно проанализировать строку формулы ячейки в:

  • preFunctionStr = Строка, предшествующая функции VLOOKUP
  • ExcelFn = "VLOOKUP"
  • Arguments = Коллекция всех аргументов в функции VLOOKUP (которые сами могут содержать функции)
  • postFunctionStr = Строка, следующая за последним ")" в строке формулы

Моя главная причина, по которой я этого хочу, - возможность конвертировать формулы Excel без изменения их ответа. Например, конвертируйте SUMIF в SUMIFS и конвертируйте VLOOKUP в комбинацию INDEX и MATCH.

В моем примере я нахожусь в ячейке, содержащей формулу =A4+VLOOKUP(2,$E$4:$F$8,MATCH("Value(1)",$E$4:$F$4,0),0) + 2000, которую мне нужно разобрать на компоненты, описанные выше.

Хотя я мог найти много материала по синтаксическому анализу формул Excel, я не смог найти тот, который разбил бы его на эти компоненты.

1 Ответ

0 голосов
/ 14 ноября 2018

В моем решении я создаю Class module со свойствами, которые требуется разделить на строку формулы, и называется ExcelFormulaParser:

Option Explicit

Public ExcelFn As String
Public Arguments As New Collection
Public preFunctionStr As String
Public postFunctionStr As String

Sub SetMeUp(formulaStr As String, FormulaToParse As String)

    Dim FormulaStartPos As Integer
    Dim OpenBracketCounter As Integer
    Dim OpenBracketCount As Integer
    Dim ClosedBracketCount As Integer
    Dim WithinQuote As Boolean
        ' whether we are within quotation marks
    Dim i As Integer

    Dim strChr As String
    Dim Arg_i As String
    Dim Arg As String

    Me.ExcelFn = FormulaToParse

    FormulaStartPos = InStr(1, formulaStr, FormulaToParse)

    Me.preFunctionStr = Mid(formulaStr, 1, FormulaStartPos - 1)
    formulaStr = Mid(formulaStr, FormulaStartPos + Len(FormulaToParse), Len(formulaStr) - Len(FormulaToParse))

    If Left(formulaStr, 1) = "(" Then
        OpenBracketCounter = 1
        formulaStr = Mid(formulaStr, 2, Len(formulaStr) - 1)
    Else
        MsgBox ("Not the full FormulaToParse")
        End
    End If

    i = 0
    Arg_i = ""
    Do While OpenBracketCounter > 0
        i = i + 1
        strChr = Left(formulaStr, 1)
        If Len(formulaStr) > 0 Then
            formulaStr = Right(formulaStr, Len(formulaStr) - 1)
        End If

        If strChr = Chr(34) Then
            WithinQuote = Not (WithinQuote) ' toggle WithinQuote on or off
            ' don't count brackets within quotation marks
        ElseIf strChr = "(" And WithinQuote = False Then
            OpenBracketCounter = OpenBracketCounter + 1
        ElseIf strChr = ")" And WithinQuote = False Then
            OpenBracketCounter = OpenBracketCounter - 1
        End If

        If OpenBracketCounter = 1 And strChr = "," Then
            Arg = Arg_i
            Me.Arguments.Add Arg
            Arg_i = ""
        ElseIf OpenBracketCounter = 0 Then
            Arg = Arg_i
            Me.Arguments.Add Arg
            Arg_i = ""
            Me.postFunctionStr = formulaStr
        Else
            Arg_i = Arg_i & strChr
        End If
    Loop

End Sub

. В качестве примера того, как вызывать и использоватьClass module, я создал следующий модуль в том же проекте VBA:

Sub TestFormulaParser()

    Dim ParsedForm As ExcelFormulaParser
    Set ParsedForm = New ExcelFormulaParser
    Dim StrToParse As String
    StrToParse = ActiveCell.Formula
        ' formula contains:
        '' =A4+VLOOKUP(2,$E$4:$F$8,MATCH("Value(1)",$E$4:$F$4,0),0) + 2000
    Call ParsedForm.SetMeUp(StrToParse, "VLOOKUP")

    preFunctionStr = ParsedForm.preFunctionStr
        ' returns the prefunction string i.e. =A4+
    ExcelFn = ParsedForm.ExcelFn
        ' returns the excel function we parsed i.e. VLOOKUP
    Arg1 = ParsedForm.Arguments(1)
        ' returns the first argument of the VLOOKUP function i.e. 2
    Arg2 = ParsedForm.Arguments(2)
        ' returns the second argument of the VLOOKUP function i.e. $E$4:$F$8
    Arg3 = ParsedForm.Arguments(3)
        ' returns the third argument of the VLOOKUP function i.e. MATCH("Value(1)",$E$4:$F$4,0)
    Arg4 = ParsedForm.Arguments(4)
        ' returns the fourth argument of the VLOOKUP function i.e. 0
    postFunctionStr = ParsedForm.postFunctionStr
        ' returns the post function string i.e.  + 2000

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...