Learn to write SQL RPG Subfiles with Clickable Sorteable Column Headers

SQLRPGLE - Sortable Subfile with Column Headings and Search using RTNCSRLOC

Here is a complete, practical example that brings everything together. We use the exact DDS display file shown below combined with the modern SQLRPGLE program SORTSFLBOB we looked at earlier.

The design is simple and effective: blue underlined column headings act as visual targets. The user positions the cursor on a heading (with mouse or keyboard) and presses F9 to sort. Search fields sit directly below the headings. All the heavy lifting for detecting which column was chosen is done with RTNCSRLOC.

DDS DSPF Design – Column Headings, Search Fields and RTNCSRLOC

     A                                      DSPSIZ(24 80 *DS3)
     A                                      INDARA
     A                                      CA03(03 'Exit')
     A                                      CF09(09 'Search')
     A          R SFL01                     SFL
     A            SORTDATE      10S 0O  9  3
     A            SORTTIME      10S 0O  9 14
     A            SORTUSER      10A  O  9 25
     A            SORTTEXT      40A  O  9 36
     A            SORTSTATUS     1A  O  9 77
     A          R CTL01                     SFLCTL(SFL01)
     A                                      RTNCSRLOC(&RCD &FLD &POS)
     A  31                                  SFLDSP
     A  32                                  SFLDSPCTL
     A  30                                  SFLCLR
     A  33                                  SFLEND(*SCRBAR *MORE)
     A                                      SFLSIZ(9999)
     A                                      SFLPAG(0013)
     A                                      OVERLAY
     A            RCD           10A  H
     A            FLD           10A  H
     A            POS            4S 0H
     A                                  1  3'SORTSFL - Column Sortable Subfile -
     A                                      Example'
     A                                      DSPATR(HI)
     A                                  3  3'You can sort this subfile two ways-
     A                                      :'
     A                                      COLOR(BLU)
     A                                  4  3'(a) Position MOUSE on a blue colum-
     A                                      n heading and press F9 to sequence -
     A                                      or'
     A                                      COLOR(BLU)
     A                                  5  3'(b) enter a partial search charact-
     A                                      er string in the search field below'
     A                                      COLOR(BLU)
     A            HEADDATE      10A  O  7  3DSPATR(UL)
     A                                      COLOR(BLU)
     A            HEADTIME      10A  O  7 14DSPATR(UL)
     A                                      COLOR(BLU)
     A            HEADUSER      10A  O  7 25DSPATR(UL)
     A                                      COLOR(BLU)
     A            HEADTEXT      40A  O  7 36DSPATR(UL)
     A                                      COLOR(BLU)
     A            HEADSTAT       1A  O  7 77DSPATR(UL)
     A                                      COLOR(BLU)
     A            SRCHDATE      10A  B  8  3CHGINPDFT
     A                                      COLOR(BLU)
     A            SRCHTIME      10A  B  8 14CHGINPDFT
     A                                      COLOR(BLU)
     A            SRCHUSER      10A  B  8 25CHGINPDFT
     A                                      COLOR(BLU)
     A            SRCHTEXT      40A  B  8 36CHGINPDFT
     A                                      COLOR(BLU)
     A            SRCHSTAT       1A  B  8 77CHGINPDFT
     A                                      COLOR(BLU)
     A          R CMD01
     A            MOUSECLICK     2Y 0B 23  3PSHBTNFLD
     A                                      PSHBTNCHC(1 '>Enter')
     A                                      PSHBTNCHC(3 'F3 e>Xit' CA03)
     A                                      PSHBTNCHC(9 'F9 >Sort' CF09)
     A                                 24  3'No Data matches the Selection crit-
     A                                      eria'
     A N69                                  DSPATR(ND)
     A                                      COLOR(RED)

A few important design points in this DDS:

  • The HEAD* fields (HEADDATE, HEADTIME, HEADUSER, HEADTEXT, HEADSTAT) are output only with underline and blue colour. They are visual targets only.
  • RTNCSRLOC(&RCD &FLD &POS) is specified on the CTL01 record so we can detect exactly where the cursor is sitting when F9 is pressed.
  • The SRCH* fields sit directly below the headings on row 8 and are input capable with CHGINPDFT.
  • At the bottom we have a PSHBTNFLD called MOUSECLICK that gives the user nice mouse-friendly buttons, including CA03 on the F3 Exit choice.
  • Helpful text on rows 3-5 tells the user exactly how to sort or search.

Detecting Column Clicks with RTNCSRLOC and the HEAD* Fields

