Wednesday, January 10, 2018

Displaying more than one subfile at a time

more than 1 subfile on a screen

I decided to write the post after being asked if I had an example of having two subfiles on the same screen. I did a quick search using Google and was unable to find what I considered a good example I felt comfortable sharing.

In this example I am going to show two subfiles horizontally (i.e. one on top of the other). I could have shown them vertically (next to one another), or even had more than two. The principals I show here can easily be adapted to fit either of those other scenarios. The most important thing to remember is that each set of subfile and subfile control record format cannot overlap another.

To reduce the size of the display file source code, shown here, I have removed all unnecessary color and display attributes codes that I use in the screens I build. I am going to show my display source in multiple parts to make it easier to understand what each record format is for. Let me start with the file level keywords.

01  A                                      DSPSIZ(24 80 *DS3)
02  A                                      PRINT
03  A                                      ERRSFL
04  A                                      INDARA
05  A                                      CA03(03 'F3=Exit')

Those of you familiar with my posts will recognize the following keywords:

Line 3: I always use the error subfile. The display file controls it without any extra programming.

Line 4: By using the indicator area I can give the display file indicators meaningful names in my RPG program rather than use the number.

The examples I did find for more than one subfile on a screen, put the page headings in a separate record format. In my example I am going to include them in the subfile control record format, CTL01, for the first subfile, SFL01.

06  A          R SFL01                     SFL
07  A            Z1RRN          5S 0H
08  A            Z1LINE        50A  O  5  3

The subfile record format for the first subfile with just two fields.

  1. Z1RRN:  The subfile record number
  2. Z1LINE:  A field of 50 characters

The subfile control record for the first subfile, CTL01, might look complicated. Rest assured it is not, most of the code is for the screen headings.

09  A          R CTL01                     SFLCTL(SFL01)
10  A                                      SFLSIZ(0030)
11  A                                      SFLPAG(0006)
12  A                                      OVERLAY
13  A  31                                  SFLDSP
14  A  30                                  SFLDSPCTL
15  A N30                                  SFLDLT
16  A  30                                  SFLEND(*MORE)
17  A                                  1  2USER
18  A                                  1 31'R P G P G M . C O M'
19  A                                  1 63TIME
20  A                                  1 72DATE
21  A                                      EDTCDE(Y)
22  A            Z1SCREEN      12A  O  2  2
23  A                                  2 26'Example screen with 2 +
                                           subfiles'
24  A                                  2 72SYSNAME
25  A                                  3  2'                       -
26  A                                                              -
27  A                                               '
28  A                                      DSPATR(UL)
29  A                                  4 36'SUBFILE 1'

Lines 10 and 11: This is a small load all subfile of 30 records (line 10), with only six displaying on the screen at one time (line 11).

Lines 13 – 16: I am using indicators 30 and 31 to condition the display of SFL01.

Lines 17 – 29: The rest of the this record format is for the screen headings.

The second subfile is just about the same as the first.

30  A          R SFL02                     SFL
31  A            Z2RRN          5S 0H
32  A            Z2LINE        50A  O 15  3

The subfile control record format, CTL02, is very simple:

33  A          R CTL02                     SFLCTL(SFL02)
34  A                                      SFLSIZ(0030)
35  A                                      SFLPAG(0006)
36  A                                      OVERLAY
37  A  33                                  SFLDSP
38  A  32                                  SFLDSPCTL
39  A N32                                  SFLDLT
40  A  32                                  SFLEND(*MORE)
41  A                                 13  2'                       -
42  A                                                              -
43  A                                               '
44  A                                      DSPATR(UL)
45  A                                 14 36'SUBFILE 2'

Lines 33 and 34: This subfile, like the first, is a load all subfile of 30 rows, and displays six at a time.

Lines 37 – 40: I could have used the same indication to display the subfile control as I did for SFL01, but I decided that this subfile deserves its own indicators.

The last record format of the display file is the footer section, which I use to display the available function keys.

