Generate a report using DFSORT - mainframe

I have a task to write a JCL job invoking ICETOOL/DFSORT to generate a report. The report takes a VSAM KSDS as input and generates a list of bank branches.
Each record in the BRANCHES KSDS is of the form
• 4-byte binary unsigned integer representing a 6-digit decimal branch sortcode (e.g. 420101)
• 1-byte EBCDIC flag: ◦ EBCDIC 'A' means the branch is owned by ZeusBank and all its accounts are held in the ACCOUNTS KSDS
◦ EBCDIC 'B' means the branch is not owned by ZeusBank so we do not hold its account information in the ACCOUNTS KSDS
• 32-byte EBCDIC character branch name (e.g. “ZEUSBANK FOOFORD BAR STREET” or “OTHERBANK QUUXHAM BAZ ROAD”), blank padded on the right.
The report should look like this
I'm pretty new to JCL so please forgive if the question is simple. Thanks.

You can try this:
//STEPSORT EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SORTIN DD DSN=DATASETNAME
//SORTOUT DD SYSOUT=*
//SYSIN DD *
SORT FIELDS=(5,1,CH,A)
OUTFIL HEADER2=(1:C'LIST OF WHATEVER BANK',4/,
1:C'SORTCODE',10:C'FLAG',15:C'BRANCH',/,
1:C'--------',10:C'----',15:C'------'),
BUILD=(1:1,4,BI,TO=ZD,LENGTH=6,10:5,1,15:6,32)
/*

Related

Add months but the parameter is from the data JCL

I have data like this
----+----1----+----2----+----3----+--
000000002320110328087YY01200000020124
I want to add the months from column 11-18, with the value from 24-26
I am thinking about the outrec field is like this
11,8,Y4T,ADDMONS,24,3,TOGREG=Y4T(-)
But when I try it , it give rc=0016, because of the operand error ,
I am thinking about store the value of 24,3 to a variable then i put it to variable , but i dont know if JCL can provide that .. anyone can help?
Notes : i use dfsort , not icetool
and i dont want to hardcode it because i already try 11,8,Y4T,ADDMONS,+12,TOGREG=Y4T(-), and it works but if can , iwant to replace the "+12" with the value from column 24-26
The syntax diagram for ADDMONS for your case is shown as:
p,m,Y4T,ADDMONS,p,m,f,TOGREG=Y4T(-)
You're missing the f subparameter. Since the number of months to add is a series of digits, the format would be UFF. I ran this sort job:
//SORT#010 EXEC PGM=ICEMAN
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SORTIN DD *
000000002320110328087YY01200000020124
/*
//SORTOUT DD SYSOUT=*
//SYSIN DD *
SORT FIELDS=COPY
OUTREC FIELDS=(11,8,Y4T,ADDMONS,24,3,UFF,TOGREG=Y4T(-))
/*
The result in SORTOUT is:
2012-03-28
Is this what you wanted?
I'm not aware of a way to do this with plain DFSORT.
For instance PARSE would not work, because it would fail to resolve %2:
INREC PARSE=(%1=(ABSPOS=11,FIXLEN=8),
%2=(ABSPOS=24,FIXLEN=3)),
BUILD=(%1,Y4T,ADDMONS,+%2,TOGREG=Y4T(-))
You might want to look at sort exits if you'd like to go with DFSORT.
You get a bad return code because DFSORT doesn't know how to interpret the three bytes you gave it with 24,3.
You should use : 11,8,Y4T,ADDMONS,24,3,ZD,TOGREG=Y4T(-)
The ZD that I have inserted means : Zoned Decimal. It corresponds to a PIC 9 USAGE DISPLAY in Cobol.
You can interpret COMP-3 with PD and COMP-5 or BINARY with BI.

copying and pasting information between datasets

How to copy data fully from one dataset to another dataset when one of the dataset consists of dots as shown bllow ?
The dots you are seeing are most likely undisplayable data so a utility is the best bet.
There are many ways to move data around on z/OS. If you are simply trying to copy an existing dataset to another to make a copy you could use a batch utility like IEBGENER. Here is some sample JCL
//IEBGENER JOB (CCCCCCCC),'HOGSTROM',
// MSGLEVEL=(1,1),
// MSGCLASS=O,
// CLASS=A,
// NOTIFY=&SYSUID
//*
//*----------------------------------------------------------
//* IEBGENER
//*----------------------------------------------------------
//GENER02 EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DSN=USER1.TEST.DATA,DISP=SHR
//SYSUT2 DD DSN=USER1.TEST.ODATA,DISP=(,CATLG,DELETE),
// UNIT=SYSDA,SPACE=(CYL,5,RLSE),DCB=USER1.TEST.DATA
//SYSIN DD DUMMY
//
You could also use online tools like ISPF Option 3.2 to create the new dataset
and 3.3 to move / copy it.
It's not clear to me what question you're asking, or why you'd do such a thing by hand. I'd instead suggest using one of the built in z/OS tools. Specifically, IEBCOPY.
//COPYLIKE JOB MSGCLASS=H,TIME=1440
//COPYREP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DSN=SYS1.LPALIB,DISP=SHR,UNIT=3390,VOL=SER=D83RL2
//SYSUT2 DD DSN=SYS1.LPALIB.ORIG,
// LIKE=SYS1.LPALIB,
// DISP=(NEW,KEEP),VOL=SER=D83RL2,UNIT=3390
//SYSIN DD *
/*
Also, as a note, the source dataset doesn't consist of dots, it consists of undisplayable data.

Setting PATH in IEBGENER from file

I'm trying to set the PATH parameter in a IEBGENER step in a JCL from a file. But I can't seem to get it to work.
Here is what the original step, that works just fine, looks like:
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD *
Some text
//SYSUT2 DD PATH='/local/Folder1/File1',
// PATHDISP=(KEEP,KEEP),
// PATHOPTS=(OWRONLY,OCREAT,OEXCL),
// PATHMODE=(SIRUSR,SIWUSR)
What I want to do is set the PATH parameter in SYSUT2 from a file that is written in some previous step. Something like this:
BROWSE TEST.FILE1 Line 0000000000 Col 001 080
Command ===> Scroll ===> CSR
********************************* Top of Data **********************************
TPATH='/local/Folder1/File1'
******************************** Bottom of Data ********************************
//SETPATH SET DSN=TEST.FILE1,DISP=SHR
//*
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD *
Some text
//SYSUT2 DD PATH='&TPATH',
// PATHDISP=(KEEP,KEEP),
// PATHOPTS=(OWRONLY,OCREAT,OEXCL),
// PATHMODE=(SIRUSR,SIWUSR)
This of course complains about no variable TPATH in the JCL, which logically makes sense as it can't find the variable name in the JCL.
Also tried putting the entire SYSUT2 in a separate file, but without success.
A "good enough" compromise would be to concatenate a file prefix with a date and time parameter, but that would only work in production when the job is run via a scheduler (with OPCSCAN or similar). Not in test where I submit the job myself, or is it possible to do that without a scheduler?
'/local/Folder1/File' & iDate & iTime -- You get the point.
Any ideas much appreciated!
One way to do this would be to write the SYSUT2 DD statement to a member in a separate PDS or PDSE, then INCLUDE that member in your IEBGENER step. The separate PDS or PDSE must be specified in a JCLLIB statement.
You could also run BPXBATCH and use cp instead of IEBGENER to copy your data.
If you have the Dovetail Technologies Co:Z Toolkit installed, fromdsn might be what you're looking for.

How to create a member in an existing pds using jcl

I've used the below jcl:
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DUMMY,RECFM=FB,LRECL=80
//SYSUT2 DD DSN=RK.MYDIR.FILES(NEW1),DISP=(SHR)
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
I was able to create it. But i can't understand the code here. Is there any possibility to create using IEFBR14. If not this is the nly way. Please kindly explain me the code. Thank you
It can't be done with IEFBR14
IEBCOPY is more appropriate:
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp?topic=/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBCOPY.htm
This is the reference which helps explain IEBGENER:
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp?topic=/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBGENER.htm
If you're interested in the reason why, understand that IEFBR14 doesn't actually open any of the DD statements you code in your JCL. Rather, it's just a shorthand way to drive the system allocation (and deallocation) routines. Indeed, if you were to look at an assembler listing of iEFBR14, you'd find it's only two instructions: set the R15 return code to zero, and exit.
With batch processing, the idea is that the system (JES plus the batch initiator) should do a lot of the work before an application even starts. Thus, if you allocate a new dataset, or reference (say) a tape device that takes time for the operator to mount, the system does all this for you before your program even starts. IEFBR14 is a convenient way to use the system allocation routines to allocate files using these capabilities of JCL.
But there's a catch when it comes to accessing PDS datasets in JCL, like you're trying to do.
When you specify DSN(MEMBER) syntax in JCL, the allocation routines don't particularly care about the MEMBER part - turns out, this isn't a function of the initiator, but is instead implemented in OPEN/CLOSE. In your example, allocation verifies that the dataset exists (since you coded DISP=SHR), and when a program OPENs the DD statement, the OPEN routines automatically issue BPAM FIND/POINT/STOW to get you to the PDS member you specified. This is how your PDS member gets created, and so you need to use a program that actually OPENs the file (IEBGENR, IEBUPDTE, IEBCOPY, IDCAMS, etc would all work).
One small unrelated comment is that you might want to be careful about updating datasets (especially PDS) using DISP=SHR. If you manage to get the timing wrong, two of these jobs could in theory run at exactly the same time, and this would likely cause corruption to your dataset. Unless you're certain you're the only task accessing the PDS, it's safer to use DISP=OLD in this case.
If you'd like to create multiple members at once, I suggest IEBUPDTE.
From IBM:
This basic example uses IEBUPDTE to add two JCL procedures to the data set named MY.PROCLIB:
//ADDPROC1 JOB 1,SMCHUGH,MSGCLASS=X
// EXEC PGM=IEBUPDTE
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DISP=OLD,DSN=MY.PROCLIB
//SYSUT2 DD DISP=OLD,DSN=MY.PROCLIB
//SYSIN DD DATA
./ ADD LIST=ALL,NAME=MYJOB1
//STEP1 EXEC=SUZNX1
//PRINT DD SYSOUT=A
// (more JCL for MYJOB1)
//SYSUDUMP DD SYSOUT=* (last JCL for MYJOB1)
./ REPL LIST=ALL,NAME=LASTJOB
//LIST EXEC PGM=SUZNLIST
// (more JCL for this procedure)
//* LAST JCL STATEMENT FOR LASTJOB
./ ENDUP
/*
This creates one new member, MYJOB1, but you can see that it can also replace members (LASTJOB).
http://publib.boulder.ibm.com/infocenter/zos/basics/topic/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBUPDTE.htm
If you are copying the contents of a DSN into the new member, use IEBGENER.
To set the attributes of the new DSN dynamically use the LIKE parameter.
For example (using Mikes example above)
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset
//SYSUT2 DD DISP=(,CATLG,DELETE),DSN=your.output.dataset,
// LIKE=your.input.dataset
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY <-- no CONTROL statements
The LIKE attribute lets you easily create a new dataset, using the attributes of the dataset you specify, I also changed the disposition to reflect what a new DSN should be set to.
Warning! -- in re using IEBGENER with SYSUT2 DD DSN=PDS(MEMBER): Don't forget to specify the MEMBER name -- if you do, IEBGENER will overwrite your PDS from the beginning with whatever it finds in SYSUT1, starting with ruining your PDS directory!
The IEBGENER utility is used to copy a single file.
The SYSUT1 DD name is used to supply the INPUT or file to be copied from.
The SYSUT2 DD name is the OUTPUT file.
The SYSIN DD provides the CONTROL statements (if any).
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset
//SYSUT2 DD DISP=SHR,DSN=your.output.dataset
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY <-- no CONTROL statements
Note that the file/dataset can be a sequential dataset or a member of a partitioned dataset.
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset(member)
//SYSUT2 DD DISP=SHR,DSN=your.output.dataset(member)

Can we add symbolic parameters in PDS members used in cataloged procedures?

I have JCL, which is executing one catalog procedure.
In catalog procesdure one COBOL-DB2 pgm is being executed.
Below is my JCL
//A JOB (#),'CALL DB2',NOTIFY=&SYSUID
//JS010 EXEC TESTPROC
Below is my TESTPROC
//TESTPROC
//PS010 EXEC PGM=IKJEFT01,,DYNAMNBR=20
//STEPLIB DD DSN=TEST.LOADLIB,DISP=SHR
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD DSN=TEST.PDS(TESTPGM),
// DISP=SHR
//SYSOUT DD SYSOUT=*
below is my SYSTIN data --TESTPGM
DSN SYSTEM(TEST)
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
My query is can I use symbolic parameters in place of TESTPGM and TESTPLAN in SYSTIN data member TESTPGM?
Regards,
Saisha :)
As mentioned below you could have the PDS Member name become a symbolic value and then define each member in the PDS to point to a different program. Using your JCL as an example:
//TESTPROC PROC MYPGM=
//PS010 EXEC PGM=IKJEFT01,,DYNAMNBR=20
//STEPLIB DD DSN=TEST.LOADLIB,DISP=SHR
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD DSN=TEST.PDS(&MYPGM),
// DISP=SHR
//SYSOUT DD SYSOUT=*
In the above example your EXEC statement would envoke the proc as:
//JS010 EXEC TESTPROC,MYPGM=TESTPGM
Another option, you could over-ride the SYSTSIN DD directly as follows:
//A JOB (#),'CALL DB2',NOTIFY=&SYSUID
//JS010 EXEC TESTPROC
//PS010.SYSTSIN DD *
DSN SYSTEM(TEST)
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
/*
//
One other suggestion...
In your final implementation you might want to consider separating the
DSN SYSTEM(TEST)
from the
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
The reason is that you may find you want to run the program in multiple DB2 environments, not just SYSTEM(TEST). To do this, simply add another parameter DB2SYS= and modify as follows:
//TESTPROC PROC DB2SYS=MYTEST,MYPGM=
...
//SYSTSIN DD DSN=TEST.PDS(&DB2SYS),DISP=SHR
// DD DSN=TEST.PDS(&MYPGM),DISP=SHR
where PDS Member MYTEST has the DSN SYSTEM(TEST) statement already coded.
The short answer is no. If you have symbolic parameters in the control cards in the PDS your SYSTSIN DD statement references, they (the symbolic parameters) will not be resolved.
One way around this is to have a separate program, executing in a separate step within your procedure prior to your PS010 step, that takes in parameters and text and writes a temporary file. The symbolic parameters will be resolved in that program's PARM=.
//PS001 EXEC PGM=LOADPARM,PARM='DSN SYSTEM(&DSNSYS)'
//SYSPRINT DD SYSOUT=*
//OUTPUT01 DD DISP=(,PASS),
// DSN=&&DSNSYS,
// AVGREC=U,
// LRECL=80,
// RECFM=FB,
// SPACE=(80,1)
//****
The hypothetical program LOADPARM would simply take its input parm and write it to OUTPUT01, being careful to pad it on the right with blanks. In PS010 you would then have a SYSTSIN that looks like...
//SYSTSIN DD DISP=(OLD,DELETE),DSN=&&DSNSYS
// DD DISP=SHR,DSN=TEST.PDS(TESTPGM)
...where the TESTPGM member looks like...
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
In this manner, your cataloged procedure is ignorant of which DB2 subsystem it is accessing. That information is supplied in the execution JCL with the DSNSYS symbolic parameter.
There are other ways to approach this problem, for instance you could have a symbolic parameter that resolves to a known member in a shared PDS, having one member per DB2 subsystem.
Nope, we cant use the symbolic parameters inside SYSTSIN. Instead of bifurcating the SYSTSIN card into two and generalizing the DB2 subsytem i prefer to maintain separate test datacards with symbolic parameter for that member name and switch it whenever needed.
But the automating the DB2 subsystem may not result desired values all the times. Anyhow thats good effort made.

Resources