Sei sulla pagina 1di 159

What is an AS400?

The AS/400 (Application System/400) was first introduced by IBM on June 20th,
1988. The AS/400 is a popular family of mid-sized computer systems which can also
be used as multiuser computer systems. By this, we mean that a single computer
can interact with more than one user at a time.

The AS/400 can be utilized for different business facets. Some models are designed
as systems that provide resources to other computers, also known as a "server" in a
network of computers, while others are set up for use with terminals or "display
stations". OS400 is the operating system for the AS/400. The AS/400 computers
offer more compatibility across the product line than the earlier System/3X
computers. Hence, the earlier IBM models of the System/36 and System/38 have
since been replaced by the AS/400 systems.

IBM has sold over 600,000 AS/400's and over 350,000 of them are still active. From
distribution warehouses to hospital administrators, and even manufacturing
companies, the AS/400 is a strong component in aiding these companies daily
business operations. The AS/400 utilizes a green screen interface, a built in
database that resembles DB2, and a vast array of software to provide business
solutions for todays business needs.

In October of 2000, IBM rebranded the AS/400 and announced its name as the IBM
iSeries 400. In doing this, IBM has shown that it is evolving this mid range family of
computers in an attempt to keep in tune with the fast paced demands and changes
that the Internet and the e-business world reside in. For the purposes of our tutorial,
we will continue to use the term AS400 rather than iSeries, although there is no
distinction between the two. As well, since 95% of AS/400's use RPG, we will
emphasize using RPG in this tutorial.

To answer the question of "why should you bother to learn to use the AS400", check
out some of the job sites on the web, such as computerjobs.com or monster.com,
and do a search on AS400 RPG, and see the career possibilities that await you.

Showcase Article - AS/400 Commands

You can run commands directly from any command line. Once you learn the commands, you
can write "Control Language" or CL programs. CL programs are simply strings of commands
that have been entered and compiled. So as you learn these commands, you are also learning
to write CL programs. Managers and administrators who have duties in different environments
may have trouble shifting gears from one operating system to another. We're going to look at
some easy ways to help you learn and remember these commands.

The AS/400 operating system is consistent in its presentation and names. Commands have
names of up to 10 letters. The commands typically take the form of three letters. For example,
to work with active jobs, the command is WRKACTJOB. That's a single word with no spaces.
WRK is the AS/400 abbreviation for "work" and ACT is the abbreviation for "active." Because
the AS/400 is consistent in its naming style, after you know some of the abbreviations, you will
be able to guess the names of commands.

1
In the sidebar are 11 important verbs and nouns that combine to form command names. The
abbreviations are not all three letters but they are used consistently throughout the system. "F"
is always the abbreviation for file. You won't have to guess if it is sometimes abbreviated as
"FIL."

If you don't know the exact name of a command, you can use the AS/400 menus to browse. If
you key in GO VERB from a command line and hit Enter, you will go to the AS/400 menu
named VERB. This menu lists all AS/400 verbs. From here you can navigate and browse to the
exact command you need. Also, to see the major command groups, GO MAJOR.

If you already know the verb, but need the rest of the syntax, there is a menu named after the
verb. For example, there is a CMDWRK menu with all "work" commands, there is a CMDDSP
menu with all "display" commands and there is a CMDADD menu with all "add" commands. So
you can key in GO CMDSTR and see all "start" commands.

To learn more about any command, type in the number of the command and then hit F1. The
AS/400 has extensive, friendly help built into every command.

Some innocuous looking commands such as CPYF are deceptively powerful and complex.
CPYF can copy a file, renaming it while selecting only records in which the field "STATE" has a
value of "DC." In fact, there are six screens of key words you can use. Learning this one
command can give the power to clean up a master file by copying only records you wish to keep
while bypassing data created by an errant task.

To see a comprehensive list of AS/400 Commands, click here.

-sidebar-

It is important to become familiar with basic AS/400 command abbreviations. The following is a
list of the most commonly used verbs and nouns that combine to make commands.

Command Abbreviations--Verbs

ADD - Add

CFG - Configure

CHG - Change

CPY - Copy

CRT - Create

DLT - Delete

DSP - Display

GO - Go to a Menu

RMV - Remove

STR - Start

2
WRK - Work with

Command Abbreviations--Nouns

DEV - Device

DEVD - Device Description

F - Files

FLR - Folder

LIB - Library

OUTQ - Output Queue

MSG - Message

SPLF - Spool File

WTR - Writer (Printer)

Library Lists

The library list on the AS/400 is similar to the "path" on PC's. Mainframe programmers may
compare it to the "steplib" or "joblib". It defines the order of libraries that the operating system
uses to find objects.

When you execute a command or call a program, the AS/400 must know where to find the
command or program. Sometimes, you specify the library explicitly. But if you don't, the AS/400
will find your command or program by looking in each library in your library list. It will use the
first one that it finds first.

This is very handy for testing. If you are testing a version of a program, you can put it in a test
library which is at the top of your library list. Then, whenever you specify a program or refer to a
file, the system will use any object it can find in the test library. If it can't find it there, it will look
further through your library list until it finds it.

So, setting up a test environment is as simple as:

1) Create a test library.

2) Put objects that you want to test in the library. These can be files, menus, programs or any
AS/400 object.

3) Insert the test library name into your library list, before your production libraries.

Now you can execute test programs and modify test data. The best part is that you don't need
to copy production programs or files into the test library unless they will be affected by the test.
That is, all those supporting database files that you need to run a program, but that are used for

3
input only, do not need to be copied to the test library. Of course, if you are unsure if a file will
be modified during your test procedure, copy it to the test library anyway.

Once you have inserted the test library name in your library list, you will want to make sure
everything is in the proper order. Use the DSPLIBL command to see your library list. You will
probably see three types of list entries:

1) The SYS libraries have operating system objects. This is where the AS/400 commands and
menus are contained.

2) The CUR library is your current library. This is your first user library and is where objects are
created if you don't specify which library to use.

3) The USR libraries list your other user libraries.

Use EDTLIBL to change your USR libraries. You can rearrange the list, remove libraries or add
libraries. Notice that you can't see the SYS or CUR libraries when you use EDTLIBL. The only
way to change the current library is with the CHGCURLIB command.

The WRKOBJ command will help see which object is being used. This command is similar to
the directory ("dir") command on PC's. Use it to list objects in your library list.

So, if you have three copies of program, "PAYCALC", in different libraries, use the command
WRKOBJ PAYCALC to see which copy of "PAYCALC" will be used. The command will list all
objects named "PAYCALC" in the sequence that the AS/400 finds them . If you ever say to
yourself in frustration, "I know I changed the program but it looks like I'm still running the original
program", it's a pretty good bet that you're executing a different copy of the program than you
think. This is only a fraction of the power of the WRKOBJ command. It is the easiest way to
navigate through an undocumented system.

When you are copying files to your test library, use special care with the logical files. It is easy to
create a logical file that resides in a test library but updates a physical file in a different library.

Review of Commands Discussed:

DSPLIBL - Display complete library list

EDTLIBL - Edit library list

CHGCURLIB - Change Current Library

WRKOBJ - Work with objects (similar to PC "dir")

Example of Library List Set Up for Testing:

QSYS SYS System Library

QSYS2 SYS System Library for CPI's

QHLPSYS SYS

4
QUSRSYS SYS

TESTFILES CUR Library for Test Files

TESTPGMS USR Library for Test Programs

GLFILES USR Library for Production G/L Files

GLPGMS USR Library for Production G/L Programs

PRPGMS USR Library for Production P/R Programs

PRFILES USR Library for Production P/R Files

TAATOOL USR Library for User Tools

QGPL USR General Purpose Library

QTEMP USR

PDM or How to Enter Programs

Before you work on this topic, there is an important option to change. From the command line, key in the
command STRPDM and hit ENTER. Then, key in 1 and hit ENTER. Then hit ENTER again. Your screen
should look like:

-------------------------------------------------------------------

Work with Libraries Using PDM

List type . . . . . . . *LIBL

Type options, press Enter.

2=Change 3=Copy 5=Display

8=Display description 9=Save 10=Restore

Opt Library Type Text

QSYS *PROD-SYS System Library

QHLPSYS *PROD-SYS

QUSRSYS *PROD-SYS

QPDA *PROD-PRD

5
QADM *PROD-PRD

QTEMP *TEST-USR

QGDDM *PROD-USR

QGPL *PROD-USR

--------------------------------------------------------------------

Now, hold down the SHIFT key and hit F6. You should now see:

---------------------------------------------------------------------

Change Defaults

Type choices, press Enter.

Object library . . . . . . . *SRCLIB Name, *CURLIB,

Replace object . . . . . . . N Y=Yes, N=No

Compile in batch . . . . . . Y Y=Yes, N=No

Run in batch . . . . . . . . N Y=Yes, N=No

Save session defaults . . . Y Y=Yes, N=No

Save/Restore option . . . . 1 1=Single, 2=All

Job description . . . . . . QBATCH Name, *USRPRF,

Library . . . . . . . . . *LIBL Name, *CURLIB,

Change type and text . . . . Y Y=Yes, N=No

Option file . . . . . . . . QAUOOPT Name

Library . . . . . . . . . QGPL Name, *CURLIB,

Member . . . . . . . . . . . QAUOOPT Name

Full screen mode . . . . . . N Y=Yes, N=No

Scan hierarchy . . . . . . . Y Y=Yes, N=No

Search path . . . . . . . . *DFT Name, *DFT

Build scope . . . . . . . . 1 1=Normal, 2=Lim

4=Direct Chain

6
--------------------------------------------------------------------

Hit TAB until the cursor is on the "Compile in batch" line. Change the value from Y to N and hit ENTER.

Okay, now you are ready for the PDM topic.

Programs are created from source statements. On the AS/400, source statements are entered using PDM,
the Program Development manager. Technically, PDM uses the Source Entry Utility (SEU) as the editor.
But you don't have to think of SEU as something different from PDM.

PDM provides a way to enter program source statements and then to compile the statements into
executable programs. The source statements are needed only for the compiler. The compiled programs are
the objects that are actually run on the AS/400. The source code and the compiled objects are separate
things. But it is easy to confuse the two. At times, you may try to open the compiled object with PDM
when you really mean to open the source code used to create the compiled object.

Source code is kept in a member of a file. The file is kept in a library. Each file can have many members.
Each member is the source code for a program.

The source code files can have any name but conventionally the names start with Q and end with SRC,
for source. Typically:

QCLSRC is the file for the CL program source statements


QDDSSRC is for the DDS program source statements
QRPGSRC is for the old RPG language
QRPGLESRC is for the new RPG/ILE language
QMNUSRC or QMENUSRC is for menus
QCBLSRC or QLBLSRC is for COBOL
QCMDSRC is for commands

You could keep most of the source statements is a single file. That is, one member could have CL source
statements and another member could have DDS and another could have RPG source statements.
Conventionally though, source code is not mixed up like that.

So, let's try it out by writing a simple CL program to change the "Current Library" to your library and to
go to the programmer menu. CL is the Control Language of the AS/400. This is a lesson in PDM so don't
fret too much about the specifics of CL.

When you got your user ID on this system, a library was also created for you with the same name as your
user ID. Suppose that your ID is USER999. That means you have a library available to you named
USER999. Some people relate an AS/400 library to a Directory or Folder on a PC.

Your library is probably empty. Since this is the first CL program ever written in your library, you need to
create a file to store the CL source statements in.

On the command line, type in:

CRTSRCPF and then hit F4. (F4 always invokes the prompts)

From the earlier lesson in commands, you should remember that commands usually are made up of 3
letter abbreviations of verbs and such. In the case, the command CRTSRCPF stands for Create Source
Physical File. That's not exactly intuitive but it's not too hard to remember.

For the library name, key in your library name, similar to USER999. For the Object (or File) name, key in
QCLSRC. Now hit ENTER and you've created a source physical file named QCLSRC in the library

7
named USER999. Remember that QCLSRC is not a magic or reserved name. But almost everyone uses
this name for their CL source.

Once you use commands for a while, you will learn how to enter simple commands without the prompts.
In this case:

CRTSRCPF USER999/QCLSRC

So now you have a place to store your CL source statements. Lets start PDM and try to enter the simple
program. PDM can be started from the programmer menu or with the Start PDM command. Most
programmers use the Start PDM command. Type in STRPDM and hit ENTER.

Your screen should look something like:

------------------------------------------------------------------------

AS/400 Programming Development Manager (PDM)

Select one of the following:

1. Work with libraries

2. Work with objects

3. Work with members

4. Work with projects

5. Work with groups

6. Work with parts

9. Work with user-defined options

Selection or command

-----------------------------------------------------------------------

8
Now for the most confusing part of PDM… And it's not that confusing. PDM will let you navigate to
your source statements 3 different ways. Let's try to draw a picture of the organization of the source
statements.

Suppose you have 2 libraries. One for General Ledger programs and one for Payroll. Each one has CL,
DDS and RPG programs. A schematic of this is:

Library Object or File Member or Program name

GLLIB QCLSRC GLC001

GLC003

GLC007

QRPGSRC GLR001

GLR002

GLR005

QDDSSRC GLD001

PRLIB QCLSRC PRC100

PRC101

PRC125AB

QRPGSRC PRR100

PRR125

QDDSSRC PRD105

PRD107

PRD108

The analogy on a PC is that you have two Folders in the root; one is GLLIB and the other is PRLIB. Each
of those folders has three folders: QCLSRC, QRPGSRC and QDDSSRC. Each of those folders has a few
documents, each one with the source statements for the program.

The schematic of your library right now is:

Library Object or File Member or Program name

USER99 QCLSRC

9
That is, you have one file in your library and that file has no members.

I prefer to navigate to my source code using selection 3 (Work with members). So, key in 3 and hit
ENTER.

Your screen now looks like:

------------------------------------------------------------------------

Specify Members to Work With

Type choices, press Enter.

File . . . . . . . . . . QCLSRC Name, F4 for list

Library . . . . . . . . USER999 *LIBL, *CURLIB, name

Member:

Name . . . . . . . . . *ALL *ALL, name, *generic*

Type . . . . . . . . . *ALL *ALL, type, *generic*

------------------------------------------------------------------------

Key in the File name of QCLSRC and the library name like USER999. Finally for member name key in
*ALL.

This is a little like saying on a PC, "Show me all the documents in the folder QCLSRC which is in the
folder USER999".

The AS/400 now shows you the "WORK WITH MEMBERS WITH PDM" display and all of the
members in QCLSRC. But since QCLSRC has no members it shows "NO MEMBERS IN FILE".

About ¼ from the top, the AS/400 tells you what options you can use in PDM. For example, 2 is to edit or
change a member, 3 is to copy a member, 4 to delete a member. If you hit F23, the AS/400 will display
more options. Your keyboard has only 12 "F" keys at the top. If you hold down the shift key when you hit
an "F" key, it adds 12 to the "F" number. So, if you hold down shift and hit F11, this is the F23 key.
When you do this, the AS/400 shows other option numbers.

Similarly, at the bottom, the AS/400 tells you what "F" keys you can use. Hitting F24 (shift while hitting
F12) will cause the AS/400 to display more "F" keys. These "F" keys are called FUNCTION KEYS.

So, finally.. Let's add a member and write a simple Control Language program.

At the bottom-right of your screen you should see that F6=Create. This means that hitting F6 will let you
create a new member. So, hit F6.

10
The screen will now show:

------------------------------------------------------------------------

Start Source Entry Utility (STRSEU)

Type choices, press Enter.

Source file . . . . . . . . . . > QCLSRC Name, *PRV

Library . . . . . . . . . . . > USER999 Name, *LIBL, *CURLIB, *PRV

Source member . . . . . . . . . FIRSTCL Name, *PRV, *SELECT

Source type . . . . . . . . . . CLP Name, *SAME, BAS, BASP...

Text 'description' . . . . . . . My First CL Program

------------------------------------------------------------------------

Fill in the Source member name. This will become the program name. Name it FIRSTCL.

The Source type is important. It will tell the AS/400 what compiler to use to compile the source code. CL
programs are designated as Source type CLP. So, enter CLP.

For the text description, enter a short description.

Now hit ENTER and the screen should look like:

-----------------------------------------------------------------------

Columns . . . : 1 71 Edit USER001/QCLSRC

SEU==> FIRSTCL

FMT ** ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7

*************** Beginning of data*************************

'''''''

'''''''

'''''''

'''''''

'''''''

11
'''''''

'''''''

'''''''

'''''''

'''''''

'''''''

'''''''

-----------------------------------------------------------------------

You now have an empty member to key source code into. If you were to hit ENTER right now, the editor
(SEU) would assume that you don't want to keep any of these lines since you haven't entered anything on
them.

So, to make things simple, key a space on the top line, then TAB twice to the next line and key another
space. Do this on about 10 lines.

Now, when you hit ENTER, SEU sees that you keyed something (a space) on those lines and it keeps
them for you.

If you did this, SEU replaced the dots on the left with numbers and should look like:

------------------------------------------------------------------------

Columns . . . : 1 71 Edit USER001/QCLSRC

SEU==> FIRSTCL

FMT ** ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7

*************** Beginning of data**************************

0001.00

0002.00

0003.00

0004.00

0005.00

0006.00

0007.00

0008.00

0009.00

12
-----------------------------------------------------------------------

Languages have syntax rules to follow. CL is mostly a free format syntax. Blank lines are allowed and
commands can be placed in any column. Also, CL programs must begin with a PGM statement.

So, key PGM on the first line and hit ENTER. Your screen should now look like:

------------------------------------------------------------------------

Columns . . . : 1 71 Edit USER001/QCLSRC

SEU==> FIRSTCL

FMT ** ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7

*************** Beginning of data**************************

0001.00 PGM

0002.00

0003.00

0004.00

0005.00

0006.00

0007.00

0008.00

0009.00

-----------------------------------------------------------------------

Now, it's time to experiment a bit with the line editor. SEU (the name of the editor being used by PDM) is
a line editor. That just means that commands to copy, insert and delete lines are entered in the left portion
of the screen where the numbers are.

Try a simple line command. Key in D right on top of the number 0001.00 at the top left. your screen
should look like:

------------------------------------------------------------------------

Columns . . . : 1 71 Edit USER001/QCLSRC

SEU==> FIRSTCL

FMT ** ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7

*************** Beginning of data**************************

13
D001.00 PGM

0002.00

0003.00

0004.00

0005.00

0006.00

0007.00

0008.00

0009.00

-----------------------------------------------------------------------

This D tells the editor to delete this line when the ENTER key is hit. So, go ahead and hit ENTER and
watch that line disappear.

Now key the PGM back in on another line.

Just to experiment, copy line 0001 and insert it after line 0005. Do this by keying a C (for "copy") on line
0001 and an A (for "after") on line 0005.

Your screen should look like:

------------------------------------------------------------------------

Columns . . . : 1 71 Edit USER001/QCLSRC

SEU==> FIRSTCL

FMT ** ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7

*************** Beginning of data**************************

C001.00 PGM

0002.00

0003.00

0004.00

A005.00

0006.00

0007.00

0008.00

14
0009.00

-----------------------------------------------------------------------

When you hit ENTER, SEU will copy line 1 and place it on a new line after line 5.

If you key C3 on line 0001, SEU will copy three lines and place them after the line with an A.

Or, if you key CC on line 0001 and CC on line 0004, SEU will copy from line 0001 thru 0004.

Similarly, putting DD on line 0001 and DD on line 2000 would delete all lines from line 1 to line 2000.

Okay, let's finish the program. The complete program will do only two things. The first is that it will
change your "CURRENT LIBRARY" to your library USER999 and the second thing is it will go to the
Program menu on the AS/400.

Since this isn't a lesson in CL programming, trust me and key in the following program. Be sure to use
your USERID in place of USER999.

------------------------------------------------------------------------

Columns . . . : 1 71 Edit USER001/QCLSRC

SEU==> FIRSTCL

FMT ** ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7

*************** Beginning of data**************************

0001.00 PGM

0002.00

0003.00 CHGCURLIB USER999

0004.00

0005.00 GO PROGRAM

0006.00

0007.00

0008.00

0009.00

-----------------------------------------------------------------------

Now hit F3 to tell PDM that you are done. Hit ENTER to accept the values on the screen. PDM has saved
your program and you can now see it in your PDM list of members.

The screen should now show:

15
---------------------------------------------------------------------

Work with Members Using PDM

File . . . . . . QCLSRC

Library . . . . USER999 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Rename

8=Display description 9=Save 13=Change text 14=Compile 15=Create

Opt Member Type Text

FIRSTCL CLP My First Cl Program

---------------------------------------------------------------------

So, you have now entered the statements needed by the AS/400 compiler to compile a CL program. Each
time you add a member, this list of members will grow. Just for fun, key a 2 next to FIRSTCL under OPT
on the screen. Hit ENTER and PDM will open the source file up again so you can see and change it. Hit
F3 and ENTER to get back.

To compile the program, key 14 under OPT next to FIRSTCL and hit enter. This tells PDM to compile
the statements that are in the member named FIRSTCL.

If all went well, in a few seconds, the AS/400 will have compiled your program. Hit TAB to get to the
bottom of the screen. This is the command line.

Key CALL USER999/FIRSTCL on the command line (be sure to use your USERID in place of
USER999). If your program compiled, you should now see:

-----------------------------------------------------------------------

PROGRAM Programming

Select one of the following:

1. Programmer menu

16
2. Programming Development Manager (PDM)

3. Utilities

4. Programming language debug

5. Structured Query Language (SQL) pre-compiler

6. Question and answer

8. Copy screen image

9. Cross System Product/Application Execution (CSP/AE)

50. System/36 programming

70. Related commands

Selection or command

-----------------------------------------------------------------------

That's the end of this lesson. Try not to be frustrated with the lack of user friendliness of PDM. The
wonderful news is that 99% of AS/400's use PDM. So anytime you log on to an AS/400, you will be
familiar with the source code editor.

It takes most people a week or so of using PDM to get comfortable with it. But you must learn PDM well.
You will use it to create files, logical files (indexes), display screens, print files, RPG programs, CL
programs and more.

Take a break and review the following link to IBM's publication site.

Finally, e-mail me and tell me how your first hands-on experience went.

Thanks,

David
dmount@texas400.com

Additional Material

Here is the link to IBM's Online Manuals

http://publib.boulder.ibm.com/pubs/html/as400/online/v4r2eng.htm

17
Click on "SEARCH OR VIEW ALL BOOKS"
Key in SEU and click on FIND.
It should find the book titled "Source Entry Utility". Chapter 13 is a tutorial on entering source code.

