AS/400 Chapter 1: Introduction This tutorial is an introduction to the AS/400 (System i5) system and to the RPG and DDS

programming languages. This is the first from a series of nine articles covering several aspects of the system. AS/400 is a computational platform launched in 1988 by IBM. Currently it is officially named System i5, although the term AS/400 is still widely used, because of that we will be using the term AS/400 throughout the tutorial, just be aware it's not its official name anymore. The machine's operating system is usually OS400. This system has several application from database managers to compilers, editors, etc. AS/400 supports several programming languages like Java, C, SQL, Assembly, COBOL,PHP, etc. Minimum requirements to complete the tutorial: Basic programming knowledge. Basic database knowledge (relational model, SQL). Access to an AS/400 server. Access terminal to the AS/400 server (in this tutorial the examples are given using Moshasoft). A small application will be built through each chapter. After the last chapter the application will be able to manage a set of shops and their clients. At the end of each chapter you will be given the source code to the complete application.

This is the application's data model

AS/400 Chapter 2: Commands To navigate through the AS/400 system you must know some commands and how to use them. There is also a simple syntax that can help you remember some forgotten command. In AS/400 the commands can be executed from the system prompt. You can find it on the lower part of the screen. It looks like this: ==> ________________________________________________________________ Underneath the system prompt there is usually a list of function keys with tasks specific to the menu you are currently in. Place the cursor at the prompt line,type GO and then press F4. A new screen will appear, specific to the GO command, where you can define all the options for this command.The F4 key can help you complete the syntax of most AS/400 commands. Type MAJOR on the “Menu” option and press Enter. This shows the same result as typing GO MAJOR in the command line. This command shows you a list with the most important commands in AS/400. The word “More...” on the bottom-right side of the list shows that there are lines that aren't visible. You can see these lines by pushing Page Down or using the mouse scroll. Place the cursor on top of any of the options on the list and press F1. A window will appear with help about the option you chose. You can use this feature in most of the menus and applications. To close the help window press F3. You can choose an option by typing its number on the prompt and pressing Enter. Let's go back to the start screen. Press F3. Command Syntax AS/400 commands usually have two parts (often with three letters each):a verb and a noun. For instance, CTRLIB is the create library command and it has a verb CRT (create) and a noun LIB (library). There are some exceptions, like the GO command we saw earlier. In the following list you can see frequently used command verbs and nouns. Verb CPY DSP DLT WRK Meaning Copy Dysplay Delete Work Noun Meaning DEV F MSG SPLF Device File Message Spool File

If you can't remember command syntax, use the command GO VERB, which will show you a list of commands ordered by their functions. AS/400 Chapter 3: Libraries You can use a library in AS/400 just as you would use a folder in Windows to organize your files; there are some differences, of course. Let's see how a library works in

