Skip to Content
Technical Articles
Author's profile photo Stefan Schnell

How to Run SAP GUI Scripting from ABAP

A long time ago I wrote here about the possibility to simulate the GetObject command with ABAP and here how to simulate CreateObject command with ABAP. Today we discussed the possibility to run SAP GUI Scripting from ABAP, and I remembered my old approach. At first needs the examples from back then a tiny update. Here the same approach in class style. Two methods which contains the possibility to get and to create a COM object via MSScriptControl.

"-Begin-----------------------------------------------------------------
CLASS z_vbscript DEFINITION
  PUBLIC
  CREATE PUBLIC .

  PUBLIC SECTION.

    "! Creates a COM object
    "!
    "! @parameter iv_class_name | Name of the COM class
    "!
    "! @parameter rv_obj        | Object of the class
    METHODS create_object
      IMPORTING
        VALUE(iv_class_name) TYPE string
      RETURNING
        VALUE(rv_obj) TYPE OBJ_RECORD.

    "! Gets an existing COM object from the ROT
    "!
    "! @parameter iv_class_name | Name of the COM class
    "!
    "! @parameter rv_obj        | Object of the class
    METHODS get_object
      IMPORTING
        VALUE(iv_class_name) TYPE string
      RETURNING
        VALUE(rv_obj) TYPE OBJ_RECORD.

    "! Executes stored OLE activities
    METHODS flush .

  PROTECTED SECTION.

  PRIVATE SECTION.

    CONSTANTS crlf(2) Type c Value cl_abap_char_utilities=>cr_lf.

ENDCLASS.



CLASS z_vbscript IMPLEMENTATION.



  METHOD create_object."------------------------------------------------

    DATA:
      lv_vb         TYPE string,
      lo_scriptctrl TYPE obj_record,
      lv_expression TYPE string.

    lv_vb =          'Function CreateObj(ClassName)'            && crlf.
    lv_vb = lv_vb && '  Dim oObj'                               && crlf.
    lv_vb = lv_vb && '  Set oObj = CreateObject(ClassName)'     && crlf.
    lv_vb = lv_vb && '  If IsObject(oObj) Then'                 && crlf.
    lv_vb = lv_vb && '    Set CreateObj = oObj'                 && crlf.
    lv_vb = lv_vb && '  End If'                                 && crlf.
    lv_vb = lv_vb && 'End Function'                             && crlf.

    CREATE OBJECT lo_scriptctrl 'MSScriptControl.ScriptControl'.
    CHECK sy-subrc = 0 AND lo_scriptctrl-handle <> 0 AND
      lo_scriptctrl-type = 'OLE2'.

    SET PROPERTY OF lo_scriptctrl 'AllowUI' = 1.
    SET PROPERTY OF lo_scriptctrl 'Language' = 'VBScript'.

    CALL METHOD OF lo_scriptctrl 'AddCode'
      EXPORTING
        #1 = lv_vb.
    CHECK sy-subrc = 0.

    lv_expression = 'CreateObj("' && iv_class_name && '")'.
    CALL METHOD OF lo_scriptctrl 'Eval' = rv_obj
      EXPORTING
        #1 = lv_expression.

    FREE OBJECT lo_scriptctrl.

  ENDMETHOD.



  METHOD get_object."---------------------------------------------------

    DATA:
      lv_vb         TYPE string,
      lo_scriptctrl TYPE obj_record,
      lv_expression TYPE string.

    lv_vb =          'Function GetObj(ClassName)'               && crlf.
    lv_vb = lv_vb && '  Dim oObj'                               && crlf.
    lv_vb = lv_vb && '  Set oObj = GetObject(ClassName)'        && crlf.
    lv_vb = lv_vb && '  If IsObject(oObj) Then'                 && crlf.
    lv_vb = lv_vb && '    Set GetObj = oObj'                    && crlf.
    lv_vb = lv_vb && '  End If'                                 && crlf.
    lv_vb = lv_vb && 'End Function'                             && crlf.

    CREATE OBJECT lo_scriptctrl 'MSScriptControl.ScriptControl'.
    CHECK sy-subrc = 0 AND lo_scriptctrl-handle <> 0 AND
      lo_scriptctrl-type = 'OLE2'.

    SET PROPERTY OF lo_scriptctrl 'AllowUI' = 1.
    SET PROPERTY OF lo_scriptctrl 'Language' = 'VBScript'.

    CALL METHOD OF lo_scriptctrl 'AddCode'
      EXPORTING
        #1 = lv_vb.
    CHECK sy-subrc = 0.

    lv_expression = 'GetObj("' && iv_class_name && '")'.
    CALL METHOD OF lo_scriptctrl 'Eval' = rv_obj
      EXPORTING
        #1 = lv_expression.

    FREE OBJECT lo_scriptctrl.

  ENDMETHOD.



  METHOD flush."--------------------------------------------------------
    CALL METHOD cl_gui_cfw=>flush.
  ENDMETHOD.



