Creating report programs still represents a large part of the AS/400 programming backlog for most shops. And, despite the clamor for on-screen queries, Windows client/server interfaces, and other programming services, a large segment of users still rely on the printed reports that the AS/400 generates. Yet printer programming gets short shrift as an area of study in most AS/400 shops. It seems that we love to buy those new, faster, feature-rich printers each year, but we never find the time to take advantage of their extra power.
Yet, as an analytical tool, one good, well-organized printed report can be worth a thousand screens and windows. So why is it that programmers shy away from report printing on the AS/400? Perhaps because the facilities are so robust, with so many different printer support options, that the task of creating a report loses some of the glamour. How do you make the most of those expensive printers? Where do you start?
This article maps out three approaches to printing on the AS/400 from the perspective of a programmer.
Before I start, I'll quickly review some basic concepts of report printing on the AS/400. You can take two general approaches toward creating a report: the traditional program-described output using RPG O-specs and externally described printer files using DDS A-specs.
Each approach has advantages and disadvantages; I wait to decide which approach I'll use until I know the type of printer on which the report will be created. Is it an SNA Character Stream (SCS) printer, an intelligent printer data stream (IPDS) printer, an ASCII printer, a laser printer? I need to know before I can maximize the output, because the AS/400 supports multiple printer data stream architectures, and the printer to which I will be sending the report will probably support only one.
Printers make their capabilities available to the printed page by interpreting commands sent from the AS/400. The format and content of these commands are dictated by printer data stream architectures. These architectures aren't static: they evolve as printer manufacturers add new capabilities to new models.
The AS/400 directly supports two native AS/400 printer data streams: SCS and Advanced Function Printing (AFP). In addition, the AS/400 can translate an SCS printer data stream from the EBCDIC character codes to the ASCII character codes so ASCII PC printers can be used.
SCS is the original IBM EBCDIC line printer control code set. Advanced Function Printing Data Stream (AFPDS) is IBM's all-points-addressable page formatting language that steps IBM's IPDS printers through their paces.
SCS translation to ASCII printer control codes offers its own realm of capabilities for printing. There's really no limit to the number of different printer data streams the AS/400 could theoretically support through EBCDIC to ASCII translation, but, in this article, I'll talk about the three most commonly recognized:
o Straight ASCII-the simple and unique codes sent to a printer through an emulation card or ASCII workstation controller interface.
o HP PCL5-Hewlett Packard's (HP's) printer control language for its laser printers. It's built upon ASCII characters, which are internally translated by the printer's firmware into page formatting controls.
o PostScript-Adobe Systems' page formatting language. It, like HP's PCL5 data stream, is built upon ASCII characters, which are internally translated by the printer's firmware.
Identifying these different printer data streams for the particular printer is important if you're going to maximize the printer's capabilities. If you want to talk to directly attached IBM printers, you need to converse in either SCS or AFP printer data streams. If, however, you want to talk to a non-AS/400 printer-a PC ASCII printer-you need to create the unique printer data stream through the SCS printer data stream and then translate that printer data stream through EBCDIC to ASCII translation tables. I'll talk about this technique in my examples.
The example assumes you have a simple program that sends a single field called DATA to a standard AS/400 SCS printer. The three operative lines of RPG code that perform this function are listed in 1.
The example assumes you have a simple program that sends a single field called DATA to a standard AS/400 SCS printer. The three operative lines of RPG code that perform this function are listed in Figure 1.
Suppose one of your users comes to you and says, "I want this report printed in italics!" The user's printer, a Panasonic KX-P1092i sitting in his office, is connected to the AS/400 with Client Access/400 and an emulation card. Here are the steps you need to follow.
Pull out the ASCII printer's operation manual and look for a section describing the printer control codes. What you'll discover is a very primitive programming language based on sending one- or two-byte data patterns to the printer. The data patterns are intercepted by the printer's control circuitry and instruct the circuit to activate or deactivate some function. Because these data patterns are usually preceded with the ASCII ESC escape character (hex 1B), this ASCII data stream is often referred to as escape sequence programming. For this Panasonic KX-P1092i printer, the command to kick the printer into italic fonts mode is composed of two bytes: hex 1B (ESC) followed by hex 34 (the ASCII character 4).
Your task, then, is to send this Panasonic printer the hex codes 1B34. To do this, you modify your original report program and add a few lines to send hex 1B34 through the AS/400 down to the printer (see 2). In this example, I created a field called ESCAPE, composed of the hex code '27' (often called the "logical not" character) and then concatenated it with the number '4' (the italic command). We'll send these two values out to the printer in a field called PNTCTL.
Your task, then, is to send this Panasonic printer the hex codes 1B34. To do this, you modify your original report program and add a few lines to send hex 1B34 through the AS/400 down to the printer (see Figure 2). In this example, I created a field called ESCAPE, composed of the hex code '27' (often called the "logical not" character) and then concatenated it with the number '4' (the italic command). We'll send these two values out to the printer in a field called PNTCTL.
The next step requires that you customize the user's EBCDIC to ASCII translation table so that the hex 27 EBCDIC character will be substituted with the ASCII character 1B. The most common means of doing this is to modify the EBCDIC to ASCII translation table residing at the interface where the ASCII printer meets the AS/400. This modification could be performed through the Client Access Emulation Software Printer translation table or-if the printer is attached by a twinaxial workstation-through the workstation's configuration options. To perform this task, you should check out the Client Access/400 Setup guide for DOS or OS/2 for information on changing printer-session options or Appendix B of IBM's OS/400 Workstation Customization Programming guide. Another means of handling this translation might be to use the host print transform function, which centralizes the EBCDIC translations for all printers. (For more information on the host print transform function, see the OS/400 Printer Device Programming manual.)
Once you've performed the translation, the DATA field will always be printed in italics when this report is printed on this user's printer.
I used program-described output specifications to specifically control the codes sent to the Panasonic printer (see 2). The hex values that control the printer's firmware are also hard coded in the program, but because these hex codes are unique to the Panasonic KX-P1092i, this report could look significantly different on a different user's HP LaserJet III. Wouldn't it be better to segment out the ASCII control mechanism so that this report could go to either printer? This leads to the second ASCII printing technique: using externally described printer files.
I used program-described output specifications to specifically control the codes sent to the Panasonic printer (see Figure 2). The hex values that control the printer's firmware are also hard coded in the program, but because these hex codes are unique to the Panasonic KX-P1092i, this report could look significantly different on a different user's HP LaserJet III. Wouldn't it be better to segment out the ASCII control mechanism so that this report could go to either printer? This leads to the second ASCII printing technique: using externally described printer files.
Since different ASCII printers are controlled by different control codes, the logical thing to do is to create separate printer drivers for each printer that might use this report. Although you can't actually create real print drivers in RPG, you can do something similar by using externally described printer files.
In the example, one user has a simple Panasonic printer, but another user has a sophisticated HP LaserJet. The Panasonic uses ASCII control codes to formulate an italic font. The HP, however, uses a completely different printer data stream language called PCL5. Here's the technique to create the separate DDS printer drivers.
Once again, go to the user's printer control code manual. For HP printers, PCL5 is a language often described in a separate book, which is usually shipped with the printer. PCL5 is an extremely robust set of commands that includes all-points-addressable page formatting, bar coding, and a lot more. It, like the simple Panasonic, builds its command structure from escape sequences, but, instead of using two-byte control codes, the HP firmware looks for an entire string of codes. You'll need to study these codes carefully to get the hang of their use.
The sample code shown in 3 includes the RPG and the DDS and represents two separate printer file specifications: the first for the Panasonic printer and the second for the HP printer. The DDS specifications are compiled separately using the Create Printer File (CRTPRTF) command.
The sample code shown in Figure 3 includes the RPG and the DDS and represents two separate printer file specifications: the first for the Panasonic printer and the second for the HP printer. The DDS specifications are compiled separately using the Create Printer File (CRTPRTF) command.
While the code in 2 sent the actual escape sequences to the printer, the RPG code in 3 uses a different technique. It WRITEs the ESCSQ format and then the RPTLN format. The actual escape sequences are embedded in the DDS for the externally described printer file, instead of the RPG. You end up with one printer file for the Panasonic printer and one for the HP.
While the code in Figure 2 sent the actual escape sequences to the printer, the RPG code in Figure 3 uses a different technique. It WRITEs the ESCSQ format and then the RPTLN format. The actual escape sequences are embedded in the DDS for the externally described printer file, instead of the RPG. You end up with one printer file for the Panasonic printer and one for the HP.
To switch from one printer to another, use the Override Printer File (OVRPRTF) command before executing the report. This command tells OS/400 to redirect the output to the appropriate externally described printer file.
Once again, it's important that the EBCDIC to ASCII translation table be configured to translate some token character into the ASCII hex 1B ESC character. In the example in 3, I used the ¬ character (again, the EBCDIC hex 27 or the logical not) as the designated token, but you could use any other seldom-printed EBCDIC code.
Once again, it's important that the EBCDIC to ASCII translation table be configured to translate some token character into the ASCII hex 1B ESC character. In the example in Figure 3, I used the ¬ character (again, the EBCDIC hex 27 or the logical not) as the designated token, but you could use any other seldom-printed EBCDIC code.
This technique shows a major advantage of the externally described printer files over the program described output in our previous example: when you buy a new printer, you don't have to tear apart the RPG-just create a new printer file.
Theoretically, you could use this same technique to create a PostScript print driver, but the level of programming quickly outstrips the patience of most RPG programmers. The PostScript language, like PCL 5, is composed of long strings of controlling commands, but, instead of the ESC character, each command begins with two ASCII hexidecimal 25s, which are represented by the percent (%) character. This language is further complicated by the depth of these commands, which quite often go on for several pages instructing the PostScript printer exactly how to formulate each bit on the page. For instance, printing the simple string "This is printed in italics" generates a PostScript file of more than 600 lines of ASCII code.
If you're intent, though, on making a real print driver for handling PostScript, the best place to begin is with IBM's PrintManager API Reference. This manual describes how to use the APIs to control, among other things, printing to a PostScript printer. You'll also need one or more manuals on the PostScript language, such as Adobe's Blue Book: PostScript Language Tutorial and Cookbook and Red Book: PostScript Language Reference Manual. Adobe also has an Internet FTP site from which other materials can be obtained at ftp://ftp.adobe.com/pub/adobe/Devel operSupport.
We started out with a simple SCS data stream and converted it to print italics on an ASCII printer. Yet, if you look at the OS/400 configuration of these ASCII devices, you'll see they are identified as standard AS/400 SCS devices. This is because the AS/400 uses the SCS data stream to send data to ASCII printers attached through emulation.
Can you develop similar printer drivers to work directly with IBM-attached SCS printers? The answer is, unfortunately, no. Why not? The answer is simple to understand if you look at the capabilities of the traditional SCS printer. SCS is based on an old technology that controlled print belts containing each printable character. The control codes that drove these belts were limited to what could be accomplished with that hardware: essentially, overprinting for making characters bold or underscoring characters.
One exception was the 5224/5225 series of dot matrix printers. If you have such an antique, you can use the DEFCHR DDS keyword. By sending specific hex codes through the DDS keyword, you can actually create your own characters by individually firing the dot matrix print head wires.
So what significance do SCS printers have for print programmers now? Most significantly, they represent OS/400's base support for printing on any AS/400 printer, and the SCS data stream offers us a translatable way to communicate with ASCII printers through emulation. But if you want to use fonts or other techniques to enhance the appearance of your reports, you must move beyond SCS to AFP.
The final printing technique I'll address in this article is the fully supported use of DDS keywords for creating graphics, such as images, overlays, and bar codes. This technique allows you to print those types of graphics as well as the normal EBCDIC character set. The facilities that make these capabilities work were historically known as AFP, but, starting with V3R1, the features became a separately ordered and chargeable feature called Print Services Facility/400 (PSF/400). Eleven DDS keywords require the PSF/400 facility. These keywords are listed in 4.
The final printing technique I'll address in this article is the fully supported use of DDS keywords for creating graphics, such as images, overlays, and bar codes. This technique allows you to print those types of graphics as well as the normal EBCDIC character set. The facilities that make these capabilities work were historically known as AFP, but, starting with V3R1, the features became a separately ordered and chargeable feature called Print Services Facility/400 (PSF/400). Eleven DDS keywords require the PSF/400 facility. These keywords are listed in Figure 4.
The AS/400's ability to print these complicated elements is intricately linked to two printer data stream architectures: AFP data stream and IPDS. IPDS is the page formatting language of the printer.
5 shows how these DDS keywords would be used to print the sample report in a Century Schoolbook 12-point font. There's no escape sequence programming, and the RPG program uses a simple WRITE statement to send out both the font and the data in one fell swoop. However, be aware that not all IPDS printers support all AFP keywords, and it's sometimes difficult to know the particular support level of the printer. Appendix A of the AS/400 AFP Utilities/400 manual provides a complete list of unsupported IPDS functions for each IBM printer. This manual is the only place you can find this information, so, before you start your project for a particular IPDS printer, check out its limitations in this book.
Figure 5 shows how these DDS keywords would be used to print the sample report in a Century Schoolbook 12-point font. There's no escape sequence programming, and the RPG program uses a simple WRITE statement to send out both the font and the data in one fell swoop. However, be aware that not all IPDS printers support all AFP keywords, and it's sometimes difficult to know the particular support level of the printer. Appendix A of the AS/400 AFP Utilities/400 manual provides a complete list of unsupported IPDS functions for each IBM printer. This manual is the only place you can find this information, so, before you start your project for a particular IPDS printer, check out its limitations in this book.
Here's one final note about IPDS printers: Some IPDS AS/400 printers support either the SCS or the AFP data stream (see 6). This is important for two reasons. First of all, the printers must be configured as *AFP in order to make all their functions available to the DDS keywords. And some printers, such as the 3812, require a special IBM diskette in order to make the AFP keywords work.
Here's one final note about IPDS printers: Some IPDS AS/400 printers support either the SCS or the AFP data stream (see Figure 6). This is important for two reasons. First of all, the printers must be configured as *AFP in order to make all their functions available to the DDS keywords. And some printers, such as the 3812, require a special IBM diskette in order to make the AFP keywords work.
Second, a very common misapprehension arises in printer emulation. Since most AS/400 printer emulation software provides a 3812 or other IPDS option, programmers naturally assume that these emulated printers support AFP. But, at present, the AFP activated keywords will only work on directly attached AS/400 printers.
So there you have it: AS/400 printing capabilities in a (very large) nutshell. The capabilities are there, and the techniques are simply waiting for you to try them. Getting to know your printer's and the AS/400's capabilities will be the path that will make you the print programming expert in your shop. But better yet, it's the skill that will keep you foremost in your user's mind. After all, you're the one who got it down "in print."
Thomas M. Stockwell is a senior technical editor for Midrange Computing. He can be reached by E-mail at
REFERENCES
Adobe Systems Incorporated. Blue Book: PostScript Language Tutorial and Cookbook. Addison-Wesley (ISBN 0-201-10179-3).
Adobe Systems Incorporated. Red Book: PostScript Language Reference Manual. Addison-Wesley (ISBN 0-201-18127-4).
AS/400 AFP Utilities/400 (SC41-3640, CD-ROM QBKAS200).
Client Access/400 for DOS Setup for V3R1 (SC41-3556, CD-ROM QBKAK000).
Client Access/400 for OS/2 Setup for V3R1 (SC41-3520, CD-ROM QBKAKI02).
OS/400 Printer Device Programming V3R1 (SC41-3713, CD-ROM QBKAUJ00).
OS/400 Workstation Customization Programming V3R1 (SC41-3605, CD-ROM QBKAQ600).
PrintManager API Reference (S544-3699, CD-ROM IB4S0M01).
Advanced AS/400 Print Programming Techniques
Figure 1: Simple Output for an SCS Printer
*..1....+....2....+....3....+....4....+....5....+....6 C EXCPT$RPTLN O E 1 $RPTLN O DATA 132
Advanced AS/400 Print Programming Techniques
Figure 2: Controlling ASCII Printers Through Escape Sequences
*..1....+....2....+....3....+....4....+....5....+....6 I X'27' C ESCAPE C MOVE '4' ITALIC ITALIC Command C MOVELESCAPE PNTCTL C MOVE ITALIC PNTCTL C EXCPT$ESCSQ C EXCPT$RPTLN O E 00 $ESCSQ O PNTCTL 1 O E 1 $RPTLN O DATA 132 *...1....+....2....+....3....+....4....+....5....+....6
Advanced AS/400 Print Programming Techniques
Figure 3: Externally Described ASCII Escape Sequence Codes
*...1....+....2....+....3....+....4....+....5....+....6 *********************************** * Panasonic KX-P1092i Driver *********************************** A R ESCSQ A 1'(4' A R RPTLN A SPACEA(001) A DATA 132A *...1....+....2....+....3....+....4....+....5....+....6 *...1....+....2....+....3....+....4....+....5....+....6 *********************************** * HP Driver *********************************** A R ESCSQ A 1'((8U(s1p12.00v0s0b4101T' A R RPTLN A SPACEA(001) A DATA 132A *..1....+....2....+....3....+....4....+....5....+....6 * RPG calling either PRTF *..1....+....2....+....3....+....4....+....5....+....6 C WRITEESCSQ C WRITERPTLNAdvanced AS/400 Print Programming Techniques
Figure 4: DDS Keywords Activated by PSF/400
Advanced AS/400 Print Programming Techniques
Figure 5: Externally Described Printer File Using AFP Font
*..1....+....2....+....3....+....4....+....5....+....6....+....7 A R RPTLN A DATA 132A A FONT(16951 (*POINTSIZE 12))
Advanced AS/400 Print Programming Techniques
Figure 6: IBM Printers That Can Be Configured as SCS or IPDS
IBM 3812 and 3816 Page Printers
IBM 3912 and 3916 Page Printers
IBM 3930 Page Printer
IBM LaserPrinter 4028
IBM 4224 and 4234 Printers
IBM 4230 Printer
IBM 6408 Printer
IBM 6412 Print
LATEST COMMENTS
MC Press Online