ALV 中的特定布局

Specific layout in an ALV

在 ITAB 中我有 3 个字段:ACCOUNT-OBJECT_AMOUNT 示例是:

64000 KAGR1 10  
64000 KAGR1 15  
64010 KAGR1 20  
64010 KAGR2 15  
64020 KAGR2 10  
64020 KAGR2 10 

我希望显示如下所示:

      KAGR1  KAGR2  
64000  25  
64010  20     15  
64020         30  

有谁知道如何在ALV中显示吗?
谢谢

这是一个通用的解决方案。请注意,方法 show_table_grouped_by 不知道 table 的类型,因此它可以与任何 table 一起使用,尽管我打赌有一些字段类型会破坏动态代码.要显示的数据可以有多个字段用作键(您的示例只有一个)和一个用于列的字段 (i_group_by) 和一个用于聚合的字段 (i_aggregate_from).这个程序的大部分想法来自 this blog,但是下面的解决方案更加动态。完整的程序处理问题中提供的数据,并更正最后一行中的值以得出示例中的结果。

如果您知道按字段分组的值将被限制为一定数量的值,您可以制定一个不太动态的解决方案,但可能会更有效。

REPORT zso_group_alv.


TYPES: BEGIN OF ts_data,
         field1 TYPE char10,
         group  TYPE char10,
         val    TYPE i,
       END OF ts_data,
       tt_data TYPE STANDARD TABLE OF ts_data.

DATA: gt_data TYPE tt_data.

CLASS lcl_alv_grouped DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS:
      show_table_grouped_by IMPORTING VALUE(it_data)   TYPE ANY TABLE
                                      i_group_by       TYPE fieldname
                                      i_aggregate_from TYPE fieldname,
      group_fld_name IMPORTING i_value         TYPE any
                     RETURNING VALUE(fld_name) TYPE fieldname.

ENDCLASS.