AS400. A library is similar to a folder in Windows. In AS/400 a library is another object that can contain other objects (executable objects, source files, etc). Libraries can't contain other libraries. AS/400 is structured as a list, the opposite of Windows which has a tree-like structure. Creating a library We're now going to create a library, called DEMO, where we'll place all the files from this tutorial. Type the command: CRTLIB DEMO Your library is now created. Changing the current library (CURLIB) You can change the current library towork more easily with objects.This way you don't have to specify the library name each time youwant to work with a file. To change the library you are currently in type: CHGCURLIB DEMO All the objects you create will be placed on your CURLIB (if you don't explicitly specify the library name). If you want to refer to the library you are currently in you can use it's name or the keyword CURLIB. You can change your default library (the library where you are when you enter the system) so that you don't have to change your current library each time you enter the system:CHGPRF CURLIB DEMO Be aware that if you don't change your opening or your current library, you can get some compilation errors. If you have a reference to a file (without it's library name) in your source code the compiler won't find it if it is placed on another library. Libray Lists Every command we use is stored in a specific system library. When a command library isn't explicitly identified, the system will search for the command in every library in its library list until the command if found. So, if you have 2 commands with the same name on different libraries, the system will execute the one that is placed on the up most library on the list. You can only have files with the same name in the same library if they are of different types. You can see the library list with the command:DSPLIBL You can see in the listing that there are different types of libraries: SYS: System libraries. All the essential objects to the system (commands, applications, compilers, etc). CUR: The library you're currently in. USR: User libraries (can be created by the user or the system manufacturer). Press F3 to go back to the previous screen. AS/400 Chapter 4: SQL In AS/400 you can use SQL to work with tables and table data. There are also some very useful built-in functions you should know about. Now that we've created a library and saw some basic AS/400 features let's have a look at how we can create and

manipulate tables using SQL. You must create the DEMO library and define it has your current library to proceed with this chapter. Type the following Start SQL command on the

system prompt: STRSQL

This way you begin a SQL session in AS/400. This application accepts most of the common SQL syntax (CREATE,INSERT, DELETE, SELECT, DROP, etc). Creating a table with SQL From the SQL command line we're going to create the CLIENTS table and then insert some rows. For this tutorial let's assume that all phone numbers have, at most, 9 digits. Press F3 to leave the table view and type the following commands. Type: CREATE LIBRARY DEMO/CLIENTS( id_cli numeric(10) PRIMARY KEY, name_cli char(50), birth_cli date, phone_cli numeric(9) ) Note: You can place the code in separate lines (like in the example) or in a continued fashion (without indentation) as long as you don't press the Enter key before you finish the command. A message will appear saying that the table was created. If you want to see more empty command lines just press Page Down or move the mouse scroll down. Now Type: SELECT * FROM CLIENTS, This way you can see that the table was created and it has no information in it. So let's insert some new rows. Press F3 to leave the table view and type the following commands. INSERT INTO CLIENTS (ID_CLI, NAME_CLI, BIRTH_CLI, PHONE_CLI) VALUES (1, 'Mary', '12/09/1967', '999999999')

INSERT INTO CLIENTS (ID_CLI, NAME_CLI, BIRTH_CLI, PHONE_CLI) VALUES (2, 'Tom', '09/01/1979', '123456789') Do the SELECT command again to check if the rows were correctly inserted.

Press F3 to leave the SQL command line. A set of options will appear. On the field you should write the option number. Try typing a number outside the option range (for instance 5) and then press Enter. As one would expect, an error message appears on the bottom of the screen. Try pressing F3 or inserting another value. It won't work because the screen is blocked. You will probably find some blocking errors and when you do press Esc the screen will go back to normal. Now select the option 1 to exit the application, saving the session. SQL Built-In Functions There are some very useful SQL built-in functions on the AS/400 system. Basic Functions If you know SQL you may already be familiar with these functions. Function MAX MIN AVG SUM COUNT Description Returns the maximum value from a set of pre-defined values. Returns the minimum value from a set of pre-defined values. Returns the average value of a set of pre-defined values. Returns the sum of a set of pre-defined values. Returns the number of elements in a set of pre-defined values.

Example (returns the maximum ID_CLI value from all the rows in the table CLIENTS): SELECT MAX(ID_CLI) FROM CLIENTS Numeric Functions Function ABS(N) Description Returns the absolute value of N.

COS(A) / ACOS(A) SIN(A) / ASIN(A) Basic trigonometric functions. TAN(A) / ATAN(A) CEILING(N) FLOOR(N) DEGREES(R) RADIANS(D) LN(N) LOG10(N) String Functions Function CHAR(N) CHAR_LENGTH(S) CONCAT(S1, S2) SUBSTR(S, I, L) LOWER(S) UPPER(S) TRIM(S) RTRIM(S) LTRIM(S) Function CURDATE() CURTIME() DATE(D) DATE(T) DAY(D) WEEK(D) MONTH(D) Description Returns the the string representation of the number N. Returns the length of a string. Concatenates S1 with S2. Returns a substring of S, starting at index I of lenght L. Returns the lowercase representation of S. Returns the uppercase representation of S. Removes spaces from the beggining and and of S. Removes spaces at the begging (right) or end (left) of S. Description Returns the system's current date/time. Converts a string representation of a date/time into into a date/time value. Returns the day(1-31) from the date D. Returns the week (1-54) from the date D. Returns the month (1-12) from the date D. Returns the rounding of N to the unit above/below. Converts a value in radians to degrees. Converts a value in degrees to radians. Returns the natural logarithm / base 10 logarithm of N.

Date and Time Functions

Function YEAR(D) DAYOFWEEK(D) DAYOFYEAR(D) HOUR(T) MINUTE(T) SECOND(T) MICROSECOND(T)

Description Returns the year from the date D. Returns the week day (1-7) from the date D where 1 is Sunday. Returns the number of the day, in a year (1-366). Returns the hour (0-24) from the time T. Returns the minute from the time T. Returns the second from the time T. Returns the microsecond from the time

DAYOFWEEK_ISO(D) Returns the week day (1-7) from the date D where 1 is Monday.

AS/400 Chapter 5: Physical Files You can use files to define tables, executable code, etc. In this chapter we'll try to explain some basic concepts of working with files. We've created a table using SQL, now we'll create the remaining tables with DDS. Source files are files that can have several members. Each member represents the source code from an executable object or an executable object. A source file is similar to a folder where you can organize its members. The source file naming follows an established convention: QRPGLESRC – file that holds the members written in RPG-ILE language. QDDSSRC – holds the members written in DDS. QRPGSRC – holds the members written in the traditional RPG language. As you can see, all the names start with a Q and end with SRC. You don't need to follow this convention and there isn't any problem at the system level if you don't. But since it's a well established convention and it really helps with the code organization, you should follow it. Let's create our first source file where we will later add our DDS tables. CRTSRCPF FILE(DEMO/QDDSSRC) If you're currently in the DEMO library you don't need to specify it in the command. PDM (Programming Development Manager) We're going to use the PDM application that enables the user to write the source code and compile it, among other things. PDM uses the SEU (Source Entry Utility) text editor, we will see how to use it in this chapter. To start the PDM type the command: STRPDM

A screen similar to this will appear:

Choose the option '3. Work with members'. We are going to create some members in the QDDSSRC source file. With the option 2 you can work with compiled objects and with option 1 work with libraries. On the next screen you will be asked for the filename and the library where it's stored. Insert the information you see in the image below:

Note: Your current library and the library you are working with in PDM are two different things. You can be working with members from DEMO and your current library can be DEMO2, for example. Now you should see the screen bellow. You will find all the options for working with file members.

Press F6 so you can create your first member (you can see in the options bellow the prompt: “F6=Create”). Insert the information as you see below:

Working with SEU (Source Entry Utility) SEU screen:

RPG and DDS are positional languages, wich means that each element has a specific line and column were it should be placed in the source code. SEU gives us a little help to position each element in its place. If you put the cursor in any of the SEU's lines and press F4 a prompt will appear, like the one in the next image, where you can write each element and the SEU will place it its right position. To close the prompt press F12.

Insert a new line Write an “i” (without quotes) on any position of the numbered column on the left. Press Enter, and a new line will be added bellow.

Delete a line Write a “d” (without quotes) on any position of the numbered column on the left and press Enter. Delete several lines Place “dd” (without quotes) on the numbered column of the first line you want to delete and another set of “dd” on the last line to delete, press Enter. DDS Syntax Let's start by defining the member SHOPS as it's written bellow. After the code you'll find the explanation of what each line means. UNIQUE R SHOPR ID_SHP 10P NAME_SHP 25A MANAGER_SH 50A K ID_SHP Line 1 To ensure that the primary key has an unique value for each record you must specify the keyword UNIQUE in the first line of the table definition. Press F4 and write unique in the functions field. Line 2 Here you define the table record name. The record identifies all the fields in a table. We will see an example of its use in the Display Files chapter. Insert a new line bellow the first, as we explained previously and press F4. Place an “R” in the Name Type field and SHOPR in the Name field. Line 3, 4 e 5 Definition of the table fields. In the third line, for instance, in the F4 prompt you should place “ID_SHP” in the Name field, 10 in the Length (must be right justified in the field), “P” in the Data Type (because it's a numeric value). Most common data types : A - Alphanumeric S – Numeric (Zoned Decimal) P – Numeric (Packed Decimal) L - Date For more information on data types press F1 after you placed the cursor on the Data Type field. Or visit ILE RPG Reference. Line 6 Definition of the primary key field. “K” is the Name Type and in the Name you should write the name of the field exactly as it is written above. For more than one primary key you should have a different “K” starting line for each primary key field.

When you finish writing the code press F3 to leave the editor and save the changes you've made. Useful DDS Functions If you want to use any of these functions place it in the Functions field. CHECK CHECK(AB): Allows the field to be blank CHECK(ME): Mandatory Enter. The field must have a value (not blank). CHECK(MF): Mandatory Fill. For example, if you have a string of size 50 all the 50 characters must be filled. COMP Compares values. The syntax is COMP(relational-operator value), where relationaloperator can be one of these values: EQ (equal) NE (not equal) LT (less than) NL (not less than) GT (greater than) NG (not greater than) LE (less than or equal to) GE (greater than or equal to) DATFMT Specifies the format of a Date field. Some of the possible formats are: *ISO: yyyy-mm-dd *EUR: dd.mm.yyyy *USA: mm/dd/yyyy *MDY: mm/dd/yy *DMY: dd/mm/yy *YMD: yy/mm/dd TIMFMT Specifies the format of a Time field. Some of the possible formats are: *ISO: hh.mm.ss *EUR: hh.mm.ss *USA: hh:mm AM/PM *HMS: hh:mm:ss RANGE Defines the maximum and minimum value a field can have. Examples: For a numeric field: RANGE(4 9)

For a non-numeric field: RANGE('4' '9') VALUES Specifies all the valid values on a field. Examples: For a numeric field: VALUES(4 5 6 7 8 9) For a non-numeric field: VALUES('a' 'b' 'c' 'd') DFT Specifies a default value. REFFLD Specifies that a field refers to a field in another table (foreign key). In this case you don't specify the Data Type or the Length of the field, but you must place an “R” in the Ref field in the F4 prompt. Example: CARD_MOV R REFFLD(ID_CRD DEMO/CARDS) Compiling Files To create the object that will save the data (the file you've just created only stores the source code) choose option '14- Compile' in the file you've created. This tutorial won't teach you to analyse the resulting files from a compilation, but if you want to give it a go write the command WRKSPLF (Work spool file) in the system prompt. The most important messages from the compilation usually appear on the file with the same name as the one you compiled (the most recent compilation appears on the bottom of the list). A quick way to check if a file's compilation was successful is to see if the new object was created. To do so you must go to the opening screen in the PDM choose option '2 – Work with objects' and put the options as you see in the image bellow and press Enter.

