Numerous SAP transactions use "table controls" to display data or to let the user enter data in tabular form. With InputAssistant you can create additional columns in a table control, both to display data or to let the user enter additional data to be processed later on in an InputScript.

The technique for displaying data is not particularly complex, but handling data entry requires a little more attention to detail. In this tutorial we first cover read-only; then in the second part the scenario of data entry into our new columns.

Our sample application for this tutorial: In transaction VA01 (order entry) we want to offer the user a new button "Show previous order info" that, when clicked,  displays the previously ordered quantity for each material entered so far. For each order item we have to read the previous orders for this material from the same customer, using an SAP BAPI call. In the table control we add 3 columns that will be used to display the quantity ordered, the order date and the order number for this material.

For producing the images of the example, we used SAP GUI 7.40 on an SAP ECC 6.0 IDES system. The example can also be used, without any changes, on previous SAP versions, e.g. on SAP 4.6C with SAP GUI 6.20 or 6.40.


VA01 Order entry: we add a button "Show previous order info" that will insert three new columns

 


The previously ordered quantity, order date and order number are shown in three new columns for each  material

 

We implement this feature in two steps. First, we implement the new button that displays three new additional table columns:

// GuiXT Script SAPMV45A.E4001.TXT

// only for transaction VA01, page sales
if
Q[Transaction=VA01] and Q[Page=Sales]

  // show button at end of table (right of iconized button "Item details: ..")
  if not V[VA_show_cols]
    Pushbutton
P[Item details: Configuration]+(0,15) "@3S@Show previous order info" process=
"VA_show_cols.txt"
  else
   
Pushbutton P[Item details: Configuration]+(0,15) "@3T@Hide previous order info" process="VA_hide_cols.txt"

    // add three new table columns to display previous order quantity for each item
    Column "Prv.Quant." size=10 name="VA_pq"  position=4 -readonly  -alignright
    Column
"Prv.Date"   size=10 name="VA_pd"  position=5 -readonly  -alignright
    Column
"Prv.OrdNo." size=10 name="VA_po"  position=6 -readonly  -alignright

  endif
endif


We can reset the flag V[VA_show_cols] in the inital screen of VA01, otherwise the configuration selected by the user (show or hide the additional info) will remain valid for the next VA01 transaction as well.

The two InputScripts are quite simple:

// InputScript VA_show_cols
Set
V[VA_show_cols] "X"
Return

// InputScript VA_hide_cols
Set
V[VA_show_cols] ""
Return


So far we have created 3 empty columns that the user can show or hide clicking the new button

It is also possible to display a suitable icon in the column headers. Example:

 


Additional icons are displayed in the column titles

As usual, this is done with the notation "@xx@text..." where xx is the SAP icon id. In this case we used the icon id @OX@.

    // add three new table columns with icons to display previous order quantity for each item
    Column "@OX@Prv.Quant." size=10 name="VA_pq"  position=4 -readonly  -alignright
    Column
"@OX@Prv.Date"   size=10 name="VA_pd"  position=5 -readonly  -alignright
    Column
"@OX@Prv.OrdNo." size=10 name="VA_po"  position=6 -readonly  -alignright

Finally, we need to put the required data into our new columns. The variables behind the columns are named according to the "name=.." parameter in the Column command, and appended with the row number. Example:

row1:         V[VA_pq.1]      V[VA_pd.1]       V[VA_po.1]
row2:         V[VA_pq.2]      V[VA_pd.2]       V[VA_po.2]
row3:         V[VA_pq.3]      V[VA_pd.3]       V[VA_po.3]
row4:         V[VA_pq.4]      V[VA_pd.4]       V[VA_po.4]
row5:         V[VA_pq.5]      V[VA_pd.5]       V[VA_po.5]
row6:         V[VA_pq.6]      V[VA_pd.6]       V[VA_po.6]
row7:         V[VA_pq.7]      V[VA_pd.7]       V[VA_po.7]
row8:         V[VA_pq.8]      V[VA_pd.8]       V[VA_po.8]
row9:         V[VA_pq.9]      V[VA_pd.9]       V[VA_po.9]
row10:       V[VA_pq.10]    V[VA_pd.10]     V[VA_po.10]

