Niedawno implementowałem raport ALV z dynamicznie definiowanymi kolumnami. Zwykle kolumny raportu ALV są określane na podstawie struktury słownika danych lub kolumny są dodawane w kodzie do katalogu pól ALV. W moim przypadku wymaganiem było, aby kolumny raportu wynikały z konfiguracji systemu, która może zmienić się w przyszłości. Raport miał się dopasować do takiej zmiany bez konieczności zmian w kodzie ABAP. Wtedy właśnie zdałem sobie sprawę z potencjału dynamicznie definiowanych typów danych:
CREATE DATA ... TYPE HANDLE ...
oraz klas CL_ABAP_DATADESCR, CL_ABAP_STRUCTDESCR i CL_ABAP_TABLEDESCR. Dzięki temu mogłem szybko zdefiniować wewnętrzną tablicę o dynamicznej strukturze ustalanej na podstawie bieżącej konfiguracji. Otwartą kwestią pozostało zbudowanie katalogu pól ALV. Jedną możliwością było dodawanie pól pojedynczo w kodzie raportu. Inną – przygotowanie uniwersalnej procedury budującej katalog pól ALV, która zrobi to automatycznie.
Oto ta procedura:
FORM build_fieldcat USING pt_tab TYPE REF TO data CHANGING pt_fc TYPE slis_t_fieldcat_alv. DATA: lo_tabledescr TYPE REF TO cl_abap_tabledescr, lo_structdescr TYPE REF TO cl_abap_structdescr, lt_components TYPE abap_component_tab, lo_elemdescr TYPE REF TO cl_abap_elemdescr, lv_pos LIKE sy-tabix, ls_dfies LIKE dfies. FIELD-SYMBOLS: <comp> LIKE LINE OF lt_components, <fc> LIKE LINE OF pt_fc. lo_tabledescr ?= cl_abap_tabledescr=>describe_by_data_ref( pt_tab ). lo_structdescr ?= lo_tabledescr->get_table_line_type( ). lt_components = lo_structdescr->get_components( ). LOOP AT lt_components ASSIGNING <comp>. lv_pos = sy-tabix. APPEND INITIAL LINE TO pt_fc ASSIGNING <fc>. lo_elemdescr ?= <comp>-type. ls_dfies = lo_elemdescr->get_ddic_field( p_langu = sy-langu ). MOVE-CORRESPONDING ls_dfies TO <fc>. CLEAR <fc>-tabname. <fc>-col_pos = lv_pos. <fc>-fieldname = <comp>-name. <fc>-reptext_ddic = ls_dfies-reptext. IF ls_dfies-convexit IS NOT INITIAL. CONCATENATE '==' ls_dfies-convexit INTO <fc>-edit_mask. ENDIF. ENDLOOP. ENDFORM. "build_fieldcat
Procedura odczytuje przy pomocy klas CL_ABAP_*DESCR pola dynamicznie zadeklarowanej tablicy wewnętrznej. Następnie zakładając, że te pola zostały zdefiniowane na podstawie elementów danych DDIC, procedura odczytuje ich atrybuty i buduje katalog pól ALV. Naturalnie ta uniwersalna procedura może być dopasowywana do indywidualnych zastosowań np. poprzez określenie pól jednostek miary czy waluty.
Podejście obiektowe
Analogiczną funkcjonalność Łukasz Pęgiel opisał na swoim blogu ABAPblog.com w artykule Create fieldcatalog from internal table:
class-methods lvc_fcat_from_internal_table importing it_table type any table returning value(rt_fcat) type lvc_t_fcat.
method lvc_fcat_from_internal_table. data: table type ref to data. create data table like it_table. assign table->* to field-symbol( <table>). try. cl_salv_table=>factory( importing r_salv_table = data(salv_table) changing t_table = <table> ). rt_fcat = cl_salv_controller_metadata=>get_lvc_fieldcatalog( r_columns = salv_table->get_columns( ) " ALV Filter r_aggregations = salv_table->get_aggregations( ) " ALV Aggregations ). catch cx_root. endtry. endmethod.
Dziękuję Łukasz za komentarze, powyższy przykład i ciekawy artykuł!
Ja to robie z wykorzystanie SALV 🙂 https://abapblog.com/articles/how-to/76-create-fieldcatalog-from-internal-table. Mniej kodu i zawsze na czasie 🙂
Dobre…
Podziel się proszę kawałkiem swojego kodu.
Jest w artykule, chciałem wkleić tutaj bo to kilka linijek, ale jakieś zabezpieczenia nie pozwalają mi na to. Pewnie znaki specjalne 🙂