The calcDays procedure just has a single executable statement, but it's one that demonstrates a couple of key new language concepts—assignment and Unknown value (?).
You're probably familiar with language statements that assign values by using what looks like an equation, where the value or expression on the right side is assigned to the field or variable on the left. ABL does this too, and uses the same equal sign for the assignment that is used for testing equality in comparisons. However, you can use the keyword EQ only in comparisons, not in assignments.
In this example, you want to subtract the ShipDate (which was passed in as the parameter pdaShip) from today's date (which, as you have seen, is returned by the built-in function TODAY) and assign the result to the OUTPUT parameter piDays.
To make this change in your sample procedure, add the following statement:
piDays = TODAY - pdaShip.
This is simple enough, but it won't work all the time. Remember that some of the Orders have not been shipped, so their ShipDate has the Unknown value (?). If you subtract an Unknown value from TODAY (or use an Unknown value in any other expression), the result of the entire expression is always the Unknown value (?). In this case you want the procedure to return 0. To do this you can use a special compact form of the IF-THEN-ELSE construct as a single ABL expression, appearing on the right side of an assignment. The general syntax for this is:
Syntax
result-value = IF logical-expression THEN value-if-true ELSE value-if-false.
This syntax is more concise than using a series of statements of the form:
Syntax
IF logical-expression THEN result-value = value-if-true.
ELSE result-value = value-if-false.
For your purposes you can refine the assignment statement in this way to allow for Unknown values:
piDays = IF pdaShip = ? THEN 0 ELSE TODAY - pdaShip.
Finally, you end each internal procedure with an END PROCEDURE statement. The keyword PROCEDURE is optional, but is always a good idea as it improves the readability of your code:
END PROCEDURE.
To see the calculated days displayed, run the procedure once more:
In summary, you define an internal procedure just as would an external procedure, with the exception that each internal procedure must start with a PROCEDURE header statement and end with its own END PROCEDURE statement. An external procedure uses neither of these.
You RUN an internal procedure just as you would an external procedure, except that there is no filename extension on the procedure name. Here are a couple of important related points.
First, it is possible for you to run an external procedure by naming it in a RUN statement without any filename extension, for example, RUN CustSample. In this case, the AVM searches for these forms of the procedure in this order:
1. An internal procedure named CustSample.
2. An external compiled file named CustSample.r.
3. An external source procedure named h-CustSample.p.
To do this, however, would be considered very bad form. When a person reading ABL code sees a RUN statement with no filename extension, it is natural for that person to expect that it is an internal procedure. There is rarely a good reason for violating this expectation.
Second, and even more exceptional, is that because a period is a valid character in a procedure name, it would be possible to have an internal procedure named, for example, calcDays.p, and to run it under that name. You should never do this. Always avoid confusing yourself or others who read your code.