row11:       V[VA_pq.11]    V[VA_pd.11      V[VA_po.11]

The row index is valid for the whole table control, not only for the visible part. For example, when the user scrolls the table control to row 4, only the rows shown in blue in the above diagram will be visible on screen.

When you set values into the column variables V[VA_pq.1],..., two different approaches are possible. Either you fill all variables at the beginning of the transaction, and do not bother about scrolling. This works fine if the whole table is in readonly mode. In our case it would not be the right approach, since the user can change the material number for each item, or can delete and insert new rows. In such cases it is better to set the column variables each time the screen is displayed, and to set it for the visible (blue coloured) part only. Essentially you need some coding of the following type in order to do this:

// loop through all visible table rows
GetTableAttribute T[All items] firstvisiblerow="fvr"

Set V[i] 1        // row number on screen (visible part only)
Set V[k] &V[fvr]
  // absolute row number; this would be k=4 in the example above

label prev_order_beg

// valid row left?
Set V[item] "&cell[All items,Item,&V[i]
]"
if not V[item]
  goto
prev_order_end
endif

//process visible row i. The absolute row number is k

...  Set V[colvar.&V[k]]  "some value"

// next row
Set V[i] &V[i] + 1
Set V[k] &V[k] + 1
goto
prev_order_beg

label prev_order_end

Finally, we need to read the right data within this framework. For this purpose we call "BAPI_SALESORDER_GETLIST" for each line. The input parameters for the BAPI are the customer number, the material number and the sales area.  The BAPI then returns a table of order items for the given customer/material/sales area. The orders are sorted according to date, with the most recent one at the top, so the first line of this table will already contain the most recent order.

Since the order quantity is returned in packed format, we apply the "-unpack" option of the "Set" command. We also delete leading zeros in the order number, and display the date in format DD.MM.YYYY. The whole script is as follows:

// GuiXT Script SAPMV45A.E4001.TXT

// only for transaction VA01, page sales
if
Q[Transaction=VA01] and Q[Page=Sales]

  // show button at end of table (right of iconized button "Item details: ..")
  if not V[VA_show_cols]
    Pushbutton
P[Item details: Configuration]+(0,15) "@3S@Show previous order info" process=
"VA_show_cols.txt"
  else
   
Pushbutton P[Item details: Configuration]+(0,15) "@3T@Hide previous order info" process="VA_hide_cols.txt"

    // add three new table columns to display previous order quantity for each item
    Column "Prv.Quant." size=10 name="VA_pq"  position=4 -readonly  -alignright
    Column
"Prv.Date"   size=10 name="VA_pd"  position=5 -readonly  -alignright
    Column
"Prv.OrdNo." size=10 name="VA_po"  position=6 -readonly  -alignright

    // loop through all visible lines
    GetTableAttribute T[All items] firstvisiblerow="fvr"

    Set V[i] 1
    Set V[k] &V[fvr]

    // delete previous values
    Set V[VA_pq.*] ""
    Set V[VA_pd.*] ""
    Set V[VA_po.*] ""

    Set V[customer] "&F[Sold-to party]"
    Set V[customer] 10000000000 + &V[customer]
    Set V[customer] &V[customer](2-11)

label prev_order_beg

    // any item left?
    Set V[item] "&cell[All items,Item,&V[i]]"
    if not V[item]
      goto prev_order_end
    endif

    Set V[matnr] "&cell[All items,Material,&V[i]]"
    if not V[matnr]
      goto prev_order_end
    endif

    // read order info via SAP BAPI
    Call "BAPI_SALESORDER_GETLIST" in.CUSTOMER_NUMBER="&V[customer]" in.SALES_ORGANIZATION="&F[Sales area]" in.MATERIAL="&V[matnr]" table.SALES_ORDERS=so

    // read first line, it contains the most recent order for this material
    CopyText fromText="so" toString="sowa" line=1

    if Q[ok]   // otherwise there is no previous order for this material

      // now move some fields from the returned BAPI table into our new columns

      // quantity: The BAPI returns it as 'packed decimal' incl. 3 decimal places
      Set V[quantity] "&V[sowa](BAPIORDERS-REQ_QTY)" -unpack
      Set V[quantity] "&V[quantity]" / 1000 decimals=0
      Set V[VA_pq.&V[k]] "&V[quantity]"

      // date: It comes in format YYYYMM, we use DD.MM.YYYY here
       Set V[date] "&V[sowa](BAPIORDERS-DOC_DATE)"
       Set V[VA_pd.&V[k]] "&V[date](7-8).&V[date](5-6).&V[date](1-4)"

      // order number: comes with leading 0 that we get rid of with a calculation
      Set V[ordno] "&V[sowa](BAPIORDERS-SD_DOC)"
      Set V[ordno] &V[ordno] + 0
      Set V[VA_po.&V[k]] "&V[ordno]"

    endif

   Set V[i] &V[i] + 1
    Set V[k] &V[k] + 1
    goto prev_order_beg

