JCL

PUSH unique ID and SEQ number using IFTHEN

PUSH defines the input field, sequence number, or identifier that will be overlaid for each group’s records. For fixed-length records, the first input and output data byte start at position 1. For variable-length records, the first input and output data byte start at position 5, after the RDW in positions 1-4.

PUSH=(c:item,…)

You can use the following in PUSH: 

c Specifies the output position (column) to be overlaid. If you do not specify c: for the first item, it defaults to 1:. If you do not specify c: for any other item, it starts after the previous item. You can specify items in any order and overlap output columns. c can be 1 to 32752. If you specify an item that extends the output record beyond the end of the input record, the record length is automatically increased to that length, and blanks are filled in on the left as needed. For variable-length records, the RDW length is increased to correspond to the larger record length after all of the items are processed. Missing bytes in specified input fields are replaced with blanks so the padded fields can be processed.

p,m Specifies a field in the first input record of each group to be propagated to every record of the group. p specifies the starting position of the field in the input record and m specifies its length. A field must not extend beyond position 32752.

ID=n Specifies a printable Zoned Decimal (ZD) identifier n bytes long. It will be added to every record of each group. For the first group, the identifier will start at 1. and for each subsequent group, it will be increased by 1. The number n can be from 1 to 15.

SEQ=n Specifies a printable ZD sequence number n bytes long. It will be added to every record of each group. For the first record of each group, the identifier will start at 1. and for each subsequent record, it will be increased by 1. The number n can be from 1 to 15.

Let’s say each transaction at a store generates a series of unlike records. All the records are collected in a file that needs to be sorted by date and register number, WHEN=GROUP can generate appropriate sort keys for each record in the group.

For detailed information on syntax and a better understanding of IFTHEN usage click here

Example of PUSH – ID – SEQ

A header record (code ‘H’) with a register number and date, detailed SKU records (code ’S’) with an SKU number, unit price, and quantity, and a trailer total record (code ’T’) are generated for each transaction. A file with 20-byte fixed-length records for three transactions might look like

 H 0003 2008/08/17
S 872567 0010.22 001
S 510945 0001.99 003
S 734018 0003.98 002
T 0024.15
H 0005 2008/08/16
S 013298 0000.69 004
S 510945 0017.03 001
T 0019.79
H 0002 2008/08/17
S 212134 0003.49 003
T 0010.47

INREC WHEN=GROUP can be used with BEGIN to identify a header record starting a group and END to identify a trailer record ending a group. PUSH extends each record by placing the date and register number from the header record at the end of each record in the group, followed by a 5-byte group number and a 3-byte record sequence number. All the records in a group will sort together.

 INREC IFTHEN=(WHEN=GROUP,BEGIN=(1,1,CH,EQ,C’H’),
 END=(1,1,CH,EQ,C’T’),
 PUSH=(21:8,10,31:3,4,35:ID=5,SEQ=3))

Output

 H 0003 2008/08/17 2008/08/17000300001001
S 872567 0010.22 0012008/08/17000300001002
S 510945 0010.99 0032008/08/17000300001003
S 734018 0003.98 0022008/08/17000300001004
T 0024.15 2008/08/17000300001005
H 0005 2008/08/16 2008/08/16000500002001
S 013298 0000.69 0042008/08/16000500002002
S 510945 0017.03 0012008/08/16000500002003
T 0019.79 2008/08/16000500002004
H 0002 2008/08/17 2008/08/17000200003001
S 212134 0003.49 0032008/08/17000200003002
T 0010.47 2008/08/17000200003003

The new PUSH data will sort the records

SORT FIELDS=(21,10,CH,A,31,4,CH,A,35,8,CH,A)

The data added by PUSH can be eliminated from the output data with a simple OUTREC statement for the original 20 bytes of the record. It can be eliminated by specifying LRECL=20 on the SORTOUT DD statement. It will create the following correctly sorted output.

 H 0005 2008/08/16
S 013298 0000.69 004
S 510945 0017.03 001
T 0019.79
H 0002 2008/08/17
S 212134 0003.49 003
T 0010.47
H 0003 2008/08/17
S 872567 0010.22 001
S 510945 0001.99 003
S 734018 0003.98 002
T 0024.15