Now check to see if there's a member named SHOPS (the same name you gave to the source code member). If you do this you need to be careful because this only works correctly for the first compilation, because an object always keeps the data from the last successful compilation. So, if after a successful compilation you alter the source code and compile it again, even if this compilation ends in error, the object will still be in the system with the definitions of a previous compilation. You can however delete the compiled object before a new compilation (in the same menu where you checked if the file exists) - this way you can be sure that the compilation was successful. You have now all the information you need to create DDS tables. Create the CARDS and MOVEMENTS tables, using the same field’s names as in the data model, because we will be using those later on. When you're finished, or if you have any doubt, check the files with the final results. AS/400 Chapter 6: RPG RPG is one of the AS400 platform pillars. Originally designed as a query tool it has been substantially enlarged, it is currently a very powerful language. Let's see how you can use it. RPG is a programming language best suited for business applications. Originally the acronym meant Report Program Generator, but currently it has no officially meaning. For the purpose of this tutorial we will use the latest RPG version: RPG IV. RPG, like DDS, is a positional language despite its last version allowing a free format where you can place the code in mostly any column or line. In the RPG code there are several different types of specifications. Each has a different function and they all appear in the file in a specific order. The letter that represents the specification must be placed in the initial position of the source code line. Next we have a description of each specification in the order they appear in a file. H Specification (header) Compile/execution options. F Specification (file) Files definition and how they are used in the program. Options in an F specification (for more info on any option place the cursor on it and press F1):

