Skip to Content
Technical Articles
Author's profile photo Jigang Zhang 张吉刚

Review and Validate Tools for SAP Script Forms

After completing a few cycles of form remediation which includes hundreds of SAP script forms, I keep trying to prepare some tools for self-check and quick validation of SAP script forms. In this article, I wrap up various programs for such purposes.

 

<1> Script Form Break-Down Tools by Michael Keller

  • 1. It can provide different colors for Element, Command, and Comment lines which will much easier to check syntax;
  • 2. Also this tool has Indentation for IF/ELSE/ENDIF/CASE/WHEN statements can help quick identity fundamental flaws;
  • 3. Fold and Unfold pairs of IF/ENDIF, etc.

Please check more details about this program at this.

 

<2> Script Form Scanner post by Sabrina Pinto

  • It will help find where used list of any text string for all SAP scripts in one shot.
  • It can check all included standard texts related to addresses or Logos easier and determine how many forms and which windows are actually sharing the same SO10 text now.

Please check more details about this program at this.

<3> Standard Text SO10 Scanner

May need to update hundreds of standard text especially related to address with conditions, I create this tiny program to check the specific text inside the standard text.

  1. This could be used to check where used list for any specific address and find which could be shared or updated together;
  2. Can be used to validate new standard text maintenance and related remediation.

REPORT z_so10_search.
TABLES: stxh.

*-----------------------------------------------------------------------
* Types& Data Definition
*-----------------------------------------------------------------------
TYPES: BEGIN OF ty_out,
         tdobject TYPE stxl-tdobject,
         tdname   TYPE stxl-tdname,
         tdid     TYPE stxl-tdid,
         tdspras  TYPE stxl-tdspras,
         tdformat TYPE tdformat,
         flag     TYPE flag,
         tdline   TYPE tdline,
       END OF ty_out.
DATA: gt_out TYPE TABLE OF ty_out,
      gs_out TYPE ty_out.

TYPES: BEGIN OF ty_stxh,
        tdobject TYPE stxl-tdobject,
        tdname LIKE stxh-tdname,
        tdspras LIKE stxh-tdspras,
      END OF ty_stxh.
DATA: gt_stxh TYPE TABLE OF ty_stxh,
      gs_stxh TYPE ty_stxh,
      gt_lines LIKE TABLE OF tline,
      gs_lines LIKE LINE OF gt_lines.

*-----------------------------------------------------------------------
* Selection Parameters
*-----------------------------------------------------------------------

SELECTION-SCREEN: BEGIN OF BLOCK a2 WITH FRAME TITLE text-002.
PARAMETERS p_search(80) OBLIGATORY.
PARAMETERS: P_match AS CHECKBOX. "display only specific line
SELECTION-SCREEN: END   OF BLOCK a2.

SELECTION-SCREEN SKIP.
SELECTION-SCREEN: BEGIN OF BLOCK a1 WITH FRAME TITLE text-001.
SELECT-OPTIONS: s_tdname FOR stxh-tdname.
PARAMETERS p_obj   TYPE stxh-tdobject OBLIGATORY DEFAULT 'TEXT'.
PARAMETERS p_id    TYPE stxh-tdid DEFAULT 'ST'.
PARAMETERS p_langu LIKE stxh-tdspras DEFAULT 'EN'.
SELECTION-SCREEN: END   OF BLOCK a1.

*-----------------------------------------------------------------------
* START-OF-SELECTION
*-----------------------------------------------------------------------
START-OF-SELECTION.
  PERFORM get_data.

*-----------------------------------------------------------------------
* FORM GET_DATA
*-----------------------------------------------------------------------
FORM get_data.
  DATA: l_tab_tadir     TYPE TABLE OF tadir,
        l_str_tadir     TYPE tadir,
        l_tabix_str(10) TYPE c,
        l_percentage    TYPE p,
        l_cnt           TYPE i,
        l_text          TYPE itex132,
        l_cnt_str(10)   TYPE c.

  REFRESH gt_stxh.
  SELECT tdobject tdname tdspras
    FROM stxh
    INTO TABLE gt_stxh
    WHERE tdname IN s_tdname
    AND tdobject = p_obj
    AND tdid = p_id
    AND tdspras = p_langu.

