Для отображения иерархической таблицы с двумя уровнями иерархии (главный и подчиненный) в SALV модели используется класс — cl_salv_hierseq_table.
Примером подобной иерархии может служить заказ на закупку, который состоит из заголовочной части и позиций заказа. Связь в этой иерархии осуществляется с помощью ключевого поля «номер заказа» в заголовке и позиции заказа.
Таблица создается с помощью фабрично-статического метода factory(). При его вызове необходимо передать две таблицы с данными и таблицу, в которой прописана связь между ними с типом salv_t_hierseq_binding. В данной таблице указываются ключевые поля которые связывают таблицы, но не более 5 полей. Если у вас больше создавайте составные ключи в технических полях.
Следующий пример покажет, как вывести иерархическую таблицу закупочных заказов с позициями:
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 |
REPORT zrep_hier_tab. CLASS lcl_report DEFINITION FINAL. PUBLIC SECTION. TYPES: BEGIN OF ty_ekko_data, ebeln TYPE ebeln, " Заказ lifnr TYPE lifnr, " Поставщик END OF ty_ekko_data, BEGIN OF ty_ekpo_data, ebeln TYPE ebeln, ebelp TYPE ebelp, matnr TYPE matnr, MENGE TYPE bstmg, aedat TYPE aedat, " Дата изменения END OF ty_ekpo_data. CLASS-DATA: go_hier_table TYPE REF TO cl_salv_hierseq_table, gt_ekko_data TYPE STANDARD TABLE OF ty_ekko_data, " Таблица с заголовками заказов gt_ekpo_data TYPE STANDARD TABLE OF ty_ekpo_data. " Таблица с позициями заказов CLASS-METHODS: get_data, " Получение данных из БД create_table, " Создание иерархической таблицы display. ENDCLASS. "lcl_report DEFINITION START-OF-SELECTION. lcl_report=>get_data( ). lcl_report=>create_table( ). lcl_report=>display( ). CLASS lcl_report IMPLEMENTATION. METHOD get_data. CLEAR: gt_ekko_data, gt_ekpo_data. SELECT * FROM ekko INTO CORRESPONDING FIELDS OF TABLE gt_ekko_data UP TO 10 ROWS WHERE bsart = 'NB'. SELECT * FROM ekpo INTO CORRESPONDING FIELDS OF TABLE gt_ekpo_data FOR ALL ENTRIES IN gt_ekko_data WHERE ebeln = gt_ekko_data-ebeln. ENDMETHOD. "get_data METHOD create_table. DATA: lt_bind TYPE salv_t_hierseq_binding, ls_bind TYPE salv_s_hierseq_binding. " Заполняем таблицу со связью между таблицми ls_bind-master = 'EBELN'. ls_bind-slave = 'EBELN'. APPEND ls_bind TO lt_bind. TRY. CALL METHOD cl_salv_hierseq_table=>factory EXPORTING t_binding_level1_level2 = lt_bind IMPORTING r_hierseq = go_hier_table CHANGING t_table_level1 = gt_ekko_data t_table_level2 = gt_ekpo_data. CATCH cx_salv_data_error cx_salv_not_found. MESSAGE 'Ошибка при создании таблицы' TYPE 'S'. ENDTRY. ENDMETHOD. "create_table METHOD display. go_hier_table->display( ). ENDMETHOD. "display ENDCLASS. "lcl_report IMPLEMENTATION |
Результат работы программы:
Настройка функций
Как и в случае с cl_salv_table, в полноэкранном режиме для установки GUI статуса необходимо использовать метод SET_SCREEN_STATUS, параметр REPORT отвечает за то из какой программы будет взят GUI статус, PFSTATUS – имя GUI статуса, SET_FUNCTIONS – определяет какие стандартные функции будут использованы в программе.
Может принимать значения: C_FUNCTIONS_DEFAULT – сортировки, фильтры, выбор формата. C_FUNCTIONS_ALL – все функции ALV, C_FUNCTIONS_NONE – по умолчанию, только пользовательские функции. Константы определены в классе: CL_SALV_MODEL_BASE.
Стандартный GUI статус можно взять в группе функций: SALV_METADATA_STATUS – статус: SALV_TABLE_STANDARD или SALV_TABLE_STDPOPUP, скопировать в свою программу и расширить необходимыми функциями.
Для того чтобы динамически исключить какую либо функцию можно применить класс cl_salv_functions, но вместо метода remove_function использовать метод set_function, параметр name определяет какую функцию будем скрывать, boolean — определяет скрыта она или нет, если скрываем, ставим в abap_true. Метод remove_function не работает для полно экранного режима.
Пример настройки функций через класс (когда используется контейнер):
1 2 3 4 5 6 7 |
METHOD setup_functions. DATA: lo_functions TYPE REF TO cl_salv_functions_list. lo_functions = go_hier_table->get_functions( ). lo_functions->set_all( ). ENDMETHOD. |
Настройка через GUI статус:
1 2 3 4 5 6 7 8 |
METHOD setup_functions. go_hier_table->set_screen_status( EXPORTING REPORT = sy-repid pfstatus = 'SALV_STANDARD' set_functions = CL_SALV_MODEL_BASE=>C_FUNCTIONS_ALL ). ENDMETHOD. |
Результат:
Настройка колонок
Настройка колонок работает так же как и с cl_salv_table, за исключением того что для настройки колонок используются классы – cl_salv_columns_hierseq и cl_salv_column_hierseq. Кроме того колонки настраиваются относительно уровня иерархии, при получении ссылки на экземпляр класса cl_salv_columns_hierseq необходимо указать уровень в иерархии.
В настройке колонок можно настроить сворачивание иерархии, для этого в структуры необходимо добавить поле expand с типом char1. И в настройке колонок верхнего уровня указать колонку, отвечающую за эту логику через метод set_expand_column.
Для того чтобы иерархия была развернута необходимо получить ссылку на экземпляр уровня иерархии представленный классом cl_salv_hierseq_level и вызвать метод – set_items_expanded. Для получения экземпляра данного класса необходимо использовать метод get_level (уровень) класса cl_salv_hierseq_table.
Пример настройки колонок:
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 |
METHOD setup_columns. DATA: lo_columns TYPE REF TO cl_salv_columns_hierseq, ls_color TYPE LVC_S_COLO, lo_level TYPE REF TO cl_salv_hierseq_level, lo_column TYPE REF TO cl_salv_column_hierseq. ls_color-col = 4. ls_color-int = 1. TRY. lo_columns = go_hier_table->get_columns( LEVEL = 1 ). lo_columns->set_expand_column( 'EXPAND' ). lo_level = go_hier_table->get_level( 1 ). lo_level->set_items_expanded( abap_true ). lo_column ?= lo_columns->get_column( 'EBELN' ). lo_column->set_cell_type( IF_SALV_C_CELL_TYPE=>hotspot ). lo_columns = go_hier_table->get_columns( LEVEL = 2 ). lo_column ?= lo_columns->get_column( 'EBELN' ). lo_column->set_cell_type( IF_SALV_C_CELL_TYPE=>hotspot ). lo_column->set_color( ls_color ). CATCH cx_salv_not_found cx_salv_method_not_supported cx_salv_data_error. ENDTRY. ENDMETHOD. |
Результат:
Настройка сортировок
Настройка сортировок как и в классе cl_salv_table происходит через класс cl_salv_sorts, за исключением того что ссылку на него мы получаем указывая уровень иерархии.
Пример настройки сортировок:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
METHOD setup_sorts. DATA: lo_sorts TYPE REF TO cl_salv_sorts. TRY. lo_sorts = go_hier_table->get_sorts( 1 ). lo_sorts->add_sort( EXPORTING columnname = 'LIFNR' sequence = IF_SALV_C_SORT=>SORT_UP group = IF_SALV_C_SORT=>group_with_newpage ). CATCH cx_salv_not_found cx_salv_existing cx_salv_data_error. ENDTRY. ENDMETHOD. |
Результат:
Обработка событий
За обработку событий отвечает класс CL_SALV_EVENTS_HIERSEQ, он позволяет обработать следующие события:
- TOP_OF_PAGE – обработка заголовка
- END_OF_PAGE – обработка подвала
- BEFORE_SALV_FUNCTION – событие срабатывает до стандартной функции
- AFTER_SALV_FUNCTION – событие срабатывающее после стандартной функции
- ADDED_FUNCTION – событие срабатывающее на нажатие своих функций
- DOUBLE_CLICK – двойной щелчок
- LINK_CLICK – обработка нажатий на активные элементы (в иерархической таблице только hotspot)
Как видно из примера выше поле EBELN мы сделали активным элементом (hotspot), допустим нам необходимо, чтобы при нажатии на него открывалась транзакция на просмотр заказа. Первое что нужно сделать, это создать обработчик события. Объявление метода:
1 |
on_link_click FOR EVENT link_click OF cl_salv_events_hierseq IMPORTING row COLUMN LEVEL. |
Его реализация:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
METHOD on_link_click. " Т.к. у нас 1 активный элемент, столбец проверять нет необходимости " Необходимо проверить на каком уровне был щелчок - level DATA: ls_ekpo_data TYPE ty_ekpo_data, lv_ebeln TYPE ebeln, ls_ekko_data TYPE ty_ekko_data. CASE LEVEL. WHEN 1. READ TABLE gt_ekko_data INTO ls_ekko_data INDEX row. lv_ebeln = ls_ekko_data-ebeln. WHEN 2. READ TABLE gt_ekpo_data INTO ls_ekpo_data INDEX row. lv_ebeln = ls_ekpo_data-ebeln. ENDCASE. CHECK lv_ebeln IS NOT INITIAL. SET PARAMETER ID 'BES' FIELD lv_ebeln. CALL TRANSACTION 'ME23N' AND SKIP FIRST SCREEN. ENDMETHOD. |
Далее необходимо зарегистрировать обработчик события:
1 2 3 4 5 6 7 |
METHOD setup_events. DATA: lo_events TYPE REF TO cl_salv_events_hierseq. lo_events = go_hier_table->get_event( ). SET HANDLER on_link_click FOR lo_events. ENDMETHOD. |
Напоследок код программы целиком:
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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
REPORT zrep_hier_tab. CLASS lcl_report DEFINITION FINAL. PUBLIC SECTION. TYPES: BEGIN OF ty_ekko_data, expand TYPE char1, ebeln TYPE ebeln, " Заказ lifnr TYPE lifnr, " Поставщик END OF ty_ekko_data, BEGIN OF ty_ekpo_data, expand TYPE char1, ebeln TYPE ebeln, ebelp TYPE ebelp, matnr TYPE matnr, MENGE TYPE bstmg, aedat TYPE aedat, " Дата изменения END OF ty_ekpo_data. CLASS-DATA: go_hier_table TYPE REF TO cl_salv_hierseq_table, gt_ekko_data TYPE STANDARD TABLE OF ty_ekko_data, " Таблица с заголовками заказов gt_ekpo_data TYPE STANDARD TABLE OF ty_ekpo_data. " Таблица с позициями заказов CLASS-METHODS: get_data, " Получение данных из БД create_table, " Создание иерархической таблицы setup_columns, " Настройка колонок setup_functions, " Настройка функций setup_sorts, " Настройка сортировки setup_events, " Настройка событий on_link_click FOR EVENT link_click OF cl_salv_events_hierseq IMPORTING row COLUMN LEVEL, display. ENDCLASS. "lcl_report DEFINITION START-OF-SELECTION. lcl_report=>get_data( ). lcl_report=>create_table( ). lcl_report=>setup_functions( ). lcl_report=>setup_columns( ). lcl_report=>setup_sorts( ). lcl_report=>setup_events( ). lcl_report=>display( ). CLASS lcl_report IMPLEMENTATION. METHOD get_data. CLEAR: gt_ekko_data, gt_ekpo_data. SELECT * FROM ekko INTO CORRESPONDING FIELDS OF TABLE gt_ekko_data UP TO 10 ROWS WHERE bsart = 'NB'. SELECT * FROM ekpo INTO CORRESPONDING FIELDS OF TABLE gt_ekpo_data FOR ALL ENTRIES IN gt_ekko_data WHERE ebeln = gt_ekko_data-ebeln. ENDMETHOD. "get_data METHOD create_table. DATA: lt_bind TYPE salv_t_hierseq_binding, ls_bind TYPE salv_s_hierseq_binding. " Заполняем таблицу со связью между таблицми ls_bind-master = 'EBELN'. ls_bind-slave = 'EBELN'. APPEND ls_bind TO lt_bind. TRY. CALL METHOD cl_salv_hierseq_table=>factory EXPORTING t_binding_level1_level2 = lt_bind IMPORTING r_hierseq = go_hier_table CHANGING t_table_level1 = gt_ekko_data t_table_level2 = gt_ekpo_data. CATCH cx_salv_data_error cx_salv_not_found. MESSAGE 'Ошибка при создании таблицы' TYPE 'S'. ENDTRY. ENDMETHOD. "create_table METHOD display. go_hier_table->display( ). ENDMETHOD. "display METHOD setup_functions. go_hier_table->set_screen_status( EXPORTING REPORT = sy-repid pfstatus = 'SALV_TABLE_STANDARD' set_functions = CL_SALV_MODEL_BASE=>C_FUNCTIONS_ALL ). ENDMETHOD. METHOD setup_sorts. DATA: lo_sorts TYPE REF TO cl_salv_sorts. TRY. lo_sorts = go_hier_table->get_sorts( 1 ). lo_sorts->add_sort( EXPORTING columnname = 'LIFNR' sequence = IF_SALV_C_SORT=>SORT_UP group = IF_SALV_C_SORT=>group_with_newpage ). CATCH cx_salv_not_found cx_salv_existing cx_salv_data_error. ENDTRY. ENDMETHOD. METHOD setup_columns. DATA: lo_columns TYPE REF TO cl_salv_columns_hierseq, ls_color TYPE LVC_S_COLO, lo_level TYPE REF TO cl_salv_hierseq_level, lo_column TYPE REF TO cl_salv_column_hierseq. ls_color-col = 4. ls_color-int = 1. TRY. lo_columns = go_hier_table->get_columns( LEVEL = 1 ). lo_columns->set_expand_column( 'EXPAND' ). lo_level = go_hier_table->get_level( 1 ). lo_level->set_items_expanded( abap_true ). lo_column ?= lo_columns->get_column( 'EBELN' ). lo_column->set_cell_type( IF_SALV_C_CELL_TYPE=>hotspot ). lo_columns = go_hier_table->get_columns( LEVEL = 2 ). lo_column ?= lo_columns->get_column( 'EBELN' ). lo_column->set_cell_type( IF_SALV_C_CELL_TYPE=>hotspot ). lo_column->set_color( ls_color ). CATCH cx_salv_not_found cx_salv_method_not_supported cx_salv_data_error. ENDTRY. ENDMETHOD. METHOD on_link_click. " Т.к. у нас 1 активный элемент, столбец проверять нет необходимости " Необходимо проверить на каком уровне был щелчок - level DATA: ls_ekpo_data TYPE ty_ekpo_data, lv_ebeln TYPE ebeln, ls_ekko_data TYPE ty_ekko_data. CASE LEVEL. WHEN 1. READ TABLE gt_ekko_data INTO ls_ekko_data INDEX row. lv_ebeln = ls_ekko_data-ebeln. WHEN 2. READ TABLE gt_ekpo_data INTO ls_ekpo_data INDEX row. lv_ebeln = ls_ekpo_data-ebeln. ENDCASE. CHECK lv_ebeln IS NOT INITIAL. SET PARAMETER ID 'BES' FIELD lv_ebeln. CALL TRANSACTION 'ME23N' AND SKIP FIRST SCREEN. ENDMETHOD. METHOD setup_events. DATA: lo_events TYPE REF TO cl_salv_events_hierseq. lo_events = go_hier_table->get_event( ). SET HANDLER on_link_click FOR lo_events. ENDMETHOD. ENDCLASS. "lcl_report IMPLEMENTATION |