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:
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).
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.
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.