Jump to content

Definir expressão com variáveis em runtime


Seabra
 Share

Recommended Posts

Olá

Necessitava de ajuda para o seguinte caso:

Tenho várias variáveis: 

Dim CV1 As Integer= 7

Dim CV2 As Integer= 12

Dim CXP1 As Integer= 500

Dim CXPZ As Integer= 45

Dim CTF As Integer

...  ...

Pretendo digitar numa caixa texto a seguinte expressão:  CTF=CV1+CXP1*6  e quando actuar num botão o resultado seja apresentado.

Claro que em runtime pretendo poder alterar a minha expressão e utilizar outras variáveis que foram definidas no desenvolvimento.

Pretendo começar não sei por onde, poderá haver já alguma forma prática para o fazer. alguem já o fez que me possa dar uma ajuda?

Cumprimentos

Link to comment
Share on other sites

Olá

Penso que será algo do género disto que precisas.

http://www.codeproject.com/KB/recipes/Dynamic_Formula_Evaluator.aspx

Public Class Evaluator

    Dim scriptControl As New MSScriptControl.ScriptControlClass
    Private _Formula As String
    Private _VariablesPreffix As String
    Private _Operators As ArrayList
    Private _CorrectedFormula As String
    Private _FormulaVariables As ArrayList
    Private _ParseCondition As ParseCondition = _
             ParseCondition.RaiseErroForUndefinedVariable

    Public ReadOnly Property Formula() As String
    Get
        Return Me._Formula
    End Get
    End Property

    Public ReadOnly Property VariablesPreffix() As String
    Get
        Return Me._VariablesPreffix
    End Get
    End Property

    Private Sub PreEvaluate(ByVal keyCode As String, ByVal keyValue As String)
        Me._Formula = Me._Formula.Replace(keyCode.ToUpper, keyValue)
    End Sub

    Private Sub PreEvaluate(ByVal keyValuesDictionary As Hashtable)
        For Each keyCode As String In keyValuesDictionary.Keys
            Me.PreEvaluate(keyCode, keyValuesDictionary(keyCode))
        Next
    End Sub

    Public Function Evaluate(ByVal values As Hashtable) As Double
        Dim tmpFormula As String = Me._Formula
        For Each var As String In Me._FormulaVariables
            Select Case var.ToLower
            Case "abs", "round", "fix", "sin", "exp", "cos", _
                 "int", "atn","tan","sqr", "sgn", "log"
            Case Else
                Dim index As Integer = CInt(var.Replace(Me._VariablesPreffix, ""))
                If Not values(index) Is Nothing Then
                    tmpFormula = tmpFormula.Replace(var, values(index))
                Else
                    If Me._ParseCondition = ParseCondition.RaiseErroForUndefinedVariable Then
                        Throw New Exception("Undefined variable!" & vbCrLf & _
                              "Base formula: " & Me._Formula & vbCrLf & _
                              "Corrected formula: " & Me._CorrectedFormula & _
                              vbCrLf & "On variable: " & var)
                    Else
                        tmpFormula = tmpFormula.Replace(var, 0)
                    End If
                End If
            End Select
        Next
        Try
            Return CDbl(scriptControl.Eval(tmpFormula))
        Catch ex As Exception
            scriptControl.Error.Clear()
            Return -1
        'Throw New Exception(tmpFormula, ex)
        End Try
    End Function

    Public Sub New(ByVal formula As String, ByVal variablePreffix As String, _
                   ByVal parseCondition As ParseCondition, _
                   Optional ByVal preEvaluateKeyValuesDictionary As Hashtable = Nothing)
        scriptControl.Language = "vbscript"
        Me._Formula = formula
        Me._VariablesPreffix = variablePreffix
        Me._ParseCondition = parseCondition
        InitializeOperators()
        If Not preEvaluateKeyValuesDictionary Is Nothing Then
            Me.PreEvaluate(preEvaluateKeyValuesDictionary)
        End If
        InitializeFormula()
    End Sub

    Private Sub InitializeOperators()
        Me._Operators = New ArrayList
        Me._Operators.Add(CChar("+"))
        Me._Operators.Add(CChar("-"))
        Me._Operators.Add(CChar("/"))
        Me._Operators.Add(CChar("*"))
        Me._Operators.Add(CChar("^"))
        Me._Operators.Add(CChar("("))
        Me._Operators.Add(CChar(")"))
        'Me._Operators.Add(CChar(","))
    End Sub

    Private Sub InitializeFormula()
        Me._CorrectedFormula = Me._Formula.Replace(" ", "")
        Me._FormulaVariables = New ArrayList
        Dim arrOperators() As Char
        Dim variables() As String = _
            Me._CorrectedFormula.Split(CType(Me._Operators.ToArray(GetType(Char)), Char()))
        For Each var As String In variables
            var = var.Trim
            If var.Length > 0 AndAlso Not IsNumeric(var) Then
                Me._FormulaVariables.Add(var)
                If Not IsNumeric(var.Replace(Me._VariablesPreffix, "")) Then
                    Select Case var.ToLower
                     Case "abs", "round", "fix", "sin", "exp", _
                          "cos", "int", "atn","tan", "sqr", "sgn", "log"
                    Case Else
                        Throw New Exception("Wrong formula!" & vbCrLf & _
                                            "Base formula: " & Me._Formula & _
                                            vbCrLf & "Corrected formula: " & _
                                            Me._CorrectedFormula & vbCrLf & _
                                            "On variable: " & var)
                    End Select
                End If
            End If
        Next
    End Sub

    Public ReadOnly Property Operators() As ArrayList
    Get
        Return Me._Operators
    End Get
    End Property

    Public ReadOnly Property ParseCondition() As ParseCondition
    Get
        Return Me._ParseCondition
    End Get
    End Property

