This article is for RPG developers who maintain or write 5250 screens, already know the basic mechanics of SFLCTL/SFLPAG/SFLDSP, and need to choose deliberately between a load-all subfile and a page-at-a-time subfile for a given screen. If you’ve decided to load an entire result set into a subfile up front, it gives you a concrete pattern to start from — and is explicit about what has, and has not, been verified.
Prerequisites
This article assumes you already know:
- The basic DDS subfile triad:
SFLCTL,SFLPAG(page size) andSFLDSP/SFLDSPCTL, and that a subfile record format is a second record format tied to a control format. - RPGLE free-format syntax (
dcl-f,dcl-s,dow/dou, inlineif/endif). - The basic file opcodes
SETLL,READ,CHAINandWRITE. If any of these are unfamiliar, start with the RPGLE File I/O Opcodes Reference and the RPGLE CHAIN Opcode Reference first.
This article does not re-teach page-at-a-time subfile paging. If your screen needs SFLNXTCHG, roll-key repositioning, or any logic to fetch “the next page” on demand, that pattern is covered in depth in RPG Subfile Programming: SFLCTL, SFLPAG and SFLDSP Paging. Read that article if paging, not load-all, is what your screen actually needs — the two patterns solve different problems and shouldn’t be mixed.
What “load-all” means, and when it’s the right call
A subfile has two sizes: SFLPAG, the number of subfile records displayed on one screen, and SFLSIZ, the number of records the subfile is initially sized to hold. In a page-at-a-time design the two are equal or close together, because the program only ever keeps a page or two of records loaded and fetches more as the user rolls.
In a load-all design, SFLSIZ is set far larger than SFLPAG — large enough to hold the entire result set the query can realistically return — and the program loads every matching record into the subfile in one pass, before the display operation ever happens. From then on, rolling up and down is handled entirely by the system against the already-loaded rows. The RPG program does no more file I/O for scrolling; it only re-engages when the user presses an action key, selects a row, or requests a new filter.
Load-all is the right call when:
- The result set is bounded and modest — typically a few dozen to a few thousand rows, not open-ended.
- The screen is a lookup, pick-list, or inquiry where the user is likely to scroll both directions, search visually, or use subfile positioning (
SFLRCDNBR) — behavior that page-at-a-time has to work harder to support. - You want simpler program logic: no
SFLNXTCHG, no tracking of “last key read,” no re-entrant paging state to manage across invocations. - The selection criteria can change the row count unpredictably, and re-fetching per page would mean re-running the same filter logic repeatedly anyway.
Load-all is the wrong call when the result set is large or effectively unbounded — a transaction history with no date filter, a full item master on a multi-million-row file — because you pay the full I/O and memory cost of the query on every invocation, whether the user ever scrolls past page one or not. In that case, use the paging pattern linked above, where the program only ever materializes the rows currently on screen.
Sizing SFLSIZ relative to SFLPAG — the real numbers
IBM i enforces a hard, documented ceiling on subfile size: 9999 records. The IBM i DDS reference for the SFLSIZ keyword states it directly: “The maximum number of records allowed is 9999.” No SFLSIZ value above 9999 is accepted, and no subfile can grow beyond 9999 records.
Two related mechanical details from the same page:
- If
SFLSIZequalsSFLPAGand the subfile doesn’t fill a full display, the system automatically raises both the page size andSFLSIZto the number of records that fit on the display. This matters for page-at-a-time designs more than load-all, but it explains why a load-all screen should setSFLSIZexplicitly and well aboveSFLPAGrather than leaving them equal. - If
SFLSIZdiffers fromSFLPAG(the load-all case) and the program writes a record beyond the currentSFLSIZ, IBM documents that “the subfile is automatically extended to contain it (up to a maximum of 9999 records).” So in a load-all design,SFLSIZis the initial allocation, not a cap — the only hard cap is 9999. SettingSFLSIZclose to your expected row count simply avoids repeated extension.
Your application’s own limit is a separate, smaller number that you choose. The example in this article uses SFLSIZ(2000) in DDS and a program variable maxRows = 2000 as a chosen application safety limit — not because IBM enforces 2000 anywhere, but because 2000 rows is a reasonable, deliberately-chosen ceiling for an item-lookup screen that should never realistically need more. Do not confuse the two numbers:
| Value | What it is | Where it comes from |
|---|---|---|
| 9999 | Hard system-enforced maximum subfile record count | IBM i DDS reference (SFLSIZ) |
| 2000 (this example) | Application-chosen safety ceiling, used in both SFLSIZ(2000) and the RPG maxRows variable | Chosen by the developer for this screen; change it to fit your use case |
If your query can plausibly return more than your chosen application limit, add explicit selection criteria (a date range, a status filter, a required search key) rather than raising the limit toward 9999 — and if you find yourself needing a number anywhere near 9999, that is a strong signal the screen should be a paging design instead of load-all.
DDS: SFLCTL, SFLPAG, SFLSIZ, SFLCLR and SFLEND (illustrative)
Verification status: IBM DOC CHECKED — SFLCLR, SFLSIZ, SFLEND, and SFLRCDNBR keyword syntax and semantics below were checked against the IBM i DDS reference pages for those keywords (see Sources Consulted). This fragment is not a full screen — just the keywords that matter for load-all sizing and sequencing, on a simple item-lookup subfile. It has not been compiled.
A*%%TS SD 20261014 000000 USER REL-V7R5M0 5.0
A R ITEMSFL SFL
A ITEMNO 7A O 4 3
A ITEMDESC 30A O 4 12
A ONHAND 7S 0O 4 44
A UNITCOST 9S 2O 4 54
A R ITEMCTL SFLCTL(ITEMSFL)
A SFLPAG(20)
A SFLSIZ(2000)
A CA03(30 'Exit')
A 02 SFLDSP
A 03 SFLDSPCTL
A 01 SFLCLR
A 50 SFLEND
A TOPLINE 79A B 1 2
A RRN 4S 0H SFLRCDNBR
SFLCLR is conditioned, not unconditional. The IBM i DDS reference for SFLCLR is explicit: “An option indicator is required for this keyword.” Without a conditioning indicator, a program that writes the control record more than once (which an EXFMT-based loop does) would have no way to clear only when intended. In the DDS above, plain indicator 01 (not negated) conditions the clear: it is turned on only for the single write that should clear the subfile, then turned off for the rest of the cycle — including the final EXFMT. That way SFLCLR fires exactly once per load cycle.
SFLDSP uses indicator 02 (scrInd.dspSfl), while SFLDSPCTL independently uses 03 (scrInd.dspSflCtl). The first is on only when rows were loaded; the second is on for every user-facing EXFMT, including the empty-result case. CA03(30 'Exit') returns indicator 30 when the user presses F3; with the INDDS data structure in the RPG, that response arrives in the data structure (scrInd.exitKey), not in *IN03.
RRN is a hidden zoned field with SFLRCDNBR, which selects which page is displayed — the page containing the record whose relative record number is in the field. The same field is also used as the RPG SFILE RRN variable, a common practice. IBM documents that the SFLRCDNBR field must be zoned decimal with zero decimal positions, and that a value less than 1 or greater than the number of records on an output operation returns an error — so the program sets it back to 1 before displaying a loaded subfile.
SFLEND with indicator 50 is discussed in detail below — note it has no parameter here, so it defaults to *PLUS (a plus sign in the lower-right corner): IBM’s reference states, “If no parameter is specified, *PLUS is used.”
Free-format RPGLE: three distinct phases — clear, load, display
Verification status: STATIC CHECKED — traced manually for internal consistency (record format names, indicator usage, variable lifecycle) against the DDS fragment above and against IBM RPG opcode semantics. Not compiled or run.
Clear, load, and display are three distinct, sequentially-ordered actions, each clearly gated:
- Clear — turn indicator 01 on and write the control record format (
ITEMCTL) once. This firesSFLCLRbecause the DDS conditions it with plain indicator 01 (not negated), so the clear keyword is active precisely when 01 is on — and nowhere else in the cycle. Indicators 02 (SFLDSP) and 03 (SFLDSPCTL) are off here, so this write clears the subfile without displaying anything. - Load — loop reading the source data and writing subfile records (
ITEMSFL), incrementingRRNby hand before eachWRITE, up to the application’smaxRowsceiling. - Display — turn indicator 01 off (so a later redisplay of the control record does not re-clear what was just loaded), turn 03 on and turn 02 on only if rows were loaded, set
RRNto 1 so the first page shows, set theSFLENDindicator as described below, andEXFMTthe control record (ITEMCTL). Every RPG reference usesitemctlanditemsfl, matching the DDSR ITEMCTLandR ITEMSFLformats exactly, and theSFILE(record-format-name : RRN-field-name)syntax matches the IBM i page on using subfiles.
**free
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-f itemmst keyed usage(*input);
dcl-f itemscr workstn
sfile(ITEMSFL : rrn) // RRN is the hidden 4S 0 field defined in
indds(scrInd); // the ITEMCTL DDS (also its SFLRCDNBR field)
dcl-ds scrInd qualified;
clearSfl ind pos(1); // SFLCLR conditioning indicator (DDS: 01 SFLCLR)
dspSfl ind pos(2); // SFLDSP only when at least one record exists
dspSflCtl ind pos(3); // SFLDSPCTL still shown for zero records
exitKey ind pos(30); // F3 response indicator (DDS: CA03(30))
noMoreRows ind pos(50); // SFLEND conditioning indicator (DDS: 50 SFLEND)
end-ds;
dcl-s maxRows packed(4 : 0) inz(2000); // application-chosen ceiling; IBM's
// hard subfile maximum is 9999 —
// these are two different numbers.
dcl-s rowsLoaded packed(4 : 0);
dow *on;
// ---- phase 1: clear ----
// Turn indicator 01 on and write the control record ONCE, outside the
// load loop. This is the only point in the cycle where SFLCLR fires.
// 02 and 03 are off, so this write clears the subfile without displaying it.
rrn = 0;
rowsLoaded = 0;
scrInd.dspSfl = *off;
scrInd.dspSflCtl = *off;
scrInd.noMoreRows = *off;
scrInd.clearSfl = *on;
write itemctl;
// ---- phase 2: load ----
// Turn the clear indicator off immediately so nothing downstream
// accidentally re-clears a format that already holds freshly-loaded rows.
scrInd.clearSfl = *off;
setll *loval itemmst;
read itemmst;
dow not %eof(itemmst);
if rowsLoaded >= maxRows;
// Safety stop: this is an APPLICATION-CHOSEN limit (2000 here), not
// the IBM-enforced ceiling of 9999. Log it, warn the user, and stop
// rather than writing past this screen's working size.
leave;
endif;
rowsLoaded += 1;
rrn = rowsLoaded; // set the SFILE RRN field before each WRITE
itemno = itmno;
itemdesc = itmdsc;
onhand = itmqoh;
unitcost = itmcst;
write itemsfl;
read itemmst;
enddo;
// ---- phase 3: display ----
// See "Working out SFLEND" below for why noMoreRows is set on for a true
// load-all pattern, not tied to rowsLoaded = 0. dspSfl (02) gates only
// SFLDSP, while dspSflCtl (03) independently enables the control record
// even if the result set contains no rows. A cleared subfile with zero
// written rows is NOT active (no SFLINZ), and IBM i returns an error if
// SFLDSP is selected in that state.
scrInd.dspSfl = (rowsLoaded > 0);
scrInd.dspSflCtl = *on;
scrInd.noMoreRows = *on;
if rowsLoaded = 0;
topline = 'No records found';
else;
rrn = 1; // SFLRCDNBR: show the page holding record 1
topline = 'Inventory results';
endif;
exfmt itemctl;
if scrInd.exitKey; // F3 = Exit
leave;
endif;
// handle selection / option processing here, then loop back to
// re-filter and reload (phases 1-3 repeat) if the user changed
// selection criteria
enddo;
*inlr = *on;
One detail worth calling out: RRN is not declared with dcl-s. It comes from the externally described display file (the hidden RRN 4S 0 field on ITEMCTL), and that same field is named in sfile(ITEMSFL : rrn). Declaring a second standalone rrn with a different type would conflict with the file’s field definition. The zero-row path leaves RRN at 0 while SFLDSP is off; whether SFLRCDNBR objects to that value when the subfile itself is not displayed is one of the paths to confirm in runtime testing.
From an SQL cursor (equally common, and often cleaner for ad hoc filters)
Verification status: NOT TESTED — illustrative only; shown to demonstrate the same three-phase shape with an SQL cursor instead of native I/O, not as a working copy-paste program (it omits the declarations, clear/display phases, and indicator handling shown in full above for brevity, and assumes the same display file, whose RRN field is the SFILE variable).
**free
exec sql
declare itemCur cursor for
select itemno, itemdesc, onhand, unitcost
from itemmst
where onhand >= 0
order by itemdesc;
exec sql open itemCur;
rrn = 0;
dow sqlcode = 0 and rrn < maxRows;
exec sql fetch next from itemCur
into :itemno, :itemdesc,
:onhand, :unitcost;
if sqlcode = 0;
rrn += 1;
write itemsfl;
endif;
enddo;
exec sql close itemCur;
Both patterns share the same shape: clear once, then loop fetch-then-write incrementing RRN by hand, stop at end-of-data or at a safety limit, then display. The WRITE uses the relative record number in the field tied to the subfile record format via SFILE in the device file declaration (sfile(ITEMSFL : rrn) above). IBM’s documentation on using subfiles states that this field “is also used to specify the record number that the RPG program uses for WRITE operation to the subfile,” and that it “must have enough positions to contain the largest record number for the file.” Your program is responsible for setting rrn before each WRITE.
Working out SFLEND for a load-all pattern
SFLEND‘s option indicator tells the system whether the subfile has reached its end. Its behavior, per the IBM i DDS reference, depends on whether paging is program-controlled or system-controlled:
- Program-controlled paging (
SFLPAGequalsSFLSIZ): the program itself handles each page by clearing and rewriting the subfile, so the indicator directly reflects whether this specific reload reached the last page. - System-controlled paging (
SFLPAGdoes not equalSFLSIZ— which is exactly the load-all case, sinceSFLSIZis deliberately set far aboveSFLPAG): IBM i shows the plus sign “as long as there are more records in the subfile to be displayed,” regardless of the indicator’s setting. The indicator matters at the last page: if it is off there, the system cannot page further on its own and expects the program to supply more records (which is what thePAGEDOWNkeyword is for in expandable designs).
A tempting but wrong approach is to set the indicator from rowsLoaded = 0 — signaling “end of data” only when the current pass loaded zero rows. That conflates “I loaded zero rows just now” with “there is nothing left to scroll to,” which are different facts — a pass that loads 500 rows still has an end. More fundamentally for load-all: because the entire result set is loaded in one pass before EXFMT ever runs, every row that will ever exist in the subfile for this display cycle is already there by the time the user sees anything. There is no later point in the cycle where the program adds more rows.
The conclusion: for a true load-all pattern, set the SFLEND indicator on, once, right before the EXFMT, regardless of rowsLoaded — including when rowsLoaded is zero. It expresses a fact that is always true for load-all by construction: nothing further will be appended to this subfile during this display cycle, so at the last page the system shows the end-of-subfile state instead of waiting for the program to add more. This also sidesteps the IBM reference’s mid-list Page Down machinery (PAGEDOWN keyword, re-adding records, SFLRCDNBR repositioning) — that exists for the case where the program might add more rows after the user scrolls further, which by definition cannot happen in load-all. If your screen conditionally becomes “load more after all” (e.g., lazy-loading past the application’s maxRows cutoff), you are no longer doing a true load-all for that case and should model it as an expandable subfile or switch to the paging pattern instead.
Empty result sets. SFLDSP and SFLDSPCTL are independent, and SFLCLR does not activate a subfile. A cleared but never populated subfile is inactive, and IBM’s SFLDSP reference describes selecting SFLDSP in that state as an error. So SFLDSP (02) is enabled only when at least one row has been written; SFLDSPCTL (03) stays on for user input even with zero rows, and the control record’s TOPLINE shows “No records found.” SFLEND is not a substitute for this display guard. This logic has not been runtime-tested on PUB400 or any live IBM i system.
Expected output and behavior
Once the three phases finish and EXFMT displays the control record, the user sees the first SFLPAG rows (20, in the DDS example above) and can roll forward and backward through the full loaded set using the normal Page Up/Page Down keys — all handled by the system, with no further RPG code running until the user presses an action key or exits. This is the main practical payoff of load-all: scrolling is “free” from the program’s perspective once the load is done, and (per the SFLEND reasoning above) the end-of-data indicator can be set once rather than recomputed per iteration.
If the result set is empty, SFLDSP stays off and SFLDSPCTL stays on for the EXFMT, so the user sees the TOPLINE “No records found” message. This is a required safety check, not merely optional presentation logic.
Common mistakes and troubleshooting
- Clearing the subfile unconditionally, or on every
EXFMT. An unconditioned clear inside a loop that also runsEXFMTrepeatedly wipes the subfile on every redisplay, not just at the start of a fresh load.SFLCLRrequires a conditioning indicator — set it on only immediately before the one write that should clear, then off again before the load loop. - Leaving
SFLDSPactive while no records have been loaded. SelectingSFLDSPfor an inactive (cleared but empty) subfile is an error. ConditioningSFLDSPon 02 andSFLDSPCTLon 03 allows a control-only empty display without activating the subfile. - Not resetting
rrnto zero before the load loop. Ifrrnis left at its value from the previous load, new rows get written at the wrong relative positions. - Leaving the
SFLRCDNBRfield at the last loaded RRN. When the same field serves as theSFILEvariable and theSFLRCDNBRfield, it holds the last record number after the load, so the user would land on the last page. Set it to 1 (or to the row you want shown) beforeEXFMT. - Checking
*IN03for F3 when the file usesINDDS. With an indicator data structure, response indicators are returned in the data structure, not in*IN. And the DDS must actually declare the key (CA03(30)here) for the program to see it at all. - Declaring free-form unsigned fields with an unsupported length. Free-form
unssupports only 3, 5, 10, or 20 digits;uns(4)does not compile. Usepacked(4:0), or the display file’s own zoned field, for subfile RRNs and counters. - Setting
SFLSIZequal to, or barely above,SFLPAG. In load-all this mostly costs repeated automatic extensions (whenSFLSIZdiffers fromSFLPAG), and setting the two equal switches the subfile to program-controlled paging semantics entirely. SizeSFLSIZnear your expected row count. - Confusing the IBM-enforced ceiling (9999) with your own application limit. They are different numbers serving different purposes — see the table earlier in this article.
- Tying
SFLENDto the wrong condition.rowsLoaded = 0is not the right signal; for load-all, set the indicator on after the load phase completes, since nothing more will ever be appended during that display cycle. - Treating load-all as free. Every row loaded is a row read from the database and formatted into the subfile buffer whether the user ever scrolls to it or not. For a filter that can return thousands of rows, this can be noticeably slower to the user than the first-page latency of a paging design, even though scrolling afterward is faster.
- Using
CHAINin a loop whereREAD/READEwould do. LoopingCHAINby incrementing a key is a common anti-pattern inherited from older code; a straightSETLL+READloop (or an SQL cursor) is simpler and avoids re-deriving the next key yourself.
Performance and security considerations
Memory and I/O. A load-all subfile materializes the entire result set in the job’s memory (as subfile buffer pages) and performs the full database read for every invocation of the screen, regardless of how much of it the user actually views. For a few hundred to a few thousand rows this is rarely a problem on current IBM i hardware, but it does not scale the way a paging design does — doubling the typical result-set size roughly doubles the load time and memory footprint, where paging’s cost stays flat per page. If users regularly complain about the screen being slow “to come up” rather than slow “to scroll,” that is a sign the result set has outgrown the load-all approach for that screen.
Row-count governance. Beyond the program’s own maxRows safety check (an application-chosen number, not an IBM-enforced one), consider whether the underlying query should have a selection-criteria requirement (a date range, a status filter, a required search key) that keeps typical result sets well-bounded, rather than relying solely on a runtime check to catch a pathological case after the fact. If a design genuinely needs to approach the IBM-enforced 9999-record ceiling, that is a strong signal to reconsider load-all for that screen entirely.
Access authority. A load-all subfile reads and holds every row the query returns, which means it also displays every row the query returns to whoever is at the screen. Make sure the underlying file’s object-level or row-level (RCAC) authority, and any application-level row filtering, are applied in the query itself — in the SETLL/WHERE logic — not assumed to be handled by what the screen chooses to show. A load-all design that bulk-loads more rows than the user is entitled to see, then relies on the program to selectively skip displaying some of them, is a real exposure if that skip logic has a bug; filter at the data access layer, not the display layer.
A realistic use case
An inventory lookup screen where a warehouse clerk searches by item description prefix or category and expects to scroll through the matches freely, sort visually, and select one to drill into. A typical filtered result is a few hundred rows, occasionally into the low thousands for a broad category; it never runs into the tens of thousands because the business process doesn’t produce catalogs that large per warehouse. This is squarely in load-all territory: bounded, scroll-heavy, and simpler to write without paging state. Contrast this with an audit-trail inquiry over unfiltered transaction history, which has no natural upper bound and belongs in a paging design instead.
FAQ
Can I switch an existing paging subfile to load-all without redesigning the screen?
Mechanically, yes — you keep the same DDS record formats and raise SFLSIZ well above SFLPAG (up to the IBM-enforced 9999 maximum), then replace the page-fetch logic with the three-phase clear/load/display cycle shown above, run once per filter change. But check why the screen was built as paging first; if it was paging because the result set is genuinely large or unbounded, raising SFLSIZ without addressing that will just move the performance problem from “slow to scroll” to “slow to open.”
Does load-all mean I never call WRITE again after the initial load?
Within one invocation of the screen, yes for the subfile rows — paging is handled by the system once the load phase is done. You call WRITE again (to itemctl, to clear, then to itemsfl, to reload) only when the user changes a filter and the subfile needs a fresh load cycle.
What happens if the WRITE loop exceeds SFLSIZ?
When SFLSIZ differs from SFLPAG, IBM documents that the subfile is extended automatically, up to 9999 records — so exceeding SFLSIZ itself is not an error in a load-all design. Writing beyond 9999 records is, and should be caught by the program (test %error with the (E) extender) — but your own maxRows check should stop the loop long before that. In this article’s example, maxRows (2000) equals SFLSIZ(2000), so a normal load never needs an extension, and both sit far below IBM’s 9999 ceiling.
Is there a hard maximum number of rows a subfile can hold?
Yes — per the IBM i DDS reference for SFLSIZ, the maximum is 9999 records, system-enforced. That is a different number from whatever application-level ceiling (like the 2000 used in this article’s example) you choose to enforce in your own program logic for a specific screen.
Should I use native I/O or an SQL cursor to load the subfile?
Both are legitimate. Native SETLL/READ is usually simpler when the selection is a straightforward keyed range. An SQL cursor is often easier to maintain when the filter logic is complex, involves joins, or needs to change based on multiple optional search fields, since the WHERE clause can be built dynamically. Either way, the load loop shape — clear, then read/write/increment RRN until end-of-data or a safety limit, then display — stays the same.
Do I need SFLEND at all for a true load-all subfile?
No. SFLEND is an optional subfile-control keyword; it is not required merely because SFLDSP/SFLDSPCTL are present. If you choose to use SFLEND for a true load-all cycle, turn its indicator on after all rows have been added, since no further records will be appended. If you find yourself writing conditional logic to decide when to turn it off again mid-cycle, that is a sign you’ve drifted from true load-all into a hybrid paging pattern and should revisit the design.
What happens if the result set is empty — does phase 3 error out?
The control format remains usable. The code turns dspSfl (02) off when rowsLoaded = 0, turns dspSflCtl (03) on, and sets TOPLINE to “No records found” before EXFMT itemctl. IBM documents that selecting SFLDSP for a subfile with no active records raises an error; clearing is not initializing. This logic is designed to avoid that error, but still needs IBM i runtime testing.
Verification Status
This article’s code examples were written and checked against the IBM i DDS keyword reference for SFLCLR, SFLSIZ, SFLEND, SFLDSP, and SFLRCDNBR, and against the IBM i documentation on using subfiles (see Sources Consulted below). They were not compiled or run on a live IBM i system or on PUB400. Status tags used per code block:
- DDS fragment (clear/load/display keywords): IBM DOC CHECKED
- Free-format RPGLE three-phase clear/load/display example: STATIC CHECKED
- SQL cursor variant: NOT TESTED (illustrative only, intentionally abbreviated)
Conditioning SFLDSP and SFLDSPCTL on their own indicators is a lifecycle design choice, not a documented IBM requirement the way SFLCLR‘s and SFLEND‘s option-indicator requirements are — IBM’s reference does not state that SFLDSP/SFLDSPCTL must be conditioned. Both the conditioned and unconditioned forms can be valid DDS, but selecting SFLDSP on an inactive subfile is a documented runtime error, which is why this article separates the two display indicators to handle the empty case safely.
Before using any of this code in a real program, compile it against your own file and screen definitions and test the clear, load, display, empty-result-set, and over-limit paths explicitly.
Sources Consulted
- SFLCLR (Subfile Clear) keyword — IBM i DDS reference,
https://www.ibm.com/docs/en/i/7.4.0?topic=80-sflclr-subfile-clear-keyword-display-files— SFLCLR requires a conditioning option indicator (“An option indicator is required for this keyword”). - SFLSIZ (Subfile Size) keyword — IBM i DDS reference,
https://www.ibm.com/docs/en/i/7.4.0?topic=80-sflsiz-subfile-size-keyword-display-files— the maximum subfile record count is 9999 (“The maximum number of records allowed is 9999”), and whenSFLSIZdiffers fromSFLPAGa record written beyond the current size causes “the subfile is automatically extended to contain it (up to a maximum of 9999 records).” - SFLEND (Subfile End) keyword — IBM i DDS reference,
https://www.ibm.com/docs/en/i/7.4.0?topic=80-sflend-subfile-end-keyword-display-files— “If no parameter is specified, *PLUS is used”; under system-controlled paging (SFLPAG ≠ SFLSIZ) the plus sign is shown “as long as there are more records in the subfile to be displayed,” regardless of the indicator; at the last page, an off indicator means the program must supply further records (viaPAGEDOWN). - SFLDSP (Subfile Display) keyword — IBM i DDS reference,
https://www.ibm.com/docs/en/i/7.6.0?topic=s-sfldsp— selectingSFLDSPfor a subfile with no active records is an error. - SFLRCDNBR (Subfile Record Number) keyword — IBM i DDS reference,
https://www.ibm.com/docs/en/i/7.4.0?topic=80-sflrcdnbr-subfile-record-number-keyword-display-files— the field must be zoned decimal with zero decimal positions; it selects the page containing that record; a value less than 1 or greater than the number of records on output returns an error. - Using subfiles — IBM i ILE RPG documentation (“Using Externally Described WORKSTN Files”),
https://www.ibm.com/docs/en/i/7.4.0?topic=files-using-subfiles— SFILE naming rules (the subfile record format, not the control format, is named in SFILE) and RRN field semantics (numeric, zero decimals, large enough for the largest record number, used for WRITE positioning). - For the paging alternative to the pattern in this article, see RPG Subfile Programming: SFLCTL, SFLPAG and SFLDSP Paging.
- For the underlying file operation opcodes used in the load loop, see the RPGLE File I/O Opcodes Reference and the RPGLE CHAIN Opcode Reference.