ENDCLASS.

"-End-------------------------------------------------------------------

The interesting question now was whether and how the SAP GUI scripting could be used. First of all, it works. In my test class I do exact the same steps as a recorded SAP GUI script. At first I get the SAPGUI object from the ROT. In the next steps I get the application, connection and session, in which the commands are to be executed. Then I just call only transaction code SE16. The corresponding VBScript commands as comments.

class ltcl_vbscript definition final for testing
  duration MEDIUM
  risk level harmless.

  private section.
    methods:
      first_test for testing raising cx_static_check.
endclass.


class ltcl_vbscript implementation.

  method first_test.

    DATA:
      lo_vbscript TYPE REF TO z_vbscript,
      lo_obj TYPE OBJ_RECORD,
      lo_application TYPE OBJ_RECORD,
      lo_connection TYPE OBJ_RECORD,
      lo_session TYPE OBJ_RECORD,
      lo_id TYPE OBJ_RECORD
      .

    CHECK sy-batch IS INITIAL.

    CALL FUNCTION 'TH_CREATE_FOREIGN_MODE'
      EXPORTING
        client = sy-mandt
        user   = sy-uname.

    "Set SapGuiAuto = GetObject("SAPGUI")
    CREATE OBJECT lo_vbscript.
    lo_obj = lo_vbscript->get_object( iv_class_name = 'SAPGUI' ).

    "Set application = SapGuiAuto.GetScriptingEngine
    CALL METHOD OF lo_obj 'GetScriptingEngine' = lo_application.

    "Set connection = application.Children(0)
    GET PROPERTY OF lo_application 'Children' = lo_connection
      EXPORTING
        #1 = 0.

    "Set session = connection.Children(1)
    GET PROPERTY OF lo_connection 'Children' = lo_session
      EXPORTING
        #1 = 1.

    "session.findById("wnd[0]/tbar[0]/okcd").text = "/nse16"
    CALL METHOD OF lo_session 'findById' = lo_id
      EXPORTING
        #1 = 'wnd[0]/tbar[0]/okcd'.
    SET PROPERTY OF lo_id 'Text' = '/nSE16'.

    "session.findById("wnd[0]").sendVKey 0
    CALL METHOD OF lo_session 'findById' = lo_id
      EXPORTING
        #1 = 'wnd[0]'.
    CALL METHOD OF lo_id 'sendVKey'
      EXPORTING
        #1 = 0.

    lo_vbscript->flush(  ).

    FREE OBJECT lo_obj.

  endmethod.

endclass.

As I wrote before, it works fine. With this tiny approach you can use SAP GUI Scripting with native ABAP. Care should only be taken when selecting the session. If the executing session is also the one in which the script should run, it is blocked.

The script code looks a bit awkward, but reflects a similar approach to what I use at PowerShell – for each VBScript command two lines.

