IBM Support

Example of a table processing program

Question & Answer


Question

How about an example of a table processing program?

Answer

Tables are an easy way to organize data in ISPF.  Here is an example of a REXX exec to collect employee data and save it in a table. The code is broken up into sections to make it easier to talk about.  You can cut and paste the parts into an ISPF edit session to get a working ISPF table application.

/* REXX */                                                              
Address ISPEXEC                                                         
"CONTROL ERRORS RETURN"                                                 
"LIBDEF ISPTABL DATASET ID('xxxxxx.PRIVATE.TABLES')"                    
"LIBDEF ISPTLIB DATASET ID('xxxxxx.PRIVATE.TABLES')"                    
"LIBDEF ISPPLIB DATASET ID('xxxxxx.PRIVATE.PANELS')"  
The initial /* REXX */ comment tells TSO that this procedure is a REXX exec. The Address ISPEXEC statement tells TSO to let ISPF handle the lines in quotation marks ("). The first statement to be processed by ISPF is CONTROL ERRORS RETURN.  The CONTROL statement tells ISPF that if any of the services fail, the application handles the error, rather than having ISPF put up a severe error panel. The next 3 statements use the LIBDEF service to define which libraries are associated with which dialog elements.  ISPTABL is the ddname for tables output library.  Since this application makes changes to a table, we must allocate a data set to ISPTABL. ISPTLIB is the ddname for the input tables. ISPPLIB is the ddname for the panels.

"TBOPEN xyztable"                                                       
If rc = 8 Then /* If table does not already exist, create it with one */  
  Do           /* blank row */                                            
    "TBCREATE xyztable",                                                  
        "NAMES(XYZACTCD, XYZNAME, XYZJOB, XYZDEPT )"                      
    "TBVCLEAR xyztable"                                                   
    "TBADD xyztable"                                                      
  End        
The next statement calls the TBOPEN service to open a table named XYZTABLE. The If statement checks the return code from the TBOPEN service.  A return code of 8 from TBOPEN indicates that the table does not exist yet.  If the table does not exist, the TBCREATE statement creates it.  The table has 3 variables for each employee. XYZNAME holds the employee name, XYZJOB holds the employee's job title, and XYZDEPT holds the department number. XYZACTCD is an action code so that users can run commands on a table row.

TBVCLEAR sets all the table variables to blank. The TBADD statement puts a new row into the table containing the current contents of all the variables in the table. These 2 statements together add a blank row to the table.

ztdsels = 0                                           
ztdtop = 1                                            
zcmd = ""                                             
cursor_loc = "CSRROW(1) CURSOR(XYZACTCD)"    
 
Variable initialization comes next. Variables starting with the letter Z are owned by ISPF.  Don't give any application variables names that start with Z. ZTDSELS and ZTDTOP are special variables set by the TBDISPL service. ZTDSELS contains the number of table rows that the user selected. ZTDTOP is the number of the first row displayed on the table. ZCMD contains whatever is typed on the command line. Cursor_loc is an application variable to hold a string that tells ISPF where to place the cursor on the panel.
Do Forever                                                       
  "TBTOP  xyztable"                                              
  "TBSKIP xyztable NUMBER("ztdtop")"                             
  If ztdsels = 0 Then                                            
    Do                                                           
      "TBDISPL xyztable PANEL(XYZPANEL) AUTOSEL(NO)" cursor_loc  
      cursor_loc = ""                                            
    End                                                          
  Else                                                           
    "TBDISPL xyztable"              
 
The Do Forever statement displays the table in an infinite loop.  Since TBTOP puts the Current Row Pointer (CRP) to before the first line of the table, the TBSKIP statement is needed to point to the first line of the table to be displayed. Variable ZTDSELS is set by the TBDISPL service to tell whether rows are selected but not yet processed.  If no rows are selected, the TBDISPL service displays the table on panel XYZPANEL. If there are rows left to be processed, the TBDISPL service does not use the PANEL keyword to tell ISPF which panel to use. Rather, since there is no panel parameter, the TBDISPL service displays the table on the same panel as the last display.
  display_rc = rc                                                 
  xyzactcd = translate(strip(xyzactcd))                           
  Select                                                          
    When xyzactcd = "" Then  /* User typed over data on the line */
      Do                                                          
        "TBPUT xyztable"                                          
        "TBQUERY xyztable POSITION(CRPNAME)"                      
        cursor_loc = "CURSOR(XYZACTCD) CSRROW("crpname")"         
      End                                                         
    When xyzactcd = "D" Then  /* Delete the line */               
      Do                                                          
        xyzactcd = ""                                             
        "TBDELETE xyztable"                                       
        "TBQUERY xyztable POSITION(CRPNAME)"                      
        crpname = crpname + 1                                     
        cursor_loc = "CURSOR(XYZACTCD) CSRROW("crpname")"         
      End                                                         
    When xyzactcd = "I" Then /* Insert a blank line */            
      Do                                                          
        xyzactcd = ""                                             
        "TBPUT xyztable"                                          
        "TBVCLEAR xyztable"                                       
        "TBADD xyztable"         
        "TBQUERY xyztable POSITION(CRPNAME)"                           
        cursor_loc = "CURSOR(XYZNAME) CSRROW("crpname")"               
      End                                                              
    When xyzactcd = "P" Then /* Display a panel with more detail */    
      Do                                                               
        xyzactcd = ""                                                  
        "CONTROL DISPLAY SAVE"                                         
        "DISPLAY PANEL(xyzpan2)"                                       
        "TBPUT xyztable"                                               
        "CONTROL DISPLAY RESTORE"                                      
        "TBQUERY xyztable POSITION(CRPNAME)"                           
        cursor_loc = "CURSOR(XYZNAME) CSRROW("crpname")"               
      End                                                              
    Otherwise                                                          
      "TBPUT xyztable"                                                 
      zerrsm = "Invalid action code"                                   
      zerrlm = "Action code '"xyzactcd"' is not valid."                
      zerralrm = "YES"                                                 
      "SETMSG MSG(ISRZ002)"                                            
      "TBQUERY xyztable POSITION(CRPNAME)"                             
      cursor_loc = "CURSOR(XYZACTCD) CSRROW("crpname")"                
    End  
ztdsels = ztdsels - 1                                                                                                                       
 
If the enter key is pressed, the TBDISPL service sets a return code of 0 .  If the end or return key is pressed, the TBDISPL service sets a return code of 8. If the TBDISPL succeeds, we want to process any changes from the panel.  The REXX Select statement tells what action is to be taken for each of the valid line commands.
  • If the characters in the row are typed over, the TBPUT statement puts the changed row into the table.
  • If the D line command is entered, the TBDELETE statement deletes that row of the table.
  • If the I line command is entered, a blank line is added to the table.
  • If the P line command is entered, the display environment is saved with the CONTROL statement. Panel XYZPAN2 is displayed to show more detail. Any changes made on panel XYZPAN2 are put into the table with the TBPUT statement. Then, the CONTROL statement restores the display environment for the next TBDISPL.
If an invalid line command is entered, the message variables are set so that an error message can be displayed.

In all cases, the TBQUERY statement locates the row that was changed most recently and sets the cursor location based on the latest change. Then, we decrement ZTDSELS, since there is now one less line to process.

If ztdsels <= 0 Then                                          
  Do                                                          
    zverb = translate(word(zcmd,1))                           
    Select                                                    
      When display_rc = 8   /* END, RETURN, =X, etc. */,      
        |  zverb = "QUIT" Then                                
        Do                                                    
          If display_rc = 8 Then                              
            "TBCLOSE xyztable"                                
          Else                                                
            "TBEND xyztable"                                  
          Leave                                               
        End                                                   
      When zverb = "SAVE" Then                                
        Do                                                    
          "TBSAVE xyztable"                                             
        End                                                   
      When zverb = "" Then                                    
        Nop                                                   
      Otherwise                                               
        zerrsm = "Invalid command"   
        zerrlm = "Action code '"zverb"' is not valid."    
        zerralrm = "YES"                                  
        "SETMSG MSG(ISRZ002)"                             
        cursor_loc = "CURSOR(ZCMD)"                       
      End                                                 
  End                                                     
End                              
Next, we want to check for commands on the command line. ISPF variable ZCMD contains the value of the command line. We set variable ZVERB to the first word on the command line.
  • If End or Return is requested, or if ZVERB is QUIT, then we check display_rc. If display_rc indicates that the END key is pressed on the panel, then we do a TBCLOSE to save the changes and close the table. If ZVERB is QUIT but the ENTER key is pressed, the TBEND service closes the table without saving the changes.
  • If ZVERB is SAVE, the TBSAVE service saves the table.
  • If nothing is entered on the command line, nothing is done.
  • Otherwise, the command is invalid, and the ISPF error message variables are set. Again, these variable names start with Z, and they have special meaning to ISPF.  ZERRSM is the contents of the short message. ZERRLM is the contents of the long message. ZERRALRM tells whether to play a sound when the message displays. The SETMSG service displays the error message on the next panel.
"LIBDEF ISPTABL"   
"LIBDEF ISPTLIB"   
"LIBDEF ISPPLIB"   
The last 3 LIBDEF statements clear the library definitions that we set at the beginning of the procedure.

In addition to the REXX function, this application requires some screen definitions. We created a member called XYZPANEL in the panel library, xxxxxx.PRIVATE.PANELS, to hold the panel definition for the TBDISPL service:
)Attr Default(%+_)                                                      
! type( input) intens(high) caps(on ) just(left ) pad('''')             
^ type( input) intens(low ) caps(off) just(asis ) pad('_')              
)Body  Expand(//)                                                       
%-/-/- Xyztable Display Panel -/-/-                           
%Command ===>_zcmd                                 / /%Scroll ===>_amt +
%                                                                       
+Enter Action D (delete), I (insert), P (personnel details),            
+  or overtype data to update row.                                      
+                                                                       
%Action   Name                          Job                Department   
+                                                                       
)Model clear(xyzactcd)                                                  
!z +     ^z                          + ^z               + ^z            
+                                                                       
)Init                                                                   
.ZVARS = '(xyzactcd xyzname xyzjob xyzdept)'                            
&amt = csr                                                              
)End   
 
The ) in the first character identifies a section of the panel definition.
  • The )Attr section tells ISPF how each field on the panel is to be displayed.
  • The )Body section is the part that shows up on the screen.
  • The )Model section processes the rows of the panel. The clear parameter resets the action code, variable XYZACTCD, to blanks. The line following the )MODEL statement is the model itself, and it shows the format for the table display.
  • The )Init section handles panel initialization. The .ZVARS statement in the )Init section assigns any occurrence of the single character z to the variable names in the order listed. In this example, the model begins with variable XYZACTCD, and continues with variables XYZNAME, XYZJOB, and XYZDEPT. &AMT is the scroll amount, and it is set to CSR so that scrolling is based on cursor location.
  • The )END section signifies the end of the panel definition.
We added a member called XYZPAN2 to the panels library to hold the definition for the employee information panel.
)ATTR DEFAULT(%+_)                                                         
$ TYPE(INPUT) INTENS(HIGH) PAD(_) CAPS(OFF)                                
)BODY                                                                      
%----------------------------- XYZ: Enter Data -------------------------   
%COMMAND ===>_ZCMD                                                         
%                                                                          
+   Type name, job, and department:                                        
+                                                                          
+                                                                          
+     Name       %===>$xyzname                                             
+     Job        %===>$xyzjob                                              
+     Department %===>$xyzdept                                             
+                                                                          
)END        
 
This simple example shows how a table can be created, opened, updated, and displayed. There are lots of ways you can change this application to make it more robust. You can add the employee number to the table and make sure it is unique, or add a variable for a phone number or office location. You can add primary commands to sort the data or copy the data to a new table. You can add a line command to repeat a line, or you can add a digit to the I command and the D command to tell how many lines to insert or delete. You can verify data formats. Try playing around with it.

[{"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Product":{"code":"SSBLLD","label":"ISPF for z\/OS"},"Component":"ISPF","Platform":[{"code":"PF035","label":"z\/OS"}],"Version":"All Versions","Edition":"","Line of Business":{"code":"","label":""}}]

Document Information

More support for:
ISPF for z/OS

Software version:
All Versions

Operating system(s):
z/OS

Document number:
726489

Modified date:
29 January 2020

UID

swg21024010

Manage My Notification Subscriptions