В качестве промо-довеска к ранее опубликованной статье приложу немного опыта и исходного кода для специфической аудитории, а именно пользователей SAP. Однажды мне пришлось полгода позаниматься изучением и программированием в этой чудесной системе, а точнее в модуле CRM. Поскольку, с одной стороны, средства для броузинга данных в SAP крайне скудны, а, с другой, я был избалован собственными привычками делать все мышкой, однажды от скуки я занялся любимым делом — «Свободой выборки», но в ABAP & light версии.
В SAPе таблиц какие-то жуткие тысячи штук, а названия у них не самые удобные и очевидные. Нормализация присутствует в изобилии. Поэтому понять, что же лежит в этой записи таблицы, скажем, BUT_000, можно лишь с некоторой натяжкой. Недолго думая, используя богатые средства рефлексии и метапрограммирования древнего как мамонт языка ABAP и сдабривая это всеми любимым alv_grid'ом я «слабал» некий код, позволяющий просматривать значения ссылок едва ли не на любую глубину, используя метаданные связей.
На память, интерфейс z-отчета это не про кассы, о, случайно зашедший! следующий:
- имя стартовой таблицы
- дополнительное условие ограничения
- количество строк
В открывшемся гриде, равно как и во вложенных, двойной клик по «ссылочному» полю проваливается в таблицу. Остальное уже забыл, не исключено, что это не все вкусности.Изучайте, внедряйте рефакторите, надеюсь вы сможете сами. Удачи!
*&---------------------------------------------------------------------*
*& Report Z_GREAT_ALV_TMP
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT z_great_alv_tmp.
DATA:
gv_ok LIKE sy-ucomm,
gv_container TYPE REF TO cl_gui_custom_container,
gv_container_name TYPE scrfname VALUE 'CONTAINER_ALV',
gv_grid TYPE REF TO cl_gui_alv_grid,
gt_fieldcat TYPE lvc_t_fcat,
gs_layout TYPE lvc_s_layo.
*&---------------------------------------------------------------------*
*& Include Z_GREAT_ALV_F01
*&---------------------------------------------------------------------*
FORM create_alv
USING
container_name TYPE scrfname
CHANGING
container TYPE REF TO cl_gui_custom_container
grid TYPE REF TO cl_gui_alv_grid.
"если грида еще нет
IF container IS NOT BOUND.
"создать контейнер
CREATE OBJECT container
EXPORTING
container_name = container_name
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
ENDIF.
ENDIF.
IF container IS BOUND.
"создать грид
* if grid is bound.
* free grid.
* endif.
IF grid IS NOT BOUND.
CREATE OBJECT grid
EXPORTING
i_parent = container
EXCEPTIONS
OTHERS = 1.
PERFORM set_great_handler.
ENDIF.
IF sy-subrc NE 0.
ENDIF.
ENDIF.
ENDFORM. "create_alv
*&---------------------------------------------------------------------*
*& Form set_great_handlers
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form display_alv
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->GRID text
* -->TAB text
*----------------------------------------------------------------------*
FORM display_alv
CHANGING
grid TYPE REF TO cl_gui_alv_grid
tab TYPE ANY TABLE.
IF grid IS BOUND.
"заполнить свойства колонок
* PERFORM prepare_field_catalog CHANGING gt_fieldcat.
*
"главный метод для показа грида
CALL METHOD grid->set_table_for_first_display
EXPORTING" i_structure_name = gv_tablename
is_layout = gs_layout
CHANGING
it_outtab = tab
it_fieldcatalog = gt_fieldcat
EXCEPTIONS
invalid_parameter_combination = 1
program_error = 2
too_many_lines = 3
OTHERS = 4.
IF sy-subrc NE 0.
ENDIF.
* "обновить данные
* CALL METHOD grid->refresh_table_display
* EXCEPTIONS
* finished = 1
* OTHERS = 2.
*
* IF sy-subrc NE 0.
* ENDIF.
ENDIF.
ENDFORM. "display_alv
*&---------------------------------------------------------------------*
*& Form prepare_field_catalog
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->PT_FIELDCAT text
*----------------------------------------------------------------------*
FORM prepare_field_catalog
USING
tabname TYPE dd02l-tabname
itab TYPE rs_bool
CHANGING
fieldcat TYPE lvc_t_fcat .
REFRESH fieldcat.
IF itab IS INITIAL.
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = tabname
CHANGING
ct_fieldcat = fieldcat
EXCEPTIONS
OTHERS = 1.
FIELD-SYMBOLS: <fs_fcat> TYPE lvc_s_fcat.
LOOP AT fieldcat ASSIGNING <fs_fcat>.
<fs_fcat>-edit = 'X'.
ENDLOOP.
ELSE.
DATA: lv_field TYPE lvc_s_fcat.
lv_field-fieldname = 'FK_TABNAME'.
lv_field-scrtext_s = 'TABNAME'.
lv_field-inttype = 'C'.
lv_field-outputlen = 50.
APPEND lv_field TO fieldcat.
lv_field-fieldname = 'FIELDNAME'.
lv_field-scrtext_s = 'FIELDNAME'.
lv_field-outputlen = 30.
APPEND lv_field TO fieldcat.
ENDIF.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM. "prepare_field_catalog
*&---------------------------------------------------------------------*
*& Form great_alv
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Include Z_GREAT_ALV_CL_DICTSERVICES
*&---------------------------------------------------------------------*
CLASS z_cl_great_alv_dictservices DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF z_fk_pair,
pk_name TYPE dd03l-fieldname,
fk_name TYPE dd03l-fieldname,
END OF z_fk_pair,
z_fk_pair_list TYPE STANDARD TABLE OF z_fk_pair,
BEGIN OF z_dependent_rec,
pk_tabname TYPE dd02l-tabname,
fk_tabname TYPE dd02l-tabname,
fieldname TYPE dd03l-fieldname,
frkart TYPE dd08l-frkart,
fieldlist TYPE REF TO data,"z_fk_pair_list,
END OF z_dependent_rec,
z_dependent_rec_list TYPE STANDARD TABLE OF z_dependent_rec.
CLASS-METHODS:
get_fk_list
IMPORTING
tabname TYPE dd02l-tabname
fieldname TYPE dd03l-fieldname
EXPORTING
dependent_rec TYPE z_dependent_rec,
get_check_fk_list
IMPORTING
tabname TYPE dd02l-tabname
fieldname TYPE dd03l-fieldname
EXPORTING
dependent_rec TYPE z_dependent_rec,
get_dependent_list
IMPORTING
tabname TYPE dd02l-tabname
EXPORTING
tablist TYPE z_dependent_rec_list.
ENDCLASS. "z_cl_great_alv_dictservices DEFINITION
*----------------------------------------------------------------------*
* CLASS z_cl_great_alv_dictservices IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS z_cl_great_alv_dictservices IMPLEMENTATION.
METHOD get_fk_list.
dependent_rec-fk_tabname = tabname.
dependent_rec-fieldname = fieldname.
SELECT SINGLE checktable frkart FROM dd08l INTO (dependent_rec-pk_tabname, dependent_rec-frkart) WHERE tabname = tabname AND fieldname = fieldname.
IF sy-subrc = 0 AND dependent_rec-pk_tabname <> '*'.
DATA: ls_fk_pair TYPE z_fk_pair,
lv_primpos TYPE dd05s-primpos.
FIELD-SYMBOLS: <fs_pair_list> TYPE z_fk_pair_list.
CREATE DATA dependent_rec-fieldlist TYPE z_fk_pair_list.
ASSIGN dependent_rec-fieldlist->* TO <fs_pair_list>.
SELECT primpos forkey FROM dd05s INTO (lv_primpos, ls_fk_pair-fk_name) WHERE tabname = tabname AND fieldname = fieldname.
SELECT SINGLE fieldname FROM dd03l INTO ls_fk_pair-pk_name WHERE tabname = dependent_rec-pk_tabname AND position = lv_primpos.
IF sy-subrc = 0.
APPEND ls_fk_pair TO <fs_pair_list>.
ENDIF.
ENDSELECT.
ENDIF.
ENDMETHOD. "get_fk_list
METHOD get_check_fk_list.
dependent_rec-fk_tabname = tabname.
dependent_rec-fieldname = fieldname.
DATA: lv_domname TYPE dd03l-domname.
SELECT SINGLE domname FROM dd03l INTO lv_domname WHERE tabname = tabname AND fieldname = fieldname.
IF sy-subrc = 0 AND lv_domname IS NOT INITIAL.
SELECT SINGLE entitytab FROM dd01l INTO dependent_rec-pk_tabname WHERE domname = lv_domname.
IF sy-subrc = 0 AND dependent_rec-pk_tabname IS NOT INITIAL.
DATA: ls_fk_pair TYPE z_fk_pair.
FIELD-SYMBOLS: <fs_pair_list> TYPE z_fk_pair_list.
CREATE DATA dependent_rec-fieldlist TYPE z_fk_pair_list.
ASSIGN dependent_rec-fieldlist->* TO <fs_pair_list>.
SELECT SINGLE fieldname FROM dd03l INTO ls_fk_pair-pk_name WHERE tabname = dependent_rec-pk_tabname AND domname = lv_domname AND keyflag = 'X'.
IF sy-subrc = 0.
ls_fk_pair-fk_name = fieldname.
APPEND ls_fk_pair TO <fs_pair_list>.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD. "get_check_fk_list
METHOD get_dependent_list.
DATA: ls_rec TYPE z_dependent_rec.
REFRESH tablist.
SELECT tabname fieldname frkart FROM dd08l INTO (ls_rec-fk_tabname, ls_rec-fieldname, ls_rec-frkart) WHERE checktable = tabname.
get_fk_list( EXPORTING
tabname = ls_rec-fk_tabname
fieldname = ls_rec-fieldname
IMPORTING
dependent_rec = ls_rec ).
IF ls_rec-fieldlist IS BOUND.
APPEND ls_rec TO tablist.
CLEAR ls_rec.
ENDIF.
ENDSELECT.
ENDMETHOD. "get_dependent_list
ENDCLASS. "z_cl_great_alv_dictservices IMPLEMENTATION
** METHOD forward_zalx.
** DATA:
** lv_rowtype TYPE zalx_clnt_genfld-rowtype,
** lv_fkrowtype TYPE zalx_clnt_genfld-fkrowtype,
** lv_fkrowpos TYPE zalx_clnt_genfld-fkrowpos,
** lv_structname TYPE zalx_clnt_genrel-structname,
** lv_tablename TYPE dd02l-tabname,
** lv_condition TYPE string,
** ls_nav_point TYPE z_nav_point.
** READ TABLE nav_stack INTO ls_nav_point INDEX nav_position.
** ls_nav_point-row_id = row_id.
** ls_nav_point-key_field = fieldname.
** MODIFY nav_stack INDEX nav_position FROM ls_nav_point.
**
** IF sy-subrc = 0.
** SELECT SINGLE rowtype FROM zalx_clnt_genrel INTO lv_rowtype WHERE structname = ls_nav_point-tab_name.
** IF sy-subrc = 0.
** SELECT SINGLE fkrowtype fkrowpos FROM zalx_clnt_genfld INTO (lv_fkrowtype, lv_fkrowpos) WHERE rowtype = lv_rowtype AND fieldname = fieldname.
** IF sy-subrc = 0.
** SELECT SINGLE structname FROM zalx_clnt_genrel INTO lv_structname WHERE rowtype = lv_fkrowtype.
** IF sy-subrc = 0.
**
** table_name = lv_structname.
** SELECT SINGLE fieldname FROM zalx_clnt_genfld INTO lv_condition WHERE rowtype = lv_fkrowtype AND rowpos = lv_fkrowpos.
** IF sy-subrc = 0.
** WRITE lv_structname.
** FIELD-SYMBOLS: <ff> TYPE ANY,
** <fs> TYPE ANY,
** <lfs_table> TYPE STANDARD TABLE.
**
** ASSIGN ls_nav_point-tab_table->* TO <lfs_table>.
** READ TABLE <lfs_table> ASSIGNING <fs> INDEX row_id-row_id.
** ASSIGN COMPONENT fieldname OF STRUCTURE <fs> TO <ff>.
** CONCATENATE lv_condition ' = ''' <ff> '''' INTO lv_condition.
**
** CLEAR ls_nav_point.
**
** lv_tablename = lv_structname.
** doselect( EXPORTING tablename = lv_tablename condition = lv_condition
** IMPORTING data_table = ls_nav_point-tab_table ).
**
** data_table = ls_nav_point-tab_table.
** ls_nav_point-tab_name = lv_structname.
**
** APPEND ls_nav_point TO nav_stack.
** ADD 1 TO nav_position.
**
** ENDIF.
**
** ENDIF.
**
** ENDIF.
** ENDIF.
** ENDIF.
**
** ENDMETHOD. "forward
*&---------------------------------------------------------------------*
*& Include Z_GREAT_ALV_CL
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Include Z_GREAT_ALV_CL_NAVSTACK
*&---------------------------------------------------------------------*
CLASS z_cl_great_alv_navstack DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF z_nav_point,
tab_name TYPE dd02l-tabname,
key_field TYPE lvc_s_col,
row_id TYPE lvc_s_roid,
tab_table TYPE REF TO data,
dependent TYPE rs_bool,
END OF z_nav_point.
CLASS-METHODS:
init
IMPORTING
tablename TYPE dd02l-tabname
reccount TYPE i
condition TYPE string
RETURNING
value(ok) TYPE rs_bool,
follow_fk
IMPORTING
fieldname TYPE lvc_s_col
row_id TYPE lvc_s_roid
RETURNING
value(ok) TYPE rs_bool,
choose_dependent
IMPORTING
fieldname TYPE lvc_s_col
row_id TYPE lvc_s_roid
table_name TYPE dd02l-tabname OPTIONAL
RETURNING
value(ok) TYPE rs_bool,
follow_pk
IMPORTING
deprec TYPE z_cl_great_alv_dictservices=>z_dependent_rec
row_id TYPE lvc_s_roid
RETURNING
value(ok) TYPE rs_bool,
follow_text
IMPORTING
row_id TYPE lvc_s_roid
RETURNING
value(ok) TYPE rs_bool,
back,
current_nav_point RETURNING
value(point) TYPE z_nav_point,
follow_zalx
IMPORTING
fieldname TYPE lvc_s_col
row_id TYPE lvc_s_roid
RETURNING
value(ok) TYPE rs_bool,
get_condition_string IMPORTING
row_id TYPE i
deprec TYPE z_cl_great_alv_dictservices=>z_dependent_rec
data_table TYPE REF TO data OPTIONAL
dependent TYPE rs_bool OPTIONAL
RETURNING value(condition) TYPE string.
PRIVATE SECTION.
CLASS-DATA:
nav_stack TYPE TABLE OF z_nav_point,
nav_position TYPE i,
rec_count TYPE i.
CLASS-METHODS:
doselect
IMPORTING
tablename TYPE dd02l-tabname
condition TYPE string OPTIONAL
EXPORTING
data_table TYPE REF TO data.
ENDCLASS. "Z_CL_GREAT_ALV_NAVSTACK DEFINITION
*----------------------------------------------------------------------*
* CLASS Z_CL_GREAT_ALV_NAVSTACK IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS z_cl_great_alv_navstack IMPLEMENTATION.
METHOD init.
REFRESH: nav_stack.
DATA: ls_nav_point TYPE z_nav_point.
rec_count = reccount.
doselect( EXPORTING tablename = tablename condition = condition
IMPORTING data_table = ls_nav_point-tab_table ).
IF ls_nav_point-tab_table IS BOUND.
ls_nav_point-tab_name = tablename.
APPEND ls_nav_point TO nav_stack.
nav_position = 1.
ok = 'X'.
ENDIF.
ENDMETHOD. "init
METHOD doselect.
CREATE DATA data_table TYPE TABLE OF (tablename).
FIELD-SYMBOLS: <fsv_table> TYPE STANDARD TABLE.
ASSIGN data_table->* TO <fsv_table>.
IF condition IS SUPPLIED.
SELECT * UP TO rec_count ROWS FROM (tablename) INTO TABLE <fsv_table> WHERE (condition).
ELSE.
SELECT * UP TO rec_count ROWS FROM (tablename) INTO TABLE <fsv_table>.
ENDIF.
ENDMETHOD. "doselect
METHOD follow_fk.
DATA: ls_dep TYPE z_cl_great_alv_dictservices=>z_dependent_rec,
ls_nav_point TYPE z_nav_point,
lv_colname TYPE lvc_s_col,
lv_condition TYPE string.
ls_nav_point = current_nav_point( ).
ls_nav_point-row_id = row_id.
ls_nav_point-key_field = fieldname.
MODIFY nav_stack INDEX nav_position FROM ls_nav_point.
IF ls_nav_point-dependent IS INITIAL.
z_cl_great_alv_dictservices=>get_fk_list( EXPORTING
tabname = ls_nav_point-tab_name
fieldname = fieldname-fieldname
IMPORTING
dependent_rec = ls_dep ).
IF ls_dep-fieldlist IS NOT BOUND.
z_cl_great_alv_dictservices=>get_check_fk_list( EXPORTING
tabname = ls_nav_point-tab_name
fieldname = fieldname-fieldname
IMPORTING
dependent_rec = ls_dep ).
ENDIF.
IF ls_dep-fieldlist IS BOUND.
lv_condition = get_condition_string(
row_id = row_id-row_id
deprec = ls_dep ).
CLEAR ls_nav_point.
doselect( EXPORTING tablename = ls_dep-pk_tabname condition = lv_condition
IMPORTING data_table = ls_nav_point-tab_table ).
IF ls_nav_point-tab_table IS BOUND.
ls_nav_point-tab_name = ls_dep-pk_tabname.
APPEND ls_nav_point TO nav_stack.
ADD 1 TO nav_position.
ok = 'X'.
ENDIF.
ENDIF.
ELSE.
FIELD-SYMBOLS: <fs_dep> TYPE z_cl_great_alv_dictservices=>z_dependent_rec_list.
ASSIGN ls_nav_point-tab_table->* TO <fs_dep>.
IF <fs_dep> IS ASSIGNED.
READ TABLE <fs_dep> INTO ls_dep INDEX row_id-row_id.
IF sy-subrc = 0.
back( ).
ls_nav_point = current_nav_point( ).
lv_colname-fieldname = ls_dep-fieldname.
ok = follow_pk( deprec = ls_dep
row_id = ls_nav_point-row_id
).
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD. "follow_fk
METHOD choose_dependent.
DATA: ls_nav_point TYPE z_nav_point,
lv_dep_list TYPE REF TO data.
FIELD-SYMBOLS <fs_deplist> TYPE z_cl_great_alv_dictservices=>z_dependent_rec_list.
ls_nav_point = current_nav_point( ).
ls_nav_point-row_id = row_id.
ls_nav_point-key_field = fieldname.
MODIFY nav_stack INDEX nav_position FROM ls_nav_point.
CREATE DATA lv_dep_list TYPE z_cl_great_alv_dictservices=>z_dependent_rec_list.
ASSIGN lv_dep_list->* TO <fs_deplist>.
z_cl_great_alv_dictservices=>get_dependent_list(
EXPORTING
tabname = ls_nav_point-tab_name
IMPORTING
tablist = <fs_deplist> ).
IF lv_dep_list IS NOT INITIAL.
SORT <fs_deplist> BY fk_tabname ASCENDING.
CLEAR ls_nav_point.
ls_nav_point-tab_table = lv_dep_list.
ls_nav_point-dependent = 'X'.
APPEND ls_nav_point TO nav_stack.
ADD 1 TO nav_position.
ok = 'X'.
ENDIF.
ENDMETHOD. "choose_dependent
METHOD follow_pk.
DATA: lv_condition TYPE string,
ls_nav_point TYPE z_nav_point.
ls_nav_point = current_nav_point( ).
ls_nav_point-row_id = row_id.
MODIFY nav_stack INDEX nav_position FROM ls_nav_point.
lv_condition = get_condition_string(
row_id = row_id-row_id
deprec = deprec
dependent = 'X' ).
CLEAR ls_nav_point.
doselect( EXPORTING tablename = deprec-fk_tabname
condition = lv_condition
IMPORTING data_table = ls_nav_point-tab_table ).
IF ls_nav_point-tab_table IS BOUND.
ls_nav_point-tab_name = deprec-fk_tabname.
APPEND ls_nav_point TO nav_stack.
ADD 1 TO nav_position.
ok = 'X'.
ENDIF.
ENDMETHOD. "follow_pk
METHOD follow_text.
DATA: ls_nav_point TYPE z_nav_point,
lv_colname TYPE lvc_s_col,
lt_dep_list TYPE z_cl_great_alv_dictservices=>z_dependent_rec_list,
ls_dep_list TYPE LINE OF z_cl_great_alv_dictservices=>z_dependent_rec_list.
ls_nav_point = current_nav_point( ).
z_cl_great_alv_dictservices=>get_dependent_list(
EXPORTING
tabname = ls_nav_point-tab_name
IMPORTING
tablist = lt_dep_list ).
LOOP AT lt_dep_list INTO ls_dep_list WHERE frkart = 'TEXT'.
lv_colname-fieldname = ls_dep_list-fieldname.
ok = follow_pk( deprec = ls_dep_list
row_id = row_id
).
EXIT. "only one text table, if any
ENDLOOP.
ENDMETHOD. "follow_text
METHOD back.
IF nav_position > 1.
DELETE nav_stack INDEX nav_position.
SUBTRACT 1 FROM nav_position.
ENDIF.
ENDMETHOD. "back
METHOD current_nav_point.
READ TABLE nav_stack INTO point INDEX nav_position.
ENDMETHOD. "current_table_name
METHOD get_condition_string.
FIELD-SYMBOLS: <ff> TYPE ANY,
<fs> TYPE ANY,
<lfs_table> TYPE STANDARD TABLE,
<lfs_fkrec> TYPE z_cl_great_alv_dictservices=>z_fk_pair_list.
DATA: ls_navpoint TYPE z_nav_point,
ls_fkpair TYPE z_cl_great_alv_dictservices=>z_fk_pair,
lv_condition TYPE string,
lt_condition TYPE TABLE OF string.
ls_navpoint = current_nav_point( ).
ASSIGN ls_navpoint-tab_table->* TO <lfs_table>.
READ TABLE <lfs_table> ASSIGNING <fs> INDEX row_id.
ASSIGN deprec-fieldlist->* TO <lfs_fkrec>.
LOOP AT <lfs_fkrec> INTO ls_fkpair.
IF dependent IS INITIAL.
ASSIGN COMPONENT ls_fkpair-fk_name OF STRUCTURE <fs> TO <ff>.
CONCATENATE ls_fkpair-pk_name ' = ''' <ff> '''' INTO lv_condition.
ELSE.
ASSIGN COMPONENT ls_fkpair-pk_name OF STRUCTURE <fs> TO <ff>.
CONCATENATE ls_fkpair-fk_name ' = ''' <ff> '''' INTO lv_condition.
ENDIF.
APPEND lv_condition TO lt_condition.
ENDLOOP.
CONCATENATE LINES OF lt_condition INTO condition SEPARATED BY ' AND '.
ENDMETHOD. "get_condition_string
METHOD follow_zalx.
DATA:
lv_rowtype TYPE zalx_clnt_genfld-rowtype,
lv_fkrowtype TYPE zalx_clnt_genfld-fkrowtype,
lv_fkrowpos TYPE zalx_clnt_genfld-fkrowpos,
lv_structname TYPE zalx_clnt_genrel-structname,
lv_tablename TYPE dd02l-tabname,
lv_condition TYPE string,
ls_nav_point TYPE z_nav_point.
READ TABLE nav_stack INTO ls_nav_point INDEX nav_position.
ls_nav_point-row_id = row_id.
ls_nav_point-key_field = fieldname.
MODIFY nav_stack INDEX nav_position FROM ls_nav_point.
IF sy-subrc = 0.
SELECT SINGLE rowtype FROM zalx_clnt_genrel INTO lv_rowtype WHERE structname = ls_nav_point-tab_name.
IF sy-subrc = 0.
SELECT SINGLE fkrowtype fkrowpos FROM zalx_clnt_genfld INTO (lv_fkrowtype, lv_fkrowpos) WHERE rowtype = lv_rowtype AND fieldname = fieldname.
IF sy-subrc = 0.
SELECT SINGLE structname FROM zalx_clnt_genrel INTO lv_structname WHERE rowtype = lv_fkrowtype.
IF sy-subrc = 0.
"table_name = lv_structname.
SELECT SINGLE fieldname FROM zalx_clnt_genfld INTO lv_condition WHERE rowtype = lv_fkrowtype AND rowpos = lv_fkrowpos.
IF sy-subrc = 0.
WRITE lv_structname.
FIELD-SYMBOLS: <ff> TYPE ANY,
<fs> TYPE ANY,
<lfs_table> TYPE STANDARD TABLE.
ASSIGN ls_nav_point-tab_table->* TO <lfs_table>.
READ TABLE <lfs_table> ASSIGNING <fs> INDEX row_id-row_id.
ASSIGN COMPONENT fieldname OF STRUCTURE <fs> TO <ff>.
CONCATENATE lv_condition ' = ''' <ff> '''' INTO lv_condition.
CLEAR ls_nav_point.
lv_tablename = lv_structname.
doselect( EXPORTING tablename = lv_tablename condition = lv_condition
IMPORTING data_table = ls_nav_point-tab_table ).
IF ls_nav_point-tab_table IS BOUND.
ls_nav_point-tab_name = lv_structname.
APPEND ls_nav_point TO nav_stack.
ADD 1 TO nav_position.
ok = 'X'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD. "forward
ENDCLASS. "Z_CL_GREAT_ALV_NAVSTACK IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS z_great_alv_handler DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS z_great_alv_handler DEFINITION.
PUBLIC SECTION.
CLASS-DATA:
zf_texting TYPE stb_button-function VALUE 'TEXTING',
zf_zalx TYPE stb_button-function VALUE 'ZALX',
zf_depend TYPE stb_button-function VALUE 'DEPEND',
zf_follow TYPE stb_button-function VALUE 'FOLLOW'.
METHODS:
double_click FOR EVENT double_click OF cl_gui_alv_grid
IMPORTING e_row e_column es_row_no,
toolbar_modify FOR EVENT toolbar OF cl_gui_alv_grid
IMPORTING e_object e_interactive,
user_command FOR EVENT user_command OF cl_gui_alv_grid
IMPORTING e_ucomm,
data_changed FOR EVENT data_changed OF cl_gui_alv_grid
IMPORTING er_data_changed e_onf4 e_onf4_before e_onf4_after e_ucomm.
ENDCLASS. "Z_GREAT_ALV_HANDLER DEFINITION
*----------------------------------------------------------------------*
* CLASS Z_GREAT_ALV_HANDLER IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS z_great_alv_handler IMPLEMENTATION.
METHOD double_click.
DATA: lv_ok TYPE rs_bool.
lv_ok = z_cl_great_alv_navstack=>follow_fk(
fieldname = e_column
row_id = es_row_no ).
IF lv_ok = 'X'.
CALL SCREEN 100.
ENDIF.
ENDMETHOD. "DOUBLE_CLICK
METHOD toolbar_modify.
DATA: lv_tbutton TYPE stb_button.
LOOP AT e_object->mt_toolbar INTO lv_tbutton WHERE function = zf_texting.
ENDLOOP.
IF sy-subrc <> 0.
CLEAR lv_tbutton.
MOVE 0 TO lv_tbutton-butn_type.
MOVE zf_follow TO lv_tbutton-function.
MOVE 'Follow foreign key/check table' TO lv_tbutton-text.
MOVE 'Follow foreign key/check table' TO lv_tbutton-quickinfo.
MOVE space TO lv_tbutton-disabled.
APPEND lv_tbutton TO e_object->mt_toolbar.
CLEAR lv_tbutton.
MOVE 0 TO lv_tbutton-butn_type.
MOVE zf_texting TO lv_tbutton-function.
MOVE 'Text table record' TO lv_tbutton-text.
MOVE 'Text table record' TO lv_tbutton-quickinfo.
MOVE space TO lv_tbutton-disabled.
APPEND lv_tbutton TO e_object->mt_toolbar.
CLEAR lv_tbutton.
MOVE 0 TO lv_tbutton-butn_type.
MOVE zf_depend TO lv_tbutton-function.
MOVE 'Dependent tables' TO lv_tbutton-text.
MOVE 'Dependent tables' TO lv_tbutton-quickinfo.
MOVE space TO lv_tbutton-disabled.
APPEND lv_tbutton TO e_object->mt_toolbar.
CLEAR lv_tbutton.
MOVE 0 TO lv_tbutton-butn_type.
MOVE zf_zalx TO lv_tbutton-function.
MOVE 'ZALX' TO lv_tbutton-text.
MOVE 'ZALX' TO lv_tbutton-quickinfo.
MOVE space TO lv_tbutton-disabled.
APPEND lv_tbutton TO e_object->mt_toolbar.
ENDIF.
ENDMETHOD. "toolbar_modify
METHOD user_command.
DATA: lv_table TYPE REF TO data,
lv_column TYPE lvc_s_col,
lv_rowno TYPE lvc_s_roid,
lv_ok TYPE rs_bool.
gv_grid->get_current_cell( IMPORTING es_col_id = lv_column
es_row_no = lv_rowno ).
CASE e_ucomm.
WHEN zf_texting.
lv_ok = z_cl_great_alv_navstack=>follow_text(
row_id = lv_rowno ).
WHEN zf_zalx.
lv_ok = z_cl_great_alv_navstack=>follow_zalx(
fieldname = lv_column
row_id = lv_rowno ).
WHEN zf_depend.
lv_ok = z_cl_great_alv_navstack=>choose_dependent(
fieldname = lv_column
row_id = lv_rowno ).
WHEN zf_follow.
lv_ok = z_cl_great_alv_navstack=>follow_fk(
fieldname = lv_column
row_id = lv_rowno ).
WHEN OTHERS.
EXIT.
ENDCASE.
IF lv_ok = 'X'.
CALL SCREEN 100.
ENDIF.
ENDMETHOD. "user_command
METHOD data_changed.
DATA: ls_nav_point TYPE z_cl_great_alv_navstack=>z_nav_point,
ls_deleted_row TYPE lvc_s_moce.
FIELD-SYMBOLS: <fst> TYPE STANDARD TABLE,
<fs> TYPE ANY.
"modify
ls_nav_point = z_cl_great_alv_navstack=>current_nav_point( ).
ASSIGN er_data_changed->mp_mod_rows->* TO <fst>.
MODIFY (ls_nav_point-tab_name) FROM TABLE <fst>.
"delete
ASSIGN ls_nav_point-tab_table->* TO <fst>.
LOOP AT er_data_changed->mt_deleted_rows INTO ls_deleted_row.
READ TABLE <fst> ASSIGNING <fs> INDEX ls_deleted_row-row_id.
IF sy-subrc = 0.
DELETE (ls_nav_point-tab_name) FROM <fs>.
ENDIF.
ENDLOOP.
ENDMETHOD. "data_changed
ENDCLASS. "Z_GREAT_ALV_HANDLER IMPLEMENTATION
*----------------------------------------------------------------------*
* MODULE PAI_01 INPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
MODULE pai_01 INPUT.
CASE gv_ok.
WHEN 'BACK'.
z_cl_great_alv_navstack=>back( ).
PERFORM great_alv.
WHEN '%EX'.
LEAVE PROGRAM.
ENDCASE.
ENDMODULE. " PAI_01 INPUT
*----------------------------------------------------------------------*
* MODULE PBO_01 OUTPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
MODULE pbo_01 OUTPUT.
CLEAR gv_ok.
SET PF-STATUS ''.
PERFORM great_alv.
ENDMODULE. " PBO_01 OUTPUT
*&---------------------------------------------------------------------*
*& Form set_great_handler
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM set_great_handler.
DATA lv_handler TYPE REF TO z_great_alv_handler.
CREATE OBJECT lv_handler.
IF gv_grid IS BOUND AND lv_handler IS BOUND.
SET HANDLER lv_handler->double_click FOR gv_grid.
SET HANDLER lv_handler->toolbar_modify FOR gv_grid.
SET HANDLER lv_handler->user_command FOR gv_grid.
SET HANDLER lv_handler->data_changed FOR gv_grid.
"grid->set_toolbar_interactive( ).
ENDIF.
ENDFORM. "set_great_handlers
*&---------------------------------------------------------------------*
*& Form great_alv
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM great_alv.
DATA: lv_nav_point TYPE z_cl_great_alv_navstack=>z_nav_point.
lv_nav_point = z_cl_great_alv_navstack=>current_nav_point( ).
PERFORM create_alv USING gv_container_name CHANGING gv_container gv_grid.
.
PERFORM prepare_field_catalog USING lv_nav_point-tab_name lv_nav_point-dependent CHANGING gt_fieldcat.
FIELD-SYMBOLS: <lfs_table> TYPE ANY TABLE.
ASSIGN lv_nav_point-tab_table->* TO <lfs_table>.
PERFORM display_alv USING gv_grid <lfs_table>.
gv_grid->set_current_cell_via_id( EXPORTING "is_row_no = lv_nav_point-row_id
is_column_id = lv_nav_point-key_field
is_row_no = lv_nav_point-row_id ).
ENDFORM. "great_alv
PARAMETERS: tabname LIKE dd02l-tabname DEFAULT 'but050',
rccount TYPE i DEFAULT 100,
condit TYPE string DEFAULT ''.
START-OF-SELECTION.
DATA: lv_ok TYPE rs_bool.
lv_ok = z_cl_great_alv_navstack=>init(
tablename = tabname
reccount = rccount
condition = condit
).
IF lv_ok = 'X'.
CALL SCREEN 100.
ENDIF.
Автор: NMM
Спасибо Автору ! Прекрасная статья !