Library Lists and Copy File

More on Library List (LIBL) and Copy File (CPYF)

If you have read through the topics you are probably getting a bit bored. It's time to jump in and start
trying things out.

First, it is important to learn a bit more about your library list. I hope you read the earlier topic on
LIBRARY LISTS and understood some of it. Sign on to the AS/400, and from a command line, key in
DSPLIBL and hit ENTER.

Your LIBRARY LIST should look like:

Opt Library Type Text

QSYS SYS System Library

QHLPSYS SYS

QUSRSYS SYS

QTEMP USR

QGDDM USR

QGPL USR

This simply means that whenever you key in a command, call a program or go to a menu, the AS/400 will
look for what it needs in those libraries and in that sequence.

In fact, when you keyed in the command DSPLIBL, the AS/400 looked for it in the first library, QSYS.
Not by accident, that is the library that has all of the AS/400 commands. So, the AS/400 executed the
command DSPLIBL that it found in the library QSYS.

Since we will do a lot of things in your personal library, it will make things easier if your library is in the
library list. For now, the best way to do this is to make your personal library the CURRENT LIBRARY.
The CURRENT LIBRARY is a slightly special designation. The CURRENT LIBRARY is the first user
library. Also, if you create files and don't tell the AS/400 where to put them, it will put them in the
CURRENT LIBRARY.

Key in the command to change the CURRENT LIBRARY to your personal library. The command is
Change Current Library. This is an excellent example of the way the AS/400 usually makes the command
name from the 3 letter abbreviations. The command is CHGCURLIB. So, key in:

CHGCURLIB USER999

Of course, replace USER999 with your user ID. When I set up your user ID, I created a library with the
same name as your user ID. So, don't get confused and think that this command changes the current
library to your user ID. It is changing your current library to a library that happens to be named the same
as your ID.

18
Now display your library list again. You remember, DSPLIBL.

Your library list now looks like:

Opt Library Type Text

QSYS SYS System Library

QHLPSYS SYS

QUSRSYS SYS

USER999 CUR

QTEMP USR

QGDDM USR

QGPL USR

Now let's have some real fun. There is a file in library USER000 named CUST. It has a little over 1,000
records in it. Some people think of a record like a line on a spreadsheet.

We will need some data for a query we will write in a minute. So, let's copy this file to your personal
library. In doing this, we will learn about AS/400 commands, the very powerful COPY FILE command
and a few other commands as well.

The command to copy the CUST file from the library USER000 to your personal library, USER999 is
pretty scary looking. It is:

CPYF FROMFILE(USER000/CUST) TOFILE(USER999/CUST) CRTFILE(*YES)

Memorizing the keywords and options would be impossible. Fortunately, it's not that hard. Let's see how
the AS/400 makes it easy to use complex commands.

First, you must remember the command name. This command, CPYF (COPY FILE) is a common
command. But if you need help remembering it you could try going to one of the menus that lists the
commands.

If you remember that COPY is abbreviated CPY, you could key in:

GO CMDCPY

You would see a list of commands and number 6 is CPYF.

Or, you could key in:

GO MAJOR

You would see a list of the major groups of commands. Since you see "more" in the lower right hand of
the screen, you know that you can hit the PAGE-DOWN key to see more. You don't need to though since
you can see that selection 5 will show you the FILE COMMANDS. you will find CPYF on that list. Or

19
you could have selected 2 for VERB COMMANDS and found the COPY COMMANDS as #18 on that
list.

Are you started to get the idea? This menu (most of them start with CMD) show you all of the commands
on the system.

Remember, we were looking for the command to copy a file. It is CPYF. So, let's see how to use a
command now that we know its name.

Key in the command on the command line but don't hit ENTER. Instead, hit F4. The AS/400 understands
that F4 means that you want to see the options and the prompts for the options.

So, key in CPYF and hit F4. You should see:

Copy File (CPYF)

Type choices, press Enter.

From file . . . . . . . . . . . Name

Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB

To file . . . . . . . . . . . . Name, *PRINT

Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB

From member . . . . . . . . . . *FIRST Name, generic*, *FIRST, *ALL

To member or label . . . . . . . *FIRST Name, *FIRST, *FROMMBR

Replace or add records . . . . . *NONE *NONE, *ADD, *REPLACE...

Create file . . . . . . . . . . *NO *NO, *YES

Print format . . . . . . . . . . *CHAR *CHAR, *HEX

Bottom

20
F3=Exit F4=Prompt F5=Refresh F10=Additional parameters F12=Cancel

F13=How to use this display F24=More keys

With just a little experimentation, you will learn that the critical values on this screen are:

FROM FILE which we want to be CUST


Library for FROM FILE which we want to be USER000
TO FILE which we want to be CUST
Library for TO FILE which should be your personal library
CREATE FILE which needs to be *YES

So your screen should look like:

From file . . . . . . . . . . . > CUST Name

Library . . . . . . . . . . . > USER000 Name, *LIBL, *CURLIB

To file . . . . . . . . . . . . > CUST Name, *PRINT

Library . . . . . . . . . . . > USER999 Name, *LIBL, *CURLIB

From member . . . . . . . . . . *FIRST Name, generic*, *FIRST, *ALL

To member or label . . . . . . . *FIRST Name, *FIRST, *FROMMBR

Replace or add records . . . . . *NONE *NONE, *ADD, *REPLACE...

Create file . . . . . . . . . . > *YES *NO, *YES

Print format . . . . . . . . . . *CHAR *CHAR, *HEX

Of course, replace USER999 with yuour personal library name. Hit ENTER now and see how quickly
these 1000 records are copied into a file in your personal library.

You now have a file named CUST in your personal library and it has over 1000 records of data in it.

Now, you can learn some important things about the way commands work. You can hit F9 to RETRIEVE
the last command executed. This is a handy shortcut. But it also shows exactly what command was
executed and what the options were. So hit F9 and you will see:

CPYF FROMFILE(USER000/CUST) TOFILE(USER999/CUST) CRTFILE(*YES)

For simple commands, the keywords (FROMFILE, TOFILE and CRTFILE) are not needed. That is, if
you key in all the right options in the right order, you may leave out the keywords. For a command as
complicated as CPYF, that is almost impossible. Most commands are simpler though.

To see the data in the file, you might expect to use a command DSPF for display file. As it turns out the
command is actually, DISPLAY PHYSICAL FILE MEMBER and is named DSPPFM.

Now that you know the name of the command, you know that you can key DSPPFM and hit F4 to see the
keywords and options. If you do, you'll see:

21
Display Physical File Member (DSPPFM)

Type choices, press Enter.

File . . . . . . . . . . . . . . Name

Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB

Member . . . . . . . . . . . . . *FIRST Name, *FIRST, *LAST

From record . . . . . . . . . . 1 Number, *END, *ALLDATA

That's not too bad. The only options are the name of the file, the library the file is in, the member (we'll
discuss this in another topic) and the first record number.

Notice that most of the default values are filled in with the value that you probably want. For example, the
FROM RECORD# is already set to 1.

So all you really need to fill in is the FILE NAME of CUST and the LIBRARY name where the FILE is
located. In fact, it's even simpler than that. The default value for the LIBRARY is *LIBL. This means that
the command will look for the FILE in the LIBRARY LIST. And since your personal library is the
CURRENT LIBRARY, all you need to enter is the file name.

So if you fill in the FILE name as CUST and hit ENTER, you should see a screen full of customer name
and address data:

001002E LUMPKIN 123 MAIN STREET ANYTOWN

001084CHISOLM 123 MAIN STREET ANYTOWN

001105HAGGINS 123 MAIN STREET ANYTOWN

001109BYRD 123 MAIN STREET ANYTOWN

001168ROMERO 123 MAIN STREET ANYTOWN

001177POUNDS 123 MAIN STREET ANYTOWN

001183HINTON 123 MAIN STREET ANYTOWN

001184YANCEY 123 MAIN STREET ANYTOWN

001186MCDOUGLE 123 MAIN STREET ANYTOWN

001202DAVIS 123 MAIN STREET ANYTOWN

001208TARVIN 123 MAIN STREET ANYTOWN

001214GOOSEBERRY 123 MAIN STREET ANYTOWN

22
001234REID 123 MAIN STREET ANYTOWN

001239COLBERT 123 MAIN STREET ANYTOWN

001259BLACKMON 123 MAIN STREET ANYTOWN

Now to keep learning about how commands are executed, hit F9 to see the command that you just ran. It
is:

DSPPFM FILE(CUST)

What happened is that the AS/400 followed a line of logic like this:

I'm supposed to run the command DSPPFM so first I need to find the command in one of the libraries in
the library list. The first library in the library list is QSYS and it has a command named DSPPFM so I'll
run that.

Next, I need to find a file named CUST. There is no CUST file in the first library QSYS. There isn't a
CUST file in QHLPSYS or QUSRSYS either. There isn't a CUST file in QPDA or QADM. There is a
CUST file in USER999, which happens to be the CURRENT LIBRARY. So, I'll run the command
DSPPFM that I found in the library QSYS and I'll display the file CUST that I found in USER999.

Like many commands, this one is so simply that you don't need to prompt the keywords. You could just
key in:

DSPPFM CUST

By the way, you could display the original CUST file that you copied from USER000. Key in DSPPFM ,
hit F4 and fill in the file name of CUST and the library name of USER000.

The shortcut form of that command is:

DSPPFM USER000/CUST

Just for fun, delete the file you copied and then copy it again.

To delete the file, use the command DELETE FILE, which is DLTF. So if you key in:

DLTF CUST

or

DLTF USER999/CUST

and hit ENTER and you will delete your CUST file.

Now, use the CPYF command to copy it again from the USER000 library. Or, if you are efficient, hit F9
a few times until your CPYF command is retrieved and then hit ENTER and run it again.

The data displayed with the DSPPFM command is unformatted. That is, it is just a string of letters and
numbers. Try the command:

RUNQRY QRYFILE(CUST)

This command is a tiny part of the QUERY/400 programming language. It displays the file but separates
the data into fields with headings. It should look like:

23
Position to line . . . . . Shift to column . . . . . .

Line ....+....1....+....2....+....3....+....4....+....5....+....6....+....7.

CSNBR CSNAME CSADR1

000001 1,002 E LUMPKIN 123 MAIN STREET

000002 1,084 CHISOLM 123 MAIN STREET

000003 1,105 HAGGINS 123 MAIN STREET

000004 1,109 BYRD 123 MAIN STREET

000005 1,168 ROMERO 123 MAIN STREET

000006 1,177 POUNDS 123 MAIN STREET

000007 1,183 HINTON 123 MAIN STREET

000008 1,184 YANCEY 123 MAIN STREET

000009 1,186 MCDOUGLE 123 MAIN STREET

000010 1,202 DAVIS 123 MAIN STREET

000011 1,208 TARVIN 123 MAIN STREET

000012 1,214 GOOSEBERRY 123 MAIN STREET

000013 1,234 REID 123 MAIN STREET

000014 1,239 COLBERT 123 MAIN STREET

000015 1,259 BLACKMON 123 MAIN STREET

000016 1,264 CRANFORD 123 MAIN STREET

You can see from the prompts at the bottom of the screen that you can shift the data to see more by hitting
F20. F20 is SHIFT and F8. F19 will shift back.

I hope you're having fun and starting to see the power of the AS/400.

Notice when you shift to the right by hitting SHIFT and F20 that the field name for the STATE is CSSTE.

For the last lesson in executing commands, let's copy the original file but select only customers from
Texas (where else?). We know that the field that has the state is CSSTE.

First, delete the file you copied:

DLTF CUST

Now, key in the CPYF command and hit F4. As before fill in the file names and library names and the
create file option.

24
Notice that at the bottom, F10 will show ADDITIONAL PARAMETERS. If you hit F10, you will see
"more…' at the bottom right of the screen. This means that you can hit the PAGE DOWN key to see more
options.

The CPYF command has many, many options. If you hit PAGE DOWN 4 times, you will see:

Copy File (CPYF)

Type choices, press Enter.

Include records by field test:

Relationship . . . . . . . . . *NONE *NONE, *IF, *AND, *OR

Field . . . . . . . . . . . . Name

Relational operator . . . . . *EQ, *GT, *LT, *NE, *GE...

Value . . . . . . . . . . . .

+ for more values

Record format field mapping . . *NONE *NONE, *NOCHK, *CVTSRC...

Source update options . . . . . *SAME *SAME, *SEQNBR, *DATE

Source sequence numbering:

Starting sequence number . . . 1.00 0.01-9999.99

Increment number . . . . . . . 1.00 0.01-9999.99

More...

Here, you can enter selection values. Fill in the top of the screen to look like:

25
Include records by field test:

Relationship . . . . . . . . . *IF *NONE, *IF, *AND, *OR

Field . . . . . . . . . . . . CSSTE Name

Relational operator . . . . . *EQ *EQ, *GT, *LT, *NE, *GE...

Value . . . . . . . . . . . . 'TX'

These values say, "copy only records in which the field CSSTE is equal to "TX""

Now if you hit enter, you will copy CUST from library USER000 to USER999 but it will copy only
customers from Texas.

When you have run this command, re-run the RUN QUERY command to see the data:

RUNQRY QRYFILE(CUST)

You should see only data for customers in Texas.

That's it for now. Experiment with your new knowledge. Use CPYF to copy your file. Use DLTF to
delete it. Use DSPPFM and RUNQRY to look at the data.

I hope you're looking forward to the next topic. I am.

Writing Queries and Looking at Print Output

Most AS/400's have the IBM provided query language QUERY/400. If is an easy to use and powerful
tool for viewing and printing data. Here, we will write a query to see some of the data in your CUST file.
Then, we'll copy it and change it to create a printed report. Then, we'll learn how to view printed reports.
Finally, I'll have a few comments on how you could actually print reports on your laser printer (don't get
too excited though, its expensive).

Make sure you have read through the earlier topic "Library Lists and Copy File". In that topic you should
have copied a file named CUST to your user library. From here on, whenever you see USER999 be sure
to substitute your user library.

There are several ways to get to the Query programming screen. My favorite is with the command
WRKQRY. After keying in WRKQRY and hitting ENTER you should see:

----------------------------------------------------------------

Work with Queries

Type choices, press Enter.

Option . . . . . . 1=Create, 2=Change, 3=Copy, 4=Delete

5=Display, 6=Print

26
8=Run in batch, 9=Run

Query . . . . . . . Name, F4 for list

Library . . . . . Name, *LIBL, F4 for list

-----------------------------------------------------------------

This interface is easy to use but is different from PDM. One of the unexpected things is that you can write
a query without ever naming it. Of course, you must name it if you wish to save it.

We are going to write a query to view the data in the CUST file. Key in 1 for the option to create a query.
We'll name it later so for now just hit ENTER.

You should see:

-----------------------------------------------------------------

Define the Query

Query . . . . . . : Option . . . . . : CREATE

Library . . . . : ZET CCSID . . . . . . : 65535

Type options, press Enter. Press F21 to select all.

1=Select

Opt Query Definition Option

1 Specify file selections

Define result fields

Select and sequence fields

Select records

Select sort fields

Select collating sequence

Specify report column formatting

Select report summary functions

Define report breaks

Select output type and output form

27
Specify processing options

-----------------------------------------------------------------

