Joined: 09 Jul 2015 Posts: 7 Location: United States
Hi,
I have an input file that has numerous groups (number of groups varies). Each group has a header and a trailer. I want to put the number of records in each group on the group header record. I've seen it done for a single file header, and I've seen it done for group trailers, but I can't figure out how to do it for group headers.
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
Basically it'll be a variation of getting the number of records onto the file-header.
JOINKEYS, with the same DSN for both intput files. Specify SORTED,NOSEQCK on the JOINKEYS statement for F1.
On JNF1CNTL, extend the record (what that means exactly depends on whether fixed-length (easiest) or variable-length records) to include a GROUP ID (BEGIN = C'CHD' END = C'CFT' PUSH=(extendingplace:ID=N, where N is large enough to account for all your groups (N=number of digits)).
ON JNF2CNTL, extend to include the ID as above and the SEQ. If the current record is not a C'CFT', set the ID to binary-zeros (NZ). F2 will be sorted by default by the JOINKEYS for F2, and all the binary-zeros will be sorted together (and they will mismatch to F1).
Code:
JOIN MATCHED,F1
This will give all the matches, which will be the original trailers from F2 with the count, and all the unmatched F1s (which will be all the other data records).
In the main task, update the matched records (adjusting the count by two for group header and trailer) so that the header has the correct value.
That's approximately it.
If unsure, do it stage by stage (with test-data going to SYSOUT) and understand what changes are happening.
EDIT: Replace invented keywords by the actually existing ones.
Joined: 09 Jul 2015 Posts: 7 Location: United States
Thanks so much!!!
I had to modify it to 'extend' the files since data could appear anywhere in the 80 characters of the record. After much trial and error I ended up with:
I have a follow-up question. The file itself has a header record ('MHD') that I would like to add a count of the group headers to. Can that be included in the above sysin (so it is done in one pass) or would I need to do this separately?
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
I've no idea how I came up with UNSORTED or UNMATCHED, thanks magesh23586.
Christopher Horowitz,
If you already have a trailer on your file, then it is a simple application of a second count and similar application to the trailer.
If you don't already have a file trailer, you temporarily make one.
You need a new step, very short:
Code:
OPTION COPY,STOPAFT=1
INREC OVERLAY=(C'something unique to indicate trailer')
Output file to specify a little space, no DCB information (SORT will fill that in from the input dataset).
This new step can be run as part of the job, to a temporary dataset, or run as as a once-off to a permanent dataset which is regenerated when the RECFM/LRECL of the dataset changes.
This way you don't need to "hard-code" any record lengths.
In the processing you set the "key" to match your actual header, and use the count (adjusting per header/trailer number of records as necessary).
If you need to count the groups, or count only the data records (likely), that can be achieved also.
Joined: 09 Jul 2015 Posts: 7 Location: United States
Thanks Bill.
I actually do just want the count of groups. My thought was to include the ID in the REFORMAT, and then use the ID value of the last CFT record and put it in the BUILD. I just couldn't get it to work.
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
If you use WHEN=GROUP to identify the group trailer, and PUSH the ID-previoyusly-specified by identifying each group-trailer and use RECORDS=2, when you get the file trailer, you will have the final ID from the groups, which is the count of the groups.
If you have a problem with that, post the code you have and we can knock it into shape. We'll assume RECFM=FB and LRECL=80.
The 8Z gives you eight binary zeros, which is used to match to the file header. I've simplified the conditions where possible. IFTHEN=(WHEN=(logicalexpression) operates like a COBOL EVALUATE. So when an IFTHEN=(WHEN=(logicalexpression) is true, no futher IFHTHEN=(WHEN=(logicalexpression) will be tested for that record, so some of your NEs disappear. You don't need the match-marker (the ? on the REFORMAT statement) for this task. The only unmatched records are data-records. All the Matched records (the Bs) are header records of one type or the other. So simply test for the type of header.