D Specification (definition) Here you can define variables and data structures, for instance:

C Specification Here you define the source code. There is a free format for this specification but to do so instead of placing a C at the beginning of a line you should place free in the beginning of the code block and end-free in the end. These keywords must start in the the second position from the beginning of the line (in SEU). Basic RPG Syntax Valid operators = (compare and attribute), +, -, *, /, >, >=, <, <=, <>, NOT, AND, OR Conditional Expressions if condition; //code else; if other-condition; ... endif; endif; Ciclo do-while doW condition; //code endDo; Creating and defining an RPG member In this chapter you're going to create a program that shows the number of cards the client with ID 1 has. You must first insert some records in the CARDS table associated

with client 1. Do this from STRSQL. Create the source file DEMO/QRPGLESRC. Inside this source file create a member named COUNTCARDS. The member type must be SQLRPGLE. Since we're not going to explicitly open any file, there won't be any lines with F specification. You must define a variable (count) that will store the number of cards from the client. Place the letter “D” in the first column of the SEU editor and press F4. This variable will be simple (place an “s” in the Declaration Type), numeric, with length 5 and 0 decimal places. Initiate the variable to zero with the function INZ(initialvalue) in the Keywords field. Were you able to declare the variable with the F4 prompt help? If not, check the final result further ahead. Try to create the code for the next three points. Keep in mind that in the free format RPG you can write your code in whatever column you like (but it must at least start in column 3 in the SEU) and that each code line must end with a semi column (;). Initiate (/free) and finalize (/end-free) the code block in separate lines, starting from the second column in SEU. Print the value of the count variable. To print values on the screen you can use the dsply function. Dsply syntax: dsply value. In the last line, before /end-free, you must activate the end of code indicator *inlr (in last row). You activate it like this: *inlr = *on; If you completed the three points and declared the variable you should have something like this: * this is a comment * variable definition Dcount s 5P 0 INZ(0) /free dsply count; * displays the count value on the screen *inlr = *on; * tells the compiler that this is the last line. /end-free Try to compile the source code now (option 14 of PDM). If the compilation was successful execute the program typing the following line in the system prompt: call DEMO/COUNTCARDS The following information should appear: dsply 0 A list of values may appear (from previous events), but the one from the current execution is the last one on the list. For instance if you call the COUNTCARDS twice on the list you'll see: dsply 0 dsply 0 We still need to count the number of cards client 1 has.

