VB - Evaluar la expresión matemática de un string

Noviembre 2016


VBA cuenta con la función Evaluate que acepta como argumento el enunciado de una formula en una variable alfanumérica y devuelve el resultado en una variable alfanumérica.
En VB, esto no existe, uno mismo tiene que implementarla.
El programa que veremos a continuación ha sido creado como respuesta a una pregunta encontrada en los foros. Este acepta los cálculos simples +, -, *, y los paréntesis. Las funciones han sido hechas de modo que sea fácil agregar tipos como Sqr ^ etc.

Esta función trabaja del mismo modo que Evaluate: entrada de la función en alfanumérica, retorno del resultado en alfanumérica. Ver la imagen.

Esta sub sirve únicamente para el test.
Sub TestCalcul()  
Dim A As String  
Dim Ret As String  
    A = "(((3*(12.223+ 15)) - 7)*21)/7"  
    Ret = Evaluer(A)  
    'Debug.Print Ret  
    '= 224.007  
    A = "((123.32/2.67)*6)+2127.34"  
    Ret = Evaluer(A)  
    '=2404.46359550562  
    'Debug.Print Ret  
End Sub  

El código de las funciones


Function Evaluar(ByVal Txt As String) As String  
Dim i As Integer, oNB As Integer, fNB As Integer  
Dim P1 As Integer, P2 As Integer  
Dim Buff As String  
Dim T As String  
'Para los calculos es necesario un punto en lugar de la coma  
    Txt = Replace(Txt, ",", ".")  
'Ver si hay (  
    For i = 1 To Len(Txt)  
        If Mid(Txt, i, 1) = "(" Then oNB = oNB + 1  
    Next i  
'Si hay ( (abiertos), ver si concuerdan) (cerrados)  
    If oNB > 0 Then  
        For i = 1 To Len(Txt)  
            If Mid(Txt, i, 1) = ")" Then fNB = fNB + 1  
        Next i  
    Else  
'No hay parentesis, Evalua directamente el calculo  
        Evaluar = EvaluaExpresion(Txt)  
        Exit Function  
    End If  
    If oNB <> fNB Then  
'Los parentesis no concuerdan, mostrar mensaje de error de parentesis  
        Exit Function  
    End If  
      
    While oNB > 0  
'busca el ultimo parentesis abierto  
        P1 = InStrRev(Txt, "(")  
'Busca el parentesis que cierra la expresion  
        P2 = InStr(Mid(Txt, P1 + 1), ")")  
'Evalua la expresion que esta entre parentesis  
        Buff = EvaluaExpresion(Mid(Txt, P1 + 1, P2 - 1))  
'Reemplazar la expresion con el resultado y eliminar los parentesis  
        Txt = Left(Txt, P1 - 1) & Buff & Mid(Txt, P1 + P2 + 1)  
        oNB = oNB - 1  
    Wend  
'no mas parentesis, evaluar la ultima expresion  
    Evaluar = EvaluaExpresion(Txt)  

End Function  
Function EvalueExpression(A As String) As String  
Dim T As Integer, S As Integer  
Dim B As String, i As Integer, C As Boolean  
Dim c1 As Double, c2 As Double, Signe As Integer  
Dim R As String, Fin As Boolean, z As Integer  
      
    'quitar los espacios  
    A = Replace(A, " ", "")  
      
    While Not Fin  
        For i = 1 To Len(A)  
            T = Asc(Mid(A, i, 1))  
            If T < 48 And T <> 46 Or i = Len(A) Then  
                If C Then 'evalua  
                    If i = Len(A) Then  
                        c2 = Val(Mid(A, S))  
                    Else  
                        c2 = Val(Mid(A, S, i - S))  
                    End If  
                    R = Str(CalculSimple(c1, c2, Signo))  
                    If i = Len(A) Then  
                        Fin = True  
                    Else  
                        A = Trim(R & Mid(A, i))  
                        C = False  
                    End If  
                    Exit For  
                Else 'separa la 1ra cifra  
                    c1 = Val(Left(A, i - 1))  
                    Signe = T  
                    S = i + 1  
                    C = True  
                End If  
            End If  
        Next i  
    Wend  
    'reemplazar la expresión con el resultado  
    EvalueExpression = Trim(R)  
End Function 


En la función de abajo es posible agregar cálculos diferentes
Function CalculSimple(n1 As Double, n2 As Double, Signe As Integer) As Double  
    Select Case Signe  
    Case 43 ' +  
        CalculSimple = n1 + n2  
    Case 45 ' -  
        CalculSimple = n1 - n2  
    Case 42 ' *  
        CalculSimple = n1 * n2  
    Case 47 ' /  
        CalculSimple = n1 / n2  
    'Aquí, agregar otro calculo...  
    End Select  
End Function 


Nota: para que concuerde con una calculadora, primero habrá que evaluar la función * y / y luego los + y -
Ejemplo: 3+5*7
Una calculadora dará como resultado 5*7=35 + 3 = 38
Aquí tendremos 3 + 5= 8*7=56
Es posible modificar la función "EvaluaExpresion" o realizar el cálculo del modo 3 + (5*7) que dará como resultado 38.
Si encuentras algún error, puedes poner tu comentario en el foro de programación.


Consulta también :
El documento «VB - Evaluar la expresión matemática de un string» de CCM (es.ccm.net) se encuentra disponible bajo una licencia Creative Commons. Puedes copiarlo o modificarlo siempre y cuando respetes las condiciones de dicha licencia y des crédito a CCM.