Дано: есть вывод отчета в ALV, в котором стандартными средствами включен расчет среднего значения.
Итоговое среднее значение стандартно расчитывается так:
( 30 + 40 + 50 + 0 ) / 4 = 30
Предположим для примера, что в четвёртой строке нулевое значение связано не с нулевым значением, а с его отсутствием.
Соответственно от заказчика есть задание: требуется выводить среднее значение, не учитывающее пустые (нулевые) значения:
Один из способов решения задачи — грязно вторгнуться во внутреннюю кухню ALV. Приступим?
Если создадим дочерний класс от главного CL_GUI_ALV_GRID, то получим возможность переопределить метод SET_DATA_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 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 |
METHOD set_data_table. CALL METHOD super->set_data_table EXPORTING no_of_lines = no_of_lines first_line = first_line CHANGING data_table = data_table EXCEPTIONS error = 1 OTHERS = 2. IF sy-subrc <> 0. RAISE error. ENDIF. me->get_frontend_fieldcatalog( IMPORTING et_fieldcatalog = DATA(lt_fc) ). LOOP AT lt_fc INTO DATA(ls_fc). IF ls_fc-do_sum = 'C' AND ls_fc-no_zero = 'X'. DATA(lv_mean) = abap_true. FIELD-SYMBOLS: <tab> TYPE STANDARD TABLE. ASSIGN mt_outtab->* TO <tab>. "[TODO] - datatype is INT as proof-of-concept DATA(lv_amount) = 0. DATA(lv_count) = 0. LOOP AT <tab> ASSIGNING FIELD-SYMBOL(<rec>). ASSIGN COMPONENT ls_fc-fieldname OF STRUCTURE <rec> TO FIELD-SYMBOL(<val>). IF <val> IS NOT INITIAL. lv_count = lv_count + 1. lv_amount = lv_amount + <val>. ENDIF. ENDLOOP. DATA(lv_total) = lv_amount / lv_count. LOOP AT data_table ASSIGNING FIELD-SYMBOL(<data_total_h>). IF <data_total_h>-style = 1048576 AND <data_total_h>-value(1) = 'T'. READ TABLE data_table ASSIGNING FIELD-SYMBOL(<data_total_v>) WITH KEY col_pos = ls_fc-col_pos row_pos = <data_total_h>-row_pos. <data_total_v>-value = lv_total. ENDIF. ENDLOOP. ENDIF. ENDLOOP. "[TODO] - subtotals are not processed, just proof-of-concept me->get_subtotals( IMPORTING et_grouplevels = DATA(lt_levels) ). IF lv_mean = abap_true. super->set_data_table( CHANGING data_table = mt_data[] ). me->set_auto_redraw( EXPORTING enable = 1 ). ENDIF. ENDMETHOD. |
Остаётся только реализовать отчет на базе нашего нового класса.
Поэтому, если изначально отчет был на CL_SALV_TABLE или REUSE_ALV_GRID_DISPLAY, то придётся потратить время и на это тоже. А можно ли хакнуть похожими методами их — отдельная история.
PS. Данный способ можно применять не только для вышеописанной задачи, но и для некоторых других. Например: можно влиять на объединение ячеек по горизонтали или вертикали (merge), если менять значения в полях MERGEHORIZ и MERGEVERT.
cl_proxy_xml_transform=>xml_xstring_to_abap(
EXPORTING
xml = gv_xstring
IMPORTING
abap_data = ct_data ).