label prev_order_end

  endif  // V[VA_show_cols]

endif // VA01 + page=Sales

 

Our second example deals with data entry in transaction ME51N (Create Purchase Requisition) using additional table columns. In this transaction most of the item information can be entered directly in table columns, but some additional fields require that we open the "Detail" view for the item, click on the right tab in the detail view, and enter the information into a separate field on this tab.

Remark: In relatively new SAP systems (e.g. SAP ERP2004 and upwards), the user can choose between a "grid control" and a "table control" for data entry in ME51N (button "Personal setting" in the toolbar). The technique that we describe here applies to the table control only, not to the grid control.


Standard screen: The user enters the "Purch.Org." in the tab "Source of supply" of the detail screen for each item

 

For one of these fields, the "Purchase Organization" in tab "Source of Supply", we want to create a new column in the table control where the user can enter the purchase organization for each item directly, without having to open up the detail view for this item.


Enhanced table: The user enters the "Purch.Org." into a new column in the table control.

 

Compared to other SAP transactions,  ME51N has certain idiosyncrasies:

  • There is no initial screen, so we have to find a convenient way to reset our variables.

  • The user can hide and display various screen parts (text area, item table, detail view).

Another difficulty that we may experience here and in numerous other transactions is that the user can "save" on a popup that is displayed when he presses F3, F12 or F15 (Return, Cancel, Leave) in the transaction. We need a way to start our updating InputScript in these cases as well.

First let's look at the GuiXT script:

if Q[Transaction=ME51N]

// if table is visible (can be hidden by user)
if T[Table]

  // no entries in table? then clear all ME51N_ variables
  GetTableAttribute T[Table] FirstVisibleRow=fvr

  if V[fvr=1]
  
Set V[matnr] "&cell[Table,Material,1]"
  
if not V[matnr]
   
Set V[ME51N_*] ""
  
endif
 
endif

  // create new column
 
Column "POrg" position=8 size=4 name="ME51N_EKORG" keycolumn="Requisn. item" techname="MEREQ3322-EKORG"

  // Additional column is active
 
Set V[ME51N_active] "X"
endif

 

// Additional column is active? else stop of script processing
if not
V[ME51N_active=X]
  Stop
endif

// no entry field in detail screen to avoid synchronization with table column
if F[Purch. organization]
 
del F[Purch. organization]
endif

// when saving call own script
on "/11"       process="ME51N_save.txt"
 

// when checking call own script
on "/39" process="ME51N_save.txt"
 
using MODE = "C"
 

// when the user leaves the transaction, handle the "do you want to save" popup
on "/3"  process="ME51N_leave.txt"
on "/12" process="ME51N_leave.txt"
on "/15" process="ME51N_leave.txt"

endif

Some comments on the script:

  • We reset the variables when the item table is empty. 

  • Our new column "POrg" uses the item number as key column. This is necessary since the user can delete items, and the absolute row number will then change for each item above the deleted one. GuiXT uses the value in the key column as index as soon as it is available.

  • We also define a searchhelp for the new column (techname=...)

  • The standard data entry field for the purchase organization is deleted from the screen. If we were to allow data entry in this field, it would become difficult to synchronize the field with the column data entry

  • When the user presses the "check" button, we also first transport the entered "POrg" fields from our added column to the standard SAP fields, so that the checking is done for these fields as well. We use the same script "ME51N_save.txt", but provide an additional parameter MODE = "C".

  • For the exit function "/3", "/12", "/15" we start a separate InputScript "ME51N_leave.txt".

  • For GuiXT versions before version 2007 Q1 1, it was also necessary to add On "/Menu=x,y" statements in order to handle menu clicks that correspond to /11, /2, /12,... This is now no longer necessary, the On "/11",... is processed automatically in these cases.

