简体   繁体   中英

Specific layout in an ALV

In an ITAB I have 3 fields: ACCOUNT-OBJECT_AMOUNT and a sample is:

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

And I want the display to be like the below:

      KAGR1  KAGR2  
64000  25  
64010  20     15  
64020         30  

Can anyone know how to display it in an ALV?
Thanks

Here is a generic solution. Note that the method show_table_grouped_by has no knowledge of the type of the table, so it can be used with any table, although I bet there are some field types that would break the dynamic code. The data to display can have multiple fields that will be used as keys (your example only has one) and one field that is used for the columns ( i_group_by ) and one field that is used to aggregate from ( i_aggregate_from ). Most of the idea of this program comes from this blog , however the solution below is more dynamic. The complete program processes the data as provided in the question, with the value in the last line corrected to come to the result in the example.

If you know that the values for your group by field will be limited to a certain number of values you can make a less dynamic solution that will probably be more efficient.

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'
  ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM