ALV Grid позволяет пользователю отображать отчет в желаемом виде. Пользователю доступны такие операции как: отображение или скрытие указанных полей, изменение порядка вывода столбцов. Зачастую, при изменении списка отображаемых полей, заказчик хочет видеть пересчет данных в разрезе отображаемых столбцов. Ниже описан способ автоматического пересчета данных в таблице, на основе каталога полей ALV Grid.
Постановка задачи
Пусть наш отчет имеет следующую структуру:
1 2 3 4 5 6 7 |
DATA: BEGIN OF gt_tab OCCURS 0, bukrs LIKE t001-bukrs, " БЕ werks LIKE t001w-werks, " Завод matnr LIKE makt-matnr, " Материал dmbtr TYPE tslxx, " Сумма END OF gt_tab. |
По умолчанию, суммы отображаются в разрезе БЕ, завода и материала. В определенный момент пользователь скрыл поле MATNR. Ожидается, что данные «схлопнутся», и отчет уже будет отображать данные в разрезе БЕ и завода. То есть в каждой строке таблицы необходимо очистить поле MATNR и сделать COLLECT всех строк в новую таблицу. Полученная таблица и будет желаемым результатом.
Алгоритм
Первое что нужно сделать, это создать копию отображаемой таблицы и в ALV Grid передавать не исходную таблицу, а ее копию. Это необходимо для того, чтобы можно было восстановить исходные данные в случае отображения скрытых полей. Если не делать копию таблицы, то после скрытия столбцов ненужные поля очистятся и данные пересчитаются, а если мы захотим отобразить скрытые поля обратно, то данные уже нельзя будет вернуть. Именно поэтому нужна копия исходной таблицы.
1 2 3 4 5 6 7 8 9 10 11 12 |
DATA gt_alv_tab LIKE STANDARD TABLE OF gt_tab. ... gt_alv_tab[] = gt_tab[]. CALL METHOD go_alv_grid->set_table_for_first_display EXPORTING is_layout = ls_layout CHANGING it_fieldcatalog = lt_fieldcat it_outtab = gt_alv_tab[]. |
После выполнения какой-либо команды пользователя в ALV Grid вызывается событие AFTER_USER_COMMAND. В этот момент необходимо сделать проверку на изменение каталога полей в ALV. Если поля изменились, то необходимо обновить внутреннюю таблицу с данными и вызвать метод REFRESH_TABLE_DISPLAY для обновления данных на экране. Пересчет табличных данных оформим во вспомогательном классе из предыдущей заметки. Для этого, определим статический метод AUTO_COLLECT в классе ZCL_ALV_GRID_HELPER.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
*----------------------------------------------------------------------* * CLASS zcl_alv_grid_helper DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS zcl_alv_grid_helper DEFINITION INHERITING FROM cl_gui_alv_grid. PUBLIC SECTION. CLASS-METHODS get_outtab_ref IMPORTING i_alv_grid TYPE REF TO cl_gui_alv_grid RETURNING value(e_outtab_ref) TYPE REF TO data. CLASS-METHODS auto_collect IMPORTING i_src_tab TYPE STANDARD TABLE i_alv_grid TYPE REF TO cl_gui_alv_grid. ENDCLASS. "zcl_alv_grid_helper DEFINITION *----------------------------------------------------------------------* * CLASS zcl_alv_grid_helper IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS zcl_alv_grid_helper IMPLEMENTATION. METHOD get_outtab_ref. e_outtab_ref = i_alv_grid->mt_outtab. ENDMETHOD. "get_outtab_ref METHOD auto_collect. DATA: lt_fieldcat TYPE lvc_t_fcat, ls_component TYPE abap_componentdescr, lt_component TYPE abap_component_tab, lo_dest_tab TYPE REF TO data, lo_empty_struct_descr TYPE REF TO cl_abap_structdescr, lo_empty_struct TYPE REF TO data, lo_row TYPE REF TO data. FIELD-SYMBOLS: <lt_src> TYPE STANDARD TABLE, <lt_dest> TYPE STANDARD TABLE, <ls_row> TYPE ANY, <lv_val> TYPE ANY, <ls_fieldcat> TYPE lvc_s_fcat, <ls_empty_struct> TYPE ANY. ASSIGN i_src_tab[] TO <lt_src>. CHECK <lt_src>[] IS NOT INITIAL. lo_dest_tab = get_outtab_ref( i_alv_grid ). ASSIGN lo_dest_tab->* TO <lt_dest>. CREATE DATA lo_row LIKE LINE OF <lt_src>. ASSIGN lo_row->* TO <ls_row>. CALL METHOD i_alv_grid->get_frontend_fieldcatalog IMPORTING et_fieldcatalog = lt_fieldcat. REFRESH lt_component. LOOP AT lt_fieldcat ASSIGNING <ls_fieldcat>. CHECK <ls_fieldcat>-tech EQ ' '. CHECK <ls_fieldcat>-no_out EQ 'X'. ASSIGN COMPONENT <ls_fieldcat>-fieldname OF STRUCTURE <ls_row> TO <lv_val>. CHECK sy-subrc EQ 0. CLEAR ls_component. ls_component-name = <ls_fieldcat>-fieldname. ls_component-type ?= cl_abap_typedescr=>describe_by_data( <lv_val> ). INSERT ls_component INTO TABLE lt_component. ENDLOOP. IF lt_component[] IS INITIAL. <lt_dest>[] = <lt_src>[]. ENDIF. CHECK lt_component[] IS NOT INITIAL. lo_empty_struct_descr = cl_abap_structdescr=>create( lt_component ). CREATE DATA lo_empty_struct TYPE HANDLE lo_empty_struct_descr. ASSIGN lo_empty_struct->* TO <ls_empty_struct>. CLEAR <ls_empty_struct>. REFRESH <lt_dest>. LOOP AT <lt_src> INTO <ls_row>. MOVE-CORRESPONDING <ls_empty_struct> TO <ls_row>. COLLECT <ls_row> INTO <lt_dest>. ENDLOOP. ENDMETHOD. "auto_collect ENDCLASS. "zcl_alv_grid_helper IMPLEMENTATION |
Вызов данного метода нужно делать в обработчике события AFTER_USER_COMMAND.
1 2 3 4 5 6 7 8 |
METHOD on_after_user_command. CALL METHOD zcl_alv_grid_helper=>auto_collect EXPORTING i_src_tab = gt_tab[] i_alv_grid = go_alv_grid. go_alv_grid->refresh_table_display( ). ENDMETHOD. "on_after_user_command |
Разбор действий
А теперь давайте разберем что происходит в методе AUTO_COLLECT.
1. Метод принимает 2 параметра: таблицу с исходными данными и ссылку на экземпляр ALV Grid.
2. После объявления переменных проверяется наличие данных в исходной таблице. Символьным переменным <lt_src> <lt_dest> присваиваются исходная и результирующая таблицы соответственно. Также создается структура строки исходной таблицы и назначается в переменную <ls_row>.
1 2 3 4 5 6 7 8 |
ASSIGN i_src_tab[] TO <lt_src>. CHECK <lt_src>[] IS NOT INITIAL. lo_dest_tab = get_outtab_ref( i_alv_grid ). ASSIGN lo_dest_tab->* TO <lt_dest>. CREATE DATA lo_row LIKE LINE OF <lt_src>. ASSIGN lo_row->* TO <ls_row>. |
3. В переменную lt_fieldcat импортируется каталог полей переданного экземпляра ALV Grid.
1 2 3 |
CALL METHOD i_alv_grid->get_frontend_fieldcatalog IMPORTING et_fieldcatalog = lt_fieldcat. |
4. Формируется таблица lt_component, содержащая скрытые, но не технические поля ALV Grid.
1 2 3 4 5 6 7 8 9 10 11 12 |
LOOP AT lt_fieldcat ASSIGNING <ls_fieldcat>. CHECK <ls_fieldcat>-tech EQ ' '. CHECK <ls_fieldcat>-no_out EQ 'X'. ASSIGN COMPONENT <ls_fieldcat>-fieldname OF STRUCTURE <ls_row> TO <lv_val>. CHECK sy-subrc EQ 0. CLEAR ls_component. ls_component-name = <ls_fieldcat>-fieldname. ls_component-type ?= cl_abap_typedescr=>describe_by_data( <lv_val> ). INSERT ls_component INTO TABLE lt_component. ENDLOOP. |
5. Далее делаем проверку, если в скрытые поля отсутствуют, то выводим таблицу как есть.
1 2 3 4 |
IF lt_component[] IS INITIAL. <lt_dest>[] = <lt_src>[]. ENDIF. CHECK lt_component[] IS NOT INITIAL. |
6. Если скрытые поля существуют то создаем структуру, состоящую из скрытых полей и очищаем ее.
1 2 3 4 5 |
lo_empty_struct_descr = cl_abap_structdescr=>create( lt_component ). CREATE DATA lo_empty_struct TYPE HANDLE lo_empty_struct_descr. ASSIGN lo_empty_struct->* TO <ls_empty_struct>. CLEAR <ls_empty_struct>. |
7. И наконец формируем итоговую таблицу
1 2 3 4 5 6 |
REFRESH <lt_dest>. LOOP AT <lt_src> INTO <ls_row>. MOVE-CORRESPONDING <ls_empty_struct> TO <ls_row>. COLLECT <ls_row> INTO <lt_dest>. ENDLOOP. |
Присоединиться к обсуждению...