Monday 30 July 2007

ABAP: How to setup a Screen containing a Table

This little guide aims to serve as a general template regarding how to create a SAP screen in a dialog module or a report program that will allow the user to edit data stored in an internal table using a table control grid. This may not appear to be the most elegant of approaches to programming but that is the way ABAP works.

First of all lets keep in mind that: in order to pass data to and from screen fields, they must have the same name as a global variable. Having said that we must define a global array containing our data and a global table view control that will be used to program the data transfers.

Let us start with the data. Assuming that the table you wish to work with corrsponds to an ABAP dictionary structure named ZMY_STRUCT, then the table definition might look something like the following:

* Basic ITAB
DATA  BEGIN OF tbl_mydata OCCURS 0.
DATA:  sel TYPE c.
       INCLUDE STRUCTURE zmy_struct.
DATA:  END OF tbl_mydata.

One can reasonably ask why a table with a header line and again why an ABAP dictionary structure. The answer to both questions will be given shortly afterwards but for now let's just say that things work much easier this way, or otherwise they don't work at all :-). The table control definition should be something like

CONTROLS :
 tc_mydata TYPE TABLEVIEW USING SCREEN 0200.

Make sure that the screen number corresponds to the actual screen number of your program. Next move to the screen and press the layout button to invoke the screen painter. Inside the screen drop a table control item and name it TC_MYDATA. Size it so that it fits your screen according to your needs. Double click on the table control to bring up the properties dialog box.

The sel field of the tbl_mydata table will mark the user selected lines. Getting a field symbol to point at the selected line is as easy as writing something like :

 FIELD-SYMBOLS
   <fs> LIKE LINE OF tbl_mydata.

 READ TABLE tbl_mydata ASSIGNING <fs> WITH KEY sel = 'X' .
 IF NOT <fs> IS ASSIGNED.
   MESSAGE s888(sabapdocu) WITH text-e01. " No Selection
 ELSE.
*   Do what ever you want with -...

 ENDIF.

Now press F6 to invoke the screen painter Dict.Program Fields window. In the field named Table field Name enter a search patter like like TBL_MYDATA-* and press the button labeled Get from program to display the matching table entries. Select the ones you wish to add to you screen and press the green ok button at the bottom. Then click inside the table view control to create the appropriate columns. Had the tbl_mydata table been declared any other way -- i.e. using a TYPES section or without the header line, then the process or field selection through F6 would not work.

Note: At this point just save the screen and exit screen painter without performing any kind of syntax check or activation.

Moving back to the screen properties, the basic flow logic should at least contain the following


PROCESS BEFORE OUTPUT.

 MODULE status_0200.

 LOOP AT tbl_mydata WITH CONTROL tc_mydata
                        CURSOR tc_mydata-current_line.

   MODULE read_tbl_line.
 ENDLOOP.


PROCESS AFTER INPUT.

 MODULE exit_screen_0200 AT EXIT-COMMAND.

 LOOP AT tbl_mydata.

   MODULE write_tbl_line.
 ENDLOOP.

 MODULE user_command_0200.

The basic idea is that during PBO the contents of the entire table are copied from the table to the table control. Then during PAI the contemns of the table control will be copied from the control back to the table.

Before copying any data though, we must first set the size of the table control. The best place to do this is probably at the status module. Now, although my mother told me never to use global variables, the usual approach to setting the table size during PBO, starts by declaring a global field named somthing liketotal_entries or table_size being of type i. Having done that your status_XXX module should at least contain the following.

MODULE status_0200 OUTPUT.
 SET TITLEBAR 'TB_200'.
 SET PF-STATUS 'SCREEN-0200'.

 DESCRIBE TABLE tbl_istat LINES total_entries.
 tc_mydata-lines = total_entries.
ENDMODULE.                 " status_0200  OUTPUT

To create the read_tbl_line module, double click on the read_tbl_line inside the screen flow editor. A message will pop up asking if the a module named read_tbl_line should be created. Answer yes and depending on the type of program you are creating select the appropriate file. After you press ok, change the text in the editor so it looks like this.

MODULE read_tbl_line OUTPUT.
 MOVE-CORRESPONDING tbl_mydata TO tc_mydata.
ENDMODULE.                 " read_tbl_line  OUTPUT

Finally the write_tbl_line PAI module does the exact opposite. It moves the data from the table control back to the internal table.

MODULE write_tbl_line INPUT.
 MODIFY tbl_mydata INDEX tc_mydata-current_line.

 IF sy-subrc <> 0.
   APPEND tbl_mydata.
 ENDIF.

ENDMODULE.                 " write_tbl_line  INPUT

From now on any code executing during the user_command_XXX module will get a consistent copy of the data.

Screen programming in ABAP is a complex subject. This post provides only the basic template for minimal operations. More post will follow explaining how to respond to data changes, sort tables based on selected columns and dynamically changing your screen.

No comments :