* Write count of programs into list
  DESCRIBE TABLE gt_stxh LINES l_cnt.
  IF l_cnt = 0.
    EXIT.
  ENDIF.

  l_cnt_str = l_cnt.
  CONDENSE l_cnt_str.

  REFRESH: gt_out.
  LOOP AT gt_stxh INTO gs_stxh.

    l_tabix_str = sy-tabix.
    CONDENSE l_tabix_str.
    IF l_cnt IS NOT INITIAL.
*   Display progress indicator
      l_percentage = 100 * ( sy-tabix / l_cnt ).

      CONCATENATE '(' 'Processing'(009) l_tabix_str 'of'(010) l_cnt_str ')'
                   'Searching Text object'(008) gs_stxh-tdname
                  INTO l_text SEPARATED BY space.
      CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
        EXPORTING
          percentage = l_percentage
          text       = l_text.
    ENDIF.

    REFRESH gt_lines.
    CALL FUNCTION 'READ_TEXT'
      EXPORTING
*       CLIENT                  = SY-MANDT
        id                      = p_id
        language                = gs_stxh-tdspras
        name                    = gs_stxh-tdname
        object                  = p_obj
      TABLES
        lines                   = gt_lines
      EXCEPTIONS
        id                      = 0
        language                = 0
        name                    = 0
        not_found               = 0
        object                  = 0
        reference_check         = 0
        wrong_access_to_archive = 0
        OTHERS                  = 0.

    FIND ALL OCCURRENCES OF REGEX p_search IN TABLE gt_lines
* RESPECTING CASE
    RESULTS DATA(results).

    SEARCH gt_lines FOR p_search.
    IF sy-subrc EQ 0.
      CONDENSE gs_stxh-tdname.
      CLEAR gs_out.
      MOVE-CORRESPONDING gs_stxh TO gs_out.
      LOOP AT gt_lines INTO gs_lines.
        gs_out-tdformat = gs_lines-tdformat.
        gs_out-tdline   = gs_lines-tdline.
        SEARCH gs_lines FOR p_search.
        IF sy-subrc EQ 0.
          gs_out-flag = 'X'.
        ELSE.
          CLEAR gs_out-flag.
          if P_match = 'X'.
            CONTINUE.
          endif.
        ENDIF.

        APPEND gs_out TO gt_out.
      ENDLOOP.
    ENDIF.
  ENDLOOP.

  IF gt_out[] IS NOT INITIAL.
    cl_demo_output=>display_data( gt_out ).
  ELSE.
    WRITE: / 'String not found!'.
  ENDIF.

ENDFORM.