If you have ever worked with a database query product (like Microsoft's Access) this will have a
familiarity to it. Microsoft Access needs about the same information as the AS/400. It just presents the
options in a way that you point and click. With QUERY/400, you must view lists and select by keying in
"1" next to each item.

The essential things that a query needs to know are:

what file(s) are you displaying or printing?

which fields are you interested in?

how should the data be presented (titles, sequence of data)?

do you want to sort or order the data?

do you want to calculate break totals?

do you want to see details or summary?

The most important question is "what file are you displaying?" This is so important that the AS/400 has
already put a "1" next to "Specify file selections". SO, just hit ENTER and you will see:

--------------------------------------------------------------

Specify File Selections

Type choices, press Enter. Press F9 to specify an additional

file selection.

File . . . . . . . . . Name, F4 for list

Library . . . . . . Name, *LIBL, F4 for list

Member . . . . . . . . *FIRST Name, *FIRST, F4 for list

Format . . . . . . . . *FIRST Name, *FIRST, F4 for list

---------------------------------------------------------------

You are simply specifying which file you want to query. Enter CUST and the file and USER999 as the
Library and hit ENTER. Hit ENTER again and you go back to the previous screen.

Now, select fields you want to see. Do this by keying "1" next to "Select and Sequence Fields". Use either
the TAB key or the "down-arrow" to get to that line and key in "1" and hit ENTER.

28
You should now see:

----------------------------------------------------------------

Select and Sequence Fields

Type sequence number (0-9999) for the names of up to 500 fields to appear in the
report,

press Enter.

Seq Field Text

CSNBR CUST NUMBER

CSNAME CUST NAME

CSADR1 ADDRESS LINE 1

CSCTY CITY

CSSTE STATE

CSZIP 9 DIGIT ZIP

CSDLOR DATE OF LAST ORDER

CSDLPM DATE OF LAST PMT

CS#OPN # OF OPEN ORDERS

CS$OPN AMT OF OPEN ORDERS

----------------------------------------------------------------

Since the AS/400 knows the file you want to see, it has retrieved the fields in the file and listed them for
you. If there were more fields, you would see the now familiar "more..." at the bottom right. "more..."
tells you that if you use the PAGE-DOWN key you will see more.

Lets make a display that shows the following columns:


cust name
cust number
cust adr1
cust city
cust state
cust zip

29
So, key in a sequence number next to each field. Key 2 next to CSNBR, 1 next to CSNAME, 3 next to
CSADR1, 4 next to CSCTY, 5 next to CSSTE and 6 next to CSZIP. Then hit ENTER twice and you'll be
back at the main screen.

One of the great things with QUERY/400 is that you can work on query, then view it, then change it,
view it again and change it until it is what you want.

F5 says that F5=Report. Maybe it should say F5=Run. If you hit F5 the query will run. It should look like:

---------------------------------------------------------------

Display Report

Report width . . . . . : 115

Position to line . . . . . Shift to column . . .

....1....+....2....+....3....+....4....+....5....+....6....+....7

CSNAME CSNBR CSADR1

000001 E LUMPKIN 1,002 123 MAIN STREET

000002 CHISOLM 1,084 123 MAIN STREET

000003 HAGGINS 1,105 123 MAIN STREET

000004 BYRD 1,109 123 MAIN STREET

000005 ROMERO 1,168 123 MAIN STREET

000006 POUNDS 1,177 123 MAIN STREET

000007 HINTON 1,183 123 MAIN STREET

000008 YANCEY 1,184 123 MAIN STREET

000009 MCDOUGLE 1,186 123 MAIN STREET

-----------------------------------------------------------------

Just like that you have written a query to display data from an AS/400 database file. Notice a few things
about the query display: it says "more..." so you can hit PAGE DOWN to go down a page. At the top is an
area to position to any line. You could key in 50 and hit ENTER and the query would advance to line 50.
You can also enter "B" (for bottom) and hit enter to go to the bottom or "T" to get back to the top.

Notice the F-KEY prompts at the bottom of the screen. If you hit F20 (Shift F8) you will scroll to the
right. F19 (Shift F7) scrolls back to the left. You can even split the screen with F21 (Shift F9).

Once you have played around with that for a while, hit F12 (cancel) to get back to the main screen.

30
Now change the titles of the rows to be description. Do this by keying "1" next to Column Formatting.
Key in more descriptive columns like Name, Customer#, etc.. You can use all three lines for the column
heading.

Anytime you want, hit F5 to see the data.

You might revisit the "Select and Sequence Fields" selection to add a field or move fields around.

If in the process of working on the query you hit F3 at the wrong time, you will see the EXIT screen
which looks like:

-------------------------------------------------------

Exit this Query

Type choices, press Enter.

Save definition . . . Y Y=Yes, N=No

Run option . . . . . . 3 1=Run interactively

2=Run in batch

3=Do not run

For a saved definition:

Query . . . . . . . Name

Library . . . . . ZET Name, F4 for list

Text . . . . . . . .

Authority . . . . . *LIBCRTAUT *LIBCRTAUT

*CHANGE, *ALL, *EXCLUDE

----------------------------------------------------------

You can hit F12 to get back to your query. Boy that wasn't very obvious was it?

Now key "1" next to "Select Sort Fields". Key a "1" next to CSNAME and hit ENTER. Now hit F5 and
your query will sort the data by name when it displays.

31
Notice that this is real-world data. Some of the names start with a space and are therefore sorted to the
beginning.

Finally, key a "1" next to select records. Lets select only the records for accounts that live in "TX". Fill in
the screen to look like:

----------------------------------------------------------

Select Records

Type comparisons, press Enter. Specify OR to start each new

Tests: EQ, NE, LE, GE, LT, GT, RANGE, LIST, LIKE, IS, ISN

AND/OR Field Test Value (Field, Number, 'Char

CSSTE EQ 'TX'

----------------------------------------------------------

Now when you hit F5 you will see only accounts in Texas and in sequence by name.

You can also create totals of columns and break totals. You can specify if you want details (like this) or
summary only.

For now, quit and save this query. Hit F3 and fill in the screen to save the query as CSQ001.

-------------------------------------------------------------

Exit this Query

Type choices, press Enter.

Save definition . . . Y Y=Yes, N=No

Run option . . . . . . 3 1=Run interactively

2=Run in batch

3=Do not run

32
For a saved definition:

Query . . . . . . . CSQ001 Name

Library . . . . . USER999 Name, F4 for list

Text . . . . . . . . Display CUST File

---------------------------------------------------------------

Now, from a command line, key in the command to run a query:

RUNQRY USER999/CSQ001

Your query should display what you saw earlier when you hit F5.

So, that was pretty incredible. In just a few minutes, you wrote and saved it so that it can be run from the
command line. Next topic will show you how to put that on a menu.

Now, copy the query and change it to print a report.

To do that, work with queries again (WRKQRY). Then fill in the screen like:

-----------------------------------------------------------------

Work with Queries

Type choices, press Enter.

Option . . . . . . 3 1=Create, 2=Change, 3=Copy

5=Display, 6=Print

8=Run in batch, 9=Run

Query . . . . . . . csq001 Name, F4 for list

Library . . . . . USER999 Name, *LIBL, F4 for list

--------------------------------------------------------------

Hit ENTER and you will see the "Copy Queries" screen. Under "To Query" change the query name from
CSQ001 to CSQ002 and hit ENTER.

There is now a query named CSQ002 that is identical to CSQ001. Open that query up so you can change
it to print. Do this by keying:

33
--------------------------------------------------------------

Work with Queries

Type choices, press Enter.

Option . . . . . . 2 1=Create, 2=Change

5=Display, 6=Print

8=Run in batch, 9=

Query . . . . . . . CSQ002 Name, F4 for list

Library . . . . . USER999 Name, *LIBL,

---------------------------------------------------------------

Put "1" next to "Select Output Type and Output Form" and hit ENTER.

You should see:

---------------------------------------------------------------

Select Output Type and Output Form

Type choices, press Enter.

Output type . . . . . . . . . . . 1 1=Display

2=Printer

3=Database file

Form of output . . . . . . . . . . 1 1=Detail

2=Summary only

Line wrapping . . . . . . . . . . N Y=Yes, N=No

34
Wrapping width . . . . . . . . . Blank, 1-378

Record on one page . . . . . . . N Y=Yes, N=No

---------------------------------------------------------------

You can see that the AS/400 defaults each query to display detail information without line wrapping. You
can experiment with the line wrapping later. For now, change the Output Type form 1 to 2 and hit
ENTER.

On the "Define Printer Output", hit ENTER to accept all of the defaults. Also hit ENTER for the "Define
Spool Output" screen.

You can try different values here but for now, change the "Print Cover Page" form "Y" to "N" and hit
ENTER.

You should now see the "Specify Page Headings and Footings". Fill it in with something like:

----------------------------------------------------------------

Specify Page Headings and Footings

Type choices, press Enter.

(Type &date, &time, and &page, or choose standard page headings.)

Print standard

page headings . . . . . Y Y=Yes, N=No

Page heading

Customer File

Texas Only

Sorted by Name

Page footing

CSQ002

---------------------------------------------------------------

I've put in a three line heading and entered the query name as a footer. Hit ENTER to get back to the main
query screen.

35
Note that if you hit F5 right now, you will see exactly what the other query saw. The headings and footers
are not displayed. They will show up in the report though.

Hit F3 to get to the EXIT screen and save the query.

Now run the query from the command line by keying in:

RUNQRY USER999/CSQ002

The query has now created a report and written it to the Spool File. The Spool File is a storage area for
the report. If you had an AS/400 printer connected and ready to print, the file would print to the report.
Since you don't have an AS/400 printer, the report is still sitting in the Spool File.

There are many Spool File areas on the AS/400. Which one is yours in? It depends on the values used to
set up your user profile. That is, when a user ID is defined, the printer for that user ID is also defined. In
your case, it isn't really a printer... it's a dummy printer.

So, how can you look at the reports in your Spool File. You use the "Work with Spool Files" command.
Key:

WRKSPLF

and hit ENTER.

You will see the Spool File with all the reports in it. Many of them will have odd names and some may be
error logs generated automatically. For example, if you disconnect from the internet before you sign off,
the AS/400 may generate a system log report of your "abnormally terminated" job.

Reports created by QUERY/400 are given the messy name of QPQUPRFIL. So you should now see a list
of all the reports in your Spool File.

Near the top of the screen you can see the options you can use. The only ones you should need are
4=DELETE and 5=DISPLAY.

By keying the option number "5" next to a report and hitting enter, you can see the report. Here you can
see your headings. Similar to the interface for QUERY/400 you can: F20 to scroll right (shift F8)
F19 to scroll left (shift F7)
Key in "B" and hit ENTER to go to the bottom
Key in "T" and hit ENTER to go to the top

Once you've looked at your report, exit out of it by hitting F3. Now put a "4" next to it in the Spool File
list and hit ENTER and you have deleted it.

Experiment by making several reports. Do this by running your query several times. Then use WRKSPLF
to view your spool file.

Feel free to delete all of the reports in your Spool File. I try to keep mine empty. Especially, feel free to
delete the reports you don't understand because they were created by the system.

In conclusion, here is a short discussion on routing print data to your printer.

Not too long ago, all AS/400 printers were connected directly to AS/400's or AS/400 remote controllers.
With the internet has come the ability to easily route print data to a remote. Doing so requires the client
machine (that is, your PC) to have an AS/400 Telnet Client that is capable of creating virtual print
devices.

36
With such a Telnet Client, you can easily print reports, like this query, directly to your printer. These
Telnet Clients are about $150 to $200. I like the one sold by Synapse (www.synapse.com). There are
others including IBM's Client Access.

You do not need print capabilities to do this tutorial. I rarely print reports out. I never print programs out.
It is important to realize how easily your reports could be printed on a PC printer though. A $200
investment for a company to be able to use a remote AS/400 is not very much money.

Showcase Article - Physical and Logical Files

The AS/400 database, DB2/400 is part of the AS/400 operating system. It is a relational
database and has features similar to other databases you may have used such as Microsoft
Access, Oracle or Dbase. The standard method of creating files is to define the specifications of
the file using DDS. Of course DDS is used for other things on the AS/400 like defining display
files and print files.

Create a Physical File

To create a physical database file, enter your source statements in a DDS source file member.
For now, name the member "CUS" for customer file. Make sure the member type is "PF". This
tells the compiler that this is for a physical file. Enter the records in Figure 1 to define a simple
customer file. Notice that the first record has an "R" in position 17. This means that this line is
specifying the record name, in this case "CUREC". The "TEXT" is optional but helps to
document the file.

After the line naming the record, each line describes a field. The field name is followed by the
field length and its data type. The three most used data types are "A" for alpha or character, "S"
for numeric and "P" for packed decimal. For numeric fields, you must also specify the number of
decimal positions. So here, the company number field is a three digit number with no decimal
places. The customer number and zip code are also numeric fields with no decimal places. The
credit limit is a numeric, packed decimal field with 9 digits, of which two are after the decimal
point. The rest of the fields are character fields.

Once you have entered the DDS source code, you must compile it. You do this by keying option
14 next to your member name on the PDM screen. If you pay attention you will see that the
AS/400 is actually executing the CRTPF (Create Physical File) command. It knows to use this
command because the member type of the source code is "PF".

You now have a database physical file. This file has built into it the fields and their attributes.

Create a Physical File With Key Fields

Let's modify this file definition to add key fields. If a physical file has key fields, programs can
randomly access the records or read them sequentially in the order of the key fields. You can
see in Figure 2 that it is simple to add key fields.

The "UNIQUE" record at the beginning of the source is used if you want the AS/400 to insist on
having no records with duplicate keys. This is optional.

At the end of the source code, there are two lines with "K" in position 17. These lines define the
key fields. So, this file will build a key using the company number and then the customer
number. Further, it will not allow a duplicate company number / customer number records to be
written.

37
The records are written to the file in arrival sequence. If you read the data by specifying keyed
access, the records will read as though they have been sorted by company number and
customer number. Also, your programs can randomly retrieve records. For example, a "CHAIN"
instruction in RPG can now randomly read the record for a specific company number / customer
number.

Create a Logical File To Resequence Order of Records

Now for the real magic. In only a few lines of source code, you can create a logical file. This is a
way of reading the file with a different key. A logical file is a list of key values that point to the
physical file. It does NOT contain copies of the data in the physical file.

To create a logical file, again enter your source statements in a DDS source file member named
"CUS01". This time, make sure the member type is "LF". Enter the source code in Figure 3.

The first line tells the compiler that this logical file will resequence the records in the physical file
named in the "PFILE" specification. In this case it is the "CUST" file. Also, notice that here we
are using the same record name as the physical file, "CUREC".

The only remaining lines are like the last two lines of the physical file source. They name the
fields that you want to use as keys.

Again compile the file by using option 14. This time, the AS/400 will execute the "CRTLF"
(create logical file) command. You now can read the customer file in city / state sequence
simply by reading the file "CUS01" in keyed sequence.

Create a Logical File To Select and Resequence Records

Finally, look at Figure 4. The "S" type record will select only records that have customer status
equal to "A". Also, this logical file will read the records in customer name sequence.

So, a program reading this file in keyed sequence, will read the records alphabetically by
customer name and will read only records of active customers.

Figure 1 - DDS for Physical File Without Key

A R CUREC TEXT('CUSTOMER FILE')

A CUCO 3S 0 TEXT('COMPANY #')

A CUSTS 1A TEXT('STATUS CODE')

A CUNUM 5S 0 TEXT('CUSTOMER #')

A CUNAME 30A TEXT('CUSTOMER NAME')

A CUADR 30A TEXT('CUSTOMER ADDRESS')

A CUCITY 18A TEXT('CUSTOMER CITY')

38
A CUSTAT 2A TEXT('CUSTOMER STATE')

A CUZIP 9S 0 TEXT('CUSTOMER ZIP')

A CUCRLM 9P 2 TEXT('CUST CREDIT LIMIT')

Figure 2 - DDS for Physical File With Key Fields

A UNIQUE

A R CUREC TEXT('CUSTOMER FILE')

A CUCO 3S 0 TEXT('COMPANY #')

A CUSTS 1A TEXT('STATUS CODE')

A CUNUM 5S 0 TEXT('CUSTOMER #')

A CUNAME 30A TEXT('CUSTOMER NAME')

A CUADR 30A TEXT('CUSTOMER ADDRESS')

A CUCITY 18A TEXT('CUSTOMER CITY')

A CUSTAT 2A TEXT('CUSTOMER STATE')

A CUZIP 9S 0 TEXT('CUSTOMER ZIP')

A CUCRLM 9P 2 TEXT('CUST CREDIT LIMIT')

A K CUCO

A K CUNUM

Figure 3 - DDS for Logical File to Resequence Order of Records

A R CUREC PFILE(CUS)

A TEXT('CUST BY CITY /
STATE')

39
A K CUCITY

A K CUSTAT

Figure 4 - DDS for Logical File to Select and Resequence

A R CUREC PFILE(CUS)

A TEXT('CUST NAME/ACTIVE
ONLY')

A K CUNAME

A S CUSTAT COMP(EQ 'A')

RPG Lesson 1 - A 7 statement RPG-III program

It is important to understand the history behind the RPG language. The language was originally
developed in the 1960's. It was a very high-level language meaning that a lot could be done with few
programming statements. It was originally intended to be used as a report writer, hence the name Report
Program Generator.

This original form of RPG was unique is several ways:

1 - 5 different record types were used to do everything

"F" was for file definitions

"I" was for input definitions (record layouts)

"C" was for calculations

"O" was for output definitions

"E" was for exception processing

2 - There were many automatic processing features like the "cycle"

The cycle processing automatically read the input file and

created the output files… that is, no read or write statements were

40
needed.

3 - Fixed column locations for values of each programming statement. That is,

unlike COBOL, C, Java, or Basic, the code is not free form.

4 - The use of Indicators or Switches was painfully required. A switch with

a value of '0' is off and a value of '1' is on. Switches were used to

determine the results of I-O operations and needed for simple compare

instructions. For example, instead of a statement that read like:

IF CTR > 0, Do SOMETHING

RPG read more like

COMPARE CTR to 0 and turn Indicator 90 on if it is >

If Indicator 90 is on, Do SOMETHING

The programs were sometimes rather ugly. The use of indicators made many programs very hard to
understand.

RPG has evolved nicely to look more and more like other modern languages. While indicators are still
used for Input-Output (read and write) operations, standard conditional operations are now available.
IF/THEN, DoWhile, Do Until and Select Case operands exist. While still not completely freeform, the
statements have portions that are free form. Also, powerful string handling functions like %trim, %subst,
%len and %scan are available. If you are familiar the concepts of structured programming you will see
that RPG has everything required for structured code.

So, while RPG is about 40 years old, its newest form (RPG IV) is modern and structured. The problem is
that many programs are still in use that have very old programming styles. So, you really must be familiar
with both RPG/400 (also known as RPG III) and RPG IV (also known as RPG ILE).

RPG is a full featured language that can do all functions of data processing: reading files, randomly
retrieving data, navigating through indexes, reading and writing to data terminal or display files, creating
print reports and database files.

If you are still concerned that RPG is too old to be useful, consider that Visual Basic and ASP are really
just new versions of BASIC. BASIC is as old as RPG. Also, you should know that RPG ILE can create
compiled objects that bind with modules written in other languages (like C) and can be used to process
CGI scripts on the internet and output dynamic HTML. No kidding.

If you have an RPG book, I suggest you use it in addition to (or in place of) this tutorial. It is a
challenging task to describe such a complex language in short, readable topics.

41
To proceed you need to be familiar with PDM (see topic 4) and should have completed the exercise in
topic 5 that copies a file.

Since it important to know the old way of doing things (RPG/400) and the new way (RPG/ILE), I will
present each program we write in both languages. Learn the RPG/400 style so you can get a job. Learn
the RPG/ILE so you can see how modern the language has become.

Topic 5 showed you how to copy a file named CUST into your user library. Since this will be the input
file to our program, make sure that your library list includes your user library. I prefer to have this library
as my current library.

So, use DSPLIBL to display your library list. If you don't see your user library in the list, use the
CHGCURLIB USER999 command. This will change your current library to USER999. Remember that
when I say USER999, I mean your user ID.

You can look at your data file with the command:


RUNQRY QRYFILE(CUST)

If this doesn't show your file, either you didn't copy the file (see Topic 5) or your library list does not
include your user library. You should see that the address for every record is "123 MAIN STREET". We
will write a program to read the first record of the file and change the address to "456 OAK". In the next
tutorial we will convert the program to RPG-ILE (RPG IV). In later topics we will change the program to
read every record in the file and change the address to "456 OAK" in every record.

We need to enter program source statements, so start PDM (STRPDM). You should see something like:

------------------------------------------------------------------------------------

AS/400 Programming Development Manager (PDM)

Select one of the following:

1. Work with libraries

2. Work with objects

3. Work with members

4. Work with projects

5. Work with groups

6. Work with parts

9. Work with user-defined options

---------------------------------------------------------------------------------

42
Key in 3 and hit ENTER. Fill in the screen to look like:

Specify Members to Work With

Type choices, press Enter.

File . . . . . . . . . . QRPGSRC Name, F4 for list

Library . . . . . . . . user999 *LIBL, *CURLIB, name

Member:

Name . . . . . . . . . *ALL *ALL, name, *generic*

Type . . . . . . . . . *ALL *ALL, type, *generic*,

-------------------------------------------------------------------------------

Of course, change the USER999 to your user ID. Hit ENTER now.

If you get an error message that QRPGSRC was not found in USER999, you need to create the file
QRPGSRC to hold your RPG-III (RPG/400) source code. For a refresher on this, review the topic on
PDM. The command to create QRPGSRC in your library is:

CRTSRCPF USER999/QRPGSRC Your screen should look like:

File . . . . . . QRPGSRC

Library . . . . USER999 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Rename

8=Display description 9=Save 13=Change text 14=Compile 15=Create module..

Opt Member Type Text

43
(No members in file)

Remember from your PDM lesson that this is trying to show you a list of all of the RPG programs that
you have entered. Since you haven't entered any, there is nothing to show.

You need to add a program. Let's call the program TUTR001. This name could be any 10 characters but if
you don't follow a naming convention you will confused quickly. This name is derived from TUT (for
tutorial), R for RPG and 001.

Hit F6 to add the program. Key in the name (the source member), RPG for the source type and a short
description. Your screen should look like:

---------------------------------------------------------------------------

Start Source Entry Utility (STRSEU)

Type choices, press Enter.

Source file . . . . . . . . . . > QRPGSRC Name, *PRV

Library . . . . . . . . . . . > USER000 Name, *LIBL, *CURLIB,

Source member . . . . . . . . . tutr001 Name, *PRV, *SELECT

Source type . . . . . . . . . . rpg Name, *SAME, BAS, BASP

Text 'description' . . . . . . . Change the first record in CUST

-----------------------------------------------------------------------

Now hit enter and you will see a blank screen where you can enter RPG source code.

Back in the seventies, programmers had to keep track of what column each operand of the RPG statement
was in. It was a mess.

With PDM (actually SEU, the Source Entry Utility), things are easier. Not easy, but easier. The problem
is that RPG is a fixed column language. It is not a free format language. SEU provides prompting to help
you but even it is a bit complicated at first.

The problem is that the different records types (F, I, E, C, O) do multiple things. That is, the I record type
can be used several different ways so it has several different ways of prompting.

The first statement of this program is a FILE specification. That is, it will name the file that we will read
and update. Since we want to read the CUST file, we will enter an F record to define the file CUST.

To do this, hit F23. Since your PC keyboard doesn't have an F23 key, the Telnet5250 product you are
using has mapped the SHIFT-F11 key as an F23 key. So, hold down SHIFT and hit F11. The top of your
screen should look like:

44
Select Prompt

Type choice, press Enter.

Prompt type . . . . . . . . . . . . Values listed below

RPG/400: H,F,FC,FK,FX,U,E,L,I,IX,J (I cont),JX,DS,SS,SV,C,O,

OD,P (O cont),N,* (Comment)

Wow. This means that there are 21 different formats to choose from. This is an easy one. Since this is a
FILE specification, we will use the F prompt. So key F for the Prompt and hit ENTER.

You should now see:

0001.00

****************** End of data ********************************

Prompt type . . . F Sequence number . . . 0001.00

File File End of File

Filename Type Designation File Sequence Format

Record Mode of Length of Record

Length Processing Key Field Address Type

File Overflow Key Field Extn

Organization Indicator Start Loc Code Device

File File

Continuation Exit Entry Addition Condition

What a mess! A couple of things have happened. The first is that the display shows your first line of the
program as line 0001.00. Not only that, the SEU editor has highlighted it because it is blank, RPG-III

45
does not allow blank lines! The rest of the screen shows all of the fields that might be used to define a
file. Don't panic yet. All you need to enter is:

CUST for Filename

I for File Type

F for File Designation

E for File Format

DISK for Device (2nd line from the bottom on the right)

Hit ENTER and your values will go in the right places. Amazingly, the one value that you can't enter here
is the F that tells RPG that this is a FILE specification. So hit enter, your screen looks like:

FMT F .....FFilenameIPEAF....RlenLK1AIOvKlocEDevice+

*************** Beginning of data ************

0001.00 CUST IF E DISK

****************** End of data ***************

It also displays an error that "The Type entry is not H, F, I, C ……"

So put your cursor on the character right before CUST and key an F.

Now you have a valid file specification:

FMT F .....FFilenameIPEAF....RlenLK1AIOvKlocEDevice+

*************** Beginning of data ************

0001.00 FCUST IF E DISK

****************** End of data ***************

Now, calm down. This may be the only time in your life that you actually key in a FILE specification. In
the world of programming, everything is copied and changed, cut and paste. Normally, you will simple
copy an existing program and then change and add statements to it.

So, what did you just define? You told the program that you will be using the file CUST, that the file is
being used for Input (you will read the file), that the file is Fixed length (almost all files are fixed length),
that the file is Externally defined (that is, it was defined by the database language of the AS/400) and
finally that the file is a DISK file (not a PRINTER or Display Screen).

Imagine for a moment a program where the user enters a customer number on the display screen. The
program reads the customer record, looks up the customer's most recent order and prints it. Such a
program will have at least 4 files: Display screen file (a WORKSTN file) Customer file (a DISK file)
Order file (a DISK file) Printer file (a PRINTER file)

46
This is a simple program. It has only one file.

Now we are ready for the processing logic of the program. The total logic of this program will be only 6
statements. Processing logic in RPG is known as CALCULATION statements and uses the C
specification and the C prompt type.

Soon, you will get more comfortable with PDM and SEU. Now, we need to add a line to after the F
statement. Do this by keying an I (for insert) on top of the 0001.00.

Your screen should look like:

FMT FX .....FFilenameIPEAF........L..I........Device+

*************** Beginning of data ************

I001.00 FCUST IF E DISK

When you hit ENTER, the editor will create a blank line for you and even place your cursor in column 6
where you can enter the C for CALCULATION. With the cursor on the line with the C, hit Shift-F11 to
prompt and this time use C for the prompt type.

Your screen will now show:

Prompt type . . . C Sequence number . . . 0002.00

Level N01N02N03 Factor 1 Operation Factor 2 Result

Decimal

Length Positions H/N/P HI LO EQ Comment

Now finally some good news. Most of the RPG programming you do is using the C specification. This
type of statement is not too messy.
The first processing step of the program is to read the first record of the CUST

file. RPG needs to know 2 things about a read statement:

1) what file to read

2) what indicator to turn on if there was not a "next" record in the file

(that is, what indicator will tell you that there is no more data in

the file)

Indicators are numbered from 01 to 99. There are some other special ones too.

47
I like to use indicators 90 thru 99 for the read statements. So enter

READ for the Operation

CUST for FACTOR 1

90 for EQ

Your screen should look like:

0001.00 FCUST IF E DISK

0002.00 C

'''''''

****************** End of data *******************************

Prompt type . . . C Sequence number . . . 0002.00

Level N01N02N03 Factor 1 Operation Factor 2 Result

READ CUST

Decimal

Length Positions H/N/P HI LO EQ Comment

90

When you hit ENTER, it will look like:

FMT FX .....FFilenameIPEAF........L..I........Device+......KExit++En

*************** Beginning of data ***************************

0001.00 FCUST IF E DISK

48
0002.00 C READ CUST 90

****************** End of data ******************************

There are 3 places to enter indicators for statements. Unfortunately, it is not always easy to figure out
which place to use. The HI, LO and EQ headings come from the obsolete way indicators were first used.
In old RPG, there were no IF statements. Instead, you used a COMP (Compare) statement to compare the
values of FACTOR1 and FACTOR2 and then would set on an indicator if FACTOR1 was higher than
FACTOR2, a different indicator if FACTOR1 was lower that FACTOR2 and finally an indicator if they
were equal. We will NEVER do this.

The lesson here is simple. For a READ instruction, the indicator mentioned in the EQ field will be turned
on when there are no more records in the file.

Let's pause for a minute and look at all that is happening with these 2 statements.

The F specification tells the AS400 to set up a way to read the CUST file. It also tells it to find the fields
and attributes of the fields using the database definition of the CUST file. In most other languages, you
would need a statement to OPEN the file. Such a statement tells the computer that you are ready to use
the file. RPG assumes that you want to read the file and automatically opens the file for you. There is a
simple way to tell the AS400 that you want to OPEN and CLOSE the file explicitly but there is no reason
to do that.

The READ statement reads the first record of the file CUST and populates an area in your program's
memory with the data that is in the first field. You program has each field defined and now has data in
each field.

After the READ, the field CSNBR has a value of 1002, the field CSNAME has a value of E LUMPKIN,
the field CSADR1 has a value of 123 MAIN STREET.

We now want to change the value in CSADR1. Unlike other languages, if we move only a few characters
to a field that is 30 characters long, RPG will change only the first 3 characters. So we will first blank out
the field and then move 456 OAK to the address.

Insert a line for a new C statement. One way to do this is to key an I over the

0002.00 and hit ENTER. Then key C in column 6 and hit Shift-F11. Key C for prompt

type and hit ENTER. We want to blank out the CSADR1 field so we will move blanks

to it. RPG has some system values defined that are named like:

*BLANK or *BLANKS

*ZERO or *ZEROES

*ON or *OFF

*IN90 (for indicator 90)

As you might guess, we want to move the value *BLANK to CSADR1. So fill in your screen to look like:

49
Prompt type . . . C Sequence number . . . 0003.00

Level N01N02N03 Factor 1 Operation Factor 2 Result

MOVE *BLANK CSADR1

Decimal

Length Positions H/N/P HI LO EQ Comment

Hit ENTER and your program should look like:

*************** Beginning of data *****************************

0001.00 FCUST IF E DISK

0002.00 C READ CUST 90

0003.00 C MOVE *BLANK CSADR1

****************** End of data ********************************

Now insert another line to MOVEL '456 OAK' to CSADR1. This says to move the characters

in between the quotes to the field named CSADR1. The operand is MOVEL for MOVE LEFT.

This means that since '456 OAK' is only 7 characters and CSADR1 is 30 characters,

move '456 OAK' to the left

You program should look like:

*************** Beginning of data **************************

0001.00 FCUST IF E DISK

0002.00 C READ CUST 90

0003.00 C MOVE *BLANK CSADR1

0004.00 C MOVE '456 OAK' CSADR1

****************** End of data *****************************

50
At this moment, the data on the disk has the value '123 MAIN STREET' in the area of

the record for CSADR1. If you ran this program, at this spot in the program, the

value of the field CSADR1 in memory would be '123 OAK'. But if you stopped here,

the new value ('123 OAK') would not get stored in the file. To do that you must

UPDATE the record. In RPG-III verbs or operands can be only 5 characters so the

verb is UPDAT. Also, you must use the record name for the file. This is too

complicated to explain here but trust me that the record name for the CUST file

is CSREC.

So add the statement to update the record CSREC. Now that we see that we are using

the file for Update (not just Input), it is time to change the I in the FILE

definition from I to U.

0001.00 FCUST UF E DISK

0002.00 C READ CUST 90

0003.00 C MOVE *BLANK CSADR1

0004.00 C MOVEL'456 OAK' CSADR1

0005.00 C UPDATCSREC

Now all that is left to do is to tell the program to stop.

First, we have to discuss a housekeeping item left over from the very early days

of RPG. We know that RPG will automatically open the file. However, it will only

close the file if the "LAST RECORD" indicator is ON. For now, just make sure the

last 2 statements to execute in a program are:

MOVE *ON *INLR

RETRN

The last statement is a RETRN which is an abbreviation of RETURN.

51
So the final program is:

0001.00 FCUST UF E DISK

0002.00 C READ CUST 90

0003.00 C MOVE *BLANK CSADR1

0004.00 C MOVEL'456 OAK' CSADR1

0005.00 C UPDATCSREC

0006.00 C MOVE *ON *INLR

0007.00 C RETRN

Now that you are finished, hit F3 and ENTER to save your statements.

So you now have the source statements to compile an RPG program. You compile it just like you
compiled the CL program. Key a 14 on the line next to the program name in PDM and hit ENTER. Like:

Work with Members Using PDM

File . . . . . . QRPGSRC

Library . . . . USER999 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Re

8=Display description 9=Save 13=Change text 14=Compile 15=Cr

Opt Member Type Text

14 TUTR001 RPG Change the first record in CUST file

By the way, this program is in the USER000 library. You can see it using PDM.

After compiling your program, you will want to look at the compiled listing. Remember, you do this with
the command:

WRKSPLF

You will see something like:

52
Work with All Spooled Files

Type options, press Enter.

1=Send 2=Change 3=Hold 4=Delete 5=Display 6=Release

8=Attributes 9=Work with printing status

Device or Total

Opt File User Queue User Data Sts Pages

TUTR001 DAVIDMOUNT PRTDGM RDY 5

TUTR001 DAVIDMOUNT PRTDGM RDY 5

Put your cursor next to the last one and key in a 5 and hit ENTER.

You will see your compiler listing. If you key in a B at the top and hit ENTER, the AS400 will take you
to the bottom of your listing. If your compile worked, it will look like:

F i n a l S u m m a r y

Message Count: (by Severity Number)

TOTAL 00 10 20 30 40 50

2 2 0 0 0 0 0

Program Source Totals:

Records . . . . . . . . . . : 7

Specifications . . . . . . : 7

Table Records . . . . . . . : 0

Comments . . . . . . . . . : 0

PRM has been called.

Program TUTR001 is placed in library USER000. 00 highest severity.

* * * * * E N D O F C O M P I L A T I O N * * * *

The phrase "Program TUTR001 is placed in library USER???" means the AS400 understood your
statements well enough to crate an executable program.

If your compile didn't work, start by making sure that you have your user library in your library list. The
easy way to do this is:

53
CHGCURLIB USER999

All that is left is to run the program. There are several ways to do this but the most straightforward way is
to use this command:

CALL TUTR001

The program will run almost instantly. Then if you look at the CUST file the address of the first record
will have changed:

RUNQRY QRYFILE(CUST)

Boy what a long topic! Each lesson will build on this program. It is important that you get familiar with
entering programs, compiling them and looking at the compile listings.

Viewing a Compiler Listing


To view the results of a program compiling, use the Work With Spool File command, WRKSPLF.

You will see a list of reports in your spool file. It will look like:

Device or Total

Opt File User Queue User Data Sts Pages

QSYSPRT AIRPGMR PRTDGM RDY 1

QPJOBLOG AIRPGMR QPRINT AIRNRA RDY 2

QSYSPRT AIRPGMR PRTDGM RDY 1

QSYSPRT AIRPGMR PRTDGM RDY 1

QPJOBLOG AIRPGMR QPRINT TQE07 RDY 2

QSYSPRT AIRPGMR PRTDGM RDY 1

QSYSPRT AIRPGMR PRTDGM RDY 1

Each line is the name of a report on your Spool File. The most recent reports are at the bottom. Key a 5 next the report you want
to view.

You should now be looking at the compiler listing. To quickly locate errors, key B (for bottom) in the CONTROL field and hit
ENTER. You are now looking at the bottom of the compiler report.

If your program compiled successfully, the last few lines will look
like:

* * * * * E N D O F F I N A L S U M M A R Y * * *
*

54
Program CMNR020 placed in library AIR. 00 highest severity. Created on

* * * * * E N D O F C O M P I L A T I O N * * * * *

If not, it will look more like:

* * * * * E N D O F F I N A L S U M M A R Y

Compilation stopped. Severity 30 errors found in program.

* * * * * E N D O F C O M P I L A T I O N * *

To find the errors, hit the PAGE UP key until you see:

* * * * * E N D O F E X T E R N A L R E F E R E N C E S *
*

5769RG1 V4R2M0 980228 RN IBM ILE RPG AIR/CMNR020

M e s s a g e S u m m a r y

Msg id Sv Number Message text

*RNF7031 00 61 The name or indicator is not referenced.

*RNF7066 00 1 Record-Format name of Externally-Described file is


not

*RNF7030 30 1 The name or indicator is not defined.

*RNF7503 30 1 Expression contains an operand that is not defined.

* * * * * E N D O F M E S S A G E S U M M A R Y * * *
*

These are the errors that need correcting. Anything with severity level 00 is NOT an error.

To find the error, go to the top of the report. Do this by keying T in the CONTROL field and hitting ENTER.

Then, key the error message ID in the FIND field. In this case, I keyed RNF7030 in the FIND field. Then, hit F16 to search.
Remember F16 is SHIFT / F4.

In my case, the errors look like:

*RNF7066 00 2 000200 Record-Format CUSREC not used for

*RNF7030 30 123 005200 The name or indicator SYSDTECC is

55
*RNF7503 30 123 005200 Expression contains an operand tha

The errors RMF7030 and RNF7503 need to be fixed. They are both related to sequence # 123 in the compile listing which is line
number 52.00 in the source file.

In my case, I misspelled a variable name. This caused 2 errors. Often, 1 error will cause more than 1 error message.

RPG Lesson 2 - Converting RPG-III to RPG IV

First RPG IV Program

Hopefully you were able to complete the previous topic and compile a simple RPG III program. Though
introduced in 1994, RPG IV is known as the "new" RPG. Because of the huge number of programs
written in RPG III, the industry has been slow to adopt RPG IV. It is undoubtedly the way of the future on
the AS/400.

RPG III is more accurately known as RPG/400 when it runs on an AS/400. RPG IV supports the
"Integrated Language Environment" concept introduced in 1994. This is known as ILE and allows
program modules to be bound together at compile time so that an RPG IV program can use routines
written in C or any other language. So RPG III is essentially the same as RPG/400 and RPG IV is
essentially the same as RPG ILE.

Before you go any further, read this short article:

Converting RPG-III to RPG-ILE

Now you are emotionally ready to convert your program TUTR001 to RPG IV.

First you must create a place for your program statements. Since RPG IV statements are longer than other
program source statements, the command to create the source physical file is slightly different. To create
the appropriately named place for RPG IV source:

CRTSRCPF FILE(USER999/QRPGLESRC) RCDLEN(112)

Of course, change the USER999 to your user ID. This command creates a source physical file named
QRPGLESRC to hold your programs written in RPG IV. The name is the AS/400 standard for RPG IV or
RPG ILE source code. It starts with "Q" followed by RPGLE (short for RPG ILE) and then SRC for
source.

Now, use the AS400 command to convert the old program to RPG ILE. Key CVTRPGSRC (Convert
RPG Source) and hit F4 to see the prompts. Your screen should look like:

Convert RPG Source (CVTRPGSRC)

Type choices, press Enter.

From file . . . . . . . . . . . Name

Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB

From member . . . . . . . . . . Name, generic*, *ALL

56
To file . . . . . . . . . . . . QRPGLESRC Name, *NONE, QRPGLESRC

Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB

To member . . . . . . . . . . . *FROMMBR Name, *FROMMBR

Now fill in the values to indicate that you want to convert the program located in source physical file
QRPGSRC in library USER999 that is named TUTR001 and that you want the converted program to be
in the same library with the name TUTR002.

Convert RPG Source (CVTRPGSRC

Type choices, press Enter.

From file . . . . . . . . . . . qrpgsrc Name

Library . . . . . . . . . . . user999 Name

From member . . . . . . . . . . tutr001 Name

To file . . . . . . . . . . . . QRPGLESRC Name

Library . . . . . . . . . . . user999 Name

To member . . . . . . . . . . . tutr002 Name

Hit ENTER and the command will copy and modify your program.

You can now use PDM to look at the converted program. From the PGM screen key in 3 and hit ENTER.
Then fill in the screen to look like:

Specify Members to Work With

Type choices, press Enter.

File . . . . . . . . . . QRPGLESRC Name, F

Library . . . . . . . . USER999 *LIBL,

Member:

Name . . . . . . . . . *ALL *ALL

57
Type . . . . . . . . . *ALL *ALL

Hit enter and you will see your converted program in the list of programs:

Work with Members Using PDM

File . . . . . . QRPGLESRC

Library . . . . USER000 Position to . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print

8=Display description 9=Save 13=Change text 14=Compile

Opt Member Type Text

TUTR002 RPGLE Change the first record in CUST

Notice that the "Type" is RPGLE. That tells the AS400 to compile this as RPG ILE instead of RPG III.

Key a 2 next to the program name (TUTR002) and hit ENTER and you will see the source code:

0001.00 FCUST UF E DISK

0002.00 C READ CUST 90

0003.00 C MOVE *BLANK CSADR1

0004.00 C MOVEL '456 OAK' CSADR1

0005.00 C UPDATE CSREC

0006.00 C MOVE *ON *INLR

0007.00 C RETURN

****************** End of data ****************************************

You can see that not much has changed. RPG IV has more room for operand names so the UPDAT and
RETRN are now spelled out. The other values are spread out a bit more.

You can compile and run this program. You should try that now. Remember that you compile by using
option 14. You can then CALL TUTR002 to run it.

58
Now copy this program and modify it to reflect the new coding style of RPG IV. Copy the program using
PDM. Simply key 3 as the option:

Work with Members Using PDM

File . . . . . . QRPGLESRC

Library . . . . USER000 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Rename

8=Display description 9=Save 13=Change text 14=Compile 15=Create

Opt Member Type Text

3 TUTR002 RPGLE Change the first record in CUST file

When you hit ENTER, fill in TUTR003 as the new name:

Copy Members

From file . . . . . . . : QRPGLESRC

From library . . . . : USER000

Type the file name and library name to receive the copied members.

To file . . . . . . . . QRPGLESRC Name, F4 for list

To library . . . . . USER000

To rename copied member, type New Name, press Enter.

59
Member New Name

TUTR002 TUTR003

Now hit ENTER again and PDM will copy TUTR002 and name it TUTR003.

Edit TUTR003 by keying 2 as the option.

One way RPG IV is different is that lower case letters are allowed. This doesn't change the functionality
of the program but it certainly makes it feel more modern.

You must tell SEU that you want to use lower case letters. When you are editing the TUTR003 program,
hit F13 (well actually Shift-F1) and you will get the options for the editor:

Change Session Defaults

Type choices, press Enter.

Amount to roll . . . . . . . . . . . C H=Half, F=Full

C=Cursor, D=Data

1-999

Uppercase input only . . . . . . . . N Y=Yes, N=No

Tabs on . . . . . . . . . . . . . . N Y=Yes, N=No

Increment of insert record . . . . . 0.01 0.01-999.99

Full screen mode . . . . . . . . . . N Y=Yes, N=No

Source type . . . . . . . . . . . . RPGLE

Syntax checking:

When added/modified . . . . . . . Y Y=Yes, N=No

From sequence number . . . . . . . 0000.00-9999.99

To sequence number . . . . . . . . 0000.00-9999.99

Set records to date . . . . . . . . / / YY/MM/DD

60
It is best to change the first value to C. This affects how the screen scrolls when you PAGE-UP and
PAGE-DOWN. Make sure the "Uppercase input only" selection is N. This allows you to key lowercase
characters.

For now, make 2 changes in the style. First, use lower case characters when you want. Second, use the
EVAL operand in place of MOVE and MOVEL. EVAL is short for EVALUATE and like the old BASIC
"LET". It is not only more like other modern languages, it has other enhancements that make string
handling easy.

Also, since there is more room, change the address to 456 OAK STREET.

The modified program should look like:

0001.00 FCUST UF E disk

0002.00 C Read CUST 90

0004.00 C Eval CSADR1 = '456 OAK STREET'

0005.00 C Update CSREC

0006.00 C Eval *inlr = *on

0007.00 C Return

Since the EVAL instruction works a little differently from the MOVE, it is no longer necessary to move
blanks to CSADR1 before moving 456 OAK STREET to it.

Now compile and run the program. After running TUTR003 you can look at the file with:

RUNQRY QRYFILE(CUST)

and see that the address has changed to 456 OAK STREET.

Boy, in just 10 minutes you have learned a new language!

You should be getting more comfortable with PDM, SEU, compiling programs and looking at spool files.
If so, you are on your way to being a productive programmer.

RPG III - Adding a Loop, IF and Subroutine

In a previous topic, you should have written a very short RPG III program to change the first record in the
CUST file.

Let's add so more statements to the program so that it will read all records in the file and change the zip
code for everyone in Tennessee.

You may want to read this very short article on data navigation first:

Data Navigation

Your program will still reference the CUST file, so, use DSPLIBL to display your library list. If you don't
see your user library in the list, use the CHGCURLIB USER999 command. This will change your current
library to USER999. Remember that when I say USER999, I mean your user ID.

61
You can look at your data file with the command: RUNQRY QRYFILE(CUST)

Now, use PDM to copy your old program. Start PDM (STRPDM). You should see something like:

---------------------------------------------------------------------

AS/400 Programming Development Manager (PDM)

Select one of the following:

1. Work with libraries

2. Work with objects

3. Work with members

4. Work with projects

5. Work with groups

6. Work with parts

9. Work with user-defined options

---------------------------------------------------------------------

Key in 3 and hit ENTER. Fill in the screen to look like:

Specify Members to Work With

Type choices, press Enter.

File . . . . . . . . . . QRPGSRC Name, F4 for list

Library . . . . . . . . user999 *LIBL, *CURLIB, name

Member:

Name . . . . . . . . . *ALL *ALL, name, *generic*

62
Type . . . . . . . . . *ALL *ALL, type, *generic*,

-----------------------------------------------------------------------

Of course, change the USER999 to your user ID. Hit ENTER now.

Your screen should look like:

File . . . . . . QRPGSRC

Library . . . . USER999 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Rename

8=Display description 9=Save 13=Change text 14=Compile 15=Create module..

Opt Member Type Text

TUTR001 RPG Change the first record in CUST file

Key a 3 as the option next to TUTR001. Hit ENTER and then fill in the screen to copy the program and
name it TUTR004:

Copy Members

From file . . . . . . . : QRPGSRC

From library . . . . : USER999

Type the file name and library name to receive the copied members

To file . . . . . . . . QRPGSRC Name, F4 for list

To library . . . . . USER999

To rename copied member, type New Name, press Enter.

63
Member New Name

TUTR001 TUTR004

Hit ETER and you should now see the copied program in your list. You may want to change the
description of the program so you'll remember which program does what. Your screen should look like:

Remember from your PDM lesson that this is trying to show you a list of all of the RPG

Work with Members Using PDM

File . . . . . . QRPGSRC

Library . . . . USER000 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Rename

8=Display description 9=Save 13=Change text 14=Compile 15=Create

Opt Member Type Text

TUTR001 RPG Change the first record in CUST file

TUTR004 RPG Change all TN records in CUST file

Key a 2 next to TUTR004 so you can change the source statements to the program.

Before we make the changes to the program we need to discuss different ways to write a loop. We want a
loop that will read every record in the CUST file and change the records that have TN (Tennessee) as the
state.

I always think of a loop as saying:

Try to Read a record from the file

If there was a record then

change it

update it

Go back and try to read the next record

Remember that when RPG III reads a record, you must specify which indicator to turn on it there are no
more records; that is, it is END OF FILE.

64
You could write the instructions above in RPG III like this:

FCUST UF E DISK

C READIT TAG

C READ CUST 90

C *IN90 IFEQ *OFF

C MOVE *BLANK CSADR1

C MOVEL'456 OAK' CSADR1

C UPDATCSREC

C GOTO READIT

C ENDIF

C MOVE *ON *INLR

C RETRN

This program says to define a file named CUST.

Then, name the first line of the Calculations READIT. The, try to read a record (if END OF FILE, move
ON to indicator# 90) If indicator# 90 is *OFF Move … Move … Update … Go back to the first line of
the program Turn on the "magic" LR indicator End the program

This will work. The only problem is that for about 15 years, it has been considered bad style to use
GOTO statements. This is an industry trend that includes all languages and all computers.

The reason is that long programs are hard to understand when there are a lot of GOTO statements.
Programs with lots of GOTO's are nicknamed spaghetti programs because the statements can be as hard
to follow as a strand of spaghetti.

SO, the industry prefers that we use DO statements. We can use a DO WHILE or a DO UNTIL. This still
leaves us with 2 good ways to write the loop. I prefer the first because it looks a lot like the GOTO loop
but without the GOTO:

FCUST UF E DISK

C *IN90 DOWEQ*OFF

C READ CUST 90

C *IN90 IFEQ *OFF

C MOVE *BLANK CSADR1

C MOVEL'456 OAK' CSADR1

65
C UPDATCSREC

C ENDIF

C ENDDO

C MOVE *ON *INLR

C RETRN

This program defines the file and then starts a DO loop.

The DOWEQ statement says that as long as indicator # 90 is OFF, execute all of the statements until the
ENDDO (End DO) statement.

Then, start back at the top (a lot like a GOTO). If indicator # 90 is still OFF, execute the statements again.
Eventually, the program will read all 1,000+ records in the file. When it does, indicator # 90 will be
turned ON.

When indicator # 90 is ON, the program will not update the record and it will not continue to loop.

The other way to code the loop is with what is called a priming read statement. This method needs 2
READ statements but does not need the IF statement.

If looks like:

FCUST UF E DISK

C READ CUST 90

C *IN90 DOWEQ*OFF

C MOVE *BLANK CSADR1

C MOVEL'456 OAK' CSADR1

C UPDATCSREC

C READ CUST 90

C ENDDO

C MOVE *ON *INLR

C RETRN

Here, the first record is read before the DO begins. The statements are executed and the READ statement
is at the end of the DO loop.

Either of these 2 methods is considered good code. I prefer the first.

Using the first acceptable loop, add the IF statement to test to see if the state is TN. Also, replace the code
so that it changes the ZIP to 987650000.

First, do this by putting in an IF statement like this:

66
C CSSTE IFEQ 'TN'

C MOVE 987650000 CSZIP

C UPDATCSREC

C ENDIF

So, the whole program looks like:

FCUST UF E DISK

C *IN90 DOWEQ*OFF

C READ CUST 90

C *IN90 IFEQ *OFF

C CSSTE IFEQ 'TN'

C MOVE 987650000 CSZIP

C UPDATCSREC

C ENDIF

C ENDIF

C ENDDO

C MOVE *ON *INLR

C RETRN

This is considered good code by most programmers. But it really helps to move the update logic to a
separate place in the program as a subroutine. This is done here only to help readability. It doesn't change
the outcome.

In RPG, subroutines begin with a BEGSR (BEGIN SUBROUTINE) statement which also has the name
of the subroutine. They end with ENDSR (END SUBROUTINE). They are run with the EXSR
(EXECUTE SUBROUTINE) command.

If we move the update logic to a subroutine named UPD, the program looks cleaner. Also, we can add
"COMMENTS" records. Any statement with a * after the record type, is a "COMMENT". In fact you can
even remove the record type (the C or F in column 6).

With a few comment lines added to define the sections of the program, we get a pretty readable program:

FCUST UF E DISK

67
*-----------------------------------------------------

C *IN90 DOWEQ*OFF

C*

C READ CUST 90

C *IN90 IFEQ *OFF

C EXSR UPD

C ENDIF

C ENDDO

C*

C MOVE *ON *INLR

C RETRN

*-----------------------------------------------------

C UPD BEGSR

C*

C CSSTE IFEQ 'TN'

C MOVE 987650000 CSZIP

C UPDATCSREC

C ENDIF

C*

C ENDSR

*------------------------------------------------------

Now, compile this (remember… option 14) and run it (CALL TUTR004).

Then use RUNQRY QRYFILE(CUST) to see the data. If you scroll right by hitting F20 (actually Shift
and F8) you will see that you changed the zip in all of the records with TN as CSSTE.

RPG III - Adding a Loop, IF and Subroutine to the RPG IV Program

In the previous topic, we added a DO loop to read all records in the file, an IF statement to test the state
for "TN" and a subroutine.

You should be beginning to sense that RPG III is powerful but ugly.

Let's recreate this program using the easier to read syntax of RPG IV. The simplest way to do this is to
copy TUTR003 in the QRPGLESRC source object and then modify the copied program.

Use PDM to copy TUTR003. Start PDM (STRPDM). You should see something like:

68
--------------------------------------------------------------------------------------
----

AS/400 Programming Development Manager (PDM)

Select one of the following:

1. Work with libraries

2. Work with objects

3. Work with members

4. Work with projects

5. Work with groups

6. Work with parts

9. Work with user-defined options

--------------------------------------------------------------------------------------
----

Key in 3 and hit ENTER. Fill in the screen to look like:

Specify Members to Work With

Type choices, press Enter.

File . . . . . . . . . . QRPGLESRC Name, F4 for list

Library . . . . . . . . user999 *LIBL, *CURLIB, name

Member:

Name . . . . . . . . . *ALL *ALL, name, *generic*

Type . . . . . . . . . *ALL *ALL, type, *generic*,

69
Of course, change the USER999 to your user ID. Hit ENTER now.

Your screen should look like:

Work with Members Using PDM

File . . . . . . QRPGLESRC

Library . . . . USER999 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Rename

8=Display description 9=Save 13=Change text 14=Compile 15=Create

Opt Member Type Text

TUTR002 RPGLE Change the first record in CUST file

TUTR003 RPGLE TUTR002 modified to modern style

Key a 3 as the option next to TUTR003. Hit ENTER and then fill in the screen to copy the program and
name it TUTR005:

Copy Members

From file . . . . . . . : QRPGLESRC

From library . . . . : USER999

Type the file name and library name to receive the copied members

To file . . . . . . . . QRPGLESRC Name, F4 for list

To library . . . . . USER999

To rename copied member, type New Name, press Enter.

70
Member New Name

TUTR003 TUTR005

Hit ENTER and you should now see the copied program in your list. You may want to change the
description of the program so you'll remember which program does what.

Key a 2 next to TUTR005 so you can change the source statements to the program.

The old syntax on the IF and DO statements is legal. So you can choose between:

C *in90 DOWEQ *off

AND

C DoW *in90 = *off

Not only is the second form more readable, it is more free form. You can put spaces and parentheses in
the conditional part of the statement like this:

C DoW (*in90 = *off)

This may not look like such a big deal, but compare this old style IF statement:

C *in90 IFEQ *off

C STATUS ANDEQ 'D'

C STATUS OREQ 'A'

C CITY ANDEQ 'ATHENS'

with the newer style

C If (In90 = *off) and

C ((STATUS = 'D') or (STATUS = 'A')) and

C (CITY = 'ATHENS')

The newer style is not only more readable but you can actually figure out how the conditions are checked.

71
One of the other big changes in form from RPG III to RPG IV is that the subroutine names can be only 6
characters in RPG III. In RPG IV, the subroutine names can be 14 characters. These longer names make
the programs many times easier to follow.

So using this new found knowledge about RPG IV, change the program to look like:

FCUST UF E disk

C*---------------------------------------------------------------------

C DoW *in90 = *off

C Read CUST 90

C If *in90 = *off

C Exsr UpdateCSREC

C EndIf

C EndDo

C Eval *inlr = *on

C Return

C*---------------------------------------------------------------------

C UpdateCSREC BegSR

C If CSSTE = 'TN'

C Eval CSZIP = 987650000

C Update CSREC

C EndIf

C EndSR

Compile the program with option 14 and you are done.

If you really hate using the indicators - and you probably do - you can use one of the new built in
functions to check to see if the last record has been read. That is, you are checking to see if the file is at
END OF FILE or EOF.

The Do loop can be written:

72
C DoW not %eof(CUST)

C Read CUST

C If not %eof(CUST)

C Exsr UpdateCSREC

C EndIf

C EndDo

In fact, the %EOF function will refer to the last file used by default. So you could write:

C DoW not %eof

C Read CUST

C If not %eof

C Exsr UpdateCSREC

C EndIf

C EndDo

If you have ever used Visual Basic, the EOF function will look familiar.

That's it!

Using SDA to set up a User Menu

You are beginning to see how to create the different pieces of a complete system. You have written
queries that display and print data, you know how to view printed data and you have written several small
programs that can change data. After this topic, you will learn to write programs to display and change
data interactively - data maintenance, entry, update and display. In this topic, you will use yet another
three letter acronym, SDA, as a tool. You will also make a couple of changes to your user profile. The
end result will be a user interface that you could use as an entry point to an application system. The user
would sign on to the AS/400 and immediately see the user menu. The user would never see the AS/400
programmer and operator menus. In summary, here is the task:
1) Create a menu named STARTMEN that will let the user:

Run the display query that you wrote in Topic 6

Run query to print a report from Topic 6

Run the program to change the address line in the CUST file

Display the CUST file using RUNQRY

Display Print Spool files

Sign Off

73
2) Change your user profile so that when you sign on, you see this new menu. One of
the

most intuitive development tools on the AS/400 is SDA, Screen Design Aid. With it, you

build display screens and menus in a WYSIWYG (what you see is what you get) mode.
We're

going to look at how easy it is to create a user menu.

Start SDA with the command STRSDA. You will see that SDA has three functions:

1) Design Screens

