REPORT z_alv_crossed_table.
*---------------------------------------------------------------------*
* This report displays data from table VBAK (Orders) in a crossed     *
* table :                                                             *
* - Column        : Sales organization                                *
* - Line          : Creation date                                     *
* - Intersection  : Number of orders created                          *
*---------------------------------------------------------------------*
* Author : Michel PIOUD - Updated 16-Nov-07                           *
* HomePage : http://www.oocities.org/mpioud                          *
*---------------------------------------------------------------------*
CONSTANTS :
  c_x VALUE 'X'.
*---------------------------------------------------------------------*
TYPE-POOLS: slis.                      " ALV Global types

TYPES :
  BEGIN OF ty_data,
    erdat TYPE sydatum,                " Creation Date
    vkorg TYPE vkorg,                  " Sales organization
    total TYPE i,                      " Total of orders
  END OF ty_data.

DATA :
  gs_vbak TYPE vbak,                   " Sales Document
  gt_data TYPE TABLE OF ty_data.

*---------------------------------------------------------------------*
SELECT-OPTIONS :
  s_vkorg FOR gs_vbak-vkorg,           " Sales organization
  s_kunnr FOR gs_vbak-kunnr,           " Sold-to party
  s_vbeln FOR gs_vbak-vbeln,           " Sales document
  s_erdat FOR gs_vbak-erdat.           " Creation Date

SELECTION-SCREEN :
  SKIP, BEGIN OF LINE,COMMENT 5(27) v_1 FOR FIELD p_max.    "#EC NEEDED
PARAMETERS p_max(3) TYPE n DEFAULT '020' OBLIGATORY.
SELECTION-SCREEN END OF LINE.

*---------------------------------------------------------------------*
INITIALIZATION.

  v_1 = 'Maximum of lines to display'.

*---------------------------------------------------------------------*
START-OF-SELECTION.

  PERFORM f_read_data.

*---------------------------------------------------------------------*
END-OF-SELECTION.

  PERFORM f_display_data.

*---------------------------------------------------------------------*
*      Form  f_read_data
*---------------------------------------------------------------------*
FORM f_read_data.

  SELECT erdat vkorg COUNT(*) AS total
    INTO TABLE gt_data
    FROM vbak
      UP TO p_max ROWS
   WHERE kunnr IN s_kunnr
     AND vbeln IN s_vbeln
     AND vkorg IN s_vkorg
     AND erdat IN s_erdat
   GROUP BY vkorg erdat
   ORDER BY erdat DESCENDING.

ENDFORM.                               " F_READ_DATA
*---------------------------------------------------------------------*
*      Form  F_DISPLAY_DATA
*---------------------------------------------------------------------*
FORM f_display_data.

  FIELD-SYMBOLS :
    <field>   TYPE ANY,
    <header>  TYPE ANY,
    <lt_data> TYPE STANDARD TABLE.     " Data to display

* Macro definition
  DEFINE m_sort.
    add 1 to ls_sort-spos.
    ls_sort-fieldname = &1.
    ls_sort-down      = c_x.
    append ls_sort to lt_sort.
  END-OF-DEFINITION.

  DATA:
    l_col(5),
    ls_data     TYPE ty_data,
    lp_struct   TYPE REF TO data,
    lp_table    TYPE REF TO data,      " Pointer to dynamic table
    ls_lvc_cat  TYPE lvc_s_fcat,
    lt_lvc_cat  TYPE lvc_t_fcat,       " Field catalog
    ls_fieldcat TYPE slis_fieldcat_alv,
    lt_fieldcat TYPE slis_t_fieldcat_alv,  " Field catalog
    lt_sort     TYPE slis_t_sortinfo_alv,
    ls_sort     TYPE slis_sortinfo_alv,
    ls_layout   TYPE slis_layout_alv,
    lt_data     TYPE TABLE OF ty_data.

* Build Fieldcatalog - First column
  ls_lvc_cat-fieldname = 'ERDAT'.
  ls_lvc_cat-ref_table = 'VBAK'.
  APPEND ls_lvc_cat TO lt_lvc_cat.

  ls_fieldcat-fieldname   = 'ERDAT'.
  ls_fieldcat-ref_tabname = 'VBAK'.
  ls_fieldcat-key  = c_x.
  APPEND ls_fieldcat TO lt_fieldcat.

  lt_data[] = gt_data[].
  SORT lt_data BY vkorg.
  DELETE ADJACENT DUPLICATES FROM lt_data COMPARING vkorg.

  LOOP AT lt_data INTO ls_data.
*   Build Fieldcatalog
    CLEAR ls_lvc_cat.
    CONCATENATE 'V' ls_data-vkorg INTO ls_lvc_cat-fieldname.
    ls_lvc_cat-datatype = 'INT4'.
    APPEND ls_lvc_cat TO lt_lvc_cat.
*   Build Fieldcatalog
    CLEAR ls_fieldcat.
    ls_fieldcat-fieldname = ls_lvc_cat-fieldname.
    ls_fieldcat-datatype  = 'INT4'.
    ls_fieldcat-seltext_s = ls_data-vkorg.
    ls_fieldcat-no_zero   = c_x.
    APPEND ls_fieldcat TO lt_fieldcat.
  ENDLOOP.

  FREE lt_data.

* Create internal table
  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = lt_lvc_cat
    IMPORTING
      ep_table        = lp_table.

  ASSIGN lp_table->* TO <lt_data>.

* Create structure = structure of the internal table
  CREATE DATA lp_struct LIKE LINE OF <lt_data>.
  ASSIGN lp_struct->* TO <header>.

  SORT gt_data BY erdat.

* Fill the internal table <lt_data>
  LOOP AT gt_data INTO ls_data.

    AT NEW erdat.
      CLEAR <header>.
      ASSIGN COMPONENT 'ERDAT' OF STRUCTURE <header> TO <field>.
      IF sy-subrc NE 0. EXIT .ENDIF.
      <field> = ls_data-erdat.
    ENDAT.

    CONCATENATE 'V' ls_data-vkorg INTO l_col.
    ASSIGN COMPONENT l_col OF STRUCTURE <header> TO <field>.
    IF sy-subrc NE 0. EXIT .ENDIF.
    <field> = ls_data-total.

    AT END OF erdat.
      APPEND <header> TO <lt_data>.
    ENDAT.

  ENDLOOP.

* Layout
  ls_layout-colwidth_optimize = c_x.
  ls_layout-zebra = c_x.

  m_sort 'ERDAT'.                      " Sort by creation date

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      is_layout   = ls_layout
      it_fieldcat = lt_fieldcat
      it_sort     = lt_sort
    TABLES
      t_outtab    = <lt_data>.

ENDFORM.                               " F_DISPLAY_DATA
************ END OF PROGRAM Z_ALV_CROSSED_TABLE **********************