Создание CDS и отчеты IDA (aka ALV on HANA) - aamelin1/SAP-FI-notes GitHub Wiki

Что такое CDS и чем они могут быть полезны?

CDS расшифровывается как Core Data Services. Это функционал, позволяющий создавать представления/ракурсы данных посредством языка DDL (Data Definition Language).

Простым языком - вы можете создать свой ракурс на основании соединений таблиц SAP с дополнительной логикой заполнения полей в этом ракурсе.

Например взять одну таблицу как основной источник, обогатить ее данными из связанных таблиц (например через соединения join/association) и добавить логику для заполнения отдельных столбцов в создаваемом ракурсе. В итоге получить ракурс с нужными вам данными и далее работать с ним напрямую, например делать выборки в abap программах или визуализировать через инструменты SAP, например через IDA или кастомное Fiori приложение через odata.

Описание CDS от SAP

Что такое IDA aka ALV on HANA?

IDA - Это инструмент визуализации данных в SAP GUI, расшифровывается как SAP List Viewer with Integrated Data Access. Иногда его называют ALV on HANA.

Основная суть инструмента - в него можно передать название CDS и дополнительные ограничения (а не готовую внутреннюю таблицу как в случае с классическим ALV), система выберет нужные данные и выведет их в виде таблицы, визуально похожей на ALV Grid, но более функциональную.

Преимущества IDA:

  • Построение иерархий, т.е. вложенных уровней и подсуммирования по ним
  • Доступны все стандартные функции ALV (кроме редактирования и части форматирования)
  • Большая производительность на больших данных (т.к. не требует предвыборки всех данных)
  • Возможность использование текстового поиска
  • Возможность добавления полей не из CDS (расчетные поля)

Основные отличия IDA от классического ALV Grid

SAP List Viewer ALV with IDA
Выборка данных Выборка данных производится до вывода ALV, сначала все данные должны быть сохранены во внутреннюю таблицу (ITAB) При вызове IDA достаточно передать только название таблицы/CDS, все выборки производятся средствами IDA
Потребление памяти В памяти хранится вся отображаемая внутренняя таблица ITAB В памяти хранится только видимая часть таблицы
Производительность Сначала выбираются все данные для внутренней таблице, потом все данные передаются для вывода на экран Выборка и передача только видимой части данных
Пролистывание отчета Обработка только на стороне сервера приложений/презентаций, не нужны запросы к БД При пролистывании вызываются новые выборки из БД для новых данных
Сортировка, фильтрация, суммирование итд На уровне сервера приложений по данным ITAB, при этом обрабатывается весь объем данных Вызывается новая выборка из БД, если используются суммы/подсуммы, то агрегация так же выполняется на уровне БД HANA

Описание IDA от SAP

Как это работает?

Предпосылки

  • У вас должна быть относительно свежая система SAP S/4HANA
  • Установлен Eclipse
  • В Eclipse установлен плагин ADT, см SAP Dev Tools
  • В Eclipse настроено подключение к системе разработки SAP
  • Вы хотите сделать отчет на основе данных из SAP используя новые функции S/4HANA

Полезные ссылки:

Installing ABAP Development Tools

Configuring the ABAP Back-end for ABAP Development Tools

Создание простой CDS

Приступим к созданию простой CDS. Для этого открываем Eclipse, выбираем нужную систему (систему разработки и нужный мандант), переходим в наш Z пакет (удобно добавить его в избранное для быстрого доступа) и нажимаем правой кнопкой по названию пакета и создаем новый объект

Выбираем core data services->data definition

Указываем имя новой CDS

И создаем новый транспортный запрос

Должна появится заготовка для CDS вида:

@AbapCatalog.sqlViewName: ''
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'test CDS'
define view ZVFI_TEST as select from data_source_name
association [1] to target_data_source_name as _association_name
    on $projection.element_name = _association_name.target_element_name {
    
    _association_name // Make association public
}

Для примера сделаем CDS с данными по плану счетов и текстами сразу на двух языках. Т.е. нам нужны будут таблицы

  • SKA1 (данные счетов ГК)
  • SKAT (текстовая таблица)

Между собой таблицы связаны по полям ktopl и saknr. В skat-spras есть еще ключевое поле spras с языком для текстов.

И итоговая таблица должна быть, допустим, со столбцами:

  • ПСч (SKA1-KTOPL)
  • Счет (SKA1-SAKNR)
  • Название на английском языке (SKAT-TXT50, где SPRAS = EN)
  • Название на португальском языке (SKAT-TXT50, где SPRAS = PT)

Сначала зададим имя CDS для репозитария (sqlViewName), по этому имени можно будет получить доступ к ракурсу например в se16n. Для этого заполним его в первой строке:

@AbapCatalog.sqlViewName: 'ZVRFI_TEST'

Далее добавим условия соединений таблиц SKA1 и SKAT и определим нужные нам поля в ракурсе, сначала для английского языка в SAKT, должно получится что-то вроде этого:

