SAP GUI Scripting and GuiXT

With SAP GUI 6.20, SAP introduced a "scripting API":  an object model that represents a screen with its controls at runtime. In Windows environment the API  can be used from any tool that supports the COM object interface, especially from the VBScript and JavaScript languages. The object model allows one to automate all user actions. 

Unlike GuiXT, the SAP GUI scripting approach is not intended to change the screen layout. It completes the GuiXT functionality, allowing us to manipulate  special controls (like the grid control) that GuiXT cannot handle directly, but is restricted to actions that a user is able to do as well.

With GuiXT you can combine the two approaches. Use the new  keyword "ApplyGuiScript" in a GuiXT script or an InputScript in order to perform further actions on the screen via a VBScript.

The general procedure, clarified with a few examples, is set out below.


1 Requirements
  • SAP GUI 6.20 and upwards
  • GuiXT 2004 Q2 2 and upwards
  • For SAP kernel 3.1I-6.10: kernel patch required, see SAP note 480149
  • For SAP kernel 6.20 and above: Included in standard delivery
  • It is necessary to activate scripting support in the SAP system, and in the SAP GUI options
  • Not possible in ITS environment (SAP GUI for HTML)

2 SAP documentation

Please see the following SAP notes concerning SAP GUI scripting:

  • 480149: Kernel patch requirements
  • 587202: Limitations of SAP GUI scripting
  • 527737: Composite SAP note on SAP GUI scripting
  • 612454: Status and Lifetime
  • 619459: SAP GUI Scripting support of SAP applications

The following links provide copies of the original SAP documents, for easy access.

SAP GUI Scripting Overview

SAP GUI Scripting User Guide

SAP GUI Scripting Security Settings

SAP GUI Scripting API Help File( .chm)

To display the most recent SAP GUI Scripting documentation, please click on the options icon in the SAP GUI window and select "SAP GUI scripting help"

 

3  GuiXT scripts and SAP GUI scripting

When you execute an ApplyGuiScript command in a GuiXT script the internal procedure is as follows:

  1. SAP GUI receives a new screen description from the application server
  2. SAP GUI calls GuiXT. GuiXT reads the GuiXT script and modifies the screen description. It saves the ApplyGuiScript command but does not yet execute the VBScript.
  3. SAP GUI builds the full object model from the modified screen description
  4. GuiXT calls SAP GUI to execute the specified VBScript  

 

4  InputScripts and SAP GUI scripting

When you execute an ApplyGuiScript command in an InputScript please observe the following:

  1. Screen command is necessary before you can work with  ApplyGuiScript in the InputScript. It is not (yet) possible to use ApplyGuiScript before the first Screen command. The ApplyGuiScript command is always applied to the preceding Screen in the InputScript.
  2. Normally an Enter is used for each Screen in the InputScript. If your VBScript contains a user action that implies an "Enter" (i.e. an application server communication), you have to omit the InputScript Enter command for this screen. Try to avoid such situations if possible, since the flow of control gets complicated if both the InputScript and the VBScript process further screens. In addition, the application server communication invalidates many variables in your VBScript (e.g. screen buttons) so that special care is necessary in writing the VBScript for a case like this.

The internal procedure is as follows:

  1. During InputScript processing, SAP GUI receives a new screen description from the application server
  2. SAP GUI calls GuiXT. GuiXT reads the script and modifies the screen description. It saves the ApplyGuiScript commands, but does not yet execute the script.
  3. SAP GUI builds the full object model from the modified screen description
  4. GuiXT calls SAP GUI to execute the specified VBScript  
  5. GuiXT performs the Enter action

5  Writing and testing the VBScript

SAP GUI provides a recording mode that can generate a VBScript directly from your actions. We suggest that you start with such a recorded script. It is a good idea to test the VBScript independently of the GuiXT script before combining both.

To test the VBScript display the SAP screen where you want to apply the script. You can either:

  • Execute the VBScript outside of SAP GUI by double-clicking on the filename or by entering the name in the MS DOS command prompt
  • Or you "drag and drop" the file into the SAP GUI window

We recommend the 2nd possibility (drag&drop), since in this case you use the same SAP GUI interface  that GuiXT uses internally. Some VBScript variables, especially the "session" variable, are already defined and preset by SAP GUI when you use drag&drop. 

 

