Writing Transformation Expressions
Your goal is NOT to write an expression, but if you absolutely must write an expression, you want to make the expression as simple as possible, with lots of explanations (comments)! (Those explanations are invaluable if you have to come back and tweak the expression.)
Take advantage of what ProAdmin can do for you. For example, if you are writing an hours transformation let the Hours Service Definition and its parameters do as much as the work as possible (e.g., measurement periods, service rounding, service accruals automatically stop at decrement, special set of calculation dates). This means fewer errors/bugs and simpler expressions. (See How create hours when they haven't been supplied for an example expression.)
Please look in ProAdmin help for similar examples or bounce your ideas off an expert in your company or by contacting ProAdmin Support.
To understand how to create the simplest expressions, you often need to know about calculation dates, but in hours and salary transformation expression these are the biggies:
Why aren't there any calculation dates in a data default expression?
There aren't any calculation dates in a Data Default expression because the set of calculation dates is determined after all data defaults have been applied and after all Calculated Dates are determined. The only dates associated with a data default expression come from the fields used in a data default (e.g., date fields, effective dates, start/stop dates), certain expression functions (e.g., #BCDATE, #DODEC, #START, #STOP , #MPGEN), temporary variables, and how you manipulate the dates (e.g., date arithmetic).
Note, not having the set of calculations dates in a data default expression can make some expressions simpler/easier in a data default than in a transformation expression.
Temporary variables in expressions
You might notice that we use a lot of temporary variables in our expressions. We do that for two reasons, the first being that many array functions don't accept expressions as arguments. But the most important reason is for checking our results and being able to properly document the "intent" of the expression (e.g., comments for each step of the process). For example, this is a perfectly executable expression, but the answer may not be what you expect:
DropEvent:= [EventHistory #IN (10, 11)] #AND [ ('P' #GETASOF EventHistory) #IN (31,41)] &
; ignore/drop 31/10 and 41/11 event combinations
By creating temporary variables to capture intermediate results, It's easier to figure out is being evaluated (e.g., when 31/11 or 41/10 event pairs start getting dropped):
IsStart := EventHistory #IN (10, 11) & ; IsStart will be a scalar not an array!
PriorEvent := ('P' #GETASOF EventHistory) &
DropEvent:= IsStart #AND [PriorEvent #IN (31,41)] &