define view ZVFI_TEST as select from SKA1
association [1..1] to skat as _skat_en  
    on ska1.ktopl = _skat_en.ktopl
    and ska1.saknr = _skat_en.saknr
    and _skat_en.spras = 'E'
{
    key SKA1.ktopl as Ktopl,
    key SKA1.saknr as Saknr,
    _skat_en.txt50
}

Активируем нашу CDS и проверим как это работает. Проверить можно двумя способами:

  1. Напрямую в Eclipse нажать F8 и посмотреть результат:
  1. Зайти в SAP GUI и запустить se16, se16n, se16h итд

После того, как мы убедились что все работает - добавим тексты на португальском языке:

define view ZVFI_TEST as select from ska1
association [1..1] to skat as _skat_en  
    on ska1.ktopl = _skat_en.ktopl
    and ska1.saknr = _skat_en.saknr
    and _skat_en.spras = 'E'
association [1..1] to skat as _skat_pt  
    on ska1.ktopl = _skat_pt.ktopl
    and ska1.saknr = _skat_pt.saknr
    and _skat_pt.spras = 'P'
{
    key ska1.ktopl as Ktopl,
    key ska1.saknr as Saknr,
    _skat_en.txt50 as en_txt50,
    _skat_pt.txt50 as pt_txt50
}

Проверим:

Все работает. Для простого примера на этом остановимся и перейдем к визуализации данных с помощью IDA. Детальней про возможности CDS можно почитать тут

Создание отчета на основе CDS с помощью IDA

Создадим новую программу в se38. В ней вызываем create_for_cds_view->fullscreen->display в классе CL_SALV_GUI_TABLE_IDA, в параметр iv_cds_view_name подставляем имя нашей CDS, т.е. так, всего одна строка кода:

REPORT ZFI_TEST_CDS.
cl_salv_gui_table_ida=>create_for_cds_view( iv_cds_view_name = 'ZVFI_TEST' )->fullscreen( )->display( ).

Активируем и проверяем что получилось, запускаем отчет (F8), получаем:

Все работает, данные из нашей CDS отображаются в отчете.

Обычно, все же, нам нужен еще и селекционный экран, где мы могли бы указать какие то ограничения. Пусть в нашем примере ограничением будут поля:

  • ПСч (SKA1-KTOPL)
  • Счет (SKA1-SAKNR)

Для этого добавим в программу блок с селекционным экраном и этими полями

TABLES: ZVRFI_TEST.

SELECT-OPTIONS so_ktopl FOR ZVRFI_TEST-ktopl.
SELECT-OPTIONS so_saknr FOR ZVRFI_TEST-saknr.

И передадим ограничения с селекционного экрана в IDA, в итоге получим:

REPORT ZFI_TEST_CDS.
TABLES: ZVRFI_TEST.

SELECT-OPTIONS so_ktopl FOR ZVRFI_TEST-ktopl.
SELECT-OPTIONS so_saknr FOR ZVRFI_TEST-saknr.

START-OF-SELECTION.
  DATA(o_ida) = cl_salv_gui_table_ida=>create_for_cds_view( iv_cds_view_name = 'ZVFI_TEST' ).
  "Формируем ограничения копируя диапазоны с сел экрана
  DATA(o_sel) = NEW cl_salv_range_tab_collector( ).
  o_sel->add_ranges_for_name( iv_name = 'KTOPL' it_ranges = so_ktopl[] ).
  o_sel->add_ranges_for_name( iv_name = 'SAKNR' it_ranges = so_saknr[] ).
  o_sel->get_collected_ranges( IMPORTING et_named_ranges = DATA(lt_sel_crit) ).
  o_ida->set_select_options( it_ranges = lt_sel_crit ).
  "Вывод АЛВ на экран
  o_ida->fullscreen( )->display( ).

В результате получим, селекционный экран при запуске:

Отчет с учетом ограничений с селекционного экрана:

Получили уже почти хороший отчет. Но, раз уж мы используем новые инструменты, то добавим красоты в отчет:

  • Переименуем столбы для текстов
  • Добавим быстрый выбор вариантов (layout)
  • Добавим выбор варианта (layout) на селекционный экран
  • Добавим полнотекстовый поиск по наименованием счетов
  • Добавим проваливание (hotspot) в мастер данные счета (тр. FSP0)
*&---------------------------------------------------------------------*
*& Report ZFI_TEST_CDS
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZFI_TEST_CDS.
TABLES: ZVRFI_TEST.

SELECT-OPTIONS so_ktopl FOR ZVRFI_TEST-ktopl.
SELECT-OPTIONS so_saknr FOR ZVRFI_TEST-saknr.
"Добавим поле с layout на сел экран
PARAMETERS: p_layout TYPE if_salv_gui_layout_persistence=>y_layout_name.

**********************************************************************
CLASS lcl_event_handler DEFINITION .
  PUBLIC SECTION .
    METHODS:
      handle_hot_spot FOR EVENT cell_action OF if_salv_gui_field_display_opt
        IMPORTING ev_field_name
                  eo_row_data.
  PRIVATE SECTION.