6 Example: Selecting a fixed row in a grid control

In IW38 you want to select a certain row, say the third row. First record the action in SAP GUI:

 

Save the generated VBScript in a suitable directory, e.g. "C:\guixt\sapgui scripts". The script looks as follows:

If Not IsObject(application) Then
  Set SapGuiAuto = GetObject("SAPGUI")
  Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
  Set connection = application.Children(0)
End If
If Not IsObject(session) Then
  Set session = connection.Children(0)
End If
If IsObject(WScript) Then
  WScript.ConnectObject session, "on" 
  WScript.ConnectObject application, "on"
End If
session.findById("wnd[0]").resizeWorkingPane 139,15,false
session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").currentCellRow = 2
session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectedRows = "2"

In your GuiXT script use "ApplyGuiScript" and specify the name of the VBScript file:

ApplyGuiScript "C:\guiXT\sapgui scripts\select_grid_row_3.vbs"

The screen will then show up like this:

You can simplify the VBScript if you always use the drag&drop method for testing, since the "session" variable is then defined automatically. The following script does the job as well:

Set aw = session.activeWindow()
aw.findById("usr/cntlGRID1/shellcont/shell").selectedRows = "2"

 Please observe that the row index starts with 0 in SAP GUI scripting, so the third row has index 2.

7 Example: Selecting variable rows in a grid control

To select a variable number of rows we use a template VBScript file "select_grid_rows.vbs":

Set aw = session.activeWindow()
aw.findById("usr/cntlGRID1/shellcont/shell").selectedRows = "&V[grid_rows]"

In the GuiXT script we use "ApplyGuiScript" and specify the name of the VBScript template:

Set V[grid_rows] "1,3,5"
ApplyGuiScript
template="C:\guiXT\sapgui scripts\select_grid_rows.vbs"

 

 

8 Example: Reading grid cells

We want to offer a new entry field "Search for" where the user can specify a short text (or a part of the text) to search for. When the user presses a pushbutton "Select rows" we select all grid rows that contain the specified text: 

The scripts look as follows:

GuiXT script:

pos X[GRID1] (2,0)
InputField (0,0) "Search for" (0,12) Size=20 name="pm_short_text" 
Pushbutton (0,34) "Select rows" process="grid_select_rows.txt"

InputScript "grid_select_rows.txt":

Screen saplslvc_fullscreen.0500
  ApplyGuiScript template="select_grid_rows_via_short_text.vbs"
  Enter

VBScript "select_grid_rows_via_short_text.vbs":

Set aw = session.activeWindow()
Set GRID1 = aw.FindById("usr/cntlGRID1/shellcont/shell")

Dim myselectedRows
myselectedRows = ""

for i = 0 to GRID1.rowCount - 1
  if InStr(1, GRID1.getCellValue(i,"KTEXT"), "&V[pm_short_text]", 1) > 0 then 

    if myselectedRows = "" then
      myselectedRows = CStr(i)
    else
      myselectedRows = myselectedRows + "," + CStr(i)
    end if

  end if 
next

GRID1.selectedRows = myselectedRows

Please observe that, in contrast to the table control, the grid control does not require one to scroll through it page by page. All rows are already accessible without scrolling.

You can also scroll the display so that the first selected line is shown:

Set aw = session.activeWindow()
Set GRID1 = aw.FindById("usr/cntlGRID1/shellcont/shell")

Dim myselectedRows
myselectedRows = ""

for i = 0 to GRID1.rowCount - 1
  if InStr(1, GRID1.getCellValue(i,"KTEXT"), "&V[pm_short_text]", 1) > 0 then 

    if myselectedRows = "" then
      myselectedRows = CStr(i)

     if i < GRID1.firstVisibleRow or i > GRID1.firstVisibleRow + GRID1.visibleRowCount-1 then
       GRID1.firstVisibleRow = i
     end if 

    else
      myselectedRows = myselectedRows + "," + CStr(i)
    end if

  end if 
next

GRID1.selectedRows = myselectedRows

9 Example: Returning values from VBScript

