ABAP: Красивий

Ця публікація призначена ABAP-розробникам в SAP ERP і всім їм співчуваючим.

Мало хто знає, що в ALV можна підключати HTML-заголовки. Ще більше не знають, що можна зробити гарний стандартний випадаючий список, він же select-box, тільки для такої по суті стандартної фічі, потрібно багато вашого Z-коду.

Виглядає приблизно так:



Ласкаво просимо під кат.

Поїхали! Визначимо глобальні змінні:

— Вихідна таблиця нашого звіту, нехай вона буде на основі всім відомої таблиці MARA;
— Змінна, в якій ми будемо зберігати поточне значення обраної селект-боксі;
— константу з подпрограммой для HTML-header;
— клас-handler, який буде спрацьовувати при виборі даних, і об'єкт handler.

*----------------------------------------------------------------------*
* Визначення глобальних змінних
*----------------------------------------------------------------------*
TYPE-POOLS: slis.
TABLES: mara.

DATA:
gt_data TYPE TABLE OF mara WITH HEADER LINE,
gv_matnr TYPE mara-matnr.

CONSTANTS:
gc_form_top TYPE slis_formname VALUE 'DO_HTML_TOP_OF_PAGE'. 

*----------------------------------------------------------------------*
* CLASS DEFINITION cl_my_event_handler
*----------------------------------------------------------------------*

CLASS cl_my_event_handler DEFINITION.
PUBLIC SECTION.
METHODS:
handle_selections FOR EVENT OF selected cl_dd_select_element
IMPORTING sender.
ENDCLASS. 

DATA:
go_hand1 TYPE REF TO cl_my_event_handler.

Напишемо головну програму звіту та підпрограми по ініціалізації, отриманні даних і виведення звіту. Тут особливо відзначу, що потрібно створити об'єкт handler і підключити HTML-заголовок: i_callback_html_top_of_page = gc_form_top.

*----------------------------------------------------------------------*
* Звіт
*----------------------------------------------------------------------*
SELECT-OPTIONS:
so_matnr FOR mara-matnr.

INITIALIZATION.

PERFORM init.

START-OF-SELECTION.

PERFORM get_data.

END-OF-SELECTION.

PERFORM reuse_alv.

*&---------------------------------------------------------------------*
*& Form init
*&---------------------------------------------------------------------*
FORM init.
" -------------------------------------------------- "
" Створимо об'єкт хендлера
" -------------------------------------------------- "
CREATE OBJECT go_hand1.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form get_data
*&---------------------------------------------------------------------*
FORM get_data.

" -------------------------------------------------- "
" Отримаємо дані
" -------------------------------------------------- "
SELECT *
FROM mara
INTO TABLE gt_data
WHERE matnr IN so_matnr.
CHECK: sy-subrc IS INITIAL.
SORT: gt_data BY matnr.

ENDFORM. "get_data

*&---------------------------------------------------------------------*
*& Form reuse_alv
*&---------------------------------------------------------------------*
FORM reuse_alv.

DATA: lt_fieldcat TYPE TABLE OF lvc_s_fcat.
CHECK gt_data[] IS NOT INITIAL.

" -------------------------------------------------- "
" Висновок ALV
" -------------------------------------------------- "
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'MARA'
CHANGING
ct_fieldcat = lt_fieldcat[]
EXCEPTIONS
inconsistent_interface = 1
program_error = 2
OTHERS = 3.

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_callback_program = sy-repid
i_callback_html_top_of_page = gc_form_top
it_fieldcat_lvc = lt_fieldcat[]
i_save = 'A'
TABLES
t_outtab = gt_data[].

ENDFORM. "reuse_alv

Для HTML-хедера створюємо підпрограму з іменем, вказаним в глобальному константі. Викличемо з неї підпрограму, яка створить нашу красу:

*&---------------------------------------------------------------------*
*& Form do_html_top_of_page
*&---------------------------------------------------------------------*
FORM do_html_top_of_page USING p_doc TYPE REF TO cl_dd_document.

DATA: lo_form TYPE REF TO cl_dd_form_area,
lo_sele TYPE REF TO cl_dd_select_element.

" -------------------------------------------------- "
" Створимо область
" -------------------------------------------------- "
CALL METHOD p_doc->add_form
IMPORTING
formarea = lo_form.