$ID = Invoke-Method -object $session -methodName "findById" -methodParameter @("wnd[0]/tbar[0]/okcd");
Set-Property -object $ID -propertyName "text" -propertyValue @("/nse16");
$ID = Invoke-Method -object $session -methodName "findById" -methodParameter @("wnd[0]");
Invoke-Method -object $ID -methodName "sendVKey" -methodParameter @(0);

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ziv Markovich
      Ziv Markovich

      Hello Stefan,

      I tried it with  FM  , it works fine and the transaction IW32 is activated but the script dose not end ( the scripting red icon in corner is still running ) . what is needed to stopped it in the folowing code ?

       

       

      FUNCTION zpm_ws_iw32_open.
      *”———————————————————————-
      *”*”Local Interface:
      *” IMPORTING
      *” VALUE(IV_ORDER) TYPE AUFNR
      *” EXPORTING
      *” VALUE(ES_RETURN) TYPE BAPIRET2
      *”———————————————————————-
      DATA: lv_aufnr TYPE aufk-aufnr.

      CLEAR es_return.

      lv_aufnr = |{ iv_order ALPHA = IN }|.

      SELECT SINGLE aufnr
      INTO lv_aufnr
      FROM aufk
      WHERE aufnr = lv_aufnr.

      IF sy-subrc <> 0.
      es_return-type = ‘E’.
      es_return-id = ‘IW’.
      es_return-number = ‘161’.
      es_return-message_v1 = |{ iv_order ALPHA = OUT }|.
      PERFORM message_text_get CHANGING es_return.
      ENDIF.

      CHECK es_return IS INITIAL.

      DATA:
      lo_vbscript TYPE REF TO z_vbscript,
      lo_obj TYPE obj_record,
      lo_application TYPE obj_record,
      lo_connection TYPE obj_record,
      lo_session TYPE obj_record,
      lo_id TYPE obj_record
      .

      CHECK sy-batch IS INITIAL.

      CALL FUNCTION ‘TH_CREATE_FOREIGN_MODE’
      EXPORTING
      client = sy-mandt
      user = sy-uname.

      “Set SapGuiAuto = GetObject(“SAPGUI”)
      CREATE OBJECT lo_vbscript.
      lo_obj = lo_vbscript->get_object( iv_class_name = ‘SAPGUI’ ).

      “Set application = SapGuiAuto.GetScriptingEngine
      CALL METHOD OF lo_obj ‘GetScriptingEngine’ = lo_application.

      “Set connection = application.Children(0)
      GET PROPERTY OF lo_application ‘Children’ = lo_connection
      EXPORTING
      #1 = 0.

      “Set session = connection.Children(1)
      GET PROPERTY OF lo_connection ‘Children’ = lo_session
      EXPORTING
      #1 = 1.

      “session.findById(“wnd[0]/tbar[0]/okcd”).text = “/nIW32”
      CALL METHOD OF lo_session ‘findById’ = lo_id
      EXPORTING
      #1 = ‘wnd[0]/tbar[0]/okcd’.
      SET PROPERTY OF lo_id ‘Text’ = ‘/nIW32’.

      “session.findById(“wnd[0]”).sendVKey 0
      CALL METHOD OF lo_session ‘findById’ = lo_id
      EXPORTING
      #1 = ‘wnd[0]’.
      CALL METHOD OF lo_id ‘sendVKey’
      EXPORTING
      #1 = 0.

      “session.findById(“wnd[0]/tbar[0]/okcd”).text = IV_AUFNR”
      CALL METHOD OF lo_session ‘findById’ = lo_id
      EXPORTING
      #1 = ‘wnd[0]/usr/ctxtCAUFVD-AUFNR’.
      SET PROPERTY OF lo_id ‘Text’ = lv_aufnr.

      “session.findById(“wnd[0]”).sendVKey 0
      CALL METHOD OF lo_session ‘findById’ = lo_id
      EXPORTING
      #1 = ‘wnd[0]’.
      CALL METHOD OF lo_id ‘sendVKey’
      EXPORTING
      #1 = 0.
      lo_vbscript->flush( ).

      FREE OBJECT lo_obj.
      ENDFUNCTION.

       

      Thanks

      Ziv