CLASS lcl_alv_grouped IMPLEMENTATION.

  METHOD group_fld_name.
    " Returns the field name for the group fields
    " This is to make sure there are no reserved names used or
    " reuse of already existing fields
    fld_name = 'fld_' && i_value.
  ENDMETHOD.

  METHOD show_table_grouped_by.
    " Shows the data in table IT_DATA in an ALV
    " The data is transposed
    " The data from field I_AGGREGATE_FROM is summed into groups
    " from the values in the field I_GROUP_BY
    " All the other fields in the table are treated as the key
    " fields for the transposed table

    DATA: ls_component      TYPE cl_abap_structdescr=>component,
          lt_components     TYPE cl_abap_structdescr=>component_table,
          lr_struct         TYPE REF TO cl_abap_structdescr,
          lt_keys           TYPE abap_sortorder_tab,
          lt_key_components TYPE cl_abap_structdescr=>component_table,
          "ls_keys           TYPE REF TO data,
          lr_trans_table    TYPE REF TO data,
          lr_trans_wa       TYPE REF TO data,
          lr_keys_type      TYPE REF TO cl_abap_structdescr,
          ls_keys           TYPE REF TO data,
          ls_keys_prev      TYPE REF TO data,
          lr_salv           TYPE REF TO cl_salv_table.

    FIELD-SYMBOLS: <trans_table> TYPE STANDARD TABLE.


    " Determine the fields in the transposed table
    LOOP AT it_data ASSIGNING FIELD-SYMBOL(<data>).

      AT FIRST.
        " Get field to aggregate
        ASSIGN COMPONENT i_aggregate_from OF STRUCTURE <data> TO FIELD-SYMBOL(<aggregate_field>).
        IF sy-subrc NE 0.
          RETURN. " Would be nice to tell the calling program about this error
        ENDIF.

        " Gather all the other fields from the data table, these are treated as keys
        lr_struct ?= cl_abap_datadescr=>describe_by_data( <data> ).
        LOOP AT lr_struct->get_components( ) ASSIGNING FIELD-SYMBOL(<component>).
          IF <component>-name NE i_aggregate_from AND
             <component>-name NE i_group_by.
            APPEND <component> TO: lt_components,
                                   lt_key_components.
            APPEND VALUE #( name = <component>-name
                            descending = abap_false
                            astext = abap_true
                          ) TO lt_keys.
          ENDIF.
        ENDLOOP.

      ENDAT. " FIRST

      " Get the group by field
      ASSIGN COMPONENT i_group_by OF STRUCTURE <data> TO FIELD-SYMBOL(<group_field>).
      IF sy-subrc NE 0.
        RETURN. " Would be nice to tell the calling program about this error
      ENDIF.

      " Gather all the values in the group by field
      DATA(l_new_group) = group_fld_name( <group_field> ).
      READ TABLE lt_components WITH KEY name = l_new_group TRANSPORTING NO FIELDS.
      IF sy-subrc NE 0.
        ls_component-name = l_new_group.
        ls_component-type ?= cl_abap_datadescr=>describe_by_data( <aggregate_field> ).
        APPEND ls_component TO lt_components.
      ENDIF.

    ENDLOOP. " IT_DATA

    " LT_COMPONENTS is now filled with all the fields to show in the ALV

    " Create the transpose table and fill its
    DATA(lr_trans_table_type) = cl_abap_tabledescr=>create( cl_abap_structdescr=>create( lt_components ) ).
    CREATE DATA lr_trans_table TYPE HANDLE lr_trans_table_type.
    ASSIGN lr_trans_table->* TO <trans_table>.

    " Data needs to be sorted to generate the rows in the transposed table
    SORT it_data BY (lt_keys).

    " Create structures to keep track of the key values
    lr_keys_type ?= cl_abap_structdescr=>create( lt_key_components ).
    CREATE DATA ls_keys TYPE HANDLE lr_keys_type.
    CREATE DATA ls_keys_prev TYPE HANDLE lr_keys_type.
    ASSIGN ls_keys->*      TO FIELD-SYMBOL(<keys>).
    ASSIGN ls_keys_prev->* TO FIELD-SYMBOL(<keys_prev>).

    " Transpose the data
    LOOP AT it_data ASSIGNING <data>.

      MOVE-CORRESPONDING <data> TO <keys>.
      IF <keys> NE <keys_prev>.
        " Found a new key combination, add a row to the transposed table
        APPEND INITIAL LINE TO <trans_table> ASSIGNING FIELD-SYMBOL(<trans_data>).
        MOVE-CORRESPONDING <data> TO <trans_data>. " Filling the key fields
      ENDIF.

      " Agragate the value into the right group
      ASSIGN COMPONENT i_aggregate_from          OF STRUCTURE <data>       TO FIELD-SYMBOL(<value>).
      ASSIGN COMPONENT i_group_by                OF STRUCTURE <data>       TO FIELD-SYMBOL(<group>).
      ASSIGN COMPONENT group_fld_name( <group> ) OF STRUCTURE <trans_data> TO FIELD-SYMBOL(<trans_value>).
      ADD <value> TO <trans_value>.

      " Remember keys to compare with the next row
      <keys_prev> = <keys>.

    ENDLOOP. " IT_DATA

    " Display transposed data in ALV
    TRY.
        cl_salv_table=>factory(
*        EXPORTING
*          list_display   = IF_SALV_C_BOOL_SAP=>FALSE    " ALV Displayed in List Mode
*          r_container    =     " Abstract Container for GUI Controls
*          container_name =
          IMPORTING
            r_salv_table   = lr_salv    " Basis Class Simple ALV Tables
          CHANGING
            t_table        = <trans_table>
        ).
      CATCH cx_salv_msg.    "
        " Some error handling would be nice

    ENDTRY.

    " Will need to do something about the column headers

    lr_salv->display( ).

  ENDMETHOD.

ENDCLASS.




START-OF-SELECTION.

  APPEND VALUE #( field1 = '64000' group = 'KAGR1' val = 10 ) TO gt_data.
  APPEND VALUE #( field1 = '64000' group = 'KAGR1' val = 15 ) TO gt_data.
  APPEND VALUE #( field1 = '64010' group = 'KAGR1' val = 20 ) TO gt_data.
  APPEND VALUE #( field1 = '64010' group = 'KAGR2' val = 15 ) TO gt_data.
  APPEND VALUE #( field1 = '64020' group = 'KAGR2' val = 10 ) TO gt_data.
  APPEND VALUE #( field1 = '64020' group = 'KAGR2' val = 20 ) TO gt_data.

  lcl_alv_grouped=>show_table_grouped_by(
    EXPORTING
      it_data          = gt_data
      i_group_by       = 'GROUP'
      i_aggregate_from = 'VAL'
  ).