" -------------------------------------------------- "
" Створимо селект-бокс
" -------------------------------------------------- "
PERFORM add_casebox
TABLES
gt_data
CHANGING
gv_matnr
lo_form
lo_sele.

ENDFORM. "do_html_top_of_page

Подивимося підпрограму по створенню селект-боксу. Тут зазначу, що якщо в звіті була команда, зняти фільтри, зачищаємо нашу глобальну змінну (gv_matnr) зі значенням. Потім створюємо лінію, яку додаємо заголовок фільтра, викликаємо підпрограму, яка заповнить нам значення в ньому, і сам фільтр на форму, закриваємо лінію:

*&---------------------------------------------------------------------*
*& Form add_casebox
*&---------------------------------------------------------------------*
FORM add_casebox
*&---------------------------------------------------------------------*
TABLES
it_data STRUCTURE mara
CHANGING
iv_matnr TYPE mara-matnr
lo_form TYPE REF TO cl_dd_form_area
lo_selec TYPE REF TO cl_dd_select_element.
*&---------------------------------------------------------------------*

DATA: lt_opt_tab TYPE sdydo_option_tab,
lv_text TYPE sdydo_text_element.

*----------------------------------------------------------------------*

DO.
CASE sy-index.
WHEN 1.

" -------------------------------------------------- "
" Скасування фільтрів
" -------------------------------------------------- "
CHECK sy-ucomm EQ '&ILD'.
CLEAR: iv_matnr.

WHEN 2.

" -------------------------------------------------- "
" Початок лінії
" -------------------------------------------------- "
CALL METHOD lo_form->line_with_layout
EXPORTING
start = 'X'.

WHEN 3.

" -------------------------------------------------- "
" Заголовок селект-боксу
" -------------------------------------------------- "
lv_text = 'Матеріал:'.
CALL METHOD lo_form->add_text
EXPORTING
text = lv_text.

WHEN 4.

" -------------------------------------------------- "
" Роздільник
" -------------------------------------------------- "
CALL METHOD lo_form->add_gap
EXPORTING
width = 2.

WHEN 5.

" -------------------------------------------------- "
" Заповнимо таблицю значень
" -------------------------------------------------- "
PERFORM fill_mat_tab
TABLES it_data
CHANGING iv_matnr
lt_opt_tab.

WHEN 6.

" -------------------------------------------------- "
" Додамо сам селект-бокс
" -------------------------------------------------- "
CALL METHOD lo_form->add_select_element
EXPORTING
OPTIONS = lt_opt_tab
value = 'P'
IMPORTING
select_element = lo_selec.

WHEN 7.

" -------------------------------------------------- "
" Підключимо хендлер
" -------------------------------------------------- "
SET HANDLER go_hand1->handle_selections
FOR lo_selec.


WHEN 8.

" -------------------------------------------------- "
" Закінчення лінії
" -------------------------------------------------- "
CALL METHOD lo_form->line_with_layout
EXPORTING
end = 'X'.


WHEN OTHERS.
EXIT.
ENDCASE.
ENDDO.

ENDFORM. 

У програмі щодо заповнення фільтру додамо спочатку те значення, яке зараз вибрано, щоб воно було першим у списку. Потім додамо значення Все, якщо у нас в таблиці більше одного значення. І потім всі записи з таблиці:

*&---------------------------------------------------------------------*
*& Form fill_mat_tab
*&---------------------------------------------------------------------*
FORM fill_mat_tab
*&---------------------------------------------------------------------*
TABLES
it_data STRUCTURE mara
CHANGING
iv_matnr TYPE matnr
it_optab TYPE sdydo_option_tab.
*&---------------------------------------------------------------------*

DATA: ls_opt TYPE sdydo_option.
REFRESH: it_optab.

*----------------------------------------------------------------------*

DO.
CASE sy-index.
WHEN 1.

" -------------------------------------------------- "
" Збережемо значення якщо воно вибрано
" -------------------------------------------------- "
CHECK iv_matnr IS NOT INITIAL.
ls_opt-value = iv_matnr.
ls_opt-text = iv_matnr.
APPEND ls_opt TO it_optab.

WHEN 2.