46  A          R FOOTER
47  A                                 23  3'F3=Exit'

The RPG program to display these two subfiles is also simple.

01  **free
02  ctl-opt option(*nodebugio:*srcstmt)
              dftactgrp(*no) ;

03  dcl-ds Pgm extname('RPG4DS') psds qualified
04  end-ds ;

05  dcl-f TESTDSPF workstn indds(Dspf)
06                   sfile(SFL01:Z1RRN) sfile(SFL02:Z2RRN) ;

07  dcl-ds Dspf qualified ;
08    Exit ind pos(3) ;

09    Sfl1DspCtl ind pos(30) ;
10    Sfl1Dsp ind pos(31) ;

11    Sfl2DspCtl ind pos(32) ;
12    Sfl2Dsp ind pos(33) ;
13  end-ds ;

14  Z1SCREEN = %trimr(Pgm.ProcNme) + '-1' ;

15  LoadSubfiles() ;

16  dow (1 = 1) ;
17    write FOOTER ;
18    write CTL01 ;
19    exfmt CTL02 ;

20    if (Dspf.Exit) ;
21      leave ;
22    endif ;
23  enddo ;

24  *inlr = *on ;

Line 1: Yes, this program is in all free RPG.

Line 2: My favorite control options, and I need to give the DFTACTGRP(*NO) as I am using a procedure in this program.

Lines 3 and 4: I want to display the program's name on the screen, which I will get from the program data structure. I have mine externally defined to make it easier to include into many different programs.

Lines 5 and 6: This is the definition of my display file. The INDDS is the other part off DDS's INDARA and gives the name of the indicator data structure. Line 6 contains the definitions for the subfiles. As I have more than one subfile that I will use I need to give each one its own SFILE.

Lines 7 – 13: Having just mentioned the indicator data structure here it is. Here I define variable names that I will be using instead of the indicator numbers. As I have defined the data structure with QUALIFIED the subfields will need to be qualified with the data structure's names.

Line 14: I am making the screen name from the program name retrieved from the program data structure.

Line 15: In this procedure the subfiles are loaded. I will show its content below.

Lines 16 – 23: Within this Do loop the screen is displayed.

Lines 17 – 19: These are the record formats being written to the screen. The footer record needs to be first. It does not matter whether CTL01 is written first or CTL02 is, providing the second control record format is EXFMT.

17    write FOOTER ;
18    write CTL02 ;
19    exfmt CTL01 ;

Lines 20 – 22: If the F3 key has been pressed I leave the Do loop.

The procedure to load the subfiles is a breeze.

25  dcl-proc LoadSubfiles ;
26    dcl-c MaxSfl 30 ;  // Maximum records in subfile

27    Dspf.Sfl1DspCtl = *off ;
28    Dspf.Sfl1Dsp = *off ;
29    write CTL01 ;
30    Dspf.Sfl1DspCtl = *on ;
31    Dspf.Sfl1Dsp = *on ;

32    for Z1RRN = 1 to MaxSfl ;
33      Z1LINE = 'Subfile No. 1  Record ' + %char(Z1RRN) ;
34      write SFL01 ;
35    endfor ;

36    Dspf.Sfl2DspCtl = *off ;
37    Dspf.Sfl2Dsp = *off ;
38    write CTL02 ;
39    Dspf.Sfl2DspCtl = *on ;
40    Dspf.Sfl2Dsp = *on ;

41    for Z2RRN = 1 to MaxSfl ;
42      Z2LINE = 'Subfile No. 2  Record ' + %char(Z2RRN) ;
43      write SFL02 ;
44    endfor ;
45  end-proc ;

Line 26: I defined a constant to contain the maximum number of records in the subfiles.

Lines 27 – 31: Initializing the subfile SFL01 and setting on the indicators to display it.

lines 32 – 35: This For group is used to load SFL01. I am just writing a string to each subfile record until the maximum is reached.

Lines 36 – 40: Initializing SFL02 as I did for SFL01.

