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.
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
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.
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