" -------------------------------------------------- "
" Якщо значення не одне, додамо рядок - Все
" -------------------------------------------------- "
READ TABLE it_data INDEX 1.
LOOP AT it_data TRANSPORTING NO FIELDS WHERE matnr NE it_data-matnr.
ls_opt-value = '*'.
ls_opt-text = 'Все'.
APPEND ls_opt TO it_optab.
EXIT.
ENDLOOP.

WHEN 3.

" -------------------------------------------------- "
" Додамо всі значення
" -------------------------------------------------- "
LOOP AT it_data WHERE matnr IS NOT INITIAL.
ls_opt-value = it_data-matnr.
ls_opt-text = it_data-matnr.
COLLECT ls_opt INTO it_optab.
ENDLOOP.

WHEN OTHERS.
EXIT.
ENDCASE.
ENDDO.


ENDFORM. 

Запровадимо наш handler. Тут в sender->value значення, вибране користувачем. Запишемо його відразу в нашу глобальну змінну gv_matnr. У підпрограмі set_filter по обробці стандартної фільтрації:

1) Отримаємо глобальний grid в локальний об'єкт;
2) Отримаємо вже встановлені параметри фільтрації, і знімемо вже був раніше встановлений фільтр, по полю, яке ми фільтруємо, через селект-бокс;
3) Додамо нові параметри фільтрації;
4) Збережемо фільтр;
5) Оновимо звіт.

*----------------------------------------------------------------------*
* CLASS cl_my_event_handler IMPLEMENTATION
*----------------------------------------------------------------------*

CLASS cl_my_event_handler IMPLEMENTATION.


METHOD handle_selections.

DATA text_buff TYPE sdydo_text_element.

text_buff = sender->value.
gv_matnr = text_buff.

" -------------------------------------------------- "
" Встановимо фільтр в звіті
" -------------------------------------------------- "

PERFORM set_filter
TABLES
gt_data
USING
gv_matnr
.
ENDMETHOD. "handle_selections

ENDCLASS. "cl_my_event_handler IMPLEMENTATION

*&---------------------------------------------------------------------*
*& Form set_filter
*&---------------------------------------------------------------------*
FORM set_filter
*&---------------------------------------------------------------------*
TABLES
it_data STRUCTURE mara
USING
iv_value TYPE mara-matnr.
*&---------------------------------------------------------------------*

DATA: lo_ref1 TYPE REF TO cl_gui_alv_grid,
lt_filtered TYPE lvc_t_filt,
lv_field TYPE char10 VALUE 'MATNR',
ls_filter LIKE LINE OF lt_filtered.

*----------------------------------------------------------------------*

DO.
CASE sy-index.
WHEN 1.

" -------------------------------------------------- "
" Отримаємо об'єкт ALV
" -------------------------------------------------- "
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = lo_ref1.

WHEN 2.

" -------------------------------------------------- "
" Отримаємо підсумки і приберемо фільтр вуст. минулого разу
" -------------------------------------------------- "
CALL METHOD lo_ref1->get_filter_criteria
IMPORTING
et_filter = lt_filtered.
DELETE lt_filtered WHERE fieldname = lv_field.

WHEN 3.

" -------------------------------------------------- "
" Додамо новий фільтр
" -------------------------------------------------- "
CHECK iv_value NE "
AND iv_value NE '*'.
ls_filter-fieldname = lv_field.
ls_filter-sign = 'I'.
ls_filter-option = 'EQ'.
ls_filter-low = iv_value.
APPEND ls_filter TO lt_filtered.

WHEN 4.

" -------------------------------------------------- "
" Збережемо фільтр
" -------------------------------------------------- "
CALL METHOD lo_ref1->set_filter_criteria
EXPORTING
it_filter = lt_filtered
EXCEPTIONS
no_fieldcatalog_available = 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.

WHEN 5.

" -------------------------------------------------- "
" Оновимо ALV
" -------------------------------------------------- "
lo_ref1->refresh_table_display( ).

WHEN OTHERS.
EXIT.
ENDCASE.
ENDDO.

ENDFORM. 

Запускаємо! Милуємося на підсумок страждань:





Ніби проста штука, а в ЅАРе потрібно ще постаратися. Всім дякую.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.