Lines 41 – 44: Loading SFL02 in the same manner I did the other subfile.

When the program is compiled and run I am presented with this screen:

SIMON                       R P G P G M . C O M             TT:TT:TT DD/DD/DD
TESTPGM-1               Example screen with 2 subfiles                DEV730
______________________________________________________________________________
                                  SUBFILE 1
 Subfile No. 1  Record 1
 Subfile No. 1  Record 2
 Subfile No. 1  Record 3
 Subfile No. 1  Record 4
 Subfile No. 1  Record 5
 Subfile No. 1  Record 6
                                                                       More...
                                                                             
______________________________________________________________________________
                                   SUBFILE 2
 Subfile No. 2  Record 1
 Subfile No. 2  Record 2
 Subfile No. 2  Record 3
 Subfile No. 2  Record 4
 Subfile No. 2  Record 5
 Subfile No. 2  Record 6
                                                                       More...

F3=Exit

I can position the cursor to either subfile and Page Up or Down to my heart's content.

I like the More... and Bottom. Others do not when they are using subfiles of a limited size like in this example, preferring the "+" to indicate there are more subfile records.

If I change to use the + I can also add a seventh record to be displayed. The changes to the display would be.

11  A                                      SFLPAG(0007)

16  A  30                                  SFLEND


35  A                                      SFLPAG(0007)

40  A  32                                  SFLEND

And the screen would look like this:

SIMON                       R P G P G M . C O M             TT:TT:TT DD/DD/DD
TESTPGM-1               Example screen with 2 subfiles                DEV730
______________________________________________________________________________
                                  SUBFILE 1
 Subfile No. 1  Record 1
 Subfile No. 1  Record 2
 Subfile No. 1  Record 3
 Subfile No. 1  Record 4
 Subfile No. 1  Record 5
 Subfile No. 1  Record 6
 Subfile No. 1  Record 7                                                     +
______________________________________________________________________________
                                  SUBFILE 2
 Subfile No. 2  Record 1
 Subfile No. 2  Record 2
 Subfile No. 2  Record 3
 Subfile No. 2  Record 4
 Subfile No. 2  Record 5
 Subfile No. 2  Record 6
 Subfile No. 2  Record 7                                                     +

F3=Exit

Having more than one subfile on a screen can be very useful for displaying information to users, and, as you have seen, is not difficult to code.

 

This article was written for IBM i 7.3, and should work for earlier releases too.

11 comments:

  1. Good exercise in controlling 2 subfiles.

    ReplyDelete
    Replies
    1. if not mistaken we can display max 4 subfiles...

      Delete
  2. Pet peeve... why not "dow (Dspf.Exit = *off)" instead of "dow (1 = 1)"? Shorter and clearer, especially if the program grows more complicated. Alternatively "dou" if it's a matter of top vs. bottom testing.

    ReplyDelete
  3. I prefer DoU ( %ShtDn ) ;

    And you can use the SFLSCROLL /SFLRCDNBR RRN in each subfile DDS to keep the subfiles on their current page if user hits ENTER.

    Ringer

    ReplyDelete
  4. I did simething like this before and it was working, but my design was not approved since it did not meet any of the company standard

    ReplyDelete
    Replies
    1. Sometimes we need to be pioneers and show others what is possible.
      Any company whose standards do not evolve with end up with dinosaurs programming for them.

      Delete
  5. Pgm extname('RPG4DS') --> what are fields in this file, mister ?

    ReplyDelete
    Replies
    1. There is a link in the sentence that describes that RPG4DS is the program data structure to a post that describes and lists all the subfields for this data structure.

      Delete
  6. Thanks, Simon. I'm writing an app that makes a call to a certain number of other programs and shows the values of the output parms. Using your method, I'll gather the input parms up top and the output parms on the bottom after validation. That's my proposal anyway. I was asked just to create a pgm and screen per module but creating a table to house the name of the modules and their parms seems much more elegant.

    ReplyDelete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.