2) Design Menus

3) Test Display Files

You'll want to experiment with each of these later. For now, use selection 2 to design a menu. Enter the
name of your new menu, where you want to store the source (usually QDDSSRC) and the library that it
will be in. SDA will look for that menu and since it can't find it, it will create it.

Your screen should look like:

Design Menus

Type choices, press Enter.

Source file . . . . . . . . QDDSSRC Name, F4 for list

Library . . . . . . . . . user999 Name, *LIBL, *CURLIB

Menu . . . . . . . . . . . startmen Name, F4 for list

Of course, replace USER999 with your user library name. When you hit ENTER you will see:

Specify Menu Functions

File . . . . . . : QDDSSRC Menu . . . . . . . : STARTMEN

Library . . . . : USER999

74
Type choices, press Enter.

Work with menu image and commands . . . . . . Y Y=Yes, N=No

Work with menu help . . . . . . . . . . . . . N Y=Yes, N=No

The AS/400 even fills in the "Y" to indicate that you want to work with menu images and commands.
Hit ENTER again and you see the following template menu.

STARTMEN STARTMEN Menu

Select one of the following:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

Selection or command

SDA creates a template for you that has the menu name and a list of ten selections. On this screen, you
list the selections for the user. On a separate screen, you list the commands associated with each selection.
Avoid keying in "insert" mode since that will shift all text on the screen. To remove text, just space over
it.

