Dont Lose Your SEU Changes
Have you ever been in the middle of modifying an existing AS/400 source file, such as an RPG IV program, and deleted or changed lines of code that you didnt really want to by using SEU? This is a frustrating and common occurrence, but there are a few things you can do to remedy the situation.
You could just press the F3 key to exit and not save any of your changes. That way, at least your original source will remain unchanged. This option will work fine, but it may not be the most desirable, since you will lose all the changes that you made. We all have enough to do without having to redo our own work.
You could exit, save your changes to another member name, edit the new member, and copy the source code you deleted or changed from the original member. This option will also work fine, with the exception of being a minor pain. Of course, you have to remember what you named the new member and then copy the changes back into the original source member. That could turn into a pretty big nightmare in a hurry.
The method that I have found that works best for me is to use the Browse/Copy Options (F15) in SEU to display a copy of the same source member Im currently editing. Now all I have to do is position the copy to the lines that I accidentally deleted, copy them, and paste them into the current source. You can also use this method to browse the original code to see what it looked like before you made your changes.
Greg Leister
SFLSIZ and SFLPAG Matters
Occasionally, its useful to retrieve SFLSIZ and SFLPAG numbers before initializing a subfile. A good example might be if the DDS file were changed and the subfile size or subfile page size were also changed. If you knew ahead of time, your program wouldnt necessarily need to be recompiled. A subfile can have two sets of these numbers: one set for *DS3 (24 x 80 mode) and another set for *DS4 (27 x 132 mode). This information is not in the open file feedback area but is available in the Retrieve Display File Description (QDFRTVFD) API.
Figure 1 shows Retrieve Subfile Size (RTVSFLSIZE), an RPG IV procedure that accepts two parameters: a 20-byte qualified display file name and a 10-byte subfile control record format name. RTVSFLSIZE calls the QDFRTVFD API and returns an 8-byte
structure of four BIN(2) numbers: the set of SFLSIZ and SFLPAG numbers for *DS3 and *DS4.
A program need call RTVSFLSIZE only once for each subfile after a display file is opened. SFLSIZ and SFLPAG numbers dont change while a display file is open. If the subfile specifies only *DS3 or *DS4 but not both, RTVSFLSIZE returns the SFLSIZ and SFLPAG numbers in the appropriate *DS3 or *DS4 subfield and returns 0,0 in the other subfields. If the display file or library doesnt exist or if the record format name isnt a subfile control record, RTVSFLSIZE returns 0,0,0,0.
Figure 2 shows a program that calls RTVSFLSIZE. This program gets the qualified display file name from the open file feedback area and requests the SFLSIZ and SFLPAG numbers for a subfile control record format named PAY01C.
The code for this tip can be downloaded at www.midrangecomputing.com/mc.
Gene Gaunt Gene_Gaunt/
**********************************************************************************************
* To Create: *
* *
* CRTRPGMOD MODULE(QTEMP/RTVSFLSIZE) SRCFILE(xxx/QRPGLESRC) + *
* SRCMBR(RTVSFLSIZE) *
* *
* CRTSRVPGM SRVPGM(xxx/RTVSFLSIZE) MODULE(QTEMP/RTVSFLSIZE) + *
* EXPORT(*ALL) *
* *
**********************************************************************************************
* Procecure: RTVSFLSIZE (Retrieve Subfile Sizes) *
* *
* Input parameters: PARM FIELD TYPE *
* 1 display file name and library name CHAR(20) *
* 2 subfile control record format name CHAR(10) *
* *
* Return structure: POS FIELD TYPE *
* 1 SFLSIZ number (*DS3 24x80 mode) BIN(2) *
* 3 SFLPAG number (*DS3 24x80 mode) BIN(2) *
* 5 SFLSIZ number (*DS4 27x132 mode) BIN(2) *
* 7 SFLPAG number (*DS4 27x132 mode) BIN(2) *
**********************************************************************************************
H nomain
D RtvSflSize PR 8A
D 20A const
D 10A const
P RtvSflSize B export
D RtvSflSize PI 8A
D FileLib 20A const
D Record 10A const
D ReturnValue DS
D SubfileSize3 5I 0 inz(0) *DS3
D SubfilePage3 5I 0 inz(0)
D SubfileSize4 5I 0 inz(0) *DS4
D SubfilePage4 5I 0 inz(0)
D Qdff_Base DS based ( Qdff_Base@ ) base file section
D Wdff_Inof 5I 0 overlay( Qdff_Base : 9 )
D Wdff_Rcs 5I 0 overlay( Qdff_Base : 11 )
D Wdff_Scr 5I 0 overlay( Qdff_Base : 14 )
D Wdff_Scrs 5A overlay( Qdff_Base : 20 ) dim(2)
D Wdff_Scia 1A overlay( Wdff_Scrs : 1 )
D Qdff_Info DS based ( Qdff_Info@ ) file header section
D Wdff_Dflo 10I 0 overlay( Qdff_Info : 1 )
D Qdfa_Rfte DS based ( Qdfa_Rfte@ ) record format table
D Wdfa_Rfte 16A overlay( Qdfa_Rfte : 1 ) dim(2000)
D Wdfa_Rfnm 10A overlay( Wdfa_Rfte : 1 )
D Wdfa_Rfof 10I 0 overlay( Wdfa_Rfte : 13 )
D Qdff_Rinf DS based ( Qdff_Rinf@ ) record headr section
D Wdff_Rflg 1A overlay( Qdff_Rinf : 13 )
D Wdff_Raof 5I 0 overlay( Qdff_Rinf : 29 )
D Qdff_Sfcr DS based ( Qdff_Sfcr@ ) subfile control
D Wdff_Sfpm 24A overlay( Qdff_Sfcr : 55 ) dim(2)
D Wdff_Sfsz 5I 0 overlay( Wdff_Sfpm : 1 )
D Wdff_Sfpg 5I 0 overlay( Wdff_Sfpm : 3 )
D GET PR extpgm(QDFRTVFD)
D 27A dummy length here
D 10I 0 const receivers length
D 8A const API format name
D 20A const display file name
D 10I 0 const API error code
D Test DS 27
D 4A
D SizeNeeded 10I 0
C callp GET( Test : 8 : DSPF0100 : FileLib : 0 ) get size needed
C alloc SizeNeeded Qdff_Base@
C callp GET( Qdff_Base: SizeNeeded : base file section
C DSPF0100 : FileLib : 0 )
C eval Qdff_Info@ = Qdff_Base@ + Wdff_Inof file header section
C eval Qdfa_Rfte@ = Qdff_Info@ + Wdff_Dflo record format table
C 1 do Wdff_Rcs X 5 0 scan record table
C Record ifeq Wdfa_Rfnm(X) if record name found
C eval Qdff_Rinf@ = Qdff_Info@ + Wdfa_Rfof(X) record headr section
C testb X20 Wdff_Rflg 21 (EQ)
C N21 iter not subfile control
C eval Qdff_Sfcr@ = Qdff_Rinf@ + Wdff_Raof subfile control rcrd
C 1 do Wdff_Scr Y 5 0 scan screen sizes
C select
C X03 wheneq Wdff_Scia(Y) if *DS3 size
C z-add Wdff_Sfsz(Y) SubfileSize3
C z-add Wdff_Sfpg(Y) SubfilePage3
C X04 wheneq Wdff_Scia(Y) if *DS4 size
C z-add Wdff_Sfsz(Y) SubfileSize4
C z-add Wdff_Sfpg(Y) SubfilePage4
C endsl
C enddo
C endif
C enddo
C dealloc Qdff_Base@
C return ReturnValue
P RtvSflSize E **************************************************************
* To Compile:
* CRTRPGMOD MODULE(QTEMP/PAY01R) +
* SRCFILE(xxx/QRPGLESRC) SRCMBR(PAY01R)
*
* CRTPGM PGM(xxx/PAY01R) MODULE(QTEMP/PAY01R) +
* BNDSRVPGM(xxx/RTVSFLSIZE)
***************************************************************
FPay01d CF E workstn infds(WsInfo)
F sfile(PAY01L:SfileRecno)
D WsInfo DS
D FileLib 83 102A
D Get PR 8A extproc('RTVSFLSIZE')
D 20A const
D 10A const
D SfileRecno S 5S 0
D Sizes DS
D SFLSIZ_3 5I 0 inz(0) *DS3
D SFLPAG_3 5I 0 inz(0)
D SFLSIZ_4 5I 0 inz(0) *DS4
D SFLPAG_4 5I 0 inz(0)
C eval Sizes = Get( FileLib : 'PAY01C' )
* now use subfile numbers for something ...
C move *on *INLR
Figure 1: RTVSFLSIZE returns subfile and page sizes.
Figure 2: This program calls the RTVSFLSIZE procedure.
Cleaning Up the AS/400 IFS
Ive written several RPG IV applications that create files in the AS/400 Integrated File System (AS/400 IFS) on our AS/400. Too often during testing, Ill miskey something, and the file name Ive created in the AS/400 IFS contains invalid characters such as a file name containing slashes or quote marks: a definite no-no.
Youd think that I could use the Work with Links (WRKLNK) command to go into that directory and delete these files, but thats not the case. The Remove (delete) function of
WRKLNK needs a valid AS/400 IFS file name as a parameter to locate the file and remove it. Since the misnamed files I created contain invalid characters, the Remove function fails.
There is a way around this problem, however: using FTP to delete the misnamed files in the AS/400 IFS. To accomplish this, do the following:
1. Start an FTP session on your AS/400 by typing FTP on any command line.
2. Change the Name Format to 1 using the namefmt 1 FTP command. This tells FTP that you are using a directory naming structure rather than a library naming structure.
3. Either change the directory to the AS/400 IFS directory where your misnamed files reside by using the FTP Change Directory (CD) command, or enter a fully qualified path name on the next step.
4. Enter the FTP command DEL YourFileName to delete the file. Remember that, if you didnt use the CD command to set the directory to the location of the misnamed file, you need to enter the fully qualified path name on the DEL command. Also keep in mind that directory and file names are case-sensitive in some AS/400 filing systems, so take care when typing.
Now you know how to clean up all those misnamed files before anyone else finds
A Better Way to CSV
Looking for a way to create a comma-separated value (CSV) containing AS/400 physical file data? There are several methods for doing this, but heres a couple you may not have considered. The first uses a CL program and a REXX program to build the CSV. The second uses a simple Java program to accomplish the same thing. The Java program is a bit more flexible, but, for those of you not as familiar with Java as you might like to be or for those of you wanting to explore the benefits of REXX (which comes free on every AS400), the first method may prove just as useful.
In the first solution, you create a list of AS/400 PTFs and build the CSV file from that data. The CL program shown in Figure 3 overrides the standard input and output files to a couple of work files, runs the Display PTF (DSPPTF) command to build the list, and outputs the results to a work file. It then calls the REXX procedure shown in Figure 4. The REXX program builds the CSV in the QTEMP library. Notice that the first record created contains nothing but the files column headers. This is useful if you want to import this file into a spreadsheet that requires headers for identification.
Once the REXX procedure is finished, the CL program executes the Copy to Stream File (CPYTOSTMF) command to move the CSV to the /Home directory of the AS/400 Integrated File System (AS/400 IFS). You can modify this procedure to work with any file on your system and move it to any directory your AS/400 has access to. The downside to this program is that it uses hardcoded column header and field names. To avoid this, you may want to use the Java program CvtToCSV, which you can download from the MC Web site at www.midrangecomputing. com/mc. CvtToCSV generates a CSV file from any AS/400 physical file, and you can include column headers if you need them. Keep in mind that the data may not load correctly in some spreadsheets without some formatting on your part.
them!
Shannon ODonnell Senior Technical Editor
Midrange Computing
To use this program, execute it from a PC DOS prompt or from an AS/400 command line or CL program, passing into it the following:
The IP address of the AS/400 where the physical file resides
A valid AS/400 user ID and password
The name of the library where the physical file is stored
The name of the physical file
The name and path on the PC where the resulting CSV file should be placed
A value of TRUE or FALSE that indicates whether or not to trim trailing blanks
A value of TRUE or FALSE that indicates whether or not the first row of the CSV file should include column headers, such as in the following: When the Java program runs, it will connect to your AS/400, retrieve the database information, and build the CSV file in the directory you specified. By adding the AS/400 TCP/IP address (or host name) to the AS/400 constructor in the Java class, you can modify this program so it doesnt require as many parameters to be passed to it. And if you dont want any user interaction at all, you can hardcode all the parameters in the Java class and build either a DOS batch file or an AS/400 command and a CL program to execute the Java program. This is useful for those situations where you want the user to be able download AS/400 data without bugging you. If the user needs the flexibility of being able to enter any file name and library and you want to make this procedure more user-friendly, you can also build a Java GUI on this class to prompt the user for the parameters as required.
Alex Garrison
/****************************************************************************/
/* */
/* To compile: */
/* */
/* CRTCLPGM PGM(XXX/PTFLISTC) SRCFILE(XXX/QCLSRC) */
/* */
/* */
/****************************************************************************/
/* PGM : PTFLISTC */
/* DESC: LIST PTFS ON SYSTEM AND CALL REXX PROCEDURE TO BUILD COMMA */
/* SEPERATED FILE IN USER'S HOME DIRECTORY */
/****************************************************************************/
PGM
/* ATTEMPT TO CREATE THE WORK FILES IN QTEMP */
CRTPF FILE(QTEMP/PTFLIST) RCDLEN(132) SIZE(*NOMAX)
MONMSG MSGID(CPF0000)
/* OVERRIDE STANDARD INPUT AND OUTPUT FILES TO WORK FILES */
OVRDBF FILE(STDOUT) TOFILE(QTEMP/PTFLIST)
OVRDBF FILE(STDIN) TOFILE(QTEMP/PTFWRK)
/* DUMP THE LIST OF PTFFS TO A WORK FILE */
DSPPTF OUTPUT(*OUTFILE) OUTFILE(QTEMP/PTFWRK)
/* STARTS A REXX PROCEDURE */
STRREXPRC SRCMBR(PTFLISTR) SRCFILE(*LIBL/QREXSRC)
/* COPY THE PHYSICAL FILE TO A COMMA SEPARATED FILE IN THE IFS */
CPYTOSTMF +
FROMMBR('QSYS.LIB/QTEMP.LIB/PTFLIST.FILE/PT+
java CvtToCSV 111.222.333.444 MYUSRPRF MYPASSWORD LIBNAME FILENAME
C:FILENAME.TXT TRUE TRUE
C:FILENAME.TXT TRUE TRUE
FLIST.MBR') TOSTMF('HOME/PTFLIST.CSV') +
STMFOPT(*REPLACE) STMFCODPAG(*PCASCII)
DLTOVR FILE(*ALL)
DLTF FILE(QTEMP/PTFLIST)
MONMSG MSGID(CPF0000)
DLTF FILE(QTEMP/PTFWRK)
MONMSG MSGID(CPF0000)
ENDPGM /****************************************************************************/
/* To Compile: NO COMPILING REQUIRED. PROGRAM WILL BE INTERPRETED. */
/* */
/****************************************************************************/
/* pgm : ptflistr */
/* desc: Builds Comma Separated File of PTFs */
/****************************************************************************/
/* output column headers */
say '"System","LicPgm","PTFid","Status","Date"'
/* output specific columns of file */
do until scptfid = ''
parse linein 2 scdate 8 ,
51 scppid 58 ,
58 scptfid 65 ,
71 scstatus 91 ,
202 scsysnm 210
if (scptfid '') then
do
say '"'scsysnm'","'scppid'","'scptfid'","'scstatus'","'scdate'"'
end
end
exit
Figure 3: This CL program executes a REXX procedure to build a CSV file.
Figure 4: This REXX procedure builds the CSV file.
LATEST COMMENTS
MC Press Online