When the user places the cursor on one of the blue underlined headings and presses F9, the program receives control with the FLD hidden field populated by RTNCSRLOC.

Here is how the HandleColumnClick procedure uses it:

Dcl-Proc HandleColumnClick;
   Dcl-S newSortField char(10) inz('');
   
   Select;
      When (fld = 'HEADDATE' or fld = 'SRCHDATE');
         newSortField = 'SORTDATE';
         
      When (fld = 'HEADTIME' or fld = 'SRCHTIME');
         newSortField = 'SORTTIME';
         
      When (fld = 'HEADUSER' or fld = 'SRCHUSER');
         newSortField = 'SORTUSER';
         
      When (fld = 'HEADTEXT' or fld = 'SRCHTEXT');
         newSortField = 'SORTTEXT';
         
      When (fld = 'HEADSTAT' or fld = 'SRCHSTAT');
         newSortField = 'SORTSTATUS';
         
      Other;
         SortField = 'SORTDATE';
         SortOrder = SORT_ASCENDING;
         Return;
   EndSl;
   
   If (newSortField <> '');
      SortField = newSortField;
      ToggleSortOrder();
   EndIf;
end-proc;

This works beautifully whether the user clicked with the mouse or tabbed to the heading and pressed F9. The FLD value tells us precisely which HEAD* field (or even which SRCH* field) the cursor was on.

Search Fields and Dynamic SQL Filtering

The SRCH* fields on row 8 feed directly into the BuildWhereClause procedure. Partial characters are allowed and the search is case-insensitive:

Dcl-Proc HandleColumnClick;
   Dcl-S newSortField char(10) inz('');
   
   Select;
      When (fld = 'HEADDATE' or fld = 'SRCHDATE');
         newSortField = 'SORTDATE';
         
      When (fld = 'HEADTIME' or fld = 'SRCHTIME');
         newSortField = 'SORTTIME';
         
      When (fld = 'HEADUSER' or fld = 'SRCHUSER');
         newSortField = 'SORTUSER';
         
      When (fld = 'HEADTEXT' or fld = 'SRCHTEXT');
         newSortField = 'SORTTEXT';
         
      When (fld = 'HEADSTAT' or fld = 'SRCHSTAT');
         newSortField = 'SORTSTATUS';
         
      Other;
         SortField = 'SORTDATE';
         SortOrder = SORT_ASCENDING;
         Return;
   EndSl;
   
   If (newSortField <> '');
      SortField = newSortField;
      ToggleSortOrder();
   EndIf;
end-proc;

The LoadSubfile procedure then builds the complete dynamic SELECT with the WHERE clause and the chosen ORDER BY, prepares it, opens a cursor, and loads the subfile. Proper cleanup with CLOSE and good error logging via LogMessage keeps everything solid.

CA versus CF Function Keys – Clean Exit with CA03

Look at the bottom push button definition in the DDS:

A            MOUSECLICK     2Y 0B 23  3PSHBTNFLD
A                                      PSHBTNCHC(3 'F3 e>Xit' CA03)
A                                      PSHBTNCHC(9 'F9 >Sort' CF09)

The Exit option uses CA03. This is the correct choice. When the user clicks F3 (or presses the key), CA03 returns only the key – it does not send the current screen data back. The user can exit immediately even if the search fields contain incomplete or invalid data. No validation gets in the way.

In the RPG we simply check the indicator:

When (indicators.exit);
   leave;

Using CA03 here gives the quick, frustration-free exit that users expect.

Using AI as Your Coding Companion

This combination of a clear DDS with visual cues on the HEAD* fields, RTNCSRLOC for cursor detection, and well-structured SQLRPGLE procedures is exactly the kind of code that benefits from having an AI pair programmer looking over your shoulder.

The AI will remind you to keep the HEAD* fields as output-only with consistent colouring and underlining so the visual target is obvious. It will check that RTNCSRLOC is returning the field name you expect and that your HandleColumnClick logic covers every HEAD* field. It will review the BuildWhereClause escaping and suggest the %scanrpl technique for single quotes. It will also catch small things like making sure the subfile clear and reload logic is clean before every EXFMT, and that you close the cursor properly after use.

Most of all it keeps the whole solution user-friendly and maintainable. When the DDS tells the user on-screen exactly how to sort or search, and the RPG reacts cleanly to either method, you end up with an application that feels thoughtful and professional.

That is the real value of treating AI as a coding companion – it helps you produce code that is not just correct, but clear, robust, and a pleasure for the next developer (or future you) to work with.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>