Consultor Eletrônico



Kbase P39990: How to evaluate a math formula stored in a character variable?
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   24/06/2010
Status: Unverified

GOAL:

How to evaluate any 4GL expression on the fly?

GOAL:

How to dynamically evaluate a mathematical expression?

GOAL:

How to dynamically evaluate a string and return a logical expression?

GOAL:

How to dynamically evaluate a character expression?

GOAL:

How to build a "calculator" in 4GL?

FACT(s) (Environment):

Progress 9.x
OpenEdge 10.x
All Supported Operating Systems

FIX:

Prior to version 9 this was possible only doing a compile on the fly operation. Since the dynamic queries were introduced in Progress 9, it is possible to dynamically evaluate a string containing a mathematical expression and return it's result.

The solution is to open a dummy dynamic query, which predicate expression calls a dynamic-function, with the expression to evaluate passed as an input parameter.
This function actually evaluates the input expression, as documented in the online help page of the FUNCTION statement, so the result could be used by the dummy query.
At this point we manage to keep track of the result in a global variable.

Down here is a short example for evaluating a string expression and return a decimal value.
A more detailed example for evaluating a string to a decimal can be found in the solution notes: this one
DEFINE VARIABLE cExpression AS CHARACTER NO-UNDO.
DEFINE VARIABLE dResult AS DECIMAL NO-UNDO.
DEFINE VARIABLE lResult AS LOGICAL NO-UNDO.
DEFINE VARIABLE cResult AS CHAR NO-UNDO.
DEFINE TEMP-TABLE tt NO-UNDO /*dummy TT*/
FIELD f1 AS INTEGER.
DEF QUERY q FOR tt. /* dummy query, but required */
FUNCTION GetDecimal RETURNS LOGICAL
(INPUT dValue AS DECIMAL).
dResult = dValue.
RETURN TRUE.
END FUNCTION.
FUNCTION GetChar RETURNS LOGICAL
(INPUT cValue AS CHAR).
cResult = cValue.
RETURN TRUE.
END FUNCTION.
FUNCTION GetLogical RETURNS LOGICAL
(INPUT lValue AS LOGICAL).
lResult = lValue.
RETURN TRUE.
END FUNCTION.
/*Evaluate a 4GL decimal expression */
cExpression = "2 + 3.141592654 * 4".
QUERY q:QUERY-PREPARE("FOR EACH tt WHERE ~
DYNAMIC-FUNCTION( 'GetDecimal', " + cExpression + ") = TRUE").
QUERY q:QUERY-OPEN().
QUERY q:QUERY-CLOSE.
MESSAGE dResult VIEW-AS ALERT-BOX INFO BUTTONS OK.
/*Evaluate a 4GL character expression */
cExpression = "'ab' + 'cd '
+ replace('HELLO user-name','user-name','PROGRESS WORLD !')".
QUERY q:QUERY-PREPARE("FOR EACH tt WHERE ~
DYNAMIC-FUNCTION( 'GetChar', " + cExpression + ") = TRUE").
QUERY q:QUERY-OPEN().
QUERY q:QUERY-CLOSE.
MESSAGE cResult VIEW-AS ALERT-BOX INFO BUTTONS OK.
/*Evaluate a 4GL logical expression */
cExpression = "IF 2 + 2 = 4 THEN YES AND (yes OR NO) ELSE 2 + 2 = 4".
QUERY q:QUERY-PREPARE("FOR EACH tt WHERE ~
DYNAMIC-FUNCTION( 'GetLogical', " + cExpression + ") = TRUE").
QUERY q:QUERY-OPEN().
QUERY q:QUERY-CLOSE.
MESSAGE lResult VIEW-AS ALERT-BOX INFO BUTTONS OK.