The "ME51N_leave.txt" script handles the popup that is displayed when the user leaves the transaction:

 // InputScript "ME51N_leave.txt"

// popup screen "do you want to save the document first"
Screen
SAPLSPO1.0100
 
On "=YES" process="ME51N_save.txt"
   
using POPUP = "X"
   
using MODE = "S"

It also starts the "save" InputScript, setting the parameter POPUP = "X". The "save" InputScript first cancels the popup and then runs through the normal "save" procedure. It also  handles cases in which the "detail" view is not yet opened by the user, i.e. the InputScript opens the view and closes it at again the end.

// InputScript "ME51N_save.txt"
Parameter
POPUP "N" // "X" means: started form leave--popup
Parameter
MODE "S" // S= Save C = Check

// No return on error, otherwise entered data could be lost
ProcessingOption ReturnOnError=Off

// A variablle indicates whether the InputScript had to open the "detail view"
Set
V[ME51N_detail] ""

// started from "do you want to save?" popup?
if U[POPUP=X]
 
Enter "=CANC" // cancel popup, save at end of InputScript
else
  Enter
endif

// Set correct title to be displayed during InputScript processing
if
U[Mode=S]
 
Set V[ME51N_Title] "Saving the Purchase Requisition... Please wait"
else
 
Set V[ME51N_Title] "Checking the Purchase Requisition... Please wait"
endif

Screen saplmegui.0014
 
Title "&V[ME51N_Title]"

  // Item table opened?
 
if T[Table]
    goto
item_table_open
  endif

 
// open item table
 
Enter "=MEV4001BUTTON"

Screen saplmegui.0014
 
Title "&V[ME51N_Title]"

  label item_table_open

  // Row index variables
 
Set V[absrow] 1 // Absolute row number
 
Set V[relrow] 1 // Relative row number

  // Position details opened?
 
if S[REQ_ITEM_DETAIL]
    goto
position_details_open
  endif

  // open position details
 
Enter "=MEV4002BUTTON"
 
Set V[ME51N_detail] "X"

Screen saplmegui.0014
 
Title "&V[ME51N_Title]"

  label position_details_open

  GetTableAttribute T[Table] FirstVisibleRow=FVisRow

  if V[FVisRow=1]
    goto
scroll_beg_done
  endif

  // scroll to first line
 
Enter "/ScrollToLine=1" Table="T[Table]"

  label new_screen

Screen saplmegui.0014
 
Title "&V[ME51N_Title]"

  label scroll_beg_done

  GetTableAttribute T[Table] FirstVisibleRow=FVisRow LastVisibleRow=LVisRow LastRow=LastRow
 
Set V[relrow] 1

  label new_row

  // end of table?
 
if V[absrow>&V[LastRow]]
    goto
end_of_table
  endif

  // end of screen?
 
if V[absrow>&V[LVisRow]]
   
Enter "/ScrollToLine=&V[absrow]" Table="T[Table]"
    goto
new_screen
   endif

  Set V[item] "&cell[Table,Requisn. item,&V[relrow]]"
 
if not V[item]
   goto
end_of_table
  endif

  Set V[ME51N_EKORG] "&V[ME51N_EKORG.&V[item]]"
 
Set V[ME51N_EKORG_previous] "&V[ME51N_EKORG.&V[item]_previous]"

  // no new input?
 
if V[ME51N_EKORG=&V[ME51N_EKORG_previous]]
   
Set V[absrow] &V[absrow] + 1
   
Set V[relrow] &V[relrow] + 1
    goto
new_row
  endif

  // Save input
 
Set V[ME51N_EKORG.&V[item]_previous] "&V[ME51N_EKORG]"

  // Set cursor into row and choose detail view
 
SetCursor cell[Table,Requisn. item,&V[relrow]]
 
