Existe uma maneira de expressar uma fórmula complexa do Excel em termos de células finais (não-fórmula, somente valor)?

4

Eu tenho uma planilha do Excel muito complicada (fórmulas acessando células com outras fórmulas em várias planilhas) que no final calcula uma única célula (saída) com entrada de várias outras células (parâmetros). Existe uma maneira automatizada (uma macro do Excel ou uma ferramenta autônoma) que poderia iniciar na célula de saída e desdobrar recursivamente os cálculos até que expressasse a fórmula em termos de células de parâmetros diretamente?

Esclarecimento

Nos comentários, houve uma sugestão da ferramenta Avaliar Fórmula. Embora não consegui encontrar como ativá-lo no Excel 2008 para Mac, de sua descrição parece que permite ao usuário passar pela avaliação de uma célula. Não é disso que eu preciso. O que eu preciso é uma maneira de converter a fórmula em uma determinada célula que pode fazer referência a outras células que contêm fórmulas, a uma fórmula equivalente expressa em termos de células finais (aquelas que contêm valores, mas não fórmulas).

Aqui está um exemplo simples. Deixe

  • A1 contém = B1 + C1
  • B1 contém = B2 * B2
  • C1 contém = C2 * C2
  • B2 contém 1
  • C2 contém 2

Avaliar a fórmula me permitiria percorrer o cálculo de A1 para chegar ao valor final de 5 . O que eu preciso é de uma ferramenta que desenrole A1 para a fórmula = B2 * B2 + C2 * C2 sem realmente avaliá-la.

    
por George Skoptsov 27.02.2013 / 02:07

2 respostas

3

O problema

Você não pode fazer isso com a Fórmula Avaliar porque este não é o propósito desta função. É por isso que é chamado avaliar , é para avaliar as fórmulas. O que você quer é algum tipo de descompactação. Esta é uma necessidade um pouco especial, por isso não é implementada como uma ferramenta no Excel, mas existem soluções se você criar algumas funções / macros do Visual Basic.

Crie um módulo de código VBA (macro) como você pode ver em este tutorial .

  1. Pressione Alt + F11
  2. Clique para Module em Insert .
  3. Colar código.
Function CellFormula(Target As Range) As String
   CellFormula = Target.Formula
End Function

Em seguida, digite o seguinte para uma célula: =CellFormula(A1)

Isto irá dizer a fórmula da célula. O único problema com este código é que ele funciona apenas para um nível. Se você quiser descompactar as fórmulas de células contidas também, então você precisa de um código mais complexo com recursão.

A solução

Foi uma longa jornada, mas criei uma macro VBA para você que implementa essa função. Não afirmo que esse código funcionará para todas as fórmulas, mas funcionará na maioria delas. Também não afirmo que este código irá gerar fórmulas que equivalem ao código inserido originalmente ou darão o mesmo resultado que o original.

Código-fonte

Option Explicit

Function isChar(char As String) As Boolean
    Select Case char
        Case "A" To "Z"
            isChar = True
        Case Else
            isChar = False
    End Select
End Function

Function isNumber(char As String, isZero As Boolean) As Boolean
    Select Case char
        Case "0"
            If isZero = True Then
                isNumber = True
            Else
                isNumber = False
            End If
        Case "1" To "9"
            isNumber = True
        Case Else
            isNumber = False
    End Select
End Function