Hope those tools could help during the work of SAP script forms remediation and new address-related maintenance.

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michael Keller
      Michael Keller

      In the meantime I have written a new business version from scratch, the "SAPscript Analysing Tools". They offer much more, including fully automatic form analysis and complexity measurement. As I said, this is software for sale.

      Author's profile photo Jigang Zhang 张吉刚
      Jigang Zhang 张吉刚
      Blog Post Author

      SAP already provides the standard program ‘RSTXSCRP’ to export/import SAP ScirptForms to a local file. Here, one program can download all script forms with contents like ‘Form Info’.

      REPORT Z_SCRIPT_DOWN message-id z1.
      *&---------------------------------------------------------------------*
      *& Report  Z_SCRIPT_DOWN
      *&
      *&---------------------------------------------------------------------*
      * Report        : Z_SCRIPT_DOWN
      * Title         : Download script forms to local with Form Info
      * Date          : 01/18/2023
      * Author        : Jimmy Zhang
      *-------------------------------------------------------------------------------*
      * CHANGE HISTORY
      *-----------------------------------------------------------------------------------------*
      *  DATE      | NAME      |  DESCRIPTION                                   | Reference
      *-----------------------------------------------------------------------------------------*
      
      * Data Declaration *************************************************
      types: begin of ty_excel,
              row      type i,
              formname type tdform,
              langu(2),
             end of ty_excel.
      
      types: begin of gty_output,
              row      type i,
              formname type tdform,
              langu(2),
              status   type char20,
              message  type char120,
             end of gty_output.
      
      * BDC data structures
      data: begin of bdc_data occurs 0.
              include structure bdcdata.
      data: end of bdc_data.
      
      data: gt_output type table of gty_output,
            gs_output type gty_output,
            gt_excel  type TABLE OF ty_excel,
            gs_excel  type ty_excel,
            i_bdcmsg like bdcmsgcoll occurs 0 with header line.
      data: gr_table  TYPE REF TO cl_salv_table.
      
      parameters : p_file type string OBLIGATORY,
                   p_path type string DEFAULT 'C:\TEMP\script',
                   p_mode type CTU_MODE DEFAULT 'N'.
      
      *    A  Display all screens
      *    E  Display errors
      *    N  Background processing
      *    P  Background processing; debugging possible
      
      **********************************************************************
      * At selection-screen
      **********************************************************************
      at selection-screen on value-request for p_file.
        data: lt_file_table type filetable,
              lv_rc type i.
        call method cl_gui_frontend_services=>file_open_dialog
          changing
            file_table              = lt_file_table
            rc                      = lv_rc
          exceptions
            file_open_dialog_failed = 1
            cntl_error              = 2
            error_no_gui            = 3
            not_supported_by_gui    = 4
            others                  = 5.
        if sy-subrc <> 0.
        endif.
        read table lt_file_table into p_file index 1.
      
      **********************************************************************
      * Start-of-selection.
      **********************************************************************
      Start-of-selection.
      * Get excel File Data
          perform get_data_from_excel.
          perform download_form.
          PERFORM data_output.
      *&---------------------------------------------------------------------*
      *&      Form  download_form
      *&---------------------------------------------------------------------*
      *       text
      *----------------------------------------------------------------------*
      *      -->P_LT_INPUT  text
      *----------------------------------------------------------------------*
      form download_form.
      data: lv_path type string,
            lv_filename type string.
      
        DATA: l_tab_tadir     TYPE TABLE OF tadir,
              l_str_tadir     TYPE tadir,
              l_tabix_str(10) TYPE c,
              l_percentage    TYPE p,
              l_cnt           TYPE i,
              l_text          TYPE itex132,
              l_cnt_str(10)   TYPE c.
      
      
        lv_path = p_path.
      
        DESCRIBE TABLE gt_excel LINES l_cnt.
        l_cnt_str = l_cnt.
        CONDENSE l_cnt_str.
      
      
        loop at gt_excel into gs_excel.
      
          l_tabix_str = sy-tabix.
          CONDENSE l_tabix_str.
          IF l_cnt IS NOT INITIAL.
      *   Display progress indicator
            l_percentage = 100 * ( sy-tabix / l_cnt ).
      
            CONCATENATE '(' 'Progess'(009) l_tabix_str 'of'(010) l_cnt_str ')'
                         'Downloading'(008) gs_excel-formname
                        INTO l_text SEPARATED BY space.
            CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
              EXPORTING
                percentage = l_percentage
                text       = l_text.
          ENDIF.
      
          clear: i_bdcmsg,i_bdcmsg[], bdc_data, bdc_data[].
      * Initial Screen
          perform bdc_dynpro using 'SAPMSSCF' '1101'.
          perform bdc_field  using 'BDC_OKCODE' '=SHOW'.
          perform bdc_field  using 'RSSCF-TDFORM' gs_excel-formname.
          perform bdc_field  using 'RSSCF-TDSPRAS' gs_excel-langu.
          perform bdc_field  using 'RSSCF-TDHEADEROB' 'X'.
      
      * select form-info
          perform bdc_dynpro using 'SAPMSSCF' '1110'.
          perform bdc_field  using 'BDC_CURSOR' 'ITCTA-TDTEXT'.
          perform bdc_field  using 'BDC_OKCODE' '=VIEW'.
      
      * save to local
          perform bdc_dynpro using 'SAPMSSY0' '0120'.
          perform bdc_field  using 'BDC_OKCODE' '=%PC'.
      
      * popup confirm
          perform bdc_dynpro using 'SAPLSPO5' '0110'.
          perform bdc_field  using 'BDC_OKCODE'	'=OK'.
          perform bdc_field  using 'BDC_SUBSCR'
                'SAPLSPO5                                0180SUBSCREEN_CONTROL'.
          perform bdc_field  using 'BDC_SUBSCR'
                'SAPLSPO5                                0150SUBSCREEN_STEPLOOP'.
          perform bdc_field  using 'BDC_SUBSCR' 'SPOPLI-SELFLAG(01)'.
      
      * filepath
          clear lv_filename.
          TRANSLATE gs_excel-langu to LOWER CASE.
          CONCATENATE   gs_excel-formname
                        '_'
                        gs_excel-langu
                        '.txt'
                        into lv_filename.
      
          perform bdc_dynpro using 'SAPLSFES' '0200'.
          perform bdc_field  using 'BDC_CURSOR' 'DY_FILENAME'.
          perform bdc_field  using 'BDC_OKCODE' '=FILE'.
          perform bdc_field  using 'DY_PATH' lv_path.
          perform bdc_field  using 'DY_FILENAME' lv_filename.
      
      * Quit
          perform bdc_dynpro using 'SAPMSSY0' '0120'.
          perform bdc_field  using 'BDC_CURSOR' '=%EX'.
      
          perform bdc_dynpro using 'SAPMSSCF' '1110'.
          perform bdc_field  using 'BDC_CURSOR' 'ITCTA-TDTEXT'.
          perform bdc_field  using 'BDC_OKCODE'	'=BEEN'.
      
          perform bdc_dynpro using 'SAPMSSCF' '1101'.
          perform bdc_field  using 'BDC_CURSOR' 'RSSCF-TDFORM'.
          perform bdc_field  using 'BDC_OKCODE'	'=BEEN'.
          perform bdc_field  using 'RSSCF-TDFORM' gs_excel-formname.
          perform bdc_field  using 'RSSCF-TDSPRAS' gs_excel-langu.
          perform bdc_field  using 'RSSCF-TDHEADEROB' 'X'.
      
      
      * download scirptform
          call transaction 'SE71' using bdc_data
                                  update 'S'
                                  mode p_mode
                                  messages into i_bdcmsg.
      
      * Add result
          gs_output-row      = gs_excel-row.
          gs_output-formname = gs_excel-formname.
          gs_output-langu    = gs_excel-langu.
          read table i_bdcmsg with key msgtyp = 'E'.
          if sy-subrc = 0.
            gs_output-status  = 'Error'.
      * Add error messages
            data: lv_msg type bapi_msg.
            loop at i_bdcmsg.
              call function 'MESSAGE_TEXT_BUILD'
                exporting
                  msgid               = i_bdcmsg-msgid
                  msgnr               = i_bdcmsg-msgnr
                  msgv1               = i_bdcmsg-msgv1
                  msgv2               = i_bdcmsg-msgv2
                  msgv3               = i_bdcmsg-msgv3
                  msgv4               = i_bdcmsg-msgv4
                importing
                  message_text_output = lv_msg.
              if gs_output-message is initial.
                gs_output-message = lv_msg.
              else.
                concatenate gs_output-message lv_msg into gs_output-message separated by ','.
              endif.
            endloop.
            append gs_output to gt_output.
          else.
            gs_output-status  = 'Success'.
            concatenate lv_filename ' - Successfully download' into gs_output-message respecting blanks.
            append gs_output to gt_output.
          endif.
        endloop.
      endform.                    " download_form
      
      *&---------------------------------------------------------------------*
      *&      Form  get_data_from_excel
      *&---------------------------------------------------------------------*
      *       text
      *----------------------------------------------------------------------*
      *      -->P_LT_INPUT  text
      *----------------------------------------------------------------------*
      form get_data_from_excel.
        data: lv_file     type rlgrap-filename,
              lt_data   type table of alsmex_tabline,
              ls_data   type alsmex_tabline,
              ls_input  type ty_excel,
              gs_output type gty_output.
        data: l_begin_col type i value '1',
              l_begin_row type i value '2',
              l_end_col   type i value '3',
              l_end_row   type i value '1000'.
      
        lv_file = p_file.
        call function 'ALSM_EXCEL_TO_INTERNAL_TABLE'
          exporting
            filename                = lv_file
            i_begin_col             = l_begin_col
            i_begin_row             = l_begin_row
            i_end_col               = l_end_col
            i_end_row               = l_end_row
          tables
            intern                  = lt_data
          exceptions
            inconsistent_parameters = 1
            upload_ole              = 2
            others                  = 3.
        if sy-subrc <> 0.
          message id 'ZC' type 'I' number '999'
              with 'Error uploading file, please check'.
          exit.
        endif.
      * Get the list of input data
        loop at lt_data into ls_data.
          condense ls_data-value.
          case ls_data-col.
            when 1.
              ls_input-row       = ls_data-value.
            when 2.
              ls_input-formname  = ls_data-value.
            when 3.
              ls_input-langu     = ls_data-value.
            when others.
          endcase.
          at end of row.
            if ls_input-langu is INITIAL.
              ls_input-langu = 'EN'.
            endif.
            append ls_input to gt_excel.
            clear ls_input.
          endat.
        endloop.
      endform.                    " get_data_from_excel
      
      *&---------------------------------------------------------------------*
      *&      Form  DATA_OUTPUT
      *&---------------------------------------------------------------------*
      *       text
      *----------------------------------------------------------------------*
      FORM data_output.
      * Functions
        DATA: lr_functions    TYPE REF TO   cl_salv_functions,
              lr_columns      TYPE REF TO   cl_salv_columns_table,
              lo_column       TYPE REF TO   cl_salv_column_table,
              lr_column       TYPE REF TO   cl_salv_column,
              lr_events       TYPE REF TO   cl_salv_events_table,
              ls_color        TYPE lvc_s_colo,
              lr_sorts        TYPE REF TO   cl_salv_sorts,
              lr_layout       TYPE REF TO   cl_salv_layout,
              lr_optimize     TYPE REF TO   cl_salv_columns_table,
              lf_variant TYPE slis_vari,
              ls_key    TYPE salv_s_layout_key,
              l_msg TYPE string.
      
        DATA: lv_sub TYPE sood-objdes.
        CLEAR lv_sub.
        DATA: lv_xml_type TYPE salv_bs_constant,
              lv_xml TYPE xstring.
      
        TRY.
            CALL METHOD cl_salv_table=>factory
              EXPORTING
                list_display = if_salv_c_bool_sap=>false
      *           r_container  =
      *           container_name =
              IMPORTING
                r_salv_table = gr_table
              CHANGING
                t_table      = gt_output.
          CATCH cx_salv_msg.
        ENDTRY.
      
      * Set Screen status.
        TRY.
            CALL METHOD gr_table->set_screen_status
              EXPORTING
                report        = sy-repid
                pfstatus      = 'ZSALV_STANDARD'
                set_functions = 0.
        ENDTRY.
      
        CALL METHOD gr_table->get_functions
          RECEIVING
            value = lr_functions.
      
      * Activate all Standard tool bar functions.
        CALL METHOD lr_functions->set_all
          EXPORTING
            value = if_salv_c_bool_sap=>true.
      
        lr_layout = gr_table->get_layout( ).
        lr_layout->set_default( abap_true ).
        lr_layout->set_save_restriction( if_salv_c_layout=>restrict_none ).
      
      * Get Output table columns.
        CALL METHOD gr_table->get_columns
          RECEIVING
            value = lr_columns.
      
      * Set column width optimize
        lr_columns->set_optimize( abap_true ).
      
      * Set sorts.
        TRY.
            lr_sorts = gr_table->get_sorts( ).
          CATCH cx_salv_not_found.
        ENDTRY.
      
      
        "Column
        TRY.
            lr_column = lr_columns->get_column( 'ROW' ).
            lr_column->set_long_text( 'Row No.' ).
            lr_column->set_MEDIUM_text( 'Row No.' ).
            lr_column->set_output_length( '10' ).
          CATCH cx_salv_not_found .
        ENDTRY.
      
        TRY.
            lr_column = lr_columns->get_column( 'FORMNAME' ).
            lr_column->set_long_text( 'Form Name' ).
            lr_column->set_output_length( '26' ).
          CATCH cx_salv_not_found .
        ENDTRY.
      
        TRY.
            lr_column = lr_columns->get_column( 'LANGU' ).
            lr_column->set_long_text( 'Language' ).
            lr_column->set_medium_text( 'Language' ).
            lr_column->set_output_length( '10' ).
          CATCH cx_salv_not_found .
        ENDTRY.
      
        TRY.
            lr_column = lr_columns->get_column( 'STATUS' ).
            lr_column->set_long_text( 'Status' ).
            lr_column->set_medium_text( 'Status' ).
            lr_column->set_output_length( '20' ).
          CATCH cx_salv_not_found .
        ENDTRY.
      
        TRY.
            lr_column = lr_columns->get_column( 'MESSAGE' ).
            lr_column->set_long_text( 'Message' ).
            lr_column->set_output_length( '100' ).
          CATCH cx_salv_not_found .
        ENDTRY.
      
      
        IF gt_output[] IS NOT INITIAL.
      * Display Data.
          CALL METHOD gr_table->display.
        ELSE.
      *    WRITE: / 'String not found!'.
        ENDIF.
      
      ENDFORM.
      
      
      *&---------------------------------------------------------------------*
      *&      Form  BDC_DYNPRO
      *&---------------------------------------------------------------------*
      *       text
      *----------------------------------------------------------------------*
      *      -->P_0499   text
      *      -->P_0500   text
      *----------------------------------------------------------------------*
      form bdc_dynpro using program dyn.
        clear bdc_data.
        bdc_data-program = program.
        bdc_data-dynpro  = dyn.
        bdc_data-dynbegin = 'X'.
        append bdc_data.
      endform.                    " NEW_DYNPRO
      *&---------------------------------------------------------------------*
      *&      Form  BDC_FIELD
      *&---------------------------------------------------------------------*
      *       text
      *----------------------------------------------------------------------*
      *      -->P_0504   text
      *      -->P_0505   text
      *----------------------------------------------------------------------*
      form bdc_field using field value.
        clear bdc_data.
        bdc_data-fnam = field.
        bdc_data-fval = value.
        append bdc_data.
      endform.                    " FILL_FIELD
      Author's profile photo Enno Wulff
      Enno Wulff

      Here is a little helper report that I wrote 19 years ago to replace texts in SO10 texts. It can alos be used for SAPScript forms.

      Author's profile photo Jigang Zhang 张吉刚
      Jigang Zhang 张吉刚
      Blog Post Author

      Enno Wulff Thanks for sharing this tool.