So, key on the screen so that it looks like:

75
STARTMEN STARTMEN Menu

Select one of the following:

1. Run Customer Query

2. Print Customer Query

3. Change Addresses in Customer file

4. Show Customer file

5. Work with Print files

6.

7.

8.

9.

10. Sign Off

When you hit enter, SDA uses your screen to build literals in a display file. F20 (Shift and F8) provides a
way to display the text blocks that SDA will use. Each text block is preceded by a hidden character that
contains the display attribute for that string of text. If you key an "H" right in front of a block of text,
SDA will display that text in high intensity or white characters. An "R" will display the text in reverse
image. "D" will delete the text.

Next, define the commands for each selection. Hit F10 to enter the commands. You now can key in the
commands for selections 1 through 99. After hitting F10, you should see:

Define Menu Commands

Menu . . . . . . : STARTMEN Position to menu option . .

Type commands, press Enter.

Option Command

01

02

76
03

04

05

06

07

Here, you enter the commands associated with each selection. So enter the commands like this:

Define Menu Commands

Menu . . . . . . : STARTMEN Position to menu option .

Type commands, press Enter.

Option Command

01 runqry csq001

02 runqry csq002

03 call tutr005

04 RUNQRY QRYFILE(CUST)

05 wrksplf

77
06

07

Then, hit page down so you can enter SIGNOFF as the command for selection 10. You can enter any
command that you want the user to run. You can run queries, submit print queries to run in batch and use
standard utility commands such as "Work with Spool Files", WRKSPLF. Finally, you can help the user
navigate to another menu with the "GO" command used for selection 6. Hit F3 a few times to exit. When
you exit SDA, check the "object library" name. This is where your compiled menu objects will go.

Your screen should look like:

Exit SDA Menus

File . . . . . . : QDDSSRC DDS member . . . . . : STARTMEN

Library . . . . : USER999 Commands member . . . : STARTMENQQ

Type choices, press Enter.

Save new or updated menu source . . . . Y Y=Yes, N=No

For choice Y=Yes:

Source file . . . . . . . . . . . . QDDSSRC Name,

F4 for list

Library . . . . . . . . . . . . . USER999 Name, *LIBL, *CURLI

Text . . . . . . . . . . . . . . . .

Replace menu members . . . . . . . . Y Y=Yes, N=No

Create menu objects . . . . . . . . . . Y Y=Yes, N=No

For choice Y=Yes:

Prompt for parameters . . . . . . . N Y=Yes, N=No

Object library . . . . . . . . . . . USER999 Name, *CURLIB

78
Replace menu objects . . . . . . . . Y Y=Yes, N=No

Wait! Let me say again - the value near the bottom of the screen - Object Library - must be your user
library. Otherwise you will create your menu somewhere else. Hit enter and the AS/400 will compile your
source code and your menu will be ready to run. SDA creates three objects, all with the same name: the
commands, the display file and a message file for the menu. If you want some added fun, go back to the
menu source using SDA and this time make the selection to "work with menu help". Here you can define
help screens that will display if your user enters the selection number and hits F1. Now you can tie this
menu to your new employee's user profile. Use the command to change your profile,CHGPRF. From a
command line key CHGPRF and hit F4.

You should see a screen like:

Change Profile (CHGPRF)

Type choices, press Enter.

Assistance level . . . . . . . . *SYSVAL *SAME, *SYSVAL, *BASIC...

Current library . . . . . . . . *crtdft Name, *SAME, *CRTDFT

Initial program to call . . . . SOC000 Name, *SAME, *NONE

Library . . . . . . . . . . . SOLIB Name, *LIBL, *CURLIB

Initial menu . . . . . . . . . . MAIN Name, *SAME, *SIGNOFF

Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB

Text 'description' . . . . . . . 'your email address'

When you sign on to the AS/400, these values tell the operator what your current library should be and
what menu is your default menu. Presently, your current library is probably *CRTDFT which is a system
value that means "NONE". Your initial menu is named MAIN. This is the menu you have gotten
accustomed to seeing when you sign on. Change your current library from *CRTDFT to your user library.
Also change your initial menu to STARTMEN. Make the LIBRARY value under your initial menu your
user library. Your screen should look like:

Change Profile (CHGPRF)

Type choices, press Enter.

Assistance level . . . . . . . . *SYSVAL *SAME, *SYSVAL, *BASIC

Current library . . . . . . . . USER999 Name, *SAME, *CRTDFT

79
Initial program to call . . . . SOC000 Name, *SAME, *NONE

Library . . . . . . . . . . . SOLIB Name, *LIBL, *CURLIB

Initial menu . . . . . . . . . . STARTMEN Name, *SAME, *SIGNOFF

Library . . . . . . . . . . . USER999 Name, *LIBL, *CURLIB

Text 'description' . . . . . . . 'your email address'

If you sign off and sign back on, you will see your new menu. By the way, if you set it up wrong, you
may have to e-mail me to reset your profile. For example, if you changed your profile to run the menu
ABCDEF as the initial menu, the AS/400 won't know what to do (since there is no ABCDEF menu). If
you want to see the familiar sign on screen, key in the command GO MAIN. It's that easy to customize
the screen selections for a user.

Using SDA to set up a simple Help Screen

One of the most intuitive development tools on the AS/400 is SDA, Screen Design Aid. With it, you build
display screens and menus in a WYSIWYG (what you see is what you get) mode. We're going to look at
how easy it is to create a simple help screen.

In only a few minutes, you can build a custom help screen for your user. Start SDA with the command
STRSDA. You will see that SDA has three functions:

1) Design Screens
2) Design Menus
3) Test Display Files

Use selection 2 to design a menu. Enter the name of your menu, where you have stored the source
(usually QDDSSRC) and the library that it is in.

Now choose the selection to "Work with menu help" by changing the "N" to a "Y". Here you can define
help screens that will display if your user enters a selection number and hits F1.

This is where you will "Create" the text for your help screen. You will also have 3 Range Options to
choose from.

Valid ranges are:

00-00 General help for the entire menu.

nn-nn Where nn is a number between 01 and 99. This is specific


help for one option of

the menu.

nn-mm Where nn is a number between 00 and 99 and mm is a number


between 01 and 99 and

is greater that nn. This is help for a range of options on


your menu.

80
Note: You cannot create more than a single page of help for each
range of options.

You will see this screen displayed. Type in a 1 for Create in the Opt field, and 01 - 01 in the Range field.
The 01 is only used for Selection 1 of your main menu selection. Option 02 is for Selection 2, etc..

Work with Menu Help Records

File . . . . . . : QDDSSRC Menu . . . . . . . :


MRCM001

Library . . . . : User999

Type options (and Range), press Enter.

1=Create 3=Copy 4=Delete 12=Update

Opt Range Text

___ __ - __

Bottom

F3=Exit F5=Refresh F9=Display image F12=Cancel

Create Menu Help Record

81
File . . . . . . : QDDSSRC Menu . . . . . . . :
MRCM001

Library . . . . : USER999

Type choices, press Enter.

Create help for option . . . . . . . . . . . . . . . 01 01-99

-OR-

Create help for option range (range xx-yy)

From menu option . . . . . . . . . . . . . . . . . ___ 00-99

To menu option . . . . . . . . . . . . . . . . . . ___ 01-99

-OR-

Create general help (range 00-00) . . . . . . . . . . N Y=Yes,


N=No

F3=Exit F5=Refresh F9=Display image F12=Cancel

From here, you will press Enter, a blank screen will appear and now
you can type in the text

you want for your help screen.

Once you have created the text help for each option you chose, you
should see the following

82
screen with your enhancements:

Work with Menu Help Records

File . . . . . . : QDDSSRC Menu . . . . . . . :


MRCM001

Library . . . . : User999

Type options (and Range), press Enter.

1=Create 3=Copy 4=Delete 12=Update

Opt Range Text

01 - 01 Run Customer Query

02 - 02 Print Customer Query

03 - 03 Change Address in Customer File

04 - 04 Show Customer File

05 - 05 Work with Printer Files

Bottom

F3=Exit F5=Refresh F9=Display image F12=Cancel

When you exit SDA, check the "object library" name. This is where your compiled menu objects will go.
Hit enter and the AS/400 will compile your source code and your menu will be ready to run. SDA creates
three objects, all with the same name: the commands, the display file and a message file for the menu.

83
When you run the menu you have created, type in selection 1 and press F1, when you do this you will see
the following help screen.

HELP Running Customer Query Information

This option will run the Customer Query. The information of

this query will show you the Customer Name, Customer Number

and Address.

Hit F3 to Exit, and Enter to run query.

F3=Exit F12=Cancel

You can also use SDA to test and design display files. With the "Test Display Files" selection of SDA,
you can see the fields and presentation of a display file. This works even if you don't have the source
code.

Use selection 25 in PDM to search through source code.

There are a couple of ways to search through source code for information you are looking for (ie. program
names, files, attributes, etc.). The 1st way is to do a search on a single or multi-program file level through

84
the work with members option, in which you search only specific program(s) for your information. The
other way is to do a search through an entire object such as QRPGLESRC or QDDSSRC.

In using the 1st method, start the Program Development Manager (STRPDM), and use option 3 to 'Work
with members'.

You will see this screen pop up.

AS/400 Programming Development Manager (PDM)

Select one of the following:

1. Work with libraries

2. Work with objects

3. Work with members

4. Work with projects

5. Work with groups

6. Work with parts

9. Work with user-defined options

Selection or command

F3=Exit F4=Prompt F9=Retrieve F10=Command entry

F12=Cancel F18=Change defaults

Now type in the needed information for the file and library to which
you want to

conduct the search.

85
Specify Members to Work With

Type choices, press Enter.

File . . . . . . . . . . QRPGLESRC Name, F4 for list

Library . . . . . . . . USER999 *LIBL, *CURLIB, name

Member:

Name . . . . . . . . . *ALL *ALL, name, *generic*

Type . . . . . . . . . *ALL *ALL, type, *generic*,


*BLANK

From here, type in 25 in the Opt space of the Member you would like to
do the search on.

If you would like to check all the programs listed on this members
screen, simple hit

F13 (Shift F1) and you will see that 25 is filled in on all the
options.

Work with Members Using PDM


S103C160

File . . . . . . QRPGLESRC

Library . . . . USER999 Position to . . . . .

Type options, press Enter.

2=Edit 3=Copy 4=Delete 5=Display 6=Print 7=Rename

86
8=Display description 9=Save 13=Change text 14=Compile 15=Create
module..

Opt Member Type Text

25 ABC101 RPGLE Add all ABC customers

25 ABC102 RPGLE Add CSBTN to customer file

25 ABC400 RPGLE SUBFILE for ABC pgm

25 SAM001 RPGLE Parse leads for Sample pgm

25 SAM002 RPGLE 1 time program to populate ADDR field

25 SAM003 RPGLE Subfile maintenance for Sample pgm Leads

25 SAM004 RPGLE Dup check leads Sample pgm

More...

Parameters or command

===>

F3=Exit F4=Prompt F5=Refresh


F6=Create

F9=Retrieve F10=Command entry F23=More options F24=More


keys

Now hit Enter, and you will see the Find String screen. In the blank
to the right of "Find",

type in the information you are seeking and press enter. In this
example we are looking for

all the programs that use the Physical File ABP001.

Find String

Type choices, press Enter.

Find . . . . . . . . . . . . . . ABP001___________________

87
From column number . . . . . . 1 1 - *RCDLEN

To column number . . . . . . . *RCDLEN 1 - *RCDLEN

Kind of match . . . . . . . . 2 1=Same case, 2=Ignore


case

Option . . . . . . . . . . . . . 2 *NONE, Valid option

Prompt . . . . . . . . . . . . N Y=Yes, N=No

Print list . . . . . . . . . . . N Y=Yes, N=No

Print records . . . . . . . . . N Y=Yes, N=No

Number to find . . . . . . . . *ALL *ALL, number

Print format . . . . . . . . . *CHAR *CHAR, *HEX, *ALTHEX

Mark record . . . . . . . . . Y Y=Yes, N=No

Record overflow . . . . . . . 1 1=Fold, 2=Truncate

Find string in batch . . . . . . N Y=Yes, N=No

Parameters . . . . . . . . . . .

F3=Exit F5=Refresh F12=Cancel F16=User


options

F18=Change defaults

You can see now that the search found the PF in program ABC102. Hit
Enter to continue the

search, and it will look through all the files you have chosen and
will pop up the screen

when it finds the PF once again.

Columns . . . : 6 76 Edit
USER999/QRPGLESRC

SEU==>
ABC102

88
FMT FX FFilename++IPEASF.....L.....A.Device+.Keywords++++++++++++++++
+++++++++

*************** Beginning of data


*************************************

0001.00 FABP001 IF E DISK

0002.00 FBT O E DISK

0003.00
*---------------------------------------------------------------------

0004.00 C DoW *In90 = *Off

0005.00 C Read ABD001


90

0006.00 C If *In90 = *Off and

0007.00 C ABCRNTO = *Zero and

0008.00 C ABBTN > 2000000000

0009.00 C Eval BTBTN = CSBTN

0010.00 C Write ABDREC

0011.00 C EndIf

0012.00 C EndDo

0013.00 C Eval *Inlr = *On

0014.00 C Return

0015.00
*---------------------------------------------------------------------

0016.00
*---------------------------------------------------------------------

F3=Exit F4=Prompt F5=Refresh F9=Retrieve F10=Cursor


F11=Toggle

F16=Repeat find F17=Repeat change F24=More keys

Another method to conduct the search is through Option 2 of the PDM.


Here is where

89
you work with objects. Once again, type in your Library name, and for
Object name, type in Q*.

This will list all of the Q objects, such as QDDSSRC, QRPGSRC, etc...

Specify Objects to Work With

Type choices, press Enter.

Library . . . . . . . . . . USER999 *CURLIB, name

Object:

Name . . . . . . . . . . . Q* *ALL, name, *generic*

Type . . . . . . . . . . . *ALL *ALL, *type

Attribute . . . . . . . . *ALL *ALL, attribute,


*generic*,

*BLANK

The next screen you see will contain the specified objects. Now all
you need to do is type

in 25 in the object you want to do the search in, and it will search
through all files/programs

associated with that object.

Work with Objects Using PDM


S103C160

Library . . . . . USER999 Position to . . . . . . . .

Position to type . . . . .

Type options, press Enter.

90
2=Change 3=Copy 4=Delete 5=Display 7=Rename

8=Display description 9=Save 10=Restore


11=Move ...

Opt Object Type Attribute Text

__ QCLSRC *FILE PF-SRC

__ QCMDSRC *FILE PF-SRC

__ QDDSSRC *FILE PF-SRC

25 QRPGLESRC *FILE PF-SRC

__ QRPGSRC *FILE PF-SRC

Bottom

Parameters or command

===>

F3=Exit F4=Prompt F5=Refresh F6=Create

F9=Retrieve F10=Command entry F23=More options F24=More


keys

Now hit Enter, and the search will begin through all the members
associated with the object you

have chosen to search. You will notice the same result as above was
located in the search.

So there you have it, 2 different ways of conducting a search for


information using Option 25 in

PDM.

Using Output Specs to Print a Report

91
There are 3 ways that reports get printed using RPG.

The oldest and obsolete method uses the RPG cycle and is not covered in this tutorial.

The next and most widely used is covered in this topic. The report is formatted using Output Specs. These
are identified with the letter O. Be sure to use F4 when entering O specs because they have many options.