End Class

Public Enum ParseCondition
    RaiseErroForUndefinedVariable
    DoNotRaiseErroForUndefinedVariable
End Enum

Dim calculator As New Evaluator("Round((P1+P3)/P2)", "P", _
               ParseCondition.DoNotRaiseErroForUndefinedVariable)
Dim parameters As New Hashtable
parameters.Add(1, 12)
parameters.Add(2, 24)
parameters.Add(3, 6)
Dim value As Double = calculator.Evaluate(parameters)
Link to comment
Share on other sites

Boas

Ao testar depois de adicionar a referencia MSScriptControl.ScriptControlClass dá-me este erro:

System.Runtime.InteropServices.COMException was unhandled

  ErrorCode=-2147221164

  Message="Retrieving the COM class factory for component with CLSID {0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC} failed due to the following error: 80040154."

Pelo que me apercebi deve-se ao facto de estar a utilizar o WIN7 64bits.

Como poderei resolver isto?

Seabra

Link to comment
Share on other sites

Hmm..

Se o problema for dos 64bits,

experimenta alterar o "Target CPU" para x86 em "Advanced Compile Option" Nas propriedades do projecto.

De facto já funciona e em principio resolve. Obrigado

Mas ainda relaçionado com o meu primeiro post,  gostava de perceber como é que, quando digito na combobox, o nome de uma variavel que defini em desenvolvimento, a posso utilizar par somar um numero inteiro?

Dim CV1 As Integer= 7

Dim CV2 As Integer= 12

Dim CXP1 As Integer= 500

Dim CXPZ As Integer= 45

Dim CTF As Integer

'digitei em runtime na combobox1  CV1

Combobox1.text

'Isto não funciona, mas a ideia é esta.

Combobox2.text=Combobox1.text + 5  '''''O ComboBox1.text tem que ter o valor que esta em CV1 que é 7 para poder somar 5

Cumprimentos

Seabra

Link to comment
Share on other sites

Deve existir alguma forma melhor de o fazer,

mas experimenta fazer replace a string com o valor da box.

Tipo:

Dim s As String = Combobox1.text

If s Like "*CV1*" Then
   Combobox2.text = s.Replace("CV1", CV1) & "+" & "5"
   'vais ficar com a string "7+5"
End If

Edit: Tinha percebido mal  👍

Combobox1.text="CV1"
Combobox2.text="Combobox1.text + 5"
Dim CV1 As Integer = 7
Dim s As String = Combobox2.text

If s Like "*Combobox1.text*" Then
'a var s vai ficar com a string "CV1 + 5"
  s = Combobox2.text.Replace("Combobox1.text", Combobox1.text)

'a var s vai ficar com a string "7 + 5"
  s = s.Replace("CV1", CV1)

End If
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.