Embedded SQL and Subroutines To view and alter tables we can use SQL code embedded in RPG code (RPG provides a way to manipulate tables, but since you should already know SQL we'll use it instead). This is how we embed SQL in RPG: c/EXEC SQL c+ SQL-instruction c/END-EXEC In each EXEC block you can only have one SQL statement. We will see a better example of this in the next chapter. So, to retrieve the number of cards we can do this query (write this code at the end of the source code, after the end-free): c/EXEC SQL c+ SELECT COUNT(*) INTO :count FROM DEMO/CARDS c+ WHERE CLIENT_CRD = 1 c/END-EXEC To better organize your code we will place this EXEC block in a subroutine. A subroutine is kind of like a function but it doesn't allow parameter passing or returning values although you can change globally defined variables. Inside a subroutine you can have free-format RPG, fixed-format RPG or EXEC instructions. The EXEC block you just created should be placed in a subroutine called getNrCards. This is how you do it (you can use the F4 prompt to place the keywords correctly): c getNrCards begsr c/EXEC SQL c+ SELECT COUNT(*) INTO :count FROM DEMO/CARDS c+ WHERE CLIENT_CRD = 1 c endsr To run the subroutine you must call it in the main /free block. Place this line before displaying the count variable. exSr getNrCards; *execute sub-routine getNrCards Compile and run the code again. Did you get the same result? If so, check to see if client 1 exists and that there are cards associated with him. And, of course, the tutorial must be correctly completed until this point. If even that doesn't work compare your code with this one: Dcount s 5P 0 INZ(0) *------------------------------------------------* /free exSr getNrCards; dsply count; *inlr = *on; /end-free

*------------------------------------------------* c getNrCards begsr c/EXEC SQL c+ SELECT COUNT(*) INTO :count FROM DEMO/CARDS c+ WHERE CLIENT_CRD = 1 c/END-EXEC c endsr AS/400 Chapter 7: Modules and Procedures Implementing modules can be extremely useful, especially in big applications because it allows the reuse of code in a fairly simple manner. A module is an executable program's component. When we compile a module's source code we don't get an executable file, but a unit that when connected to other units results in the executable object. A module can have on or more procedures. A procedure is like a function. You can pass parameters to it and return values. One of the advantages of modules is the possibility of reusing the code, since you can use a module as a component of several different executable objects. Creating modules We're going to create two modules and then connect them into an executable object. What the modules will do: the main module sends a client's birth date to a procedure in the other module and this procedure will return the age of the client. We're going to calculate the age of all the clients. Let's start with the main module. Create an SQLRPGLE member called MAIN_MOD. Define a date variable to store the birth date (name it birth) and a numeric one to store the age (name it age). Let's build a cursor to go through all the records in the CLIENTS table. For the cursor we need 4 subroutines: Declaring the cursor (subroutine name: declareCursor) DECLARE CURSOR1 CURSOR FOR SELECT BIRTH_CLI FROM DEMO/CLIENTS Opening the cursor (openCursor) OPEN CURSOR1 Fetching values from the cursor (fetchCursor) FETCH CURSOR1 INTO :birth Closing the cursor (closeCursor) CLOSE CURSOR1 Now for the main block of the code, call the subroutine to declare the cursor and to open it. Then, inside a cycle, fetch values from the cursor like this: exSr fetchCursor; dow sqlcod <> 100; ... exSr fetchCursor; enddo;

or dow sqlstt = '00000'; exSr fetchCursor; ... enddo; sqlcod and sqlstt variables store the state from the last SQL instruction performed. Sqlstt = '00000' means success, while sqlcod = 100 means the last instruction didn't retrieve any data. Let's close this module and create the second module with the procedure that calculates the age. Create a new RPGLE type member named CALC_AGE.On the first line of this member should be HNOMAIN, starting at the first SEU column. This means that this module won't be a main module. Procedures Now we're going to see how to declare a procedure and its parameters. A procedure is delimited by: 1. Pnome_proc B EXPORT 2. Dnome_proc PI 3i 0 3. Dparametro1 D 4. 5. ...declarações de código 6. 7. P E Line 1 Beginning of the procedure, with a P starting the line. The B (begin) defines the beginning of the procedure and the E (end) at line 4 defines its end. The EXPORT keyword makes this procedure public to other modules. If it didn't have this keyword it could only be used inside this module. Line 2 The name of the procedure is repeated this time in a D specification. In this line the return type is declared. The return type of this procedure is “3i 0” - an integer of length 3 with 0 decimal places. If the procedure doesn't return any value, declare this line without the return type. In this case you wouldn't declare '3i 0'. Line 3 Defines a parameter. A procedure can have more than one parameter and each one should be declared in a different line. By default the parameter is passed by reference. To pass a parameter by value we use the VALUE keyword in the functions field. With the CONST keyword the parameter is passed by reference and its value can't be altered in the procedure. Linha 7 End of procedure. Now you can define the beginning and end of the CALC_AGE procedure (it has the same name as the file but it could have another name). The

procedure will receive a date by parameter and return an integer - define them. Outside the parameter definition declare an auxiliary variable to store the age (name it age). When you're through with this, check if it looks like what we have bellowed, and add line 6 to your code: 1. Dage S 3P 0 2. PCALC_AGE B EXPORT 3. dCALC_AGE PI 3i 0 4. Db_date D 5. /free 6. age = %diff (%date() : b_date : *years); 7. return age; 8. /end-free 9. P E Linha 6 The %date() function returns the system date. The %diff function calculates the difference between two dates (%date() and bdate) in years (*years). Notice how the values are separated by a colon (:). This is the parameter separator used in RPG. It's just like the comma used in C++ or Java. For more information on manipulating dates in RPG check this site. Linha 7 Returns the value. There is still one detail missing in the declaration of procedures. Every time we declare a procedure or we need to call it from another module we must place the procedure's prototype in the D specification of the file. This procedure's prototype: DCALC_AGE PR 3i 0 Db_date D So, you must put these lines in the CALC_AGE file (before or after the declaration of the age variable). You declare it there and on the MAIN_MOD file, because you need to call this procedure there. Notice de declaration of the return type and the parameters on the prototype. These values must match those on the beginning of the procedure. * HNOMAIN * Dage S 3P 0 DCALC_AGE PR 3i 0 Db_date D * PCALC_AGE B EXPORT

dCALC_AGE PI 3i 0 Db_date D /free age = %diff (%date() : b_date : *years); return age; /end-free P E Back to MAIN_MOD, we're going to declare the procedure's prototype and call it. You should have something like this: Dbirth s d Dage s 3i 0 /free exsr declareCursor; exsr openCursor; exsr fetchCursor; dow sqlcod <> 100; exsr fetchCursor; enddo; exsr closeCursor; *inlr = *on; return; /end-free * * declaração das sub-rotinas * Declare the prototype exactly the same way as you declared it on the CALC_AGE file.Inside the cycle you must call the procedure: age = CALC_AGE(birth); The cycle should look like this: dow sqlcod <> 100; age = CALC_AGE(birth); dsply age; exsr fetchCursor; enddo;

Compiling modules Compile the two members (MAIN_MOD and CALC_AGE) with PDM's option “15-Create module” (this is the one you should always use to compile modules). After compiling the modules, connect them into an executable file, as we show you next. Criação de um programa a partir de módulos You connect modules with the command: CRTPGM(PGM_NAME) MODULE(MAIN_MOD MOD1 MOD2...) The first module on the modules' list is always assumed to be the main one. In this case, MAIN_MOD is the program's main module. To call the program from the system prompt: CALL PGM_NAME AS/400 Chapter 8: Display Files In this chapter you will see how to create menus and screens in AS400. Display files are DDS files that enable us to create AS/400 menus and screens to interact with the user. Display files can have several records. Each record defines part of the screen's appearance. These records may or may not overlap each other. The SDA application allows us to “draw” what should show up on the screen and creates the DDS code from our “drawing”. Next we'll create a screen with DDS and afterward we'll look at some code excerpts, because sometimes it's easier to alter the screen through its code. In this chapter we'll create a screen to show a clients data. To open SDA type STRSDA on the system prompt. This screen should appear:

Choose option 1 and type the options as you see them on the image below. Source file

is the file where the code will be stored. Member is the name of member we're creating.

Press Enter. A new screen appears. Add a new record, named TOP, typing what you see on the image bellow.

Now specify the record type, in this case it's RECORD:

After the Enter an empty screen appears. In this screen you can “draw” the top record. Add the content you see on the image bellow. When you type a string you should place it between apostrophes. If you don't each word will be handled like a different field. Placing the apostrophes allows you to manipulate all the words as a single field. The *USER function shows the username on the screen. There are other functions that retrieve information from the system: *DATE (shows the system current date), *TIME(shows the system current time), *SYSNAME (shows the system name).

After typing what you see on the image press Enter. Always check what you've done before pressing Enter, because after that you can only alter the screen by manipulating its code. You can also exit the record editing without saving your work, but then you'll lose all you've done since you last opened the record for editing.

Moving a field You can move a field to the right placing “>” characters to the right of the field. The number of > you type will be the number of columns the field will move. To move the field to the left place < signs on the left side of the field.

Centering a field To center a field on the screen place an 'ac' at the left of the field and the 'c' must be overlapping the first character of the field. Then press Enter. Press F3 to finish editing this record. Choose option 1 to save your work:

Create another record named BOTTOM, the same way you've created the TOP record. When you open the new record for editing press F9. This menu will appear:

So that you don't overlap the records you can choose to visualize other records in the menu. You can see that the status of the BOTTOM record is “In Use” wich means it is the one currently being edited. You can select at most 3 records to visualize. To do so place numbers 1 to 3 on the records you want. Select the TOP record and press Enter.

The names of the selected fields appear on the bottom of the screen. Don't forget you are only “drawing” on the record in use. The other records only help you place your elements on the right place. “Draw” something similar to what you see in the next

image.Use the underscore to make the line.

Changing field proprieties We're going to edit the proprieties of the “F3=Exit” field. Place an '*' at the left of the field and press Enter:

This screen appears. Place an 'Y' in the Colors option. We're going to change the color of the characters.

Place an 1 in the Blue field:

Press Enter until you're back in the editing screen. The field is now blue. Exit the editing screen (F3) and save your work. Create a new record, MIDDLE; the same way you've created the previous records. Press F9 to visualize the records you already created:

Draw what you can see in the following image. Press Enter when you're done.

Using table records We're going to select the fields from the Clients table to show them on the screen. Press F10. On that menu select the Database File Clients for output (option 3). You can also select fields for input or input/output choosing one of the other options. You should write this on the menu and press Enter:

On the bottom of the screen there's a message with all the Client's field names preceded by a number. To use a field on the screen you should write its correspondent number preceded with an '&'. You can see it in the next image. Be careful, because if you write a number and press Enter the order of the list on the bottom will change.

The final result:

Exit the record editing. We now need to make a few adjustments to the file options. Record level options (overlay) Choose option 8 to the TOP record:

Select option Overlay Keywords:

Place an Y at the option Overlay without erasing. This option allows to display this record on the screen together with the others. Press Enter until you reach the menu with the record listing. Activate this option on the other records.

File level options (indicadores) We need to declare the indicator 03 (so that “F3=Exit” works) at the file level. On the menu with the record listing press F14 (F13=shift+F1; F14=shift+F2; F15=shift+F3, etc.). On the following screen choose the option Indicator Keywords.

Insert the data you see on the image below:

Press Enter until you've reached the starting menu. Press F3 and save the file. Display Files DDS code You can check out the code from this display at QDDSSRC, the member is SHW_CLI. At the beginning of the file should be something like this: A DSPSIZ(24 80 *DS3) A CF03(03 'Exit') These are the file-level options. You should add a line to this area that later will allow you to rename the indicators used. Add this line after the DSPSIZ line:

A INDARA You should also have some lines like these: A R TOP A OVERLAY A 1 65USER A 3 27'Client Details:' In these four lines are the definitions to the TOP record. Notice the OVERLAY option we had defined in SDA. The keyword USER is placed on the 1st line, column 65. Look at this line from MIDDLE record: A ID_CLI R O 8 23REFFLD(CLIENTS/ID_CLI DEMO/CLIENTS) Here you have a reference to the ID_CLI field on the CLIENTS table and this reference is positioned at line 8 column 23, an can only be accessed for reading (O). Compile the file (option 14) after you've closed the member. Executing display files To run the screen you must create an RPGLE member wich will handle all the possible events (pressing F3 for example). Check out the file QRPGLESRC.SHW_CLI to see how this member should be defined. Create a file like QRPGLESRC.SHW_CLI and run it. The result should be something like this:

If you press Enter:

AS/400 Chapter 9: Subfiles With subfiles you can create a display file with lists of items. Let's see how that's done. A subfile is a display file where you can place a listing of values and process changes on the list. The list of members that you can see in the PDM is an example of a subfile. In this chapter we'll create a subfile wich will show all the cards from a client given its ID. To make the manipulation of several tables easier, we'll create a view with the fields we'll use on the subfile. In STRSQL insert this code: CREATE VIEW CLICARD AS SELECT CL.ID_CLI, CR.ID_CRD, SH.NAME_SHP, CR.SHOP_CRD FROM DEMO/CLIENTS CL, DEMO/SHOP SH, DEMO/CARDS CR WHERE CL.ID_CLI = CR.CLIENT_CRD AND CR.SHOP_CRD = SH.ID_SHP Open SDA (STRSDA) and create a new member:

Create a BOTTOM record that should look like this:

And the TOP record like this:

Let's create the subfile now. Create a new record, name it LIST, the record type is SFL:

When you press Enter a new record appears. Write SFLCTL on it:

This field creates a subfile control record, wich works like the heading on the list. You have to activate some options now:

On the General Keywords menu insert the data you see below:

These indicators allow us to manipulate the status of the subfile from the RPG code. Press Enter to go back to the previous screen. Select Subfile display layout.

On subfile maximum size type 9999 and on the number of records for page type 9:

Press enter to go back. Select the option Select Record Keyword:

Choose Overlay keywords:

Select Overlay without erasing:

Press Enter until you're back on this screen:

Open the SFLCTL record. By default the record list is already visible on the design screen. Select to visualize the other 2 records, TOM and BOTTOM (F9).

Back to the design screen, write at the top “Client Nr.”. Select the fields from CLICARD view for input/output (F10) and select the ID_CLI field:

Type the titles of the subfile's columns and a separating line:

Let's add some proprieties to the Client ID field. Place an * before to the left of the field.

We're going to add an indicator to this field, wich will be activated when no record is found for an ID inserted (either the ID doesn't exist or it doesn't have any associated cards). Option Error Messages:

Insert the following information:

Close this record and open the LIST record. Select the TOP and BOTTOM records for display (F9):

To create an input field, where the user will type the options, type '+i' on the same position as in the following image and press Enter.

Notice how the field spread across the 9 line you previously defined as the subfile page size.

Select the records from CLICARD view for output.

The fields will probably be listed twice, because the SDA will show you the field that had been previously loaded from I/O in the SFLCTL record. You should select the fields further to the right, because they are the last ones loaded. You must be careful selecting the fields.If there are more fields than the ones that can fit the message line, a plus (+) sign will appear at the end of the line. Press Page Down to see the remaining fields.

Place the fields on their positions:

The final result:

Don't forget to activate the indicator 03 at file-level so that “F3=Exit” can work and add the keyword INDARA to the code. Check out the Display file chapter if you don't remember how to do this. You must add the red line to the SFLCTL record: A R SFLCTL SFLCTL(LIST) A SFLSIZ(9999) A SFLPAG(0009) A OVERLAY A 30 SFLDSP A 31 SFLDSPCTL A 35 SFLCLR A 33 SFLEND(*MORE) A 4 8'Client Nr.' A ID_CLI R B 4 19REFFLD(CLICARD/ID_CLI DEMO/CLICARD) A 90 ERRMSG('No Data Found') A 6 4'Op.' A 6 12'Card Nr.' A 6 27'Shop Nr.' A 6 42'Shop Name' A 7 2'__________________________________A ___________________________________A __________' A RRN 4S 0H SFLRCDNBR(CURSOR) In the LIST record change the name of the input field to OPTION. By default it must be named FLD001, or something like it. A R LIST SFL A OPTION 1A I 9 5 (...)

Executing the subfile To run the subfile you must create an RPGLE member. Check out the file QRPGLESRC.SHW_SFL for more details on how to write this member. When you run the RPGLE code:

And so we finish this series on AS/400.