Friday 13 July 2018

Getting the currently selected line in a TableCtrl (before PAI) dynamically

I have two table controls on my dynpro screen and in one of them there is a field which, upon F4, should check the value of another field and then execute one of two possible search helps, depending on the value of the other field.

I decided to create a fully generic code which returns the selected line in any given TableCtrl object before the PAI event. I checked class CL_TABLECONTROL but couldn’t find any similar method to do so.

Unfortunately, it seems that it cannot be implemented as an external Method (in my Utilities class) because the table control object (of type CXTAB_CONTROL) does not exist in this OO context. So the logic must be implemented as a Form in the dynpro program.

SAP ABAP Development, SAP ABAP Learning, SAP ABAP Tutorials and Materials, SAP ABAP Certifications

I would be glad to hear your thoughts on this!

Anyway, here is the logic:

FORM tc_get_curr_line USING    is_structure      TYPE any
                               iv_structure_name TYPE dynfnam
                               iv_tc_name        TYPE dynfnam
                      CHANGING es_curr_tc_line   TYPE any.

  DATA: lv_selected_index       TYPE sy-stepl,

        lo_struct_descr         TYPE REF TO cl_abap_structdescr,
        lv_struct_dynp_name     TYPE dynfnam,

        ls_tc_column            TYPE LINE OF cxtab_control-cols,

        lt_dynpfields           TYPE dynpread_tabtype,
        ls_dynpfield            LIKE LINE OF lt_dynpfields[],

        ls_selected_line        TYPE REF TO data.

  FIELD-SYMBOLS: <ls_tc_attr>           TYPE cxtab_control,
                 <ls_selected_line>     TYPE ANY,
                 <lv_line_field_value>  TYPE ANY,
                 <ls_tc_line_to_return> TYPE ANY.

  " Getting the relevant TableControl structure with all attributes of the TableCtrl itself:
  ASSIGN (iv_tc_name) TO <ls_tc_attr>.

  IF sy-subrc <> 0.
    MESSAGE 'Error getting the desired TableControl screen component' TYPE 'E'.

  ELSE.
    " Getting the index of the currently selected line in the TableCtrl:
    CALL FUNCTION 'DYNP_GET_STEPL'
      IMPORTING
        povstepl        = lv_selected_index
      EXCEPTIONS
        stepl_not_found = 1
        OTHERS          = 2.

    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid
              TYPE sy-msgty
              NUMBER sy-msgno
              WITH sy-msgv1
                   sy-msgv2
                   sy-msgv3
                   sy-msgv4.

    ENDIF.

    ls_dynpfield-stepl = lv_selected_index.

    " Building a DynproFields table with the names of all the displayed fields in
    " the given TableCtrl (only the ones that are OUTPUT - which means without any pushbuttons if exist)
    LOOP AT <ls_tc_attr>-cols
      INTO ls_tc_column
      WHERE screen-output EQ 1.
      ls_dynpfield-fieldname = ls_tc_column-screen-name.
      APPEND ls_dynpfield TO lt_dynpfields[].

    ENDLOOP.

    " Getting the DDIC description (fields' names and attributes) of the
    " given structure that I need to return eventually:
    lo_struct_descr ?= cl_abap_typedescr=>describe_by_data( is_structure ).

    " Reading the values from the currently selected line in the given TableCtrl:
    CALL FUNCTION 'DYNP_VALUES_READ'
      EXPORTING
        dyname                          = sy-cprog
        dynumb                          = sy-dynnr
*        translate_to_upper              = ' '
*        request                         = ' '
*        perform_conversion_exits        = ' '
*        perform_input_conversion        = ' '
*        determine_loop_index            = ' '
        start_search_in_current_screen  = abap_true
*        start_search_in_main_screen     = ' '
*        start_search_in_stacked_screen  = ' '
*        start_search_on_scr_stackpos    = ' '
*        search_own_subscreens_first     = ' '
*        searchpath_of_subscreen_areas   = ' '
      TABLES
        dynpfields                      = lt_dynpfields[]
      EXCEPTIONS
        invalid_abapworkarea            = 1
        invalid_dynprofield             = 2
        invalid_dynproname              = 3
        invalid_dynpronummer            = 4
        invalid_request                 = 5
        no_fielddescription             = 6
        invalid_parameter               = 7
        undefind_error                  = 8
        double_conversion               = 9
        stepl_not_found                 = 10
        OTHERS                          = 11
        .

    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid
              TYPE sy-msgty
              NUMBER sy-msgno
              WITH sy-msgv1
                   sy-msgv2
                   sy-msgv3
                   sy-msgv4.

    ELSEIF lt_dynpfields[] IS NOT INITIAL.
      " Creating the structure to return:
      CREATE DATA: ls_selected_line TYPE HANDLE lo_struct_descr.
      ASSIGN ls_selected_line->* TO <ls_selected_line>.

      " Going over the Dynpro screen fields to copy their values
      LOOP AT lt_dynpfields[] INTO ls_dynpfield.
        " The Dynpro Fields table contains the names of the Screen fields: The DynproStructure's name and
        " a hyphen '-' (e.g. 'GS_TC_DATA-MY_LOVELY_FIELD'). I need to compare between the names of the Dynpro FIELDS themselves
        " and the names of the DDIC fields in the DDIC structure. So I need only the fields' names without the structure's name.
        " I'm building a string with the Dynpro Structure's name and a hyphen:
        CONCATENATE iv_structure_name
                    '-'
               INTO lv_struct_dynp_name.

        " Now I'm removing the name of the Dynpro Structure (and the '-') from FIELDNAME in the DynpFields table:
        REPLACE lv_struct_dynp_name
          IN ls_dynpfield-fieldname
          WITH space
          IGNORING CASE.

        " Now I have the name of the actual FIELD in the dynpro structure, which should correspond to
        " the name of the matching field in the DDIC structure that I need to return.
        " So finally I can dynamically assign that field in the returned DDIC structure and copy
        " the value from the Dynpro field to it:
        ASSIGN COMPONENT ls_dynpfield-fieldname
          OF STRUCTURE <ls_selected_line>
          TO <lv_line_field_value>.

        IF    sy-subrc EQ 0
          AND <lv_line_field_value> IS ASSIGNED.
          " Copying the value from the Dynpro Screen field to the returned DDIC structure's field:
          <lv_line_field_value> = ls_dynpfield-fieldvalue.

        ENDIF.

      ENDLOOP.

      ASSIGN es_curr_tc_line
        TO <ls_tc_line_to_return>.

      " Copying the complete local structure to the returned Dynpro Screen structure:
      IF    sy-subrc EQ 0
        AND <ls_tc_line_to_return> IS ASSIGNED.
        <ls_tc_line_to_return> = <ls_selected_line>.

      ENDIF.

    ENDIF.

  ENDIF.

ENDFORM.                    "tc_get_curr_line

No comments:

Post a Comment