Returning values from VBScript is not yet fully supported. You have to use a temporary file to pass the value. In addition please bear in mind that the VBScript is not processed synchronously with the GuiXT script or InputScript. You have to wait for the next screen display before you can read the file generated in VBScript. 

As a  demonstration of  this technique we enhance the last example, returning the number of selected grid lines:

The scripts look as follows:

GuiXT script:

pos X[GRID1] (2,0)
InputField (0,0) "Search for" (0,12) Size=20 name="pm_short_text" 
Pushbutton (0,34) "Select rows" process="grid_select_rows.txt"

InputScript "grid_select_rows.txt":

Screen saplslvc_fullscreen.0500
  Set V[return_filename] "&%[TEMP]\guixtscriptreturn.txt"
  ApplyGuiScript template="C:\guiXT\sapgui scripts\select_grid_rows_via_short_text.vbs"
  Enter 

Screen saplslvc_fullscreen.0500
  OpenFile "&V[return_filename]"
  if Q[ok]
    ReadFile "&V[return_filename]" pm_selcount
    CloseFile "&V[return_filename]"
    Message "I: &V[pm_selcount] rows with short text ""&V[pm_short_text]""" -statusline
    RemoveFile "&V[return_filename]"
  endif
  Enter

VBScript "select_grid_rows_via_short_text.vbs":

Set aw = session.activeWindow()
Set GRID1 = aw.FindById("usr/cntlGRID1/shellcont/shell")

Dim myselectedRows
myselectedRows = ""
Dim mycount
mycount = 0

for i = 0 to GRID1.rowCount - 1
  if InStr(1, GRID1.getCellValue(i,"KTEXT"), "&V[pm_short_text]", 1) > 0 then 

    if myselectedRows = "" then
      myselectedRows = CStr(i)

      if i < GRID1.firstVisibleRow or i > GRID1.firstVisibleRow + GRID1.visibleRowCount-1 then
        GRID1.firstVisibleRow = i
      end if 

    else
        myselectedRows = myselectedRows + "," + CStr(i)
    end if

    mycount = mycount + 1 

  end if 
next

GRID1.selectedRows = myselectedRows

' Generate return file
Dim oFS
Set oFS = CreateObject("Scripting.FileSystemObject")
Dim oTS
Set oTS = oFS.CreateTextFile("&V[return_filename]")
oTS.writeLine(CStr(mycount))
oTS.Close 

 

10 Example: Collecting data from selected rows

This example shows how we can collect data from all selected grid rows. We generate a simple file containing the order numbers of all selected grid rows. We include this example since the handling of intervals like "3,10,12-20,34", the format that SAP GUI returns for the selected grid rows, has to be done in VBScript. The script still refers to the IW38 grid.

VBScript

Set aw = session.ActiveWindow
Dim GRID1
Set GRID1 = aw.FindById("usr/cntlGRID1/shellcont/shell")

Dim oFS
Set oFS = CreateObject("Scripting.FileSystemObject")
Dim oTS
Set oTS = oFS.CreateTextFile("C:\GuiXT\script100.txt")

sel = Split(GRID1.selectedRows, ",") 
for each interval in sel
  lim = Split(interval, "-")
  if UBound(lim) = 0 then
    oTS.writeLine(GRID1.getCellValue(interval,"AUFNR"))
  else 
    for i = lim(0) to lim(1)
      oTS.writeLine(GRID1.getCellValue(i,"AUFNR"))
    next
  end if 
next

oTS.Close 


11 Example: Activate object services

 

In the toolbar we want to add a new pushbutton that calls up a function from the "object services menu".  Since there are no normal menu entries for these special functions, a short VBScript is needed.

In this case the VBScript leads to an application server request, so that we have to omit the "Enter" in the InputScript.

 


 

 

GuiXT script:

Pushbutton (toolbar) "@FM@Send with note" process="send_with_note.txt" 

InputScript "send_with_note.txt":

Screen sapmv45a.0100
  ApplyGuiScript "object_services_1.vbs"

VBScript "object_services_1.vbs":

session.findById("wnd[0]/titl/shellcont/shell").pressButton "%GOS_TOOLBOX"
session.findById("wnd[0]/shellcont/shell").pressButton "SO_SENDSERV"