MainframeMaster

Conditional Output Formatting

Conditional output formatting in DFSORT means applying different output layouts or overlays to different records when writing the final result—so the same sort step can produce one stream where record type A has one format, type B another, and everything else a default. You do this in two main ways: (1) OUTREC IFTHEN with WHEN=INIT, WHEN=(logical expression), WHEN=NONE, and WHEN=ANY, using BUILD or OVERLAY per branch; or (2) multiple OUTFIL statements, each with its own INCLUDE/OMIT and BUILD/FIELDS, so different record types go to different output files with different formats. This page focuses on the output side: when to use each WHEN type, how to combine WHEN=INIT with OVERLAY for maintainable layouts, and when to choose OUTFIL INCLUDE/OMIT vs a single stream with IFTHEN.

OUTREC / OUTFIL
Progress0 of 0 lessons

Why Conditional Output?

In many batch jobs, the input has mixed record types (e.g. headers, details, trailers) or values that require different display formats. You might want to mask a field only when it contains sensitive data, format amounts with commas only for detail records, or write headers to one file and details to another with different column layouts. Doing this in the same SORT step avoids multiple passes and keeps logic in one place. Conditional output formatting lets you choose the output layout or overlay based on a condition evaluated at output time (after the sort).

OUTREC IFTHEN: WHEN=INIT, WHEN=(logexp), WHEN=NONE, WHEN=ANY

OUTREC IFTHEN takes a list of clauses. Each clause has a WHEN= part and an action (BUILD= or OVERLAY= or FINDREP=). The WHEN types are:

IFTHEN WHEN types (processed in order)
WHEN typePurposeOrder
WHEN=INITApply BUILD/OVERLAY to all records firstProcessed first (with WHEN=GROUP)
WHEN=(logexp)Apply BUILD/OVERLAY if logical expression is trueEvaluated in order; first match typically wins
WHEN=NONEApply to records that matched no WHEN=(logexp)Default/else branch
WHEN=ANYApply to records that matched at least one WHEN=(logexp)After WHEN=(logexp) evaluation

WHEN=INIT runs first and applies to every record. Use it to establish the base output (e.g. copy the full record or build a standard layout). Then add WHEN=(logexp) clauses for specific conditions—e.g. WHEN=(1,2,CH,EQ,C'01') for record type 01—with OVERLAY to change only the positions that differ, or BUILD to replace the whole record for that type. WHEN=NONE applies to records that did not match any WHEN=(logexp); it is the default branch. WHEN=ANY applies to all records that matched at least one WHEN=(logexp); use it to apply a common overlay (e.g. add a flag) to every record that "hit" any condition. Order of evaluation is INIT (and GROUP) first, then WHEN=(logexp) in order (first match often wins unless you use options like HIT=NEXT), then NONE and ANY as defined by the product.

Example: WHEN=INIT and OVERLAY

Start with an 80-byte record for everyone; then overlay position 30–34 with '*****' only when position 5 is 'X':

text
1
2
OUTREC IFTHEN=(WHEN=INIT,BUILD=(1,80)), IFTHEN=(WHEN=(5,1,CH,EQ,C'X'),OVERLAY=(30:C'*****'))

Every record gets 1–80 first. Records with byte 5 = 'X' then get the overlay at 30–34. Others are unchanged. Using OVERLAY in the WHEN clause avoids repeating the full BUILD.

Example: Multiple WHEN=(logexp) and WHEN=NONE

Different output for different record types: first 3 bytes 'ABC' → append 'FOUND_ABC'; otherwise append 'NO_MATCH':

text
1
2
OUTREC IFTHEN=(WHEN=(1,3,CH,EQ,C'ABC'),BUILD=(1,20,C'FOUND_ABC')), IFTHEN=(WHEN=NONE,BUILD=(1,20,C'NO_MATCH'))

Records matching the condition get 20 bytes from input plus 'FOUND_ABC'. All others get 20 bytes plus 'NO_MATCH'. You must specify the field type in the condition (e.g. CH for character); omitting it can cause format errors.

Example: Numeric Condition

Format differently based on a numeric field (e.g. 4-byte zoned at position 10): over 1000 vs 1000 or less:

