Report totals are the numbers at the end of a report (or after each group) that summarize your data: how many records were written, or the sum (or min/max/avg) of a numeric field. In DFSORT OUTFIL you put these in the report trailer (TRAILER1) for a single grand total at the end, or in the section trailer (TRAILER3) when using SECTIONS for subtotals after each control-break group. You can either generate a new trailer line with TRAILER1= (or TRAILER3=) using COUNT= for record count and TOTAL= (or TOT=) for the sum of a numeric field, or update an existing trailer record in your input file using IFTRAIL with TRLID= and TRLUPD=. This page covers COUNT=, TOTAL=, TRAILER1, TRAILER3, IFTRAIL, and how to combine SECTIONS with section and grand totals.
OUTFIL has two trailer types that are used for totals. TRAILER1 is the report trailer: it is written once at the very end of the output. Use it for the grand total (e.g. total record count, or sum of a dollar field across all records). TRAILER3 is the section trailer: it is written after each section when you use SECTIONS=. Use it for subtotals (e.g. count and sum per department). So you get one grand total from TRAILER1 and, when using SECTIONS, one subtotal block from TRAILER3 after each group.
| Trailer | When it appears | Typical use |
|---|---|---|
| TRAILER1 | Once at end of report | Grand total, grand count |
| TRAILER3 | After each section (with SECTIONS=) | Subtotal, section count |
COUNT= writes the number of records that were written to the output (or, in IFTRAIL, the count used to update the trailer). The value is formatted so it fits in a fixed-width report. Syntax is product-dependent; a common form is COUNT=(M11,LENGTH=7) where M11 is an edit mask and LENGTH=7 reserves 7 character positions for the number. Other products use COUNT=(position,LENGTH=n). The result is right-justified (or according to the edit mask) so columns line up.
In TRAILER1, COUNT= is the total number of detail records in the entire report. In TRAILER3 (inside SECTIONS), COUNT= is the number of records in that section only. So each section trailer can show how many records belonged to that group, and the report trailer can show the overall count.
123SORT FIELDS=COPY OUTFIL FNAMES=SORTOUT, TRAILER1=('TOTAL RECORDS: ',COUNT=(M11,LENGTH=7))
This adds one line at the end of SORTOUT with the literal "TOTAL RECORDS: " followed by the total record count, formatted in 7 positions. If 12,345 records were written, the trailer might show "TOTAL RECORDS: 12345" (exact layout depends on M11 and spacing).
TOTAL= (or TOT=) sums a numeric field from every record and writes the result in the trailer. You specify where the field is in the record (position and length), its format (ZD for zoned decimal, PD for packed decimal, BI for binary, etc.), and how the sum should be formatted in the output (e.g. TO=ZD and LENGTH=10). DFSORT adds the value from each record and places the total in the trailer at the position you specify (or after the preceding literal).
If you use the wrong format (e.g. ZD for a packed field), the sum will be wrong because the bytes will be interpreted incorrectly. So ensure the format matches your data.
123SORT FIELDS=COPY OUTFIL FNAMES=SORTOUT, TRAILER1=('TOTAL SALES: ',TOTAL=(10,5,ZD,LENGTH=10))
The 5-byte zoned decimal field at positions 10–14 in each record is summed. The result is written in the trailer after "TOTAL SALES: ", in 10 character positions. So every record contributes its sales value to the total, and the trailer shows the grand total.
Sometimes the input file already has a trailer record (e.g. a line with "T" in column 1 and placeholder values like zeros). IFTRAIL tells DFSORT to find that record, treat it as the trailer (not as data), and update specific positions in it with the actual count and totals. That way you keep your existing report layout and only the totals are filled in.
IFTRAIL uses three main parts. TRLID= identifies the trailer record, using the same kind of logical expression as INCLUDE (e.g. position, length, format, comparison). For example TRLID=(1,1,CH,EQ,C'T') means "the record with T in position 1 is the trailer." TRLUPD= specifies what to update: you give a position and then COUNT= or TOT= (or TOTAL=) with the same kind of operands as in TRAILER1. HD=YES tells DFSORT that the first record is a header so it is not counted or included in totals.
12345OPTION COPY OUTFIL FNAMES=OUTPUT1,INCLUDE=(30,5,CH,EQ,C'dept1'), IFTRAIL=(HD=YES, TRLID=(1,1,CH,EQ,C'T'), TRLUPD=(6:COUNT=(M11,LENGTH=4),14:TOT=(41,3,ZD,TO=ZD,LENGTH=6)))
The input has a header (e.g. "H 2017/01/17") and a trailer line starting with "T". HD=YES skips the header. TRLID=(1,1,CH,EQ,C'T') marks the record with "T" in column 1 as the trailer. TRLUPD= updates position 6 with a 4-digit record count and position 14 with the sum of the 3-byte zoned decimal field at positions 41–43, formatted to 6 digits. So the existing trailer line is kept but the count and total are replaced with actual values.
For control-break style reports you sort by a key (e.g. department), then use OUTFIL SECTIONS=(position,length,format,...,TRAILER3=(...)). SECTIONS groups records by that key. After the last record of each group, TRAILER3 is written. In TRAILER3 you can use COUNT= for the number of records in that section and TOTAL= (or product-specific SUBTOTAL=) for the sum of a numeric field in that section. So you get a subtotal line after each department (or region, or whatever the section key is).
The section key must match the sort order. If you sort by department and then by employee, SECTIONS should be defined on the same department field so that each section is one department and TRAILER3 prints once per department. If you need multiple levels of subtotals (e.g. by region and then by department), some products support nested SECTIONS with TRAILER3 at each level; the exact syntax is in your manual.
12345SORT FIELDS=(1,10,CH,A) OUTFIL FNAMES=REPORT,LINES=60, SECTIONS=(25,10,CH,TRAILER3=(1:'Subtotal: ',COUNT=(M11,LENGTH=6),15:TOTAL=(35,8,PD,LENGTH=12))), BUILD=(1,80), TRAILER1=(2/,1:'GRAND TOTAL: ',COUNT=(M11,LENGTH=6),15:TOTAL=(35,8,PD,LENGTH=12))
Data is sorted by positions 1–10 (e.g. key). SECTIONS groups by positions 25–34 (e.g. department). After each group, TRAILER3 prints "Subtotal: ", the section record count, and the sum of the 8-byte packed decimal at 35–42. At the end of the report, TRAILER1 prints the grand total count and grand total sum. So you get both section subtotals and a grand total in one pass.
COUNT= and TOTAL= (or TOT=) often take an edit mask and LENGTH. The edit mask (e.g. M10, M11) controls how the number is formatted (leading zeros, commas, signs). M11 is commonly used for unsigned integers. LENGTH is the number of character positions reserved in the output. If the number is too large for LENGTH, some products truncate or use overflow formatting; check your manual. For TOTAL=, the TO= format (e.g. TO=ZD) and LENGTH define the output format of the sum.
You do not use both for the same output: either you generate a new trailer (TRAILER1) or you update an existing one (IFTRAIL).
Imagine you have a list of toys and their prices. At the end of the list you want to write "Total toys: 10" and "Total cost: 50 dollars." TRAILER1 is that last line (or block of lines): the computer counts how many toys and adds up the prices, then writes that at the very end. If you also group by "type of toy" (e.g. cars, dolls), after each group you might write "Subtotal: 3 cars, 15 dollars." That line is TRAILER3: one subtotal after each group. So TRAILER1 = one big total at the end; TRAILER3 = a small total after each group. IFTRAIL is when you already have a line that says "T ??? ???" and you want the computer to replace the ??? with the real numbers.
1. Where do you put a grand total (e.g. total record count or sum of amounts) in an OUTFIL report?
2. What is the purpose of IFTRAIL in OUTFIL?
3. How do you get a subtotal after each group (e.g. each department) in a report?
4. In TOTAL=(10,5,ZD,LENGTH=10), what do 10 and 5 represent?
5. When would you use HD=YES in IFTRAIL?