MainframeMaster

Report Totals in OUTFIL

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 Advanced
Progress0 of 0 lessons

Where Totals Appear: TRAILER1 vs TRAILER3

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 types for totals
TrailerWhen it appearsTypical use
TRAILER1Once at end of reportGrand total, grand count
TRAILER3After each section (with SECTIONS=)Subtotal, section count

COUNT=: Record Count in a Trailer

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.

Example: TRAILER1 with record count

text
1
2
3
SORT 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= and TOT=: Sum of a Numeric Field

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).

  • Position and length: the starting column and length of the field in the input record (the field that is summed).
  • Format: ZD (zoned decimal), PD (packed decimal), BI (binary), etc. Must match how the data is stored.
  • TO= and LENGTH: the output format and width for the total (e.g. TO=ZD,LENGTH=10).

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.

Example: TRAILER1 with sum of a numeric field

text
1
2
3
SORT 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.

IFTRAIL: Updating an Existing Trailer Record

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.

Example: IFTRAIL with header and trailer

text
1
2
3
4
5
OPTION 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.

Section Subtotals with SECTIONS and TRAILER3

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.

Example: SECTIONS with TRAILER3 subtotal

text
1
2
3
4
5
SORT 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.

Edit Masks and LENGTH for COUNT= and TOTAL=

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.

Comparing TRAILER1 Totals and IFTRAIL

  • TRAILER1= with COUNT= and TOTAL=: DFSORT creates a new trailer line at the end of the report and fills it with the grand count and/or sum. Use this when you are building the report from scratch.
  • IFTRAIL with TRLUPD=: DFSORT updates an existing record in the input that you identified with TRLID=. Use this when the input already has a trailer template (e.g. from a previous step) and you only need to fill in the numbers.

You do not use both for the same output: either you generate a new trailer (TRAILER1) or you update an existing one (IFTRAIL).

Explain It Like I'm Five

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.

Exercises

  1. Write an OUTFIL that adds TRAILER1 with the text "Records: " and a 5-digit record count. Use your product's COUNT= syntax.
  2. Your input has a 4-byte packed decimal amount at positions 50–53. Write TRAILER1 to print "Total amount: " and the sum of that field. Specify position, length, format (PD), and output LENGTH.
  3. When would you use IFTRAIL instead of TRAILER1? What must be true about the input file?
  4. Sort a file by department (positions 20–29). Use SECTIONS and TRAILER3 to print a subtotal line after each department with the section record count and the sum of a numeric field. Add TRAILER1 for the grand total.

Quiz

Test Your Knowledge

1. Where do you put a grand total (e.g. total record count or sum of amounts) in an OUTFIL report?

  • In HEADER1
  • In TRAILER1—the report trailer at the end of the report
  • In TRAILER2 only
  • In BUILD=

2. What is the purpose of IFTRAIL in OUTFIL?

  • To add a new trailer at the end
  • To update an existing trailer record in the input with actual counts and totals (TRLID identifies the trailer, TRLUPD specifies what to update)
  • To remove trailers
  • To sort by trailer

3. How do you get a subtotal after each group (e.g. each department) in a report?

  • Use TRAILER1 only
  • Sort by the group key, then use OUTFIL SECTIONS=(key,TRAILER3=(...)) so TRAILER3 prints after each section with COUNT= or TOTAL= for that section
  • Use INCLUDE only
  • Use two OUTFILs

4. In TOTAL=(10,5,ZD,LENGTH=10), what do 10 and 5 represent?

  • Line 10 and column 5
  • Starting position 10 and length 5 of the numeric field in the input record to sum (ZD = zoned decimal)
  • Output positions only
  • Page and line

5. When would you use HD=YES in IFTRAIL?

  • Always
  • When the input file has a header record so DFSORT skips it and does not treat it as data when computing counts/totals
  • Only for TRAILER3
  • To add a header