Function CellFormulaExpand(formula As String) As String
    Dim result As String
    Dim previousResult As String
    Dim cell As Range
    Dim stringArray() As String
    Dim arraySize As Integer
    Dim n As Integer
    Dim trimmer As String

    Dim c As Integer 'character number
    Dim chr As String 'current character
    Dim tempcell As String 'suspected cell's temporaly result
    Dim state As Integer 'state machine's state:
    Dim stringSize As Integer

    result = formula
    previousResult = result
    state = 0
    stringSize = 0

    For c = 0 To Len(formula) Step 1
        chr = Mid(formula, c + 1, 1)
        Select Case state
            Case 0
                If isChar(chr) Then
                    state = 1
                    tempcell = tempcell & chr
                ElseIf chr = "$" Then
                    state = 5
                    tempcell = tempcell & chr
                Else
                    state = 0
                    tempcell = ""
                End If
            Case 1
                If isNumber(chr, False) Then
                    state = 4
                    tempcell = tempcell & chr
                ElseIf isChar(chr) Then
                    state = 2
                    tempcell = tempcell & chr
                ElseIf chr = "$" Then
                    state = 6
                    tempcell = tempcell & chr
                Else
                    state = 0
                    tempcell = ""
                End If
            Case 2
                If isNumber(chr, False) Then
                    state = 4
                    tempcell = tempcell + chr
                ElseIf isChar(chr) Then
                    state = 3
                    tempcell = tempcell + chr
                ElseIf chr = "$" Then
                    state = 6
                    tempcell = tempcell + chr
                Else
                    state = 0
                    tempcell = ""
                End If
            Case 3
                If isNumber(chr, False) Then
                    state = 4
                    tempcell = tempcell + chr
                ElseIf chr = "$" Then
                    state = 6
                    tempcell = tempcell + chr
                Else
                    state = 0
                    tempcell = ""
                End If
            Case 4
                If isNumber(chr, True) Then
                    state = 4
                    tempcell = tempcell + chr
                Else
                    state = 0
                    stringSize = stringSize + 1
                    ReDim Preserve stringArray(stringSize - 1)
                    stringArray(stringSize - 1) = tempcell
                    tempcell = ""
                End If
            Case 5
                If isChar(chr) Then
                    state = 1
                    tempcell = tempcell + chr
                Else
                    state = 0
                    tempcell = ""
                End If
            Case 6
                If isNumber(chr, False) Then
                    state = 4
                    tempcell = tempcell + chr
                Else
                    state = 0
                    tempcell = ""
                End If
            Case Else
                state = 0
                tempcell = ""
        End Select
    Next c
    If stringSize = 0 Then
        CellFormulaExpand = result
    Else
        arraySize = UBound(stringArray)
        For n = 0 To arraySize Step 1
            Set cell = Range(stringArray(n))
            If Mid(cell.formula, 1, 1) = "=" Then
                trimmer = Mid(cell.formula, 2, Len(cell.formula) - 1)
                If trimmer <> "" Then
                    result = Replace(result, stringArray(n), trimmer)
                End If
            End If
        Next
        If previousResult <> result Then
            result = CellFormulaExpand(result)
        End If
    End If
    CellFormulaExpand = result
End Function

Function CellFormula(rng As Range) As String
    CellFormula = CellFormulaExpand(rng.formula)
End Function

Para que funcione, basta criar uma macro (como descrevi no início da resposta) e copiar e colar o código. Depois disso, você pode usá-lo com o =CellFormula(A1) , em que A1 pode ser qualquer tipo de célula 1x1.

Casos que funcionam

Eu criei alguns exemplos para que você possa vê-lo em ação. Neste caso, eu demonstro o uso com strings. Você pode ver que funciona perfeitamente. O único pequeno bug é que em algum lugar o algoritmo muda o ponto e vírgula para vírgula. Depois de substituí-los (como fiz neste exemplo), você obtém a saída correta.

Aquivocêpodevercomofuncionacomnúmeros.Agoraenfrentamosoprimeiroproblema,queoalgoritmonãosepreocupacomasequênciadeoperaçõesmatemáticas,éporissoqueonúmerovermelhoé6quandodeveriaser10.Secolocarmosasoperaçõessensíveis(comoadiçãoesubtração)entreparênteses,entãoodadofórmulaintroduzidadevoltadaráamesmasaídaquevocêpodevernonúmeroverdenaparteinferiorquediz10.

Casos que não funcionam

Este algoritmo não é perfeito. Eu só tentei implementar os usos mais comuns, para que ele possa ser melhorado adicionando mais recursos que lidam com outros casos como intervalos. Como você pode ver neste exemplo, usei SUM() com um intervalo como parâmetro. Como o algoritmo descriptografa o conteúdo das células de cima para baixo, ele começa com a substituição dos parâmetros SUM() do que mais tarde por qualquer outra coisa. Portanto, o : fica em seu lugar enquanto tudo ao redor é substituído, então as novas células são substituídas perto dele, o que mudará o significado dele. Assim, a saída estará errada. Portanto, neste caso, você só pode usar essa macro para estudar a fórmula original.

    
por 08.03.2013 / 05:19
1

Considerando seu uso da palavra "trace" em sua pergunta, eu suponho que você esteja familiarizado com as funções Trace Precendents e Trace Dependents na seção de Auditoria de fórmulas do Excel?

Aqui está uma breve explicação de cada uma das ferramentas de auditoria de fórmulas do site dummies.com:

Entendendo as ferramentas de auditoria de fórmulas do Excel 2010

    
por 07.03.2013 / 11:10