An O spec is written by using the EXCEPT operation. This comes from the history of RPG. When using
the RPG cycle, the O Specs are automatically written. When you don't use the RPG cycle, the O Specs are
written as an EXCEPTion to the cycle.

The F spec for the printer file QPRINT identifies an indicator which the AS/400 turns *ON when the
page is full.

The third way of printing will be covered in the next topic. It uses a printer file defined using DDS specs

Writing a Print Program in RPG with O specs

This is the RPG program for writing a Print Report using O Specs. At the bottom, you will see a sample
of the report layout in the spool file.

Columns . . . : 1 71 Edit
USER000/QRPGSRC

SEU==>
TUTR005

FMT FX .....FFilenameIPEAF........L..I........Device+......KExit+
+Entry+A....U

*************** Beginning of data


*************************************

0001.00 FCUST IF E DISK

0002.00 * The AS/400 includes a pre-defined printer file named


QPRINT

0003.00 * Here, I use indicator 10 as the overflow


indicator

0004.00 * That means that *IN10 will be *ON when the


printed page

0005.00 * is full.

0006.00 FQPRINT O F 132 10 PRINTER

0007.00
*----------------------------------------------------------------

0008.00 C* Print the heading

0009.00 C EXCPTHEADS

92
0010.00 C* Read the first record

0011.00 C READ CUST 90

0012.00 C*

0013.00 C *IN90 DOWEQ*OFF

0014.00 C* See if the page is full. If so, print the heading.

0015.00 C *IN10 IFEQ *ON

0016.00 C EXCPTHEADS

0017.00 C MOVE *OFF *IN10

0018.00 C ENDIF

0019.00 C* Print the detail

0020.00 C EXCPTDETAIL

0021.00 C READ CUST 90

0022.00 C ENDDO

0023.00 C*

0024.00 C MOVE *ON *INLR

0025.00 C RETRN

0026.00
*----------------------------------------------------------------

0027.00 OQPRINT E 202 HEADS

0028.00 O 6 'PAGE'

0029.00 C* PAGE is a system value that will keep track of the


page#

0030.00 O PAGE 10

0031.00 O 47 'CUSTOMER ORDER


REPORT'

0032.00 O 65 'DATE'

0033.00 C* UDATE is a system value that is today's date

0034.00 C* The edit code Y will edit the date like xx/xx/xx

0035.00 O UDATE Y 75

0036.00 O*

93
0037.00 O E 1 HEADS

0038.00 O 61 '# OPEN'

0039.00 O 71 'AMT OPEN'

0040.00 O*

0041.00 O E 1 HEADS

0042.00 O 17 'CUST #'

0043.00 O 23 'NAME'

0044.00 O 61 'ORDERS'

0045.00 O 70 'ORDERS'

0046.00 O*

0047.00 O E 1 DETAIL

0048.00 O CSNBR 17

0049.00 O CSNAME 49

0050.00 C* The edit code 1 will edit the amount like 1,234.50

0051.00 O CS#OPN1 60

0052.00 O CS$OPN1 70

****************** End of data


****************************************

Once you have written the program, compile it using option 14. After
you have compiled the

program, you want to call it and see what the report looks like. To
call the program, simply

type on the command line: CALL PGM(USER000/TUTROO5)

Next, go to the Work Spool File (WRKSPLF), find the program, and key
in a 5 to view the report.

This is what the report will look like:

94
PAGE 1 CUSTOMER ORDER REPORT DATE
11/14/02

# OPEN AMT
OPEN

CUST # NAME ORDERS


ORDERS

001002 E LUMPKIN 0 .
00

001084 CHISOLM 0 .
00

001105 HAGGINS 0 .
00

001109 BYRD 0 .
00

001168 ROMERO 0 .
00

001177 POUNDS 0 .
00

001183 HINTON 0 .
00

001184 YANCEY 0 .
00

001186 MCDOUGLE 0 .
00

001202 DAVIS 0 .
00

001208 TARVIN 0 .
00

001214 GOOSEBERRY 0 .
00

001234 REID 0 .
00

001239 COLBERT 0 .
00

001259 BLACKMON 0 .
00

95
001264 CRANFORD 0 .
00

001266 DODSON 0 .
00

001269 LENSON 0 .
00

001274 JACKSON 0 .
00

001284 TAPER 0 .
00

001287 WILLIAMS 0 .
00

001293 FEAZELL 0 .
00

001294 MC CULLUM 0 .
00

001301 SMITH 0 .
00

001303 MCGHEE 0 .
00

001308 WALLACE 0 .
00

001318 ROBINSON 0 .
00

001321 SPIVEY 0 .
00

001322 HILLARD 0 .
00

PAGE 2 CUSTOMER ORDER REPORT DATE


11/14/02

# OPEN AMT
OPEN

CUST # NAME ORDERS


ORDERS

001480 BAILEY 0 .
00

96
001485 POLLARD 0 .
00

001492 JORDAN 0 .
00

001502 EVERETT 0 .
00

001504 HIGGINS 0 .
00

001509 JONES 0 .
00

001523 BENDER 0 .
00

001539 BUDD 0 .
00

001557 KINSEY 0 .
00

001561 PILKINGTON 0 .
00

001579 HAWKINS 0 .
00

001583 MOBBS 0 .
00

001584 SELLERS 0 .
00

001587 WALKER 0 .
00

001591 SLACK 0 .
00

001604 HINKLE 0 .
00

001606 ALLEN 0 .
00

Writing a Print Program in RPG-ILE with O specs

This is the RPG-ILE program for writing a Print Report using O Specs. At the bottom, you will see a
sample of the report layout in the spool file.

97
Columns . . . : 6 76 Edit
USER000/QRPGLESRC

SEU==>
TUTR006

FMT FX FFilename++IPEASF.....L.....A.Device+.Keywords++++++++++++++++
+++++++++

*************** Beginning of data


*************************************

0001.00 FCUST IF E DISK

0002.00 * The AS/400 includes a pre-defined printer file named


QPRINT

0003.00 * Here, I use indicator 10 as the overflow indicator

0004.00 * That means that *IN10 will be *ON when the printed
page

0005.00 * is full.

0006.00 FQPRINT O F 132 PRINTER OFLIND(*In10)

0007.00
*----------------------------------------------------------------

0008.00 C* Print the heading

0009.00 C Except Headings

0010.00 C* Read the first record

0011.00 C Read CSREC


90

0012.00 C*

0013.00 C DoW *In90 = *Off

0014.00 C* See if the page is full. If so, print the heading.

0015.00 C If *In10 = *On

0016.00 C Except Headings

0017.00 C Eval *In10 = *Off

0018.00 C EndIf

0019.00 C Except Detail

98
0020.00 C Read CSREC
90

0021.00 C EndDo

0022.00 C*

0023.00 C Eval *InLR = *On

0024.00 C Return

0025.00
*----------------------------------------------------------------

0026.00 OQPRINT E Headings 2 2

0027.00 O 6 'PAGE'

0028.00 C* PAGE is a system value that will keep track of the page#

0029.00 O Page 10

0030.00 O 47 'CUSTOMER ORDER


REPORT'

0031.00 O 65 'DATE'

0032.00 C* UDATE is a system value that is today's date

0033.00 C* The edit code Y will edit the date like xx/xx/xx

0034.00 O Udate Y 75

0035.00 O*

0036.00 O E Headings 1

0037.00 O 61 '# OPEN'

0038.00 O 71 'AMT OPEN'

0039.00 O*

0040.00 O E Headings 1

0041.00 O 17 'CUST #'

0042.00 O 23 'NAME'

0043.00 O 61 'ORDERS'

0044.00 O 70 'ORDERS'

0045.00 O*

0046.00 O E Detail 1

99
0047.00 O CSNBR 17

0048.00 O CSNAME 49

0049.00 C* The edit code 1 will edit the amount like 1,234.50

0050.00 O CS#OPN 1 60

0051.00 O CS$OPN 1 70

****************** End of data


****************************************

Once you have written the program, compile it using option 14. After
you have compiled the

program, you want to call it and see what the report looks like. To
call the program, simply

type on the command line: CALL PGM(USER000/TUTROO5)

Next, go to the Work Spool File (WRKSPLF), find the program, and key
in a 5 to view the report.

This is what the report will look like:

PAGE 1 CUSTOMER ORDER REPORT DATE


11/14/02

# OPEN AMT
OPEN

CUST # NAME ORDERS


ORDERS

001002 E LUMPKIN 0 .
00

001084 CHISOLM 0 .
00

001105 HAGGINS 0 .
00

001109 BYRD 0 .
00

100
001168 ROMERO 0 .
00

001177 POUNDS 0 .
00

001183 HINTON 0 .
00

001184 YANCEY 0 .
00

001186 MCDOUGLE 0 .
00

001202 DAVIS 0 .
00

001208 TARVIN 0 .
00

001214 GOOSEBERRY 0 .
00

001234 REID 0 .
00

001239 COLBERT 0 .
00

001259 BLACKMON 0 .
00

001264 CRANFORD 0 .
00

001266 DODSON 0 .
00

001269 LENSON 0 .
00

001274 JACKSON 0 .
00

001284 TAPER 0 .
00

001287 WILLIAMS 0 .
00

001293 FEAZELL 0 .
00

101
001294 MC CULLUM 0 .
00

001301 SMITH 0 .
00

001303 MCGHEE 0 .
00

001308 WALLACE 0 .
00

001318 ROBINSON 0 .
00

001321 SPIVEY 0 .
00

001322 HILLARD 0 .
00

PAGE 2 CUSTOMER ORDER REPORT DATE


11/14/02

# OPEN AMT
OPEN

CUST # NAME ORDERS


ORDERS

001480 BAILEY 0 .
00

001485 POLLARD 0 .
00

001492 JORDAN 0 .
00

001502 EVERETT 0 .
00

001504 HIGGINS 0 .
00

001509 JONES 0 .
00

001523 BENDER 0 .
00

001539 BUDD 0 .
00

102
001557 KINSEY 0 .
00

001561 PILKINGTON 0 .
00

001579 HAWKINS 0 .
00

001583 MOBBS 0 .
00

001584 SELLERS 0 .
00

001587 WALKER 0 .
00

001591 SLACK 0 .
00

001604 HINKLE 0 .
00

001606 ALLEN 0 .
00

Using DDS Specs to Print a Report

As mentioned in the previous topic, there are 3 ways that reports get printed using RPG.

This topic will look at how to print using a print file defined with DDS specs.

In an earlier topic, we saw how to use DDS to define a physical file and a logical file. DDS is also used to
define print files and display files. A future topic will discuss display files.

A display and print file are different from a physical file in two ways:
1) A physical file can have only 1 record definition.
2) A print file and a display file are really defining different records, not data. I think of print files as a
buffer in memory that describes a print line.

To create the print file, STRPDM and add a member to QDDSSRC in your library. Make sure the TYPE
is PRTF.

Add a member named CUSW007. Enter the specs shown in the DDS attachment. Or if you are lazy, copy
it from library USER000.

Columns . . . : 1 71 Edit
USER000/QDDSSRC

SEU==>
CUSW007

103
FMT A* .....A*. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+...
6 ...+... 7

*************** Beginning of data


*************************************

0001.00 A* THE NEXT LINE TELLS THE COMPILER TO LOOK IN THIS FILE

0002.00 A* FOR FIELDS THAT USE THE R FOR REFERENCE

0003.00 A REF(CUST)

0004.00 A* SKIPB(1) MEANS SKIP TO THE TOP OF THE NEXT PAGE BEFORE

0005.00 A* PRINTING THE HDG1 RECORD

0006.00 A R HDG1

0007.00 A SKIPB(1)

0008.00 A 2DATE(*YY)

0009.00 A 26'CUSTOMER ORDER


REPORT'

0010.00 A 60'PAGE'

0011.00 A 67PAGNBR

0012.00 A* SPACEA(2) MEANS TO SPACE DOWN 2 LINES AFTER THE HDG1


RECORD

0013.00 A SPACEA(2)

0014.00
A*----------------------------------------------------------------

0015.00 A R HDG2

0016.00 A SPACEA(1)

0017.00 A 48'# OPEN'

0018.00 A 59'AMT OPEN'

0019.00
A*----------------------------------------------------------------

0020.00 A R HDG3

0021.00 A SPACEA(1)

0022.00 A 2'CUST #'

0023.00 A 10'CUSTOMER NAME'

104
0024.00 A 48'ORDERS'

0025.00 A 60'ORDERS'

0026.00 A SPACEA(2)

0027.00
A*----------------------------------------------------------------

0028.00 A R DETAIL

0029.00 A SPACEA(001)

0030.00 A CSNBR 6S 0O 2

0031.00 A CSNAME 30A O 10

0032.00 A* THE EDTCDE(1) INDICATES TO EDIT THE NUMERIC FIELD


USING

0033.00 A* THE SYSTME DEFINED CODE OF 1. THIS IS WITH COMMAS,


DECIMALS

0034.00 A* AND NEGATIVE SIGN

0035.00 A CS$OPN R O 45EDTCDE(1)

0036.00 A CS#OPN R O 58EDTCDE(1)

0037.00
A*----------------------------------------------------------------

0038.00 A R TOTAL

0039.00 A SPACEA(001)

0040.00 A 30'TOTAL'

0041.00 A TOTOPN 9S 2O 58EDTCDE(1)

****************** End of data


****************************************

I have chosen to use the same field names in the print file as the input file that I will read. I could have
used different field names, but RPG handles fields with identical names in an interesting way.

If a field is defined in more than one place:


1) it must be the same length and type in all places.
2) the most recently assigned value will be used for all occurrences of the field.

So, since we use the same values in the print file as the input, we need only read the input file and write
the print records. As before, we still need to take care of headings and page control.

To show you different techniques, I stated the length and type of CSNBR and CSNAME in the DDS. For
the other fields, I put in R in the REF column. This tells the compiler to look for the field with this name
in the file named at the top in the REF option. It gets the field type and length from the file CUST since

105
that is the file named in the REF parameter. Defined fields using the REF technique are easier and
preferred.

If you are familiar with RLU (Report Layout Utility), you could use it to create the DDS for the print file.
RLU is confusing to most AS/400 programmers and is not widely used.

When you have entered the DDS, use option 14 to compile it. Since the type is PRTF, the AS/400
compiler knows to execute command CRTPRTF.

Then, enter the RPG or RPG-ILE source code and compile. Notice that the RPG programs use the printer
file as the output file.

Call the program from the command line and a print file will be created. Use WRKSPLF to see it.

Writing an RPG Print Program using DDS

This is the RPG program for writing a Print Report using DDS. At the bottom, you will see a sample of
the report layout in the spool file.

Columns . . . : 1 71 Edit
USER000/QRPGSRC

SEU==>
TUTR007

FMT FX .....FFilenameIPEAF........L..I........Device+......KExit+
+Entry+A....U

*************** Beginning of data


*************************************

0001.00 FCUST IF E DISK

0002.00 * The AS/400 includes a pre-defined printer file named


QPRINT

0003.00 * Here, I use indicator 10 as the overflow


indicator

0004.00 * That means that *IN10 will be *ON when the


printed page

0005.00 * is full.

0006.00 FCUSW007 O E 10 PRINTER

0007.00
*----------------------------------------------------------------

0008.00 C* Print the heading

0009.00 C WRITEHDG1

0010.00 C WRITEHDG2

106
0011.00 C WRITEHDG3

0012.00 C* Read the first record

0013.00 C READ CUST 90

0014.00 C*

0015.00 C *IN90 DOWEQ*OFF

0016.00 C* See if the page is full. If so, print the heading.

0017.00 C *IN10 IFEQ *ON

0018.00 C WRITEHDG1

0019.00 C WRITEHDG2

0020.00 C WRITEHDG3

0021.00 C MOVE *OFF *IN10

0022.00 C ENDIF

0023.00 C* Print the detail

0024.00 C WRITEDETAIL

0025.00 C READ CUST 90

0026.00 C ENDDO

0027.00 C*

0028.00 C MOVE *ON *INLR

0029.00 C RETRN

****************** End of data


****************************************

Once you have written the program, compile it using option 14. After
you have compiled the

program, you want to call it and see what the report looks like. To
call the program, simply

type on the command line: CALL PGM(USER000/TUTROO7)

Next, go to the Work Spool File (WRKSPLF), find the program, and key
in a 5 to view the report.

107
This is what the report will look like:

11192002 CUSTOMER ORDER REPORT PAGE


0001

# OPEN AMT OPEN

CUST # CUSTOMER NAME ORDERS ORDERS

001002 E LUMPKIN .00 0

001084 CHISOLM .00 0

001105 HAGGINS .00 0

001109 BYRD .00 0

001168 ROMERO .00 0

001177 POUNDS .00 0

001183 HINTON .00 0

001184 YANCEY .00 0

001186 MCDOUGLE .00 0

001202 DAVIS .00 0

001208 TARVIN .00 0

001214 GOOSEBERRY .00 0

001234 REID .00 0

001239 COLBERT .00 0

001259 BLACKMON .00 0

001264 CRANFORD .00 0

001266 DODSON .00 0

001269 LENSON .00 0

001274 JACKSON .00 0

001284 TAPER .00 0

001287 WILLIAMS .00 0

001293 FEAZELL .00 0

108
001294 MC CULLUM .00 0

001301 SMITH .00 0

001303 MCGHEE .00 0

001308 WALLACE .00 0

001318 ROBINSON .00 0

11192002 CUSTOMER ORDER REPORT PAGE


0002

# OPEN AMT OPEN

CUST # CUSTOMER NAME ORDERS ORDERS

001480 VALLIERE .00 0

001480 BAILEY .00 0

001485 POLLARD .00 0

001492 JORDAN .00 0

001502 EVERETT .00 0

001504 HIGGINS .00 0

001509 JONES .00 0

001523 BENDER .00 0

001539 BUDD .00 0

001557 KINSEY .00 0

001561 PILKINGTON .00 0

001579 HAWKINS .00 0

001583 MOBBS .00 0

001584 SELLERS .00 0

001587 WALKER .00 0

001591 SLACK .00 0

001604 HINKLE .00 0

001606 ALLEN .00 0

001608 R MALONE .00 0

001614 JACKSON .00 0

109
Writing an RPG Print Program using DDS

This is the RPG program for writing a Print Report using DDS. At the bottom, you will see a sample of
the report layout in the spool file.

Columns . . . : 6 76 Edit
USER000/QRPGLESRC

SEU==>
TUTR008

FMT FX FFilename++IPEASF.....L.....A.Device+.Keywords++++++++++++++++
+++++++++

*************** Beginning of data


*************************************

0001.00 FCUST IF E DISK

0002.00 * The AS/400 includes a pre-defined printer file named


QPRINT

0003.00 * Here, I use indicator 10 as the overflow indicator

0004.00 * That means that *IN10 will be *ON when the printed
page

0005.00 * is full.

0006.00 FCUSW007 O E PRINTER OFLIND(*In10)

0007.00
*----------------------------------------------------------------

0008.00 C* Print the heading

0009.00 C Write Hdg1

0010.00 C Write Hdg2

0011.00 C Write Hdg3

0012.00 C* Read the first record

0013.00 C Read CSREC


90

0014.00 C*

0015.00 C DoW *In90 = *Off

0016.00 C* See if the page is full. If so, print the heading.

110
0017.00 C If *In10 = *On

0018.00 C Write Hdg1

0019.00 C Write Hdg2

0020.00 C Write Hdg3

0021.00 C Eval *In10 = *Off

0022.00 C EndIf

0023.00 C Write Detail

0024.00 C Read CSREC


90

0025.00 C EndDo

0026.00 C*

0027.00 C Eval *InLR = *On

0028.00 C Return

****************** End of data


****************************************

Once you have written the program, compile it using option 14. After
you have compiled the

program, you want to call it and see what the report looks like. To
call the program, simply

type on the command line: CALL PGM(USER000/TUTROO8)

Next, go to the Work Spool File (WRKSPLF), find the program, and key
in a 5 to view the report.

This is what the report will look like:

11192002 CUSTOMER ORDER REPORT PAGE


0001

# OPEN AMT OPEN

111
CUST # CUSTOMER NAME ORDERS ORDERS

001002 E LUMPKIN .00 0

001084 CHISOLM .00 0

001105 HAGGINS .00 0

001109 BYRD .00 0

001168 ROMERO .00 0

001177 POUNDS .00 0

001183 HINTON .00 0

001184 YANCEY .00 0

001186 MCDOUGLE .00 0

001202 DAVIS .00 0

001208 TARVIN .00 0

001214 GOOSEBERRY .00 0

001234 REID .00 0

001239 COLBERT .00 0

001259 BLACKMON .00 0

001264 CRANFORD .00 0

001266 DODSON .00 0

001269 LENSON .00 0

001274 JACKSON .00 0

001284 TAPER .00 0

001287 WILLIAMS .00 0

001293 FEAZELL .00 0

001294 MC CULLUM .00 0

001301 SMITH .00 0

001303 MCGHEE .00 0

001308 WALLACE .00 0

001318 ROBINSON .00 0

112
11192002 CUSTOMER ORDER REPORT PAGE
0002

# OPEN AMT OPEN

CUST # CUSTOMER NAME ORDERS ORDERS

001480 VALLIERE .00 0

001480 BAILEY .00 0

001485 POLLARD .00 0

001492 JORDAN .00 0

001502 EVERETT .00 0

001504 HIGGINS .00 0

001509 JONES .00 0

001523 BENDER .00 0

001539 BUDD .00 0

001557 KINSEY .00 0

001561 PILKINGTON .00 0

001579 HAWKINS .00 0

001583 MOBBS .00 0

001584 SELLERS .00 0

001587 WALKER .00 0

001591 SLACK .00 0

001604 HINKLE .00 0

001606 ALLEN .00 0

001608 R MALONE .00 0

001614 JACKSON .00 0

RPG Program to Change Database Records Using a Display File

Finally, we get to the fun stuff! Hold on tight because things are about to get a lot more complicated.

Up to now, you have learned about the Control Language of the AS/400. You have also been introduced
to DDS. In fact, you have seen how to use DDS to define a Physical File, a Logical File and a Print File.
You have also seen some simple RPG programs.

113
Now, we will use DDS to create a Display File. Then, we will write a program to look up a Customer#
record and change it. In the next topic, we will add the ability to enter new records and to delete records.
Then, we will modify the program search by customer name.

Rather than talk you through all of the details, I am showing you the source code with lots of comments.
There are so many comments that it looks harder than it is. So, I have also provided source code without
the comments.

First, you must create a display file. This is often thought of as a screen map. It maps fields and characters
on the screen. Each record in the display file is a different screen.