Scenario -1

If desired, a simple report can be created using OUTFIL IFTHEN to identify each different record type, format it appropriately, and remove the data added by PUSH. SECTIONS is used to generate a report header for each transaction.

OUTFIL SECTIONS=(35,5,HEADER3=(’ DATE REG# ID’),SKIP=L),
IFTHEN=(WHEN=(1,1,CH,EQ,C’H’), FOR HEADER RECORDS:
BUILD=(21,10,2X,3,4,2X,3,4,2X,35,5)), DATE, REG NUM, TRAN ID
IFTHEN=(WHEN=(1,1,CH,EQ,C’S’),
BUILD=(C’SKU#: ’,3,6,C’ PRICE: $’,10,7,
C’ QUANTITY: ’,18,3)),
IFTHEN=(WHEN=(1,1,CH,EQ,C’T’), FOR TRAILER RECORDS:
BUILD=(C’TOTAL: $’,3,7))

The report produced is

 DATE REG# ID
 2008/08/16 0005 00002
 SKU#: 013298 PRICE: $0000.69 QUANTITY: 004
 SKU#: 510945 PRICE: $0017.03 QUANTITY: 001
 TOTAL: $0019.79
 DATE REG# ID
 2008/08/17 0002 00003
 SKU#: 212134 PRICE: $0003.49 QUANTITY: 003
 TOTAL: $0010.47
 DATE REG# ID
 2008/08/17 0003 00001
 SKU#: 872567 PRICE: $00010.22 QUANTITY: 001
 SKU#: 510945 PRICE: $0001.99 QUANTITY: 003
 SKU#: 734018 PRICE: $0003.98 QUANTITY: 002
 TOTAL: $0024.15

Scenario -2

This example illustrates how you can SORT and INCLUDE groups of FB records depending on a value in the first record of each group. We propagate the value in the first record of the group to every record of the group, SORT and INCLUDE on the value, and then remove it. 

INREC IFTHEN=(WHEN=GROUP,BEGIN=(2,4,CH,EQ,C’RPT.’),
              PUSH=(31:6,8))
OPTION EQUALS
SORT FIELDS=(31,8,CH,A)
OUTFIL INCLUDE=(31,8,CH,EQ,C’FRANK’,OR,
                31,8,CH,EQ,C’SRIHARI’),BUILD=(1,30)

The 30-byte FBA input records might look like this: 

1RPT.SRIHARI
 LINE  1 FOR REPORT 1
 LINE  2 FOR REPORT 1
...
1RPT.VICKY
 LINE  1 FOR REPORT 2
 LINE  2 FOR REPORT 2
...
1RPT.FRANK 
 LINE  1 FOR REPORT 3
 LINE  2 FOR REPORT 3
...
1RPT.DAVID
 LINE  1 FOR REPORT 4
 LINE  2 FOR REPORT 4
 ...

Each report starts with ‘RPT.reptname’ in positions 2-13. In the output data set we only want to include records for reports with specific reptname values, and the reptname values we want can change from run to run. We also want to sort by the reptname values in ascending order. For this example, let’s say we just want the SRIHARI and FRANK reports. 

We use an IFTHEN WHEN=GROUP clause to propagate the reptname value to each record of the group. BEGIN indicates a group starts with ‘RPT.’ in positions 2-5. PUSH overlays the reptname value from the first record of the group (the ‘RPT.reptname’ record) at positions 31-38 (after the end of the record) in each record of the group including the first. After the IFTHEN GROUP clause is executed, the intermediate records look like this: 

1RPT.SRIHARI
 LINE  1 FOR REPORT 1   SRIHARI
 LINE  2 FOR REPORT 1   SRIHARI
 …                      SRIHARI
1RPT.VICKY              VICKY
 LINE  1 FOR REPORT 2   VICKY
 LINE  2 FOR REPORT 2   VICKY
 …                      VICKY
1RPT.FRANK              FRANK
 LINE  1 FOR REPORT 3   FRANK
 LINE  2 FOR REPORT 3   FRANK
 …                      FRANK
1RPT.DAVID              DAVID
 LINE  1 FOR REPORT 4   DAVID
 LINE  2 FOR REPORT 4   DAVID
 …                      DAVID

Note that the records of each group have the reptname value from the first record of that group in positions 31-38. 

We use a SORT statement to sort ascending on the reptname in positions 31-38. We use the EQUALS option to ensure that records in the same group (that is, with the same reptname value) are kept in their original order. After the SORT statement is executed, the intermediate records look like this: 

1RPT.DAVID               DAVID
 LINE  1 FOR REPORT 4    DAVID
 LINE  2 FOR REPORT 4    DAVID
 …                       DAVID
1RPT.FRANK               FRANK
 LINE  1 FOR REPORT 3    FRANK
 LINE  2 FOR REPORT 3    FRANK
 …                       FRANK
1RPT.SRIHARI             SRIHARI
 LINE  1 FOR REPORT 1    SRIHARI
 LINE  2 FOR REPORT 1    SRIHARI
 …                       SRIHARI
1RPT.VICKY               VICKY
 LINE  1 FOR REPORT 2    VICKY
 LINE  2 FOR REPORT 2    VICKY
 ….                      VICKY

We use an OUTFIL statement to only INCLUDE the records with a reptname of FRANK or SRIHARI in positions 31-38, and to remove the reptname from positions 31-38 so the included output records will be identical to the input records. After the OUTFIL statement is executed, the final output records look like this: 

1RPT.FRANK
 LINE  1 FOR REPORT 3
 LINE  2 FOR REPORT 3
 ...
1RPT.SRIHARI
 LINE  1 FOR REPORT 1
 LINE  2 FOR REPORT 1

Scenario -3

This example illustrates how you can INCLUDE specific relative records from groups of VB records. We insert a sequence number between the RDW and the first data byte of each record. The sequence number restarts at 1 for the first record in each group. We INCLUDE the sequence number and then remove it.

OPTION COPY OUTREC IFTHEN=(WHEN=INIT,BUILD=(1,4,8:5)), 
IFTHEN=(WHEN=GROUP,BEGIN=(8,5,CH,EQ,C'PAGE:'), 
        PUSH=(5:SEQ=3)) 
OUTFIL INCLUDE=(5,3,ZD,EQ,2,OR,5,3,ZD,EQ,3), 
        BUILD=(1,4,5:8)

The VB input records might look like this:

Len|Data 
12|PAGE: 1 
22|LINE 1 OF REPORT A 
22|LINE 2 OF REPORT A 
22|LINE 3 OF REPORT A 
22|LINE 4 OF REPORT A
  |... 
12|PAGE: 2 
23|LINE 66 OF REPORT A 
23|LINE 67 OF REPORT A 
23|LINE 68 OF REPORT A 
23|LINE 69 OF REPORT A
  |... 
12|PAGE: 3 
24|LINE 131 OF REPORT A 
24|LINE 132 OF REPORT A 
24|LINE 133 OF REPORT A 
24|LINE

Note that positions 5-7 are blank and the ‘PAGE:’ characters have been shifted over to positions 8-12.

We use an IFTHEN WHEN=GROUP clause to put a 3-byte sequence number in each record. BEGIN indicates a group starts with a record that has ‘PAGE:’ in positions 8-12. PUSH overlays a 3-byte sequence number at positions 5-7 of each record. The sequence number starts at 1 for the ®rst record of a group and is incremented by 1 for each subsequent record of the group. After the IFTHEN GROUP clause is executed, the intermediate records look like this:

Len|Data 
15|001PAGE: 1 
25|002LINE 1 OF REPORT A 
25|003LINE 2 OF REPORT A 
25|004LINE 3 OF REPORT A 
25|005LINE 4 OF REPORT A
  |006... 
15|001PAGE: 2 
26|002LINE 66 OF REPORT A 
26|003LINE 67 OF REPORT A 
26|004LINE 68 OF REPORT A 
26|005LINE 69 OF REPORT A
  |006... 
15|001PAGE: 3 
27|002LINE 131 OF REPORT A 
27|003LINE 132 OF REPORT A 
27|004LINE 133 OF REPORT A
27|005LINE 134 OF REPORT A
  |006…

Note that the records in each group are numbered starting with 001 for the ®rst record of each group. The records we want have sequence numbers 002 and 003. We use an OUTFIL statement to only INCLUDE the records with sequence number 002 or 003, and to remove the sequence numbers so the included output records will be identical to the input records. After the OUTFIL statement is executed, the ®nl output records look like this: 

Len|Data 
22|LINE 1 OF REPORT A 
22|LINE 2 OF REPORT A 
23|LINE 66 OF REPORT A 
23|LINE 67 OF REPORT A 
24|LINE 131 OF REPORT A 
24|LINE 132 OF REPORT A

Scenario -4

This example illustrates how you can INCLUDE groups of FB records between a header and a trailer. We add an ID after the end of each record to indicate whether it’s part of a group or not, INCLUDE on the ID, and then remove it.

OPTION COPY 
OUTREC IFTHEN=(WHEN=GROUP,BEGIN=(1,3,CH,EQ,C'HDR'), 
END=(1,3,CH,EQ,C'TRL'),PUSH=(31:ID=1)) 
OUTFIL INCLUDE=(31,1,CH,NE,C' '),BUILD=(1,30)

The 30-byte FB input records might look like this:

C33 Not in a group 
HDR Start Group 1 
A01 Group 1 record 
B02 Group 1 record 
C03 Group 1 record 
TRL End Group 1 
R24 Not in a group 
T02 Not in a group 
HDR Start Group 2 
D04 Group 2 record 
E05 Group 2 record 
TRL End Group 2 
F97 Not in a group

In the output data set we only want to include groups of records that start with ‘HDR’ and end with ‘TRL’. 

We use an IFTHEN WHEN=GROUP clause to put a non-blank character in each record that is part of a group. BEGIN indicates a group starts with a record that has ‘HDR’ in positions 1-3. END indicates a group ends with a record that has ‘TRL’ in positions 1-3. PUSH overlays a 1-byte ID character at position 31 in each record of a group (after the end of the record). After the IFTHEN GROUP clause is executed, the intermediate records look like this:

C33 Not in a group 
HDR Start Group 1 1 
A01 Group 1 record 1 
B02 Group 1 record 1 
C03 Group 1 record 1 
TRL End Group 1 1 
R24 Not in a group 
T02 Not in a group 
HDR Start Group 2 2 
D04 Group 2 record 2 
E05 Group 2 record 2 
TRL End Group 2 2 
F97 Not in a group

Note that the records within a group have a non-blank character in position 31 whereas the records outside groups have a blank character in position 31. The ID starts at 1 for the first group and is incremented by 1 for each subsequent group. Since we are only allowing one character for the ID, when the ID counter gets to 10, a ‘0’ will appear in position 31. That’s fine since we are just looking for a nonblank to indicate a record within a group, or a blank to indicate a record outside of a group. We use an OUTFIL statement to only INCLUDE records with a non-blank in position 31, and to remove the ID character so the included output records will be identical to the input records. After the OUTFIL statement is executed, the final output records look like this: 

HDR Start Group 1 
A01 Group 1 record 
B02 Group 1 record 
C03 Group 1 record 
TRL End Group 1 
HDR Start Group 2 
D04 Group 2 record 
E05 Group 2 record 
TRL End Group 2

Scenario -5

This example illustrates how you can INCLUDE groups of VB records between a header and a trailer. It’s similar to Example 16, but here the records are variable-length. For the FB records, we could add the ID after the end of each record and then remove it without changing the records. But we can’t add the ID at the end of each VB record because that would pad all of the records to a fixed length. So, instead we insert the ID between the RDW and the first data byte of each record, and later remove it.

OPTION COPY 
OUTREC IFTHEN=(WHEN=INIT,BUILD=(1,4,6:5)),    
       IFTHEN=(WHEN=GROUP,BEGIN=(6,3,CH,EQ,C'HDR'),  
       END=(6,3,CH,EQ,C'TRL'),PUSH=(5:ID=1)) 
OUTFIL INCLUDE=(5,1,CH,NE,C' ‘),BUILD=(1,4,5:6)

The VB input records might look like this:

Len|Data 
23|C33 Not in a group 
23|HDR Start Group 1 
25|A01 Group 1 record 
25|B02 Group 1 record 
25|C03 Group 1 record 
21|TRL End Group 1 
23|R24 Not in a group 
23|T02 Not in a group 
23|HDR Start Group 2 
25|D04 Group 2 record 
25|E05 Group 2 record 
21|TRL End Group 2 
25|F97 Not in a group

In the output data set we only want to include groups of records that start with ‘HDR’ and end with ‘TRL’. We use an IFTHEN WHEN=INIT clause to reformat each record so it has room for the ID byte between the RDW and the first data byte. After the WHEN=INIT clause is executed, the intermediate records look like this:

Len|Data 
24| C33 Not in a group 
24| HDR Start Group 1 
26| A01 Group 1 record 
26| B02 Group 1 record 
26| C03 Group 1 record 
22| TRL End Group 1 
24| R24 Not in a group 
24| T02 Not in a group 
24| HDR Start Group 2 
26| D04 Group 2 record 
26| E05 Group 2 record 
22| TRL End Group 2 
26| F97 Not in a group

Note that position 5 is blank and the ‘HDR’ and ‘TRL’ characters have been shifted over to positions 6-8.

We use an IFTHEN WHEN=GROUP clause to put a non-blank character in each record that is part of a group. BEGIN indicates a group starts with a record that has ‘HDR’ in positions 6-8. END indicates a group ends with a record that has ‘TRL’ in positions 6-8. PUSH overlays a 1-byte ID character at position 5 in each record of a group. After the IFTHEN GROUP clause is executed, the intermediate records look like this:

Len|Data 
24| C33 Not in a group 
24|1HDR Start Group 1 
26|1A01 Group 1 record 
26|1B02 Group 1 record 
26|1C03 Group 1 record 
22|1TRL End Group 1 
24| R24 Not in a group 
24| T02 Not in a group 
24|2HDR Start Group 2 
26|2D04 Group 2 record 
26|2E05 Group 2 record 
22|2TRL End Group 2 
26| F97 Not in a group

Note that the records within a group have a non-blank character in position 5 whereas the records outside groups have a blank character in position 5. The ID starts at 1 for the first group and is incremented by 1 for each subsequent group. Since we are only allowing one character for the ID, when the ID counter gets to 10, a ‘0’ will appear in position 5. That’s fine since we are just looking for a non-blank to indicate a record within a group, or a blank to indicate a record outside of a group. We use an OUTFIL statement to only INCLUDE records with a non-blank in position 5, and to remove the ID character so the included output records will be identical to the input records. After the OUTFIL statement is executed, the final output records look like this: 

Len|Data 
23|HDR Start Group 1 
25|A01 Group 1 record 
25|B02 Group 1 record 
25|C03 Group 1 record 
21|TRL End Group 1 
23|HDR Start Group 2 
25|D04 Group 2 record 
25|E05 Group 2 record 
21|TRL End Group 2

Read JCL blogs: Click Here SYNCSORT Manual: Click Here

Admin

Share
Published by
Admin

Recent Posts

Increase Transparency and Collaboration Product Backlog

A well-maintained product backlog is crucial for successful product development. It serves as a single…

4 weeks ago

Product Backlog – Incremental value to the customer

Incremental value to the customer refers to the gradual delivery of small, functional parts of…

4 weeks ago

Product Market, Customer’s Desire, Need, and Challenges

A Product Market refers to the group of potential customers who might be interested in…

1 month ago

PAL-EBM Professional Agile Leadership – EBM Certification

The Professional Agile Leadership - Evidence-Based Management (PAL-EBM) certification offered by Scrum.org is designed for…

4 months ago

PAL I Professional Agile Leadership Certification

The Professional Agile Leadership (PAL I) certification, offered by Scrum.org, is designed to equip leaders…

4 months ago

Scrum Master Certification: CSM, PSM, SSM

Choosing the right Scrum Master Certification depends on your current experience and career goals. If…

6 months ago