Supported RPG Features

When a program uses READC to read changed records from a subfile, the file declaration must include the SFILE keyword to identify which record format is a subfile and which variable holds the relative record number (RRN).

DCL-F CUSTLIST WORKSTN SFILE(SFLREC:wRRN);
DCL-S wRRN INT(5);

SFILE is equally a fixed-format F-spec keyword - subfile programs do not have to be converted to free-format. Write it in the keyword area (columns 44-80), either beside the device or, as is more usual since it rarely fits, on a continuation F-spec:

     FCUSTLIST  CF   E             WORKSTN SFILE(SFLREC:RRN)
     D RRN             S              4S 0
     FCUSTLIST  CF   E             WORKSTN
     F                                     SFILE(SFLREC:RRN)

Both forms behave identically, and READC, WRITE and CHAIN on the subfile format resolve against either.

Continuation F-specs work for every device, not just WORKSTN. A blank file-name field continues the keyword area of the F-spec above it, and the keywords accumulate across as many continuation lines as you write:

     FEMPMAST   IF   E             DISK
     F                                     INFDS(fInfo)
     F                                     USROPN

Keywords go in columns 44-80 of the continuation line, the same area they occupy on the primary line. A continuation line with no F-spec above it is an error (TRN1004).

The SFILE keyword takes two colon-separated arguments:

  1. The subfile record format name (must match a format with the SFL keyword in the DDS)
  2. The RRN variable name (must be declared as a numeric variable with zero decimal positions)

The RRN variable is shared between WRITE and READC operations:

// Writing records - set wRRN before each WRITE
wRRN = 1;
CUSTNAME = 'Alice';
WRITE SFLREC;

wRRN = 2;
CUSTNAME = 'Bob';
WRITE SFLREC;

// Reading changed records - wRRN is set by READC
READC SFLREC;
IF NOT %EOF();
  // wRRN now contains the RRN of the changed record
ENDIF;

If READC is used on a subfile format without a corresponding SFILE keyword on the file declaration, the compiler reports an error:

[ERROR] MYPGM.rpgle:10:2 - READC 'SFLREC' requires the SFILE keyword on the declaration of 'CUSTLIST' - use SFILE(SFLREC:<rrn-variable>)

Multiple SFILE keywords may be specified on a single file declaration if the display file contains multiple subfiles.

WRITE to a subfile-control format dispatches on the control record's conditioning indicators. A WRITE to the SFLCTL format does not read input; it performs the control actions whose indicators are active, in order:

// Initialize the subfile to SFLSIZ blank rows and display it, without reading
*IN32 = *ON;    // SFLINZ conditioning indicator
*IN30 = *ON;    // SFLDSP / SFLDSPCTL conditioning indicator
WRITE SFLCTL;   // subfile now holds SFLSIZ blank records and is painted

Reading input from the subfile still uses EXFMT SFLCTL (display-and-read) followed by READC.

A WRITE to the control format also leaves the resulting record count in the INFDS subfile record-count subfield (position 380), so the count can be read straight after the WRITE without displaying anything.

Subfile Records Not Active (SFLRNA)

SFLRNA on the subfile-control record makes the records SFLINZ initializes exist without being active. They are still displayed, and the operator can still key into them - that is the point of the keyword - but until something writes into a record, that record is invisible to the program:

A record becomes active as soon as data is put in it, either by the program writing to the subfile record format or by the operator keying into its line. Activation is per record, and the count is a count rather than a high-water mark - writing only the record at RRN 3 into a freshly initialized subfile reports a count of 1, not 3.

*IN32 = *ON;         // SFLINZ
*IN33 = *ON;         // SFLRNA
WRITE SFLCTL;        // 10 records exist, none active -> SflCnt = 0

RRN = 3;
SFLFLD = 'ROW3';
WRITE SFLREC;        // that one record is now active -> SflCnt = 1

This is what makes an entry subfile efficient: after the operator fills in a few lines, READC returns just those lines instead of all SFLSIZ of them.

Without SFLRNA, the records SFLINZ creates are active from the start, so they are all counted, all reachable by CHAIN immediately - and writing into one is a duplicate-record error rather than a load. See below.

Writing a Subfile Record That Already Exists

A WRITE to a subfile relative record number that already holds an active record fails with file status 1021 ("tried to write a record that already exists"). It is not treated as an overwrite.

MONITOR;
  RRN = 1;
  WRITE SFLREC;          // RRN 1 already active
ON-ERROR;
  // %STATUS = 1021
ENDMON;

The error is trappable the usual ways - a MONITOR/ON-ERROR block, or the (E) extender with %ERROR and %STATUS. Left untrapped it halts the program, as an unmonitored error does. A rejected WRITE leaves the existing record unchanged.

Three cases are not errors, because the target RRN holds no active record:

To change a record that is already active, read it first with READC or CHAIN and use UPDATE - see UPDATE on Subfile Records.