You can copy the display file from the USER000 library or key it in yourself.

Before you get started, try using SDA to view the screens that I have created in USER000. First, start
SDA with the command STRSDA. Use selection 3 to TEST DISPLAY FILES. For the display file, use
TUTD010. For library, use USER000. For RECORD TO BE TESTED, put the cursor in the field and hit
F4. SDA will list all records defined. Select a record and hit ENTER a few times to see the screen.

To use SDA this way, the display file must already be created. That is, the source code must have been
entered and it must have been compiled successfully.

Now that you can see what you want to create, try keying in the source code.

To key it in, STRPDM. Use option 3. Fill in file QDDSSRC, in your library for *ALL member names.
Use F6 to add the member TUTD010. Make sure the TYPE is DSPF (for DISPLAY FILE).

When entering source code lines, try using F4 to prompt the fields. To turn off prompting, hit F12.

Click here to see the source code with all the comments. This is TUTD010 in QDDSSRC in USER000.

Click here to see the source code without all the comments. This is TUTD011 in QDDSSRC in
USER000.

When you are finished, compile the source code with option 14. This is running the command CRTDSPF
(Create Display File). When you are done, try using SDA again to test your display file.

If you have gotten this far, pat yourself on the back.

Now, we need to write the RPG program.

The program will display the first screen, SCRN1. The user will enter an A to add, C to CHANGE or D to
DELETE. But for this portion, we will only program the CHANGE logic. In the next topice, we will add
the ADD and DELETE logic.

The user also must enter a Customer #.

The program will first check to make sure that a C for CHANGE was entered. It then looks in the CUST
database file for the Customer #. If either of these conditions is not met, the program moves an error
message to the field DSPMSG and shows SCRN1 again.

If a Customer # is found, the program shows SCRN2. This screen shows the values in the record. If the
user changes any values and hits ENTER, the program will rewrite the changes to the database.

Click here to see the RPG III source code with all the comments. This is TUTR010 in QRPGSRC in
USER000.

114
TUTR010 in QRPGSRC in USER000

* Define the CUST file with file type U for UPDATE

* (update means that you can read and re-write data)

* and with record address type K for Keyed.

* (Keyed means the data can be directly read using the key field

FCUST UF E K DISK

* Next, define the display file. It must already exist.

* The C indeicates combined input and output. WORKSTN is

* always used to indicate a display file.

FTUTD010 CF E WORKSTN

*----------------------------------------------------------------

I* This next few statements define constants that will be used

I* as error messages

I 'You must enter A, C,-C ERR1

I ' or D'

I 'Customer # is not fo-C ERR2

I 'und'

I 'Name cannot be blank'C ERR3

I 'Addr cannot be blank'C ERR4

I 'City cannot be blank'C ERR5

I 'State cannot be blan-C ERR6

I 'k'

I 'Zip is invalid' C ERR7

*---------------------------------------------------------------

C* This is the main loop.

C* It will continue to show the first screen until F3 is pressed.

C* When F3 is pressed, *IN03 will be truned *ON

115
C *IN03 DOWEQ*OFF

C* The next statement, executes the format (EXFMT) for SCRN1.

C* EXFMT displays the SCRN1 and waits until the user presses

C* ENTER or F3. Then, it continues to the next statement.

C EXFMTSCRN1

C* If F3 was pressed, *IN03 will be *ON so the IF will go to

C* ENDIF and the DO will go to ENDDO

C *IN03 IFEQ *OFF

C* EXSR is Execute Subroutine. It will process the subroutine

C* named MAIN.

C EXSR MAIN

C ENDIF

C ENDDO

C* The next 2 statements end the program.

C MOVE *ON *INLR

C RETRN

C*----------------------------------------------------------------

C* Subroutines begin with BEGSR and end with ENDSR.

C*

C MAIN BEGSR

C* Use the CHAIN instruction to look for the Cust# entered in

C* the field DSPCST.

C* This statement says to use the value in DSPACT to look up

C* the value in CUST and to turn *IN90 to *ON if it is NOT found.

C DSPCST CHAINCUST 95

C*

C MOVE *BLANKS DSPMSG

C MOVE *OFF *IN90

C*

116
C* Because this will eventually test for Add, Chg, Delete

C* use the SELEC instead of IF.

C SELEC

C DSPACT WHEQ 'C'

C* If user wants to Change the record but it was not found,

C* show error message. Otherwise Execute Subroutine to change it.

C *IN95 IFEQ *ON

C MOVELERR2 DSPMSG

C MOVE *ON *IN90

C ELSE

C EXSR CHG

C ENDIF

C*

C OTHER

C* MOVEL is Move Left. It moves the value and justifies left.

C MOVELERR1 DSPMSG

C* Setting *IN90 to *ON will cause the error message to be

C* displayed in reverse image (see the DDS for DSPMSG).

C MOVE *ON *IN90

C ENDSL

C*

C ENDSR

C*----------------------------------------------------------------

C CHG BEGSR

C*

C* Show SCRN2. The values will be loaded from the CHAIN.

C* Continue showing SCRN2 until either F12 is pressed or

C* the data entered is OK. The subroutine EDTVAL will put

C* a message in DSPMSG if there is an error. If DSPMSG is

117
C* still blank after EDTVAL, then data is OK.

C*

C* This starts a DO loop that will continue to loop

C* until DSPMSG is not blank OR *IN12 is *ON.

C DSPMSG DOUNE*BLANKS

C *IN12 OREQ *ON

C EXFMTSCRN2

C* If the user hits F12 do not process,

C* otherwise, Edit the values to see if they are OK.

C *IN12 IFEQ *OFF

C EXSR EDTVAL

C* If there are no errors, update the record. The UPDAT

C* uses the record name for the CUST file.

C DSPMSG IFEQ *BLANK

C* UPDAT rewrites the record in the database file. Since the

C* field names in the display file are the same as in the

C* database file, RPG synchronizes the values.

C UPDATCSREC

C* LEAVE will go to the ENDDO.

C LEAVE

C ENDIF

C ENDIF

C*

C ENDDO

C*

C ENDSR

C*----------------------------------------------------------------

C EDTVAL BEGSR

C* Make sure the values on the screen are OK.

118
C CSNAME IFEQ *BLANKS

C MOVELERR3 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSADR1 IFEQ *BLANKS

C MOVELERR4 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSCTY IFEQ *BLANKS

C MOVELERR5 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSSTE IFEQ *BLANKS

C MOVELERR6 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSZIP IFLT 10000000

C MOVELERR7 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C ENDSR

Click here to see the RPG III source code without the comments. This is TUTR010NC.

TUTR010NC in QRPGSRC in USER000

119
FCUST UF E K DISK

FTUTD010 CF E WORKSTN

*----------------------------------------------------------------

I 'You must enter A, C,-C ERR1

I ' or D'

I 'Customer # is not fo-C ERR2

I 'und'

I 'Name cannot be blank'C ERR3

I 'Addr cannot be blank'C ERR4

I 'City cannot be blank'C ERR5

I 'State cannot be blan-C ERR6

I 'k'

I 'Zip is invalid' C ERR7

*----------------------------------------------------------------

C *IN03 DOWEQ*OFF

C EXFMTSCRN1

C EXFMTSCRN1

C*

C *IN03 IFEQ *OFF

C EXSR MAIN

C ENDIF

C*

C ENDDO

C*

C MOVE *ON *INLR

C RETRN

C*----------------------------------------------------------------

120
C MAIN BEGSR

C*

C DSPCST CHAINCUST 95

C*

C MOVE *BLANKS DSPMSG

C MOVE *OFF *IN90

C*

C SELEC

C DSPACT WHEQ 'C'

C *IN95 IFEQ *ON

C MOVELERR2 DSPMSG

C MOVE *ON *IN90

C ELSE

C EXSR CHG

C ENDIF

C*

C OTHER

C MOVELERR1 DSPMSG

C MOVE *ON *IN90

C ENDSL

C*

C ENDSR

C*----------------------------------------------------------------

C CHG BEGSR

C*

C DSPMSG DOUNE*BLANKS

C *IN12 OREQ *ON

C EXFMTSCRN2

C *IN12 IFEQ *OFF

121
C EXSR EDTVAL

C DSPMSG IFEQ *BLANK

C UPDATCSREC

C LEAVE

C ENDIF

C ENDIF

C*

C ENDDO

C*

C ENDSR

C*----------------------------------------------------------------

C EDTVAL BEGSR

C* Make sure the values on the screen are OK

C CSNAME IFEQ *BLANKS

C MOVELERR3 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSADR1 IFEQ *BLANKS

C MOVELERR4 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSCTY IFEQ *BLANKS

C MOVELERR5 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSSTE IFEQ *BLANKS

122
C MOVELERR6 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C CSZIP IFLT 10000000

C MOVELERR7 DSPMSG

C MOVE *ON *IN90

C ENDIF

C*

C ENDSR

Click here to see the RPG IV source code with all the comments. This is TUTR011 in QRPGLESRC in
USER000.

TUTR011 in QRPGLESRC in USER000

* Define the CUST file with file type U for UPDATE

* (update means that you can read and re-write data)

* and with record address type K for Keyed.

* (Keyed means the data can be directly read using the key field)

FCUST UF E K DISK

* Next, define the display file. It must already exist.

* The C indicates combined input and output. WORKSTN is

* always used to indicate a display file.

FTUTD010 CF E WORKSTN

*----------------------------------------------------------------

D* This next few statements define constants that will be used

D* as error messages.

D ERR1 C CONST('You must enter A, C,-

123
D or D')

D ERR2 C CONST('Customer # is not fo-

D und')

D ERR3 C CONST('Name cannot be blank')

D ERR4 C CONST('Addr cannot be blank')

D ERR5 C CONST('City cannot be blank')

D ERR6 C CONST('State cannot be blan-

D k')

D ERR7 C CONST('Zip is invalid')

*----------------------------------------------------------------

C* This is the main loop.

C* It will continue to show the first screen until F3 is pressed.

C* When F3 is pressed, *IN03 will be truned *ON

C DoW *in03 = *off

C* The next statement, executes the format (EXFMT) for SCRN1

C* EXFMT displays the SCRN1 and waits until the user presses

C* ENTER or F3. Then, it continues to the next statement.

C ExFmt SCRN1

C* If F3 was pressed, *IN03 will be *ON so the IF will go to

C* ENDIF and the DO will go to ENDDO.

C If *in03 = *off

C* EXSR is Execute Subroutine. It will process the subroutine

C* named MAIN.

C ExSr Main

C EndIf

C EndDo

C* The next 2 statments end the program.

C Eval *inlr = *on

C Return

124
C*----------------------------------------------------------------

C* Subroutines begin with BEGSR and end with ENDSR.

C*

C Main BegSr

C* Use the CHAIN instruction to look for the Cust# entered in

C* the field DSPCST.

C* This statements says to use the value in DSPACT to look up

C* the value in CUST and to turn *IN90 to *ON if it is NOT found.

C DSPCST Chain CUST 95

C*

C Eval DSPMSG = *blanks

C Eval *in90 = *off

C*

C* Because this will eventually test for Add, Chg, Delete

C* use the SELECT instead of IF.

C Select

C When DSPACT = 'C'

C* If user wants to Change the record but it was not found,

C* show error message. Otherwise Execute Subroutine to change it.

C If *in95 = *on

C Eval DSPMSG = ERR2

C Eval *in90 = *on

C Else

C ExSr ChangeRecord

C EndIf

C*

C Other

C Eval DSPMSG = ERR1

C* Setting *IN90 to *ON will cause the error message to be

125
C* displayed in reverse image (see the DDS for DSPMSG).

C Eval *in90 = *on

C EndSl

C*

C EndSr

C*----------------------------------------------------------------

C ChangeRecord BegSr

C*

C*

C* Show SCRN2. The values will be loaded from the CHAIN.

C* Continue showing SCRN2 until either F12 is pressed or

C* the data entered is OK. The subroutine EDITVALUES will put

C* a message in DSPMSG if there is an error. If DSPMSG is

C* still blank after EDITVALUES, then data is OK.

C*

C* This starts a DO loop that will continue to loop

C* Until DSPMSG is not blank OR *IN12 is *ON.

C DoU DSPMSG = *BLANKS or

C *in12 = *on

C ExFmt SCRN2

C* If the user hits F12 do not process,

C* otherwise, Edit the values to see if they are OK.

C If *in12 = *off

C ExSr EditValues

C* If there are no errors, update the record. The UPDATE

C* uses the record name for the CUST file.

C If DSPMSG = *blanks

C* UPDATE rewrites the record in the database file. Since the

C* field names in the display file are the same as in the

126
C* database file, RPG synchronizes the values.

C Update CSREC

C* LEAVE will go to the ENDDO.

C Leave

C EndIf

C EndIf

C*

C EndDo

C*

C EndSr

C*----------------------------------------------------------------

C EditValues BegSr

C* Make sure the values on the screen are OK.

C If CSNAME = *BLANKS

C Eval DSPMSG = ERR3

C Eval *in90 = *on

C EndIf

C*

C If CSADR1 = *BLANKS

C Eval DSPMSG = ERR4

C Eval *in90 = *on

C EndIf

C*

C If CSCTY = *BLANKS

C Eval DSPMSG = ERR5

C Eval *in90 = *on

C EndIf

C*

C If CSSTE = *BLANKS

127
C Eval DSPMSG = ERR6

C Eval *in90 = *on

C EndIf

C*

C If CSZIP < 10000000

C Eval DSPMSG = ERR7

C Eval *in90 = *on

C EndIf

C*

C EndSr

Click here to see the RPG IV source code without the comments. This is TUTR011NC.

TUTR011NC in QRPGLESRC in USER000

FCUST UF E K DISK

FTUTD010 CF E WORKSTN

*----------------------------------------------------------------

D ERR1 C CONST('You must enter A, C,-

D or D')

D ERR2 C CONST('Customer # is not fo-

D und')

D ERR3 C CONST('Name cannot be blank')

D ERR4 C CONST('Addr cannot be blank')

D ERR5 C CONST('City cannot be blank')

D ERR6 C CONST('State cannot be blan-

D k')

D ERR7 C CONST('Zip is invalid')

*----------------------------------------------------------------

128
C DoW *in03 = *off

C ExFmt SCRN1

C If *in03 = *off

C ExSr Main

C EndIf

C EndDo

C Eval *inlr = *on

C Return

C*----------------------------------------------------------------

C Main BegSr

C DSPCST Chain CUST 95

C Eval DSPMSG = *blanks

C Eval *in90 = *off

C Select

C When DSPACT = 'C'

C If *in95 = *on

C Eval DSPMSG = ERR2

C Eval *in90 = *on

C Else

C ExSr ChangeRecord

C EndIf

129
C

C Other

C Eval DSPMSG = ERR1

C Eval *in90 = *on

C EndSl

C EndSr

C*----------------------------------------------------------------

C ChangeRecord BegSr

C* This starts a DO loop that will continue to loop

C* Until DSPMSG is not blank OR *IN12 is *ON

C DoU DSPMSG = *BLANKS or

C *in12 = *on

C ExFmt SCRN2

C If *in12 = *off

C ExSr EditValues

C If DSPMSG = *blanks

C Update CSREC

C Leave

C EndIf

C EndIf

C EndDo

C EndSr

C*----------------------------------------------------------------

C EditValues BegSr

130
C* Make sure the values on the screen are OK

C If CSNAME = *BLANKS

C Eval DSPMSG = ERR3

C Eval *in90 = *on

C EndIf

C If CSADR1 = *BLANKS

C Eval DSPMSG = ERR4

C Eval *in90 = *on

C EndIf

C If CSCTY = *BLANKS

C Eval DSPMSG = ERR5

C Eval *in90 = *on

C EndIf

C If CSSTE = *BLANKS

C Eval DSPMSG = ERR6

C Eval *in90 = *on

C EndIf

C If CSZIP < 10000000

C Eval DSPMSG = ERR7

C Eval *in90 = *on

C EndIf

C EndSr

Debugging RPG ILE with the iSeries / AS400 Debugger STRDBG

131
The AS/400 has a built in debugging tool, though very powerful, it is not completely intuitive. Sometimes
you may find yourself in need of a procedure that can help you locate program errors that you cannot
visually find by looking at your program. RPG-ILE's program debugger can be very useful in these
situations. It allows you to trace a program as it is executing, stepping through a program a statement at a
time, or stopping at "breakpoints" that you designate so you can see the values of fields at that point of
execution. Follow the steps below to start the "debugging" mode for your programs.

First, you must compile the program in an appropriate mode. Do this from PDM by keying a 14 next the
program source and hitting F4.

Your screen should look like this:

Create Bound RPG Program (CRTBNDRPG)

Type choices, press Enter.

Program . . . . . . . . . . . . > LXR001 Name, *CTLSPEC

Library . . . . . . . . . . . > T40 Name, *CURLIB

Source file . . . . . . . . . . > QRPGLESRC Name, QRPGLESRC

Library . . . . . . . . . . . > T40 Name, *LIBL, *CURLIB

Source member . . . . . . . . . > LXR001 Name, *PGM

Generation severity level . . . 10 0-20

Text 'description' . . . . . . . *SRCMBRTXT

Default activation group . . . . *YES *YES, *NO

Now, hit F10 to get more options. Key in *LIST as the value for "Debugging View".

The screen should look like:

Create Bound RPG Program (CRTBNDRPG)

Type choices, press Enter.

Program . . . . . . . . . . . . > LXR001 Name, *CTLSPEC

Library . . . . . . . . . . . > T40 Name, *CURLIB

132
Source file . . . . . . . . . . > QRPGLESRC Name, QRPGLESRC

Library . . . . . . . . . . . > T40 Name, *LIBL, *CURLIB

Source member . . . . . . . . . > LXR001 Name, *PGM

Generation severity level . . . 10 0-20

Text 'description' . . . . . . . *SRCMBRTXT

Default activation group . . . . *YES *YES, *NO

Additional Parameters

Compiler options . . . . . . . . *XREF, *NOXREF,


*GEN...

+ for more values

Debugging views . . . . . . . . *LIST *STMT, *SOURCE,


*LIST...

Output . . . . . . . . . . . . . *PRINT *PRINT, *NONE

Now ENTER to compile your program. If this program calls other programs, you may want to compile
them in debug mode also.

Now it gets a little tricky. Start the debugging mode with the "Start Debug" for the program you want to
debug. In this case, the program is LXR001 so the command to use is STRDBG LXR001. Key in
STRDBG LXR001 and hit F14:

Start Debug (STRDBG)

Type choices, press Enter.

Program . . . . . . . . . . . . > LXR001 Name, *NONE

Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB

+ for more values

*LIBL

Default program . . . . . . . . *PGM Name, *PGM, *NONE

133
Maximum trace statements . . . . 200 Number

Trace full . . . . . . . . . . . *STOPTRC *STOPTRC, *WRAP

Update production files . . . . *NO *NO, *YES

OPM source level debug . . . . . *NO *NO, *YES

Service program . . . . . . . . *NONE Name, *NONE

Library . . . . . . . . . . . Name, *LIBL, *CURLIB

+ for more values

If your program updates or writes data to a file in a library that is defined as *PROD, you must change the
"Update production files" option to *YES. Then, hit ENTER.

The debugger now displays the source code of the program. You MUST define a breakpoint where the
debugger will actually start debugging. The easiest thing to do is to page down to the first executable
statement of the program. Put the cursor on that line of source code and hit F6 to define that line as a
breakpoint.

Now, hit F3 and you will return to the PDM menu.

Your session is now in "debug" mode. It will stay in "debug" mode until you end debug mode with the
command ENDDBG.

Finally, it is time to start running your program. Call the program from the command line. In this case:
CALL LXR001

The program will start running. The debug feature will display a listing of the program. The display is
showing that the breakpoint is about to execute. You can scroll up or down, position the cursor on any
field and hit F11. The debugger will display the value of the field.

Now hit F10 repeatedly to step through the source code. The line of code that is about to execute will be
highlighted.

Note that the debugger has the annoying habit of stepping through every field in each file that is read or
updated. To prevent this, add a "header" record as the first line of code in the program. "Header" records
are not required and not usually used. Use an "H" as the record type with a value of "option(*nodebugio).
That is, add this line to the beginning of your program:

H OPTION(*NODEBUGIO)

When you are finished debuggin, key ENDDBG to turn off the debugger.

To summarize:

1) Add this line to the beginning of your program: H OPTION(*NODEBUGIO)

2) Compile the program with Debug View set to *LIST

3) Start the debugger with the command: STRDBG pgmname (Update Production files *YES)

134
4) Put cursor on the first line that you want to see and hit F6. Exit with F3.

5) Call your program: CALL pgmname

6) Use F10 to step through the program. Use F11 to see values.

7) If you wish, set additional breakpoints and use F12 to run until the next breakpoint.

As before, try using F4 to prompt the fields. To turn off prompting, hit F12.

Also, as with all programs, compile the source code with option 14.

View your compile listing with the Work With Spool File command, WRKSPLF. Look for errors at the
bottom of the listing.

To run the program, key CALL TUTR010 or CALL TUTR011.

Use any valid Customer #. 1002 is a valid #.

If you completed this topic, you are well on your way to becoming an RPG programmer.

Complete RPG Maintenance Program

Now that you have worked with RPG some, take a moment to review this maintenance program. It is
written in both RPG III and RPG IV.

Writing an Add/Change/Delete/Inquiry
maintenance program
This is the DDS for the Display Program named CUSTD01.

A REF(CUST)

A CA03(03 'F3=EXIT')

A R SCR1

A 1 2USER

A O 1 28'ADD/UPDATE/DELETE/INQUIRE'

A DSPATR(HI)

A 1 72DATE

A EDTCDE(Y)

A 2 2'CUSTR01'

A 2 72TIME

135
A O 6 8'(A)dd, (U)pdate, (D)elete'

A O 6 34'(I)nquire, (N)ext'

A ACTION 1 B 6 53DSPATR(HI)

A O 8 28'Cust#'

A CUS# R B 8 35DSPATR(HI) EDTCDE(4)

A ERRLIN 78 O 22 2

A 90 DSPATR(RI)

A O 23 14'F3=EXIT'

A*----------------------------------------------------------------

A R SCR2

A CA09(09 'F9=DELETE')

A 1 2USER

A 1 28'CUSTOMER FILE MAINTENANCE'

A 1 72DATE

A EDTCDE(Y)

A 2 2'CUSTR01'

A MODE 7 O 2 37

A 2 72TIME

A 3 28'Cust#'

