Now it's time for another digression to introduce you to a powerful feature of ABL that will be helpful in completing the temp-table example. You might have noticed that to pass a temp-table from one procedure to another, you need to have an equivalent temp-table definition in both procedures. So the next thing you have to do in the Customers and Orders window is define the same temp-table as you just did in h-fetchOlines.p so you can use it as an INPUT parameter to the RUN statement to that procedure. Surely there must be a better way to duplicate code than retyping it or coping and pasting it?
ABL provides a mechanism for just this purpose, called an include file. An include file is a source procedure that is included in another procedure file to form a complete procedure that you can then compile. Using include files saves you from having to copy and paste code from one procedure to another when you need the same definition or other code in multiple places. More important, it can also save you from many maintenance headaches when you need to change the duplicated code. Rather than having to identify all the places where the code exists and change every one of them consistently, you just have to change the one include file and recompile the procedures that use it.
Having said this, it is important to make an observation about include files in an OpenEdge application. In later chapters, you learn how to use dynamic language constructs to allow the same procedure to work many different ways. For example, you can use them to manage a query on different tables or with different WHERE clauses that are defined dynamically at run time or to build a window that can display fields and a browse for many different tables, with all the objects defined dynamically, so their attributes can be changed at run time. This limits the need for include files in many cases.
In earlier applications, written before these dynamic features existed, ABL developers used include files to pass in, for example, the name of a table or a list of fields or a WHERE clause for a FOR EACH statement. In this way, the same procedure could be compiled many different ways to do similar jobs. With dynamic programming, you can often modify the same kinds of procedure attributes at run time, allowing a single compiled procedure to handle all the cases that you need, without creating many different .r files for all the different cases, or compiling and running procedures on the fly during program execution. For that reason, once you have learned about dynamic programming, if you find yourself doing extraordinarily complex or clever things with include files in a new application, you should consider whether you could do the same job more easily and more effectively with dynamic language constructs that are part of the language for exactly this purpose.
With these disclaimers aside, it is still valuable to know about include files and when you might use them. If nothing else, you will find many include file references in existing ABL code.
The syntax for an include file is extremely simple. You merely place the include filename, enclosed in braces ( { } ) into your procedure exactly where you want the code it contains to be inserted. This can be anywhere at all in your procedure. An include file can contain a complete statement, a whole set of statements, a partial statement, a single keyword or name, or even a fraction of a name, depending on what purpose it serves. The only limitation is that ABL always inserts a single space after (but not before) the contents of the include file when it pulls it in during the compilation. This means you could append a partial name or keyword directly to the end of a code fragment in the main procedure, but not to the beginning without a space being inserted.
By convention, include files end in the .i extension, but this is not actually required. If ABL needs a pathname relative to the Propath to locate your include file, then you need to include the pathname within the braces just as you would specify a relative pathname as part of the filename in a RUN statement. (Note that the ABL does not search procedure libraries for include files.)
In the simplest case, an include file just inserts the contents of the file into the procedure that includes it when the main procedure is compiled. You can also define arguments to include files. To add an argument to an include file, place the string {1} into the include file where you want the argument inserted. Then, in each include file reference, add the value of the argument after the name of the include file, separated by a space. For example, in the next section you will replace the four button triggers for the First, Next, Prev, and Last buttons with an include file. The code for all of those buttons is the same except for the one keyword in the GET statement FIRST, NEXT, PREV, and LAST. You can write all four triggers with one include file by adding an argument to the include file. If you call it h-ButtonTrig1.i, then the first line of code in h-ButtonTrig1.i is GET {1} CustQuery. And the trigger for the First button becomes {h-ButtonTrig.i FIRST}.
For multiple arguments to an include file, just mark them with placeholders {1}, {2}, and so on. You can also create named arguments that let you determine the arguments you pass into the include file when it becomes part of the compilation. For a complete description of include files and their arguments, see the Include File Reference topic in the online help.