Hi folks,
Here is a method I find incredibly useful. It's another one of those things I suspect a lot of you have already written but I haven't seen anyone talking about it so I will. This method allows you to write a formula as a text string referring to object keys then pass the formula and c-obj to the method. The key values are inserted into the formula and the result is returned. Optionally you can specify a result key and the result will be written to the object as well. The method assumes you're using Canon's OBJ component. If not just substitute whatever you use for getting/setting object values. This is v15 compatible. It could easily be modified to use the new dot-notation in v16. Note that you must wrap key names in the backtic (`). I needed something to identify a key from anything else and there are not a lot of unique options on the keyboard anymore. The actual calculation uses #4DEVAL so your formula can include: key names 4D methods project methods process and IP variables constants A formula might look like this: " ((`y` * 23) + `abs.frt`)^ `123.frt`" The extra spaces are just for readability - they are ignored in execution. All keys are read as REAL. Text keys are converted to real as are long and boolean keys. Missing keys are zero. If I want to assign the result of the formula to a key in the object: " `x`= ((`y` * 23)+`abs.frt`)^ `123.frt`" If x doesn't exist it's created. If it does it's updated. Finally the 3rd para allows you to specify writing the result as text in the object. Why you do that? There are good reasons for managing all values in a c-obj as text (it's easier). But this also allows you to do things like date operations and save the result as a date string, for example. Here are few uses: $formula:="`x` = Cos(`y`) " $formula:="`x`=((`y`*23) + `abs.frt`) ^ `123.frt`" $formula:="`x` = (<>IPconstant * processConstant)" // referring to keys is optional $formula:="`newDate`=String(Add to date(Current date;`year`;`month`;`day`);Internal date long)" This last one is particularly cool. It works because #4DEVAL simply evaluates the string passed to it. $formula:="<!--#4DEVAL "+$formula+"-->" //calculation PROCESS 4D TAGS($formula;$result) The result is text even though the calculation may return a real (or any other) value. Here's where the 3rd parameter comes in because it allows me to write this text result to the object. Consider an object: { "year": 0, "month": 1, "day": 23, } I pass the formula above: $x:=OB_calculate ($obj;$formula;True) The object is updated to: { "year": 0, "month": 1, "day": 23, "newDate": "March 16, 2018" } and $x is 162018 which is simply the numbers of the date string and meaningless. I developed this method to manage listboxes where the data for the listbox is in a hidden object array. This is a handy interface approach. It makes it possible to display a listbox where the calculations involve a large number of other values. Using arrays for the listbox data would typically involve a lot of hidden arrays. Using an object array involves only the columns of interest with the other data in the object. With this method I can update the object array as required. And since the formulas are all text based I don't even have to hard code the business logic of the formulas. I could allow end users to define their own business logic for their data, for instance. Or tailor how an interface works for particular instances. You can do that now too, of course, but this is probably a little easier. Note on string objects. In v15 using $real:=OB get($obj;"key";Is real) doesn't correctly convert a text value if it contains commas. Using the Num function accounts for this and also allows you to control the separator so I suggest using: $real:=Num(OB get($obj;"key";Is text)) If the key is already a real this won't matter and if it's text it will be handled correctly including currency symbols. Final note on key names - $pattern doesn't check for spaces in key names. This is technically allowed but usually discouraged. If you need to recognize key names with spaces tweak $pattern to suit. It does find hyphenated keys, eg. "pad-right". Be sure to add your preferred error checking code! ================================================= // OB_calculate // Written by: Kirk as Designer, Created: 01/21/18, 11:17:23 // ------------------ // Method: OB_calculate (c-obj; text{;bool}) -> real // $1 is a c-obj // $2 is a formula // ex: ((`y`*23)+`abs.frt`)^`123.frt` // or: `x`= ((`y`*23)+`abs.frt`)^`123.frt // write result to x // $3 is TRUE to write result to object as text - default is false // ignored if result isn't written to object // $0 is result // Purpose: The formula will be populated with key values and calculated // All keys are treated as REAL but the keys may be text, real, long, bool or date // Missing keys = 0 // Key names must be wrapped in backtic: `thisKey` and not contain spaces // any formatting in the key values will be ignored // This can also be used to simply write a value to an object. // The result key, if specified, will be added if it's not there // negative numbers in the object must be specified as -1234 // can not user parens to indicate negatives // Formula may contain 4D expressions and process or IP vars C_OBJECT($obj;$1) C_TEXT($2;$formula) C_BOOLEAN($3;$isText) C_TEXT($resultKey) C_REAL($0;$value) C_LONGINT($i;$n) C_TEXT($result;$pattern;$key;$str) $obj:=OB_New $obj:=$1 $formula:=$2 If (Count parameters>2) $isText:=$3 End if If (Position("=";$formula)>0) $resultKey:=Substring($formula;1;Position("=";$formula)-1) $resultKey:=Replace string($resultKey;"`";"") $formula:=Substring($formula;Position("=";$formula)+1) End if // -------------------------------------------------------- $pattern:="`([\\w\\d\\. - ]+)`" // for finding keys ARRAY LONGINT($aLen;0) ARRAY LONGINT($aPos;0) While (Match regex($pattern;$formula;1;$aPos;$aLen)) $key:=Substring($formula;$aPos{1};$aLen{1}) $value:=OBJ_Get_Real ($obj;$key) $str:=Substring($formula;$aPos{0};$aLen{0}) // the entire match string $formula:=Replace string($formula;$str;String($value)) End while // -------------------------------------------------------- $formula:="<!--#4DEVAL "+$formula+"-->" //calculation PROCESS 4D TAGS($formula;$result) // -------------------------------------------------------- $0:=Num($result) Case of : ($resultKey="") : ($isText) OBJ_Set_Text ($obj;$resultKey;$result) Else OBJ_Set_Real ($obj;$resultKey;Num($result)) End case -- Kirk Brooks San Francisco, CA ======================= *We go vote - they go home* ********************************************************************** 4D Internet Users Group (4D iNUG) FAQ: http://lists.4d.com/faqnug.html Archive: http://lists.4d.com/archives.html Options: http://lists.4d.com/mailman/options/4d_tech Unsub: mailto:[hidden email] ********************************************************************** |
Free forum by Nabble | Edit this page |