A CUS# R O 3 37EDTCDE(4) DSPATR(RI)

A 8 28'Name'

A CUSNAM R B 8 42

A N80 DSPATR(HI)

A 80 DSPATR(PR)

A 9 28'Address 1'

A CUSAD1 R B 9 42

A N80 DSPATR(HI)

A 80 DSPATR(PR)

A 10 28'Address 2'

136
A CUSAD2 R B 10 42

A N80 DSPATR(HI)

A 80 DSPATR(PR)

A 11 28'City'

A CUSCTY R B 11 42

A N80 DSPATR(HI)

A 80 DSPATR(PR)

A 12 28'State'

A CUSSTA R B 12 42

A N80 DSPATR(HI)

A 80 DSPATR(PR)

A 13 28'Zip'

A CUSZIP R Y B 13 42

A N80 DSPATR(HI)

A 80 DSPATR(PR)

A ERRLIN 78 O 22 2

A 90 DSPATR(RI)

A O 23 14'F3=EXIT'

Writing an Add/Change/Delete/Inquiry maintenance program in RPG III

This is the RPG III source code for the Add/Change/Delete program named CUSTR01.

FCUSTD01 CF E WORKSTN

FCUST UF E K DISK A

*----------------------------------------------------------------

* Define error messages here

I 'RECORD ALREADY ON FI-C ERR1

I 'LE'

I 'RECORD IS NOT ON FIL-C ERR2

I 'E'

137
I 'NO MORE RECORDS' C ERR3

I 'ZIP CANNOT BE ZERO' C ERR6

I 'NAME MUST NOT BE BL-C ERR7

I 'ANK'

I 'STATE MUST NOT BE BL-C ERR8

I 'ANK'

I 'ACTION MUST BE A, U,-C ERR9

I ' D OR I'

I 'RECORD ADDED SUCCE- C MSG1

I 'SSFULLY'

I 'RECORD UPDATED SUC- C MSG2

I 'CESSFULLY'

I 'RECORD DELETED SUC- C MSG3

I 'CESSFULLY'

I 'HIT F9 TO DELETE' C MSG4

I 'NO ACTION TAKEN' C MSG9

*----------------------------------------------------------------

* Key List for customer file

* (a key list is not needed since this file has only 1 key

* field, but this makes the program easier to modify if

* the file has multiple key fields)

C KEYLST KLIST

C KFLD CUS#

*----------------------------------------------------------------

* Stay in Main DO LOOP until F3 is hit from SCR1

*----------------------------------------------------------------

C *IN03 DOWEQ*OFF

* Show main ADD/UPD/INQ/DLT screen

C EXFMTSCR1

138
C CLEARERRLIN

C MOVE *OFF *IN90

* If user didn't hit F3, process screen based on action

C *IN03 IFEQ *OFF

C SELEC

C ACTION WHEQ 'A'

C EXSR ADDREC

C ACTION WHEQ 'D'

C EXSR DLTREC

C ACTION WHEQ 'I'

C EXSR INQREC

C ACTION WHEQ 'N'

C EXSR NXTREC

C ACTION WHEQ 'U'

C EXSR UPDREC

C OTHER

C CLEARERRLIN

C MOVELERR9 ERRLIN

C MOVE *ON *IN90

C ENDSL

C ENDIF

C ENDDO

C MOVE *ON *INLR

C RETRN

*----------------------------------------------------------------

C ADDREC BEGSR

* Unprotect fields but setting *in80 off

C MOVE *OFF *IN80

139
C MOVE ' ADD ' MODE

* See if customer # is already in CUST file

C KEYLST CHAINCUST 91

C *IN91 IFEQ *OFF

* If customer # is already in cust file, load up ERR MSG

C CLEARERRLIN

C MOVELERR1 ERRLIN

C MOVE *ON *IN90

C ELSE

C EXSR ADDSCR

C ENDIF

C ENDSR

*----------------------------------------------------------------

* SHOW ADD SCREEN

*----------------------------------------------------------------

C ADDSCR BEGSR

* Clear customer record except for key field(s)

C *NOKEY CLEARCUSTR

C MOVE 'N' RECOK 1

* Keep showing screen until record passes edit or F3 is hit

C RECOK DOWEQ'N'

C *IN03 ANDEQ*OFF

C EXFMTSCR2

C *IN03 IFEQ *OFF

C EXSR EDTCUS

C RECOK IFEQ 'Y'

C WRITECUSTR

* Show messaage that ADD was successful

140
C CLEARERRLIN

C MOVELMSG1 ERRLIN

C ENDIF

C ELSE

* Show message that no action was taken because F3 was hit

C CLEARERRLIN

C MOVELMSG9 ERRLIN

C ENDIF

C ENDDO

C MOVE *OFF *IN03

C ENDSR

*----------------------------------------------------------------

C DLTREC BEGSR

* Disable fields for entry by setting *IN80 on

C MOVE *ON *IN80

C MOVE 'DELETE' MODE

C CLEARERRLIN

C MOVELMSG4 ERRLIN

C MOVE *ON *IN90

* See if customer # is in CUST file

C KEYLST CHAINCUST 91

C *IN91 IFEQ *ON

* If customer # is not in CUST file, show ERR MSG

C CLEARERRLIN

C MOVELERR2 ERRLIN

C MOVE *ON *IN90

C ELSE

141
C EXFMTSCR2

C MOVE *OFF *IN90

C *IN09 IFEQ *ON

C DELETCUSTR

C CLEARERRLIN

C MOVELMSG3 ERRLIN

C ELSE

C CLEARERRLIN

C MOVELMSG9 ERRLIN

C ENDIF

C ENDIF

C MOVE *OFF *IN03

C ENDSR

*----------------------------------------------------------------

C INQREC BEGSR

* Disable fields for entry by setting *IN80 on

C MOVE *ON *IN80

C MOVE 'INQUIRY' MODE

* See if customer # is in CUST file

C KEYLST CHAINCUST 91

C *IN91 IFEQ *ON

* If customer # is not in CUST file, show ERR MSG

C CLEARERRLIN

C MOVELERR2 ERRLIN

C MOVE *ON *IN90

C ELSE

* Show Inquiry Screen

142
C EXFMTSCR2

C ENDIF

C MOVE *OFF *IN03

C ENDSR

*----------------------------------------------------------------

C NXTREC BEGSR

C MOVE *ON *IN80

C MOVE 'INQUIRY' MODE

C CLEARERRLIN

* Go forward in the file to the next record

C KEYLST SETLLCUST 92 93

* If *in92 is on, we have reached end of file

C *IN92 IFEQ *ON

C MOVELERR3 ERRLIN

C MOVE *ON *IN90

C ENDIF

* Read next record

C ERRLIN IFEQ *BLANKS

C READ CUST 90

* If *in90 is on, we have reached end of file

C *IN92 IFEQ *ON

C MOVELERR3 ERRLIN

C MOVE *ON *IN90

C ENDIF

C ENDIF

* If *in93 is on, we are at an existing record and we need

143
* to read past it

C ERRLIN IFEQ *BLANKS

C *IN93 IFEQ *ON

C READ CUST 90

* If *in90 is on, we have reached end of file

C *IN90 IFEQ *ON

C MOVELERR3 ERRLIN

C MOVE *ON *IN90

C ENDIF

C ENDIF

C ENDIF

C ERRLIN IFEQ *BLANKS

C EXFMTSCR2

C ENDIF

C MOVE *OFF *IN03

C ENDSR

*----------------------------------------------------------------

C UPDREC BEGSR

* Unprotect fields but setting *in80 off

C MOVE *OFF *IN80

C MOVE 'UPDATE ' MODE

* See if customer # is already in CUST file

C KEYLST CHAINCUST 91

C *IN91 IFEQ *ON

* If customer # is not in cust file, load up ERR MSG

C CLEARERRLIN

144
C MOVELERR2 ERRLIN

C MOVE *ON *IN90

C ELSE

C EXSR UPDSCR

C ENDIF

C ENDSR

*----------------------------------------------------------------

* SHOW UPDATE SCREEN

*----------------------------------------------------------------

C UPDSCR BEGSR

C MOVE 'N' RECOK 1

* Keep showing screen until record passes edit or F3 is hit

C RECOK DOWEQ'N'

C *IN03 ANDEQ*OFF

C EXFMTSCR2

C *IN03 IFEQ *OFF

C EXSR EDTCUS

C RECOK IFEQ 'Y'

C UPDATCUSTR

* Show messaage that UPDATE was successful

C CLEARERRLIN

C MOVELMSG2 ERRLIN

C ENDIF

C ELSE

* Show message that no action was taken because F3 was hit

C CLEARERRLIN

C MOVELMSG9 ERRLIN

C ENDIF

145
C ENDDO

C MOVE *OFF *IN03

C ENDSR

*----------------------------------------------------------------

C EDTCUS BEGSR

* First, set error switch that record is OK

C MOVE 'Y' RECOK

* Now, perform each edit

C CUSNAM IFEQ *BLANKS

C MOVE 'N' RECOK

C CLEARERRLIN

C MOVELERR7 ERRLIN

C MOVE *ON *IN90

C ENDIF

C CUSSTA IFEQ *BLANKS

C MOVE 'N' RECOK

C CLEARERRLIN

C MOVELERR8 ERRLIN

C MOVE *ON *IN90

C ENDIF

C CUSZIP IFEQ *ZERO

C MOVE 'N' RECOK

C CLEARERRLIN

C MOVELERR6 ERRLIN

C MOVE *ON *IN90

146
C ENDIF

C ENDSR

*----------------------------------------------------------------

Writing an Add/Change/Delete/Inquiry maintenance program in RPG IV

This is the RPG IV source code for the Add/Change/Delete program named CUSTR01.
FCUSTD01 CF E WORKSTN

FCUST UF A E K DISK

*---------------------------------------------------------------------

D RecOK S 1a

*---------------------------------------------------------------------

D Err1 C CONST('RECORD ALREADY ON FI-

D LE')

D Err2 C CONST('RECORD IS NOT ON FI-

D LE')

D Err3 C CONST('NO MORE RECORDS')

D Err4 C CONST('ZIP CAN NOT BE BLANK')

D Err5 C CONST('NAME IS MANDATORY')

D Err6 C CONST('STATE IS MANDATORY')

D Err7 C CONST('INVALID ACTION')

D Err8 C CONST('NO MORE RECORDS')

D Msg1 C CONST('RECORD ADDED')

D Msg2 C CONST('RECORD UPDATED')

D Msg3 C CONST('RECORD DELETED')

D Msg4 C CONST('HIT F9 TO DELETE')

D Msg9 C CONST('NO ACTION TAKEN')

*---------------------------------------------------------------------

C KEYLST KLIST

147
C KFLD CSNBR

C*---------------------------------------------------------------------

C* Display the add, delete, inquire, next, or update screen

C* and process unless user hit F3 (indicator 03)

C DoW *in03 = *off

C ExFmt SCR1

C Eval ERRLIN = *blanks

C Eval *in90 = *off

C If *in03 = *off

C Select

C When Action = 'A'

C ExSr AddRecord

C When Action = 'D'

C ExSr DltRecord

C When Action = 'I'

C ExSr InqRecord

C When Action = 'N'

C ExSr NextRecord

C When Action = 'U'

C ExSr UpdRecord

C Other

C Eval ERRLIN = Err7

C Eval *in90 = *on

C EndSl

C EndIf

C EndDo

C Eval *inlr = *on

148
C Return

C*---------------------------------------------------------------------

C AddRecord BegSr

C* Indicator 80 is used by the display file to protect most fields

C* since we are in ADD mode, set the indicator off to allow field entry

C Eval *IN80 = *off

C Eval MODE = ' ADD'

C* See if customer is already on file. If so, display error

C KEYLST Chain CUST 91

C If *in91 = *off

C Eval ERRLIN = Err1

C* Indicator 90 draws attention to the error line with reverse display

C Eval *in90 = *on

C Else

C ExSr AddScreen

C EndIf

C EndSr

C*---------------------------------------------------------------------

C AddScreen BegSr

C* Clear all fields except the key field

C *NOKEY Clear CSREC

C Eval RecOK = 'n'

C* Stay on this screen until user gets it right or hits F3

C Dow RecOK = 'n' and

C *in03 = *off

C ExFmt SCR2

149
C If *in03 = *off

C ExSr EditRecord

C If recOK = 'y'

C Write CSREC

C Eval ERRLIN = Msg9

C EndIf

C Else

C Eval ERRLIN = Msg9

C EndIf

C EndDo

C Eval *in03 = *off

C EndSr

C*---------------------------------------------------------------------

C DltRecord BegSr

C* Indicator 80 is used by the display file to protect most fields

C* since we are in DLT mode, set the indicator on for no field entry

C Eval *in80 = *on

C Eval MODE = 'DELETE'

C* Display "Hit F9 to DELETE" in ERRLIN

C Eval ERRLIN = Msg4

C Eval *in90 = *on

C* See if customer is on file. If not, show error Msg

C KEYLST Chain CUST 91

C If *in91 = *on

C Eval ERRLIN = Err2

C Else

150
C* If customer is on file, show screen again and see if user hit F9

C* to confirm delete

C ExFmt SCR2

C Eval *in90 = *off

C If *in09 = *on

C Delete CSREC

C Eval ERRLIN = Msg3

C Else

C Eval ERRLIN = Msg9

C EndIf

C EndIf

C Eval *in03 = *off

C EndSr

C*---------------------------------------------------------------------

C InqRecord BegSr

C* Indicator 80 is used by the display file to protect most fields

C* since we are in DLT mode, set the indicator on for no field entry

C Eval *in80 = *on

C Eval MODE = 'INQUIRY'

C KEYLST Chain CUST 91

C If *in91 = *on

C Eval ERRLIN = Err2

C Eval *In90 = *on

C Else

C ExFmt SCR2

C EndIf

151
C Eval *in03 = *off

C EndSr

C*---------------------------------------------------------------------

C NextRecord BegSr

C Eval *in80 = *on

C Eval MODE = 'INQUIRY'

C Eval ERRLIN = *blanks

C* Set file cursor at cust from screen

C KEYLST SetLL CUST 92 93

C If *in92 = *on

C Eval ERRLIN = Err3

C Eval *in90 = *on

C EndIf

C* Read file to get next customer

C If ERRLIN = *BLANKS

C Read CUST 90

C If *in92 = *on

C Eval ERRLIN = Err3

C Eval *in90 = *on

C EndIf

C EndIf

C* If *in93 is on, we are at an existing record and need to read past it

C If *in93 = *on and

C ERRLIN = *blanks

C Read CUST 90

152
C If *in90 = *on

C Eval ERRLIN = Err3

C Eval *in90 = *on

C EndIf

C EndIf

C If ERRLIN = *blanks

C ExFmt SCR2

C EndIf

C Eval *in03 = *off

C EndSr

C*---------------------------------------------------------------------

C UpdRecord BegSr

C Eval *IN80 = *off

C Eval MODE = ' UPDATE '

C KEYLST Chain CUST 91

C If *in91 = *on

C Eval ERRLIN = Err2

C Eval *in90 = *on

C Else

C ExSr UpdScreen

C EndIf

C EndSr

C*---------------------------------------------------------------------

C UpdScreen BegSr

C Eval RecOK = 'n'

153
C DoW RecOK = 'n' and

C *in03 = *off

C ExFmt SCR2

C If *in03 = *off

C ExSr EditRecord

C If RecOK = 'y'

C Update CSREC

C Eval ERRLIN = Msg2

C EndIf

C Else

C Eval ERRLIN = Msg9

C EndIf

C EndDo

C Eval *in03 = *off

C EndSr

C*---------------------------------------------------------------------

C EditRecord BegSr

C Eval RecOK = 'y'

C If CSNAME = *blanks

C Eval RecOK = 'n'

C Eval ERRLIN = Err5

C Eval *in90 = *on

C EndIf

C If CSSTE = *blanks

C Eval RecOK = 'n'

C Eval ERRLIN = Err6

C Eval *in90 = *on

154
C EndIf

C If CSZIP = *zero

C Eval RecOK = 'n'

C Eval ERRLIN = Err4

C Eval *in90 = *on

C EndIf

C EndSr

*----------------------------------------------------------------

Showcase Article - Report Layout Utility (RLU)

Learning to use the tools on the AS/400 is one of the best ways to leverage your expertise.
Managers may be surprised to learn how easy it is to provide users with sample report layouts
that can be designed with an on-line tool. This on-line tool is RLU, Report Layout Utility.
Because many programmers find its interface to be confusing, not many have become proficient
RLU users. Read on and you will learn to create report layouts quickly and easily.

In the early days of RPG, reports were always printed using OUTPUT specifications. With the
advent of DDS, it became possible to make print files using DDS. This is similar to the way DDS
is used to make display files. The AS/400 provides SDA, Screen Design Aid, as an on-line tool
to design display files. Similarly, RLU, is an on-line tool to design reports.

Suppose a user needs a report showing:

1. Customer number

2. Customer name

3. Customer city

4. Annual purchase amount

These fields are in the customer master file, CUST. We will write an RPG program, CUSR005 to
read the CUST file and write a print file, CUSW005.

Figure 1 shows the finished report that we will design with RLU. To start RLU, enter the
command STRRLU and hit F4. Enter QDDSSRC as the source file. Enter the library name and
CUSW005 as the source member. Since this is a narrow report, enter 65 for the page width. For
a standard width report, you would use 132 for the page width.

RLU now displays its DESIGN REPORT screen. RLU uses so many function keys that there is
a base set of function keys and an alternate set of keys. F22 is used to toggle between the base

155
keys and the alternate keys. Right now RLU shows the word, BASE in the upper left portion of
the screen to indicate that the base set of function keys is in use. F22 changes to the alternate
keys and the changes the display from BASE to ALT.

The simplest way to use RLU is to define each line as a separate record. To start working with a
line of the report, key DR for DEFINE RECORD in the command area on a blank line. When you
hit the enter key, RLU names the record with the default name RCD001. After defining a record,
enter VF for VIEW FIELDS in the command area of the same line. RLU then adds a line above
the record to show the field information.

The heading for the report will be CUSTOMER ANNUAL PURCHASES. On the line with
RCD001, key in the heading. Then, convert this string of characters to a constant. Do this by
placing the cursor on the first character of the heading and hitting F11 for DEFINE FIELD. Hit
F11 again and then ENTER to convert the string of characters to a constant. Finally, center the
heading by keying CF for CENTER FIELD on the command portion of the RCD001 line. When
you hit ENTER, the heading will center.

Now, create a second record. This will be used to print the customer fields. First insert a line to
work with. Key I for INSERT in the command area of the RCD001 line and hit ENTER. Then, as
before, key DR to define this as a record and then VF for VIEW FIELDS.

Next, use RLU to retrieve the field definitions from the master file. Hit F10 for DATABASE
FIELDS. Key 1 for the option to ADD FIELD. Leave the FIELD value blank. Enter the library
name and CUST for the File. Enter the record name of the CUST file. RLU will then retrieve all
the fields in the CUST file and list them. Select the fields for the report. Hit ENTER until you
return to the DESIGN REPORT screen.

The names of the fields you selected are at the bottom of the screen. Each field is sequentially
numbered. To insert the first field in the report, key 1 in the text area of the FLD record above
the detail record line. When you hit ENTER, RLU puts that field in the layout. RLU has re-
sequenced the remaining fields. Place the remaining fields in the report.

If you overlap fields, RLU can get confusing. The simplest way to recover is to delete the record
by keying a D in the command area of the record. Then start the record over. If you want to
remove a field, put the cursor on the field and hit F16. If you need to move a field, use F13 to
mark where the cursor is positioned and then F15 to move the field to a new location.

Now that you have placed the fields in a detail record, create headings for the detail line. Insert
a line above the detail line. As always, key DR for DEFINE RECORD and then VF to VIEW
FIELDS. Simply key the headings in the text area of the blank record that you inserted. Then
convert each field to a constant by putting the cursor on the first character of each literal and
hitting F11 twice.

To help visualize the report, create some sample data lines. Make 5 copies of the detail line by
keying SD5 on the command line of the detail line.

Now, add a line at the bottom of the report for the total annual purchases. Do this by keying I in
the command line of the last record on the screen. As always, key DR and then VF in the
command area of the record.

Key the word TOTAL in the text area of the record. Convert the word to a constant by placing
the cursor on the first letter of the word and hitting F11 twice. Now, add a new field for the
accumulated total. This can get confusing.

156
Place the cursor where you want the total amount to print. Hit F11 to DEFINE FIELD. On the
DEFINE FIELD INFORMATION screen, change the name of the field from the default FLD001
to TOTPUR. Change the length of data to 9. Hit PAGE DOWN. Change the data type to 2 for
ZONED and enter 2 for decimal positions. Then hit F10 to WORK WITH KEYWORDS. Select
EDTCDE by keying 2 next to it. Hit ENTER and key 1 for the EDTCDE value. Hit ENTER a few
times and you will see that you have added a field for the total purchases.

Finally, add the date and page counter to the first heading line. Do this by adding a field of the
appropriate length, converting it to a constant and then selecting the appropriate keyword. Also,
rename the records by using F18 for RECORD KEYWORDS and then F10 to rename the
record.

Exit RLU with F3. You can save the DDS, compile it and generate a prototype report all from the
exit screen.

Figure 2 shows the complete RPG program to print the report.

Figure 1 - This is the finished report designed by RLU.

FLD1 <........> <.......................>


<..> <...>
HDG1 01/04/2001 CUSTOMER ANNUAL PURCHASES
Page 9,999
FLD1 <..> <...........> <..>
<..........>
HDG2 CUS# CUSTOMER NAME CITY
ANNUAL PURCH
00004 +
FLD1 <....> <.......................> <.............>
<.......>
DTL 999999 XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
99,999.99
00006 S 999999 XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
99,999.99
00007 S 999999 XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
99,999.99

157
00008 S 999999 XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
99,999.99
00009 S 999999 XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
99,999.99
00010 S 999999 XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
99,999.99
FLD1 <...>
<..........>
TOTL TOTAL
9,999,999.99

Figure 2 - This is the complete RPG program to print the


report.

FCUST IF E K DISK
FCUSW005 O E PRINTER OFLIND(*In99)
C Move *On *In99
C Read CUST
90
C *In90 DoWEq *Off
C *In99 IfEq *ON
C Write HDG1
C Write HDG2
C Move *Off *In99
C EndIf
C Add CUSAP TOTPUR
C Write DTL
C Read CUST
90

158
C EndDo
C Write TOTL
C Eval *INLR = *On
C Return

159

Potrebbero piacerti anche