ABAP: Красивый

в 8:04, , рубрики: abap, ERP-системы, SAP ERP, метки:

Эта публикация предназначена ABAP-разработчикам в SAP ERP и всем им сочувствующим.

Немногие знают, что в ALV можно подключать HTML-заголовки. Еще больше не знают, что можно сделать красивый стандартный выпадающий список, он же select-box, только для такой по сути стандартной фичи, потребуется много вашего Z-кода.

Выглядит примерно так:

ABAP: Красивый - 1

Добро пожаловать под кат.

Поехали! Определим глобальные переменные:

— Выходная таблица нашего отчета, пусть она будет на основе всем известной таблицы 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 cl_my_event_handler DEFINITION
*----------------------------------------------------------------------*

CLASS cl_my_event_handler DEFINITION.
  PUBLIC SECTION.
    METHODS:
      handle_selections FOR EVENT selected OF 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.  

Запускаем! Любуемся на итог страданий:

ABAP: Красивый - 2

ABAP: Красивый - 3

Вроде простая штука, а в SAPе нужно постараться еще. Всем спасибо.

Автор: Endrews

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js