• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • An Alternative to Externally Described Printer Files

    April 14, 2004 Cletus the Codeslinger

    [The code for this article is available for download.]

    There is no shortage of ways to build a report from an iSeries database. IBM offers Query/400, Query Management, and SQL/400, but they’re all limited in one way or another. For example, Query/400 has to be told to read the library list, it has no conditional processing, it has limited calculation abilities, and passing parameters to a Query/400 query is hardly intuitive. There are many third-party query packages. Some run on the iSeries; some run on PCs. Many overcome the limitations of IBM’s query offerings.

    Nonetheless, most query packages run out of steam. A Query/400 query may work fine, until a user requests that a certain calculation be done for control breaks, or that a field be printed only under certain circumstances. That’s when you have no choice but to drag out the RPG or COBOL compiler.

    If, like me, you have a job and a family, and constantly feel like you’re trying to live six lives at once, you look for ways to do things quickly. In this article, I’ll share one technique that I use to make quick work of a boring but necessary job: generating reports with RPG. This technique is applicable to COBOL, as well.

    A THIRD WAY

    In many iSeries shops, the debate over report-creation methodologies rages. Old-timers want to use the RPG cycle and output specifications. Others don’t understand the cycle and want to use externally described printer files.

    Please participate in our iSeries programming survey at
    http://www.surveymonkey.com/s.asp?u=74193419903

    I have developed a third technique that doesn’t require coding O-specs or DDS or using RLU. I don’t claim it’s appropriate for all situations, but it works for many general SCS-type reports. Rather than O-specs or DDS, I define a data structure containing columns for field values.

    When I use the word “column,” I don’t mean print positions, as in “there are 132 columns on a report printed on standard green-bar paper at ten characters per inch.” I use the word column to mean a group of one or more print positions in which a value is printed. This approach fits many run-of-the-mill reports. For example, a report might have eight columns, which contain company number, customer number, customer name, sales rep number, sales rep name, current receivable balance, past-due balance, and date of last payment. Here’s the data structure I would define:

    D PrintLine       DS           132 
    D  Column01                      4 
    D                                1 
    D  Column02                      5 
    D                                1 
    D  Column03                     20 
    D                                1 
    D  Column04                      5 
    D                                1 
    D  Column05                     18 
    D                                1 
    D  Column06                     12 
    D                                1 
    D  Column07                     12 
    D                                1 
    D  Column08                      8 
    

    I initially define each column with what I estimate to be an appropriate width. I use unnamed spacer subfields to separate the columns from one another. As I develop the report, I will adjust the column widths and spacer widths as needed.

    Here is what I most like about this approach to building repots. I use these columns for column headings, detail fields, and total fields. When I adjust the size of a column or the width of a spacer, I automatically keep headings, details, and totals in alignment. It beats the heck out of RLU.

    To load the columns, I use EVAL for non-numeric fields and use EVALR for numeric fields. To copy a numeric value to a column, I use an appropriate edit code or edit word. The following three groups of source code lines show how I load a customer name (alpha) and current accounts receivable balance (numeric):

     * load the detail line
    EVAL      Column03 = CustomerName         
    EVALR     Column06 = %EDITC(CurBalance:'J')
    
     * load the column heading
    EVAL      Column03 = 'Name'   
    EVALR     Column06 = 'Balance'
    
     * load the final totals
    EVALR     Column06 = %EDITC(TotCurBalance:'J')
    

    Using this approach makes it easy for me to:

    • Increase or decrease the size of a column.

    • Leave more or less space between columns.

    • Reorder the columns, since I do not rename the columns when moving them around in the data structure.

    • Insert new columns or remove columns.

    PRINTING THINGS THAT DON’T FIT IN THE COLUMNS

    Some things don’t fit the columns. The first line of a report often includes a title, a run date, a page number, and such. I load these things into the data structure by referring to the data structure directly:

    EVAL      PrintLine = 'Current Accounts Receivable'  
    EVAL      %SUBST(PrintLine:70) = %CHAR(SysDate:*MDY) 
                + '   Page ' + %CHAR(PageNbr)            
    

    VERTICAL SPACING

    Since there are no data definition specifications or output specifications, I use a printer control data structure to control vertical spacing:

    FQSYSPRT   O    F  132        PRINTER OFLIND(Overflow)
    F                                     PRTCTL(PrtCtlDS)
    
    D PrtCtlDS        DS            15 
    D  pcSpacing              1     12
    D  pcSpcBefore            1      3 
    D  pcSpcAfter             4      6 
    D  pcSkpBefore            7      9 
    D  pcSkpAfter            10     12 
    D  pcLineNbr             13     15
    D
    D Overflow        S               N
    

    Before printing a line, I load the appropriate space or skip entries. After printing a line, I clear the space and skip entries to prepare for the next printed line.

    THE PRINT ROUTINE

    My programs contain only one WRITE command to the printer file. Here is the subroutine that contains that command:

    C     Write         BEGSR                               
    C                                                       
    C                   IF        pcSpacing = *blanks     
    C                   EVAL      pcSpcBefore = '001'       
    C                   ENDIF                               
    C                                                       
    C                   WRITE     QSYSPRT       PrintLine   
    C                   CLEAR                   PrintLine   
    C                   CLEAR                   pcSpacing
    C                                                       
    C                   ENDSR                               
    

    If no spacing or skipping is selected, this routine single-spaces by default.

    A SAMPLE PROGRAM

    The code fragments listed above came from a sample program I put together for this article. I’ve also provided the output produced by this program from four customer records.

    Permit me to make a few comments about the program.

    First, I use SQL to read the input, but this technique works for native I/O as well. I like SQL because of the flexibility it offers. For example, SQL lets me sort on calculated fields, something that is difficult to do with native I/O.

    Second, I have intentionally kept this example as simple as possible; therefore it does not do anything that couldn’t be done with a query program. The beauty of this technique becomes apparent when you add additional calculations to handle special circumstances.

    Third, this technique also works with double lines. For example, if you want to print the customer name on the line following the one with the customer number, you can define two separate sets of columns within the data structure. In the following code, columns 1 through 7 print on one line and column 8 prints on a separate line:

    D PrintLine       DS           132                        
    D  Column01                      4                        
    D                                1                        
    D  Column02                      5                        
    D                                1                        
    D  Column03                      5                        
    D                                1                        
    D  Column04                     18                        
    D                                1                        
    D  Column05                     12                        
    D                                1                        
    D  Column06                     12                        
    D                                1                        
    D  Column07                      8                        
    D                                1                        
    D  Column08                     20    OVERLAY(PrintLine:6)
    

    COBOL TECHNIQUES

    COBOL programmers can use the same technique. Define a group item to contain the columns in the working-storage section. Use the MOVE verb to load the columns in the procedure division. To control spacing, use a variable after the ADVANCING phrase of the WRITE verb. I’ve provided a rough equivalent of the RPG program presented above.

    You may also be interested in reading the report “Simplifying Batch Outputting in COBOL” (in PDF format), by Barbara Russell of Northwestern State University. Russell does not define columns for the data, as I do, but she does create print lines in the procedure division. Notice the comparisons she makes to “traditional” methods of report definition.

    THE PROCESS

    I have found this technique easy to use and productive. When I am called on to build a report, I usually begin by creating a Query/400 that builds the desired report as much as possible. I use the Retrieve QM Query (RTVQMQRY) command to build a SQL statement, which I paste into the new RPG source member. The column widths in the query become the starting definitions of the columns in the data structure. In a short time, I have a working RPG report program that I can modify and tweak as necessary.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    WorksRight Software

    Do you need area code information?
    Do you need ZIP Code information?
    Do you need ZIP+4 information?
    Do you need city name information?
    Do you need county information?
    Do you need a nearest dealer locator system?

    We can HELP! We have affordable AS/400 software and data to do all of the above. Whether you need a simple city name retrieval system or a sophisticated CASS postal coding system, we have it for you!

    The ZIP/CITY system is based on 5-digit ZIP Codes. You can retrieve city names, state names, county names, area codes, time zones, latitude, longitude, and more just by knowing the ZIP Code. We supply information on all the latest area code changes. A nearest dealer locator function is also included. ZIP/CITY includes software, data, monthly updates, and unlimited support. The cost is $495 per year.

    PER/ZIP4 is a sophisticated CASS certified postal coding system for assigning ZIP Codes, ZIP+4, carrier route, and delivery point codes. PER/ZIP4 also provides county names and FIPS codes. PER/ZIP4 can be used interactively, in batch, and with callable programs. PER/ZIP4 includes software, data, monthly updates, and unlimited support. The cost is $3,900 for the first year, and $1,950 for renewal.

    Just call us and we’ll arrange for 30 days FREE use of either ZIP/CITY or PER/ZIP4.

    WorksRight Software, Inc.
    Phone: 601-856-8337
    Fax: 601-856-9432
    Email: software@worksright.com
    Website: www.worksright.com

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Ricoh Printers Get Better iSeries Connectivity with WCO Power5 OS/400 Servers to Ship by End of June

    Leave a Reply Cancel reply

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • IBM Tweaks Some Power Systems Prices Down, Others Up
  • Disaster Recovery: From OS/400 V5R3 To IBM i 7.4 In 36 Hours
  • The Disconnect In Modernization Planning And Execution
  • Superior Support: One Of The Reasons You Pay The Power Systems Premium
  • IBM i PTF Guide, Volume 25, Number 13
  • IBM i Has a Future ‘If Kept Up To Date,’ IDC Says
  • When You Need Us, We Are Ready To Do Grunt Work
  • Generative AI: Coming to an ERP Near You
  • Four Hundred Monitor, March 22
  • IBM i PTF Guide, Volume 25, Number 12

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2023 IT Jungle