• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Admin Alert: Automatically Moving Printed Spooled Files Between Output Queues

    February 21, 2007 Joe Hertvik

    A reader recently wrote in looking for an automated technique to move spooled files between i5/OS output queues after printing. His goal was to retain spooled files in an output queue with a longer retention date than the printer output queue that the files were originally printed to. This week, I’ll look at a utility program that performs this function and the benefits it can provide your shop.

    The Basic Template

    In my research, I found that IBM didn’t seem to offer any APIs to perform a function similar to what I was looking for with this utility. This led me to create my own utility, based on another program I had previously created. In order to automatically move printed spooled files from a source output queue to a target output queue, I started with the following basic assumptions and requirements.

    1.  The spooled files to be moved have already been printed and saved in the source output queue. That is, their status will be marked as ‘SAV’ (saved). I’m assuming that these files had been marked as saved after printing through the use of an Override with Printer File command (OVRPRTF) before creation. Working with an already printed file is the minimum requirement that must be met before a spooled file becomes eligible to be moved to the longer retention output queue.

    2.  The spooled files to be moved are identifiable. The solution needs to capture all the data about all the spooled files in the source output queue, so that it can uniquely identify each file to be moved to the target output queue.

    This latter requirement also allows the code to look through the queue and pick out files to move according to the content of other spooled file attributes (besides the fact that a spooled file has already been printed and saved on the system). The additional attributes that it can examine for determining spooled file moves include the spooled file name; the user name who created the file; the value in the spooled file User Data field; or the form type. Although I could add several more tests to the code for determining which spooled files to move, the code for this example will only move those spooled files with a spooled file status of ‘SAV’, as indicated in requirement 1.

    Having these two requirements for moving a spooled file, I created a CL program to move all the printer files that meet my criteria. This program is based on another program I earlier wrote that selectively deletes spooled files from an output queue. My new CL program is called MOVSPLF and it requires two things:

    1. A work file called WRKOUTQPRT, which contains a listing of all the spooled files in the source output queue; and
    2. Four parameters that designate the source output queue and library that the spooled files will be moved from and the target output queue and library where the spooled files will be moved to

    Knowing these requirements and parameters, it was fairly easy to modify my original solution to meet this need (for a more complete explanation of some of the components that make up MOVSPLF, see the article titled Selectively Deleting Spooled Files).

    The Solution

    To create this solution, here’s the DDS code I needed for creating the WRKOUTQPRT file. WRKOUTQPRT will contain the captured spooled file information from the source output queue.

    A          R QPRTSPLQ                                               
    A            FILL0          1A         TEXT('FILLER')               
    A            SPLFIL        10A         TEXT('SPOOLED FILE NAME')            
    A            FILL1          1A         TEXT('FILLER')               
    A            USER          10A         TEXT('USER NAME')            
    A            FILL2          1A         TEXT('FILLER')               
    A            USRDTA        10A         TEXT('USER DATA')            
    A            FILL3          2A         TEXT('FILLER')               
    A            STATUS         5A         TEXT('STATUS')               
    A            FILL4          1A         TEXT('FILLER')               
    A            PAGES          5A         TEXT('NUMBER OF PAGES')      
    A            FILL5          1A         TEXT('FILLER')               
    A            COPIES         5A         TEXT('NUMBER OF COPIES')     
    A            FILL6          2A         TEXT('FILLER')               
    A            FRMTYP        10A         TEXT('FORM TYPE')            
    A            FILL7          1A         TEXT('FILLER')               
    A            PTY            2A         TEXT('PRIORITY')             
    A            FILL8          5A         TEXT('FILLER')               
    A            FILNUM         6A         TEXT('FILE NUMBER')          
    A            FILL9          5A         TEXT('FILLER')      
    A            JOB           10A         TEXT('JOB NAME')    
    A            FILL10         1A         TEXT('FILLER')      
    A            JOBNUM         6A         TEXT('JOB NUMBER')  
    A            FILL11         1A         TEXT('FILLER')      
    A            JOBDTE         8A         TEXT('JOB DATE')    
    A            FILL12        22A         TEXT('FILLER')      
    

    MOVSPLF uses this file to create a list of all the current spooled files in the source output queue. My WRKOUTQPRT DDS is a roll your own file that was created by mapping the lines on the Work with Output queue report (QPRTSPLQ) to DDS specifications. This is necessary because IBM doesn’t offer any physical file output from the WRKOUTQ command, so you should be aware that the report layout could change if and when you update your AS/400, i5, and iSeries to a newer version of the i5/OS operating system.

    Here’s the code for the MOVSPL program. This program automatically moves all spooled files with a status of ‘SAV’ from the source output queue to the target output queue.

    0001.00    PGM        PARM(&OUTQNAME &OUTQLIB &TGTOUTQ &TGTOUTQLIB)   
    0002.00    DCL        VAR(&OUTQNAME) TYPE(*CHAR) LEN(10)  
    0003.00    DCL        VAR(&OUTQLIB) TYPE(*CHAR) LEN(10)       
    0004.00    DCL        VAR(&TGTOUTQ) TYPE(*CHAR) LEN(10)     
    0005.00    DCL        VAR(&TGTOUTQLIB) TYPE(*CHAR) LEN(10) 
    0006.00    
    0007.00    DCL        VAR(&COUNTER) TYPE(*DEC) LEN(15 5) VALUE(1) 
    0008.00    DCL        VAR(&WORK) TYPE(*CHAR) LEN(1) VALUE('0')        
    0009.00    DCL        VAR(&WORK1) TYPE(*CHAR) LEN(1) VALUE('0')       
    0010.00    DCL        VAR(&ZERO) TYPE(*CHAR) LEN(1) VALUE('0')        
    0011.00    DCL        VAR(&COPIES1) TYPE(*CHAR) LEN(5) VALUE(' ')     
    0012.00    DCL        VAR(&FILNUM1) TYPE(*CHAR) LEN(6) VALUE(' ')     
    0013.00    
    0014.00    
    0015.00    DCLF       FILE(WRKOUTQPRT)                                
    0016.00    
    0017.00    CHKOBJ     OBJ(QTEMP/WRKOUTQPRT) OBJTYPE(*FILE)            
    0018.00    MONMSG     MSGID(CPF9801) EXEC(CRTDUPOBJ +                 
    0019.00    OBJ(WRKOUTQPRT) FROMLIB(QGPL) +               
    0020.00    OBJTYPE(*FILE) TOLIB(QTEMP))               
    0021.00    
    0022.00    OVRDBF     FILE(WRKOUTQPRT) TOFILE(QTEMP/WRKOUTQPRT) +  
    0023.00    MBR(*FIRST)                                
    0024.00    
    0025.00    WRKOUTQ    OUTQ(&OUTQLIB/&OUTQNAME) OUTPUT(*PRINT)      
    0026.00    
    0027.00    CPYSPLF    FILE(QPRTSPLQ) TOFILE(QTEMP/WRKOUTQPRT) +    
    0028.00    SPLNBR(*LAST)                              
    0029.00    
    0030.00    GETIT:                                                  
    0031.00    RCVF                                                    
    0032.00    MONMSG     MSGID(CPF0864) EXEC(GOTO CMDLBL(ENDPGM))     
    0033.00    
    0034.00    CHGVAR     VAR(&COPIES1) VALUE(' ')                     
    0035.00    
    0036.00    CHGVAR     VAR(&FILNUM1) VALUE(' ')                     
    0037.00    CHGVAR     VAR(&COUNTER) VALUE(0)                       
    0038.00    COUNT:                                                  
    0039.00    
    0040.00    IF         COND(&COUNTER *LT 6) THEN(DO)                 
    0041.00    CHGVAR     VAR(&COUNTER) VALUE(&COUNTER + 1)             
    0042.00    
    0043.00    IF         COND(&COUNTER *LT 6) THEN(DO)                 
    0044.00    CHGVAR     VAR(&WORK) VALUE(%SST(&COPIES &COUNTER 1))    
    0045.00    
    0046.00    IF         COND(&WORK *EQ ' ') THEN(CHGVAR +             
    0047.00    VAR(&COPIES1) VALUE(&COPIES1 *TCAT &ZERO))  
    0048.00    ELSE       CMD(CHGVAR VAR(&COPIES1) VALUE(&COPIES1 +     
    0049.00         *TCAT &WORK))                               
    0050.00    ENDDO                                                    
    0051.00                                                                       
    0052.00    CHGVAR     VAR(&WORK1) VALUE(%SST(&FILNUM &COUNTER 1))   
    0053.00    IF         COND(&WORK1 *EQ ' ') THEN(CHGVAR +            
    0054.00    VAR(&FILNUM1) VALUE(&FILNUM1 *TCAT &ZERO))  
    0055.00    ELSE       CMD(CHGVAR VAR(&FILNUM1) VALUE(&FILNUM1 +     
    0056.00                      *TCAT &WORK1))                              
    0057.00    GOTO       CMDLBL(COUNT)                                 
    0058.00                                                                       
    0059.00    ENDDO                                                    
    0060.00                                                                        
    0061.00                                                                        
    0062.00    IF         COND(&COPIES1 *LE '00000') THEN(GOTO +         
    0063.00                CMDLBL(GETIT))                               
    0064.00                                                                        
    0065.00   IF         COND(&COPIES1 *GE '99999') THEN(GOTO +         
    0066.00                CMDLBL(GETIT))                               
    0067.00                                                                        
    0068.00                                                                        
    0069.00                                                                        
    0070.00                                                                        
    0071.00   IF         COND(&STATUS *EQ 'SAV') THEN(DO)               
    0072.00   CHGSPLFA   FILE(&SPLFIL) JOB(&JOBNUM/&USER/&JOB) +        
    0073.00                SPLNBR(&FILNUM1) OUTQ(&TGTOUTQLIB/&TGTOUTQ)  
    0074.00   ENDDO                                                     
    0075.00                                                                        
    0076.00   GOTO       CMDLBL(GETIT)                                  
    0077.00                                                                        
    0078.00   ENDPGM:                                                     
    0079.00                                                  
    0080.00   DLTOVR     FILE(WRKOUTQPRT)           
    0081.00                                                  
    0082.00   DLTF       FILE(QTEMP/WRKOUTQPRT)     
    0083.00                                                  
    0084.00   ENDPGM                                
    

    MOVSPLF works in the following way.

    1. The source and target output queues and their libraries are passed in as parameters with the program call (statement 1.00).
    2. MOVSPLF creates a temporary copy of the WRKOUTQPRT file in the QTEMP library and uses the Work with Output Queue command (WRKOUTQ) to create a printout containing information about all the spooled files in the source output queue (statements 17.00 through 26.00). It then uses the Copy Spooled File command (CPYSPLF) to copy the WRKOUTQ information from the QPRTSPLQ report into the temporary WRKOUTQPRT file, providing a physical file record of all the spooled files residing in that output queue (statements 27.00-28.00).
    3. The program reads all the records in the WRKOUTQPRT file to determine whether or not the spooled files they represent should be moved to the target output queue. Before MOVSPLF can evaluate the records, it needs to zero-fill two numeric fields that will be used in the logic. The code zero-fills the number of copies field and the spooled file number field (statements 34.00-60.00). The full fields will be used in later sections of the code.
    4. Because the populated WRKOUTQPRT file essentially contains a line by line copy of the QPRTSPLQ report, this means that not every record in that report will describe an actual spooled file. Some of the records will contain the report header and other report line information that was used to create the report. To determine which records list off information on spooled files that I may want to move, I look for records where the number of copies field contains a literal between ‘00000’ and ‘99999’ (statements 62.00-66.00). If the program is looking at a record that does not have a numeric value in this field, it doesn’t evaluate that record for moving a spooled file. That’s why the program zero-filled the number of copies field in statements 34.00-60.00.
    5. The file looks to see if the current record’s spooled file status is ‘SAV’, which means that the spooled file listed in this record has been printed. If it’s been printed, the code uses the Change Spool File Attributes command (CHGSPLFA) to move the file to the target output queue (statements 71.00-74.00). Notice that CHGSPLFA uses the zero-filled job number field to help identify which spooled file to move.
    6. The program ends and cleans up after itself by deleting the file override it used to read the WRKOUTQPRT file in QTEMP. It then deletes the temporary copy of WRKOUTQPRT that it created in the QTEMP library (statements 78.00-84.00).

    The end result of this program is that it moves all printed and saved spooled files from the source output queue to the target output queue. If you want to further refine the files that are moved, you could also pass in additional qualifiers to be used in statements 71.00-74.00, which would allow you to compare the spooled files by user name (versus the USER field in the WRKOUTQPRT file), spooled file name (versus WRKOUTQPRT’s SPLFIL field), the spooled file’s user data field (the USRDTA field), form type (FRMTYP), or job name (JOB). You can get more versatile with this code and pass in any number of fields to determine whether or not you want to move a particular spooled file to the target output queue.

    The other nice thing that you could do with this program is to turn it into a server job, where it can run as an infinitely looping batch job that evaluates and moves spooled files as they enter the source output queue and are printed. To do that, I would first put a LOOP: label in front of the WRKOUTQ statement on statement 22.00. Then, to allow the program to loop through its evaluation every half-hour, I would place the following lines after statement 78.

    0078.01              CLRPFM     FILE(QTEMP/WRKOUTQPRT)  
    0078.02              DLYJOB     DLY(1800)               
    0078.03              GOTO       CMDLBL(LOOP)            
    

    Statement 78.01 clears the WRKOUTQPRT work file after usage, statement 78.02 delays the job for a half-hour before beginning processing again, and statement 78.03 sends the job back to the beginning of the loop where WRKOUTQPRT can be reloaded and re-evaluated for new spooled files that can be moved to the target output queue.

    Adding these statements would allow the program to act as a server. If you do this, however, you may also want to add some code to end the program after a certain number of iterations. If you don’t want MOVSPLF to function as a server job, you could also set it up in the i5 job scheduler to run several times a day.

    About Our Testing Environment

    All configurations described in this article were tested on an i5 box running i5/OS V5R3. However, most of these commands and features are also available on i5/OS V5R4 and most earlier versions of OS/400 V4R5 and below running on AS/400 and iSeries machines.

    RELATED STORY

    Selectively Deleting Spooled Files



                         Post this story to del.icio.us
                   Post this story to Digg
        Post this story to Slashdot

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Maxava

    Migrate IBM i with Confidence

    Tired of costly and risky migrations? Maxava Migrate Live minimizes disruption with seamless transitions. Upgrading to Power10 or cloud hosted system, Maxava has you covered!

    Learn More

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    Aldon:  ALM solutions to accelerate your application development
    COMMON:  Join us at the 2007 conference, April 29 – May 3, in Anaheim, California
    Maximum Availabilty:  Secure, cost-effect, real-time iSeries replication software

    Books on Sale at the IT Jungle Store: 30 Percent Off for 30 Days

    The System i Pocket RPG & RPG IV Guide: List Price, $69.95; Sale Price, $49.00
    The iSeries Pocket Database Guide: List Price, $59.00; Sale Price, $41.00
    The iSeries Pocket Developers' Guide: List Price, $59.00; Sale Price, $41.00
    The iSeries Pocket SQL Guide: List Price, $59.00; Sale Price, $41.00
    The iSeries Pocket Query Guide: List Price, $49.00; Sale Price, $34.00
    The iSeries Pocket WebFacing Primer: List Price, $39.00; Sale Price, $27.00
    Migrating to WebSphere Express for iSeries: List Price, $49.00; Sale Price, $34.00
    iSeries Express Web Implementer's Guide: List Price, $59.00; Sale Price, $41.00
    Getting Started with WebSphere Development Studio for iSeries: List Price, $79.95; Sale Price, $56.00
    Getting Started With WebSphere Development Studio Client for iSeries: List Price, $89.00; Sale Price, $62.00
    Getting Started with WebSphere Express for iSeries: List Price, $49.00; Sale Price, $34.00
    WebFacing Application Design and Development Guide: List Price, $55.00; Sale Price, $38.00
    Can the AS/400 Survive IBM?: List Price, $49.00; Sale Price, $34.00
    The All-Everything Machine: List Price, $29.95; Sale Price, $21.00
    Chip Wars: List Price, $29.95; Sale Price, $21.00

    Fujifilm Introduces Tape Cases for Secure Media Transport Magic Puts Focus Back on eDeveloper with Giveaway, Contest

    Leave a Reply Cancel reply

Volume 7, Number 7 -- February 21, 2007
THIS ISSUE SPONSORED BY:

SEQUEL
WorksRight Software
RPG & DB2 Summit

Table of Contents

  • Get Connected with Remote Systems Explorer
  • A Handy Tip for Testing Batch Job Streams
  • Admin Alert: Automatically Moving Printed Spooled Files Between Output Queues

Content archive

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

Recent Posts

  • POWERUp 2025 –Your Source For IBM i 7.6 Information
  • Maxava Consulting Services Does More Than HA/DR Project Management – A Lot More
  • Guru: Creating An SQL Stored Procedure That Returns A Result Set
  • As I See It: At Any Cost
  • IBM i PTF Guide, Volume 27, Number 19
  • IBM Unveils Manzan, A New Open Source Event Monitor For IBM i
  • Say Goodbye To Downtime: Update Your Database Without Taking Your Business Offline
  • i-Rays Brings Observability To IBM i Performance Problems
  • Another Non-TR “Technology Refresh” Happens With IBM i TR6
  • IBM i PTF Guide, Volume 27, Number 18

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 © 2025 IT Jungle