text
1
2
OUTREC IFTHEN=(WHEN=(10,4,ZD,GT,1000),BUILD=(1,10,C'OVER_1000')), IFTHEN=(WHEN=(10,4,ZD,LE,1000),BUILD=(1,10,C'UNDER_1000'))

Each branch uses a full BUILD here; for long records you could use WHEN=INIT and OVERLAY to change only a small part.

Multiple OUTFIL with INCLUDE/OMIT

When you want different record types in different files (not just different formats in one stream), use multiple OUTFIL statements. Each OUTFIL can have INCLUDE=(condition) or OMIT=(condition) so only matching records go to that output, and its own BUILD= or FIELDS= to format those records. Example: headers (type 01) to one file, details (type 02) to another, each with a different layout:

text
1
2
OUTFIL FNAMES=HEADER,INCLUDE=(1,2,CH,EQ,C'01'),BUILD=(1,80) OUTFIL FNAMES=DETAIL,INCLUDE=(1,2,CH,EQ,C'02'),BUILD=(1,10,15,30,45,20)

Records with bytes 1–2 = '01' go to HEADER with 80-byte copy; records with '02' go to DETAIL with a shorter built layout. JCL must define HEADER and DETAIL. Records that match neither are not written to either OUTFIL (they may still go to SORTOUT if you have no INCLUDE/OMIT on SORTOUT; with OUTFIL only, often only matching records are written).

OUTREC vs OUTFIL for Conditional Formatting

Use OUTREC IFTHEN when all records (or the subset you care about) go to a single output and you want different layouts or overlays by condition in that one stream. Use multiple OUTFIL with INCLUDE/OMIT when you want to split records by type (or value) into different files, each with its own format. You can combine both: one OUTFIL that uses IFTHEN to format different record types differently in the same file.

Explain It Like I'm Five

Imagine you have a stack of cards: some are blue, some red, some green. When you copy them onto a new sheet, you want blue cards to have a star at the top, red cards to have a circle, and green cards to look like the original. Conditional output formatting is the rule that says: "For each card, look at the color (the condition); then write it in the right way (the format)." WHEN=INIT is like drawing the same border for every card first; then we add the star or circle only for the right color. When we put blue cards in one pile and red in another, each with its own shape, that’s like multiple OUTFILs with INCLUDE—different piles (files) with different rules.

Exercises

  1. Write OUTREC IFTHEN so that records with byte 1 = 'H' get BUILD=(1,80,C'HEADER') and all others get BUILD=(1,80,C'OTHER'). Use WHEN=NONE for the default.
  2. When would you use multiple OUTFIL with INCLUDE instead of one OUTREC with IFTHEN?
  3. What happens if you omit WHEN=NONE and a record matches no WHEN=(logexp)? (Check your product; typically the record is unchanged or uses INIT-only.)
  4. Use WHEN=INIT to copy 1–100, then OVERLAY position 50 with C'X' when position 10,1,CH EQ C'Y'. Write the control statements.

Quiz

Test Your Knowledge

1. What is WHEN=INIT used for in OUTREC IFTHEN?

  • To skip records
  • To apply a base BUILD or OVERLAY to all records first; later WHEN=(logexp) or OVERLAY then modify only what differs
  • Only for INCLUDE
  • To set the sort key

2. When is WHEN=NONE applied?

  • To every record
  • Only to records that did not match any of the preceding WHEN=(logexp) conditions
  • Only when WHEN=INIT is missing
  • To the first record only

3. How can you write different record types to different output files with different formats?

  • Only with two SORT steps
  • Use multiple OUTFIL statements, each with its own INCLUDE/OMIT (or INCLUDE/OMIT with different conditions) and BUILD/FIELDS
  • OUTFIL cannot have INCLUDE
  • Only OUTREC supports IFTHEN

4. What is WHEN=ANY used for?

  • First record only
  • Records that matched at least one of the preceding WHEN=(logexp) clauses; used to apply an additional OVERLAY or BUILD to all such records
  • Only with MERGE
  • To duplicate records

5. In OUTREC IFTHEN, why use OVERLAY in a WHEN=(logexp) instead of a full BUILD?

  • OVERLAY is required
  • OVERLAY changes only specified positions; the rest of the record stays as built by WHEN=INIT, so you avoid repeating the entire layout and reduce maintenance
  • BUILD cannot be used in WHEN
  • Only BUILD supports constants