Enter "/2"

Screen SAPLMEGUI.0014
 
Title "&V[ME51N_Title]"

  if F[Purch. organization]
    goto
screen_EKORG
  endif

  // To TAB "Source of Supply"
 
Enter "=TABREQDT7"

Screen SAPLMEGUI.0014
 
Title "&V[ME51N_Title]"

  label screen_EKORG

  Set F[Purch. organization] "&V[ME51N_EKORG]"
 
Set V[absrow] &V[absrow] + 1
 
Set V[relrow] &V[relrow] + 1
  goto
new_row

label end_of_table

  // detail view opened?
 
if not V[ME51N_detail=X]
   goto
screen_collapse_done
  endif

  // collapse detail view again
 
Enter "=MEV4002BUTTON"

Screen SAPLMEGUI.0014
 
Title "&V[ME51N_Title]"

  label screen_collapse_done

  // Save or check
 
if U[MODE=S]
   
Enter "/11"
  else
   
Enter "/39"
  endif

  // started from popup? else end of script
 
if not U[POPUP=X]
   Leave
  endif

 

// back to main screen after popup + save procedure
Screen
SAPLMEGUI.0014
 
Enter "/3"

// popup is displayed again (but nothing to save now) -> press "No" to leave the transaction
Screen SAPLSPO1.0100
 
Enter "=NO"

 

When you use "goto" and "label" in the script, please observe the difference between the following versions (the correct one and a wrong one):

(1)

Screen saplmegui.0014
// Item table opened?

 
if T[Table]
    goto
item_table_open
  endif

 
// open item table
 
Enter "=MEV4001BUTTON"

Screen saplmegui.0014
 
  label item_table_open

(2)

 Screen saplmegui.0014
// Item table opened?
 
if T[Table]
    goto
item_table_open
  endif

 
// open item table
 
Enter "=MEV4001BUTTON"

  label item_table_open
Screen
saplmegui.0014
 
 

The second version (label before Screen command) would be wrong: no "Enter" is executed for the first "Screen" command, and therefore the InputScript will display the screen and wait for user input instead of continuing.

Another possible error would be to include a Screen command into an if...endif clause:

 Screen saplmegui.0014
// Item table opened?
 
if not T[Table]

     // open item table
    
Enter "=MEV4001BUTTON"

     Screen saplmegui.0014 
  
  endif

Here GuiXT would issue a syntax error message, since  if...endif clauses have to be closed within one static Screen block.

After these negative examples, here is an alternative that will work: You use the "goto" to go back to the same Screen command, after entering a suitable function code to open up the table or detail view.

...
label
main_screen

Screen saplmegui.0014
 
Title "&V[ME51N_Title]"

  // Item table opened?
 
if not T[Table]
   
// open item table
   
Enter "=MEV4001BUTTON"
    goto
main_screen
  endif
 

 // Position details opened?
 
if not S[REQ_ITEM_DETAIL]
   
// open position details
   
Enter "=MEV4002BUTTON"
    goto
main_screen
  endif

  GetTableAttribute T[Table] FirstVisibleRow=FVisRow
  if V[FVisRow=1]
    goto
scroll_beg_done
  endif

   // scroll to first line
  
Enter "/ScrollToLine=1" Table="T[Table]"
 

label new_screen

Screen saplmegui.0014
 
Title "&V[ME51N_Title]"

  label scroll_beg_done

...

In this case, it is important that you put the label "main_screen" before the Screen command. If you put it after the Screen command,  GuiXT would continue, after the Enter, to execute the script. You would then end up with more than one  Enter for one screen, which makes no sense and in fact would lead to a GuiXT syntax error message, and the first "Enter" would be lost. So when you write complex InputScripts please bear in mind that you perform at most one  Enter  for each Screen, and in most cases exactly one. There are only two cases where it makes sense to have a Screen command without Enter: Either when you want to display the Screen and still stay within the InputScript, a possibility that we used in the "ME51N_leave.txt" InputScript above to handle the popup. Or (a very special case) when you use the "ApplyGUIScript" statement to call up  VBScript, and your VBScript program performs an "Enter" action itself (e.g. presses a pushbutton).