ENDCLASS.
**********************************************************************
CLASS lcl_event_handler IMPLEMENTATION .
  METHOD handle_hot_spot.
    DATA: ls_wa TYPE ZVRFI_TEST.
    TRY.
        eo_row_data->get_row_data(
              EXPORTING iv_request_type = if_salv_gui_selection_ida=>cs_request_type-all_fields
              IMPORTING es_row          =  ls_wa ).
*        Hotspot actions
        CASE ev_field_name.
          WHEN 'SAKNR'.
            SET PARAMETER ID 'SAK' FIELD ls_wa-saknr.
            SET PARAMETER ID 'KPL' FIELD ls_wa-ktopl.
            CALL TRANSACTION 'FSP0'.
          WHEN OTHERS.
        ENDCASE.
      CATCH cx_salv_ida_contract_violation
              cx_salv_ida_sel_row_deleted.
    ENDTRY.
  ENDMETHOD.
ENDCLASS .


INITIALIZATION.
 DATA ls_persistence_key TYPE if_salv_gui_layout_persistence=>ys_persistence_key.
 ls_persistence_key-report_name = sy-repid.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_layout.
  cl_salv_gui_grid_utils_ida=>f4_for_layouts( EXPORTING is_persistence_key = ls_persistence_key
                                              IMPORTING es_selected_layout = DATA(ls_selected_layout) ).
  p_layout = ls_selected_layout-name.

START-OF-SELECTION.
  DATA(o_ida) = cl_salv_gui_table_ida=>create_for_cds_view( iv_cds_view_name = 'ZVFI_TEST' ).

  "Формируем ограничения копируя диапазоны с сел экрана
  DATA(o_sel) = NEW cl_salv_range_tab_collector( ).
  o_sel->add_ranges_for_name( iv_name = 'KTOPL' it_ranges = so_ktopl[] ).
  o_sel->add_ranges_for_name( iv_name = 'SAKNR' it_ranges = so_saknr[] ).
  o_sel->get_collected_ranges( IMPORTING et_named_ranges = DATA(lt_sel_crit) ).
  o_ida->set_select_options( it_ranges = lt_sel_crit ).

  "Поменяем название столбцов
  o_ida->field_catalog( )->set_field_header_texts( iv_field_name    = 'EN_TXT50' iv_header_text   = 'EN Name' ).
  o_ida->field_catalog( )->set_field_header_texts( iv_field_name    = 'PT_TXT50' iv_header_text   = 'PT Name' ).

  "Включаем поиск по текстовым полям
  o_ida->standard_functions( )->set_text_search_active( abap_true ).
  o_ida->field_catalog( )->enable_text_search( 'EN_TXT50' ).
  o_ida->field_catalog( )->enable_text_search( 'PT_TXT50' ).

  "установим режимы layout
  o_ida->layout_persistence( )->set_persistence_options( is_persistence_key = VALUE #( report_name = sy-repid )
                                                         i_global_save_allowed = abap_true
                                                         i_user_specific_save_allowed = abap_true ).
  o_ida->toolbar( )->enable_listbox_for_layouts( ). "включим выпадающий список вариантов
  if p_layout is not initial. "установим layout с селекционного экрана
    try.
         o_ida->layout_persistence( )->set_start_layout( p_layout ).
      catch cx_salv_ida_unknown_name.
        message i000(0k) with |Layout { p_layout } unknown - continue w/o start| | layout...|.
    endtry.
  endif.

  "Добавим обработчик проваливаний
  TRY.
    DATA: gr_event_handler TYPE REF TO lcl_event_handler.
    CREATE OBJECT gr_event_handler.
    o_ida->field_catalog( )->display_options( )->display_as_link_to_action( 'SAKNR' ).
    SET HANDLER gr_event_handler->handle_hot_spot FOR o_ida->field_catalog( )->display_options( ).
  CATCH cx_salv_ida_unknown_name cx_salv_call_after_1st_display.
  ENDTRY.

  "Вывод АЛВ на экран
  o_ida->fullscreen( )->display( ).

Что получили в итоге, обычный селекционный экран (добавили только поле с вариантами):

В самом отчете переименовались колонки и появились новые функции:

По сравнению с классическим ALV:

  • Текстовый поиск (два механизм: search и fuzzy search), пример как работает:
  • Быстрый выбор вариантов (layout), в тулбаре наверху появился выпадающий список с сохраненными вариантами (я предсохранил варианты ttt и ttt2):

В некоторых версиях системы есть ошибка с сохранением вариантов, лечится нотой 3196994 - "IDA-ALV - ALV Layout not being saved"

  • Механизм группировок (на мой взгляд это очень удобный функционал)

С помощью него можно выстраивать любые иерархии в отчетах (по нескольким полям сразу), делать подсуммы итд. Пример двухуровневой иерархии, первый уровень - план счетов, второй уровень - счет и его название (через слэш):

Дополнительно про IDA можно почитать тут

Или посмотреть в системе примеры программ по маске SALV_IDA*