display one or more ALV tables local class

REPORT ZLVLISTMULTITABLE .
*&---------------------------------------------------------------------*
*&  Include           Z_TABLE_DISPLAY
*&---------------------------------------------------------------------*
* VERSION 2
*
* Code from Fran?ois Henrotte (EPONA Solutions)
*                             http://www.eponasolutions.com
*                             Belgium
* Please keep reference !
*********************************************************************
* HOW TO
*
* Display an ALV grid :
* CALL METHOD lcl_table_display=>display_grid( 'tabname' ).
*
* Display a hierarchical list with header and detail :
* CALL METHOD lcl_table_display=>display_hier( in_header = 'table1'
*                                              in_detail = 'table2' ).
*
* Display a block list with two tables :
* CALL METHOD lcl_table_display=>set_block_mode( 'X' ).
* CALL METHOD lcl_table_display=>display_grid( 'table1' ).
* CALL METHOD lcl_table_display=>display_grid( 'table2' ).
* CALL METHOD lcl_table_display=>end_block_list( ).
*
* You never have to deal with field catalog of tables !!
*
* What if field catalog has to be changed anyway ?
*
* ob_table = lcl_table_display=>create_table( 'tabname' ).
* CALL METHOD ob_table->set_alv_fieldtext( in_field = field
*                                          in_ftext = 'text' ).
* CALL METHOD lcl_table_display=>display_grid( 'tabname' ).
*********************************************************************

type-pools: abap, slis.

*----------------------------------------------------------------------*
*   LCL_TABLE_DISPLAY DEFINITION
*----------------------------------------------------------------------*
class lcl_table_display definition.

  public section.

    class-methods: display_list importing in_tabname  type any,
                   display_grid importing in_tabname  type any,
                   display_hier importing in_header   type any
                                          in_detail   type any
                                          in_level    type i optional,

                   set_block_mode importing in_mode type c,
                   set_block_text importing in_text type any,
                   end_block_list importing in_print
                                       type slis_print_alv optional
                                 exceptions display_error,

                   create_table
                     importing
                       in_tabname type tabname
                     returning
                       value(out_table) type ref to lcl_table_display
                     exceptions
                       create_error,

                   get_existing_table
                     importing
                       in_tabname type any optional
                       in_repid   type any optional
                       in_struc   type any optional
                     returning
                       value(out_table) type ref to lcl_table_display
                     exceptions
                       no_parameter
                       not_found,

                   refresh_objects.

    methods: constructor importing in_data type standard table
                         exceptions casting_error
                                    empty_fieldcat.

    methods: get_alv_fieldcat  returning value(out_fieldcat)
                                    type slis_t_fieldcat_alv.

    methods: set_table_name     importing in_tabname  type any,
             set_alv_title      importing in_title    type any,
             set_alv_fieldcat   importing in_fieldcat
                                     type slis_t_fieldcat_alv,
             set_alv_fieldnoout importing in_field    type any
                                          in_noout    type c optional
                                          in_tech     type c optional,
             set_alv_fieldedit  importing in_field    type any
                                          in_edit     type c optional,
             set_alv_fieldtext  importing in_field    type any
                                          in_ftext    type any,
             set_alv_fieldsum   importing in_field    type any
                                          in_dosum    type c optional,
             set_alv_linebreak  importing in_field    type any,
             set_alv_settings   importing in_settings type any,
             set_alv_layout     importing in_layout   type any,
             set_alv_print      importing in_print    type any,
             set_alv_sorting    importing in_field    type any
                                          in_desc     type c optional
                                          in_group    type any optional
                                          in_subtot   type c optional,
             set_alv_keys       importing in_level    type i
                                          in_key      type c optional,
             set_alv_event      importing in_name     type any
                                          in_form     type any,
             set_all_events.


  protected section.

    data: g_table_type type slis_list_type.

    data: g_title      type lvc_title,
          gt_fcat      type slis_t_fieldcat_alv,
          gs_sett      type lvc_s_glay,
          gs_layo      type slis_layout_alv,
          gt_sort      type slis_t_sortinfo_alv,
          gt_evnt      type slis_t_event,
          gs_prin      type slis_print_alv.

    class-methods: output_hierarchy exceptions display_error.

    methods: output_table importing mode type c
                         exceptions display_error,
             output_list,
             output_grid.


  private section.

    class-data: gt_table_obj   type table of ref to lcl_table_display,
                g_header_table type ref to lcl_table_display,
                g_detail_table type ref to lcl_table_display.

    class-data: g_variant_level type i.

    class-data: g_block_mode    type c,
                g_block_text    type slis_text40.

    types: begin of ty_defin,
             fieldname     type fieldname,
             ref_tabname   type tabname,
             ref_fieldname type fieldname,
           end of ty_defin.

    data: g_repid  type repid,
          g_struc  type tabname,
          g_table  type tabname.

    data: gt_data  type ref to data.

    data: gt_defin type table of ty_defin,
          g_level  type tabname.


    methods: init_block_list,
             fill_fieldcat importing repid type repid
                                     struc type tabname
                            changing fcat  type slis_t_fieldcat_alv
                          exceptions no_definition,
             get_definition importing repid type repid
                                      struc type tabname
                             changing abap  type rsfb_source,
             recursive_definition importing repid type repid
                                   changing abap  type rsfb_source,
             map_structure importing source type any
                            changing destin type any,
             get_default_variant changing out_variant type disvariant.

endclass.                    "lcl_table_display DEFINITION


*----------------------------------------------------------------------*
*   LCL_TABLE_DISPLAY IMPLEMENTATION
*----------------------------------------------------------------------*
class lcl_table_display implementation.
***
*   Display table in ALV list
***
  method display_list.
    data: l_object  type ref to lcl_table_display,
          l_tabname type tabname,
          l_found   type c.

    l_tabname = in_tabname.
    loop at gt_table_obj into l_object.
      if l_object->g_table = l_tabname.
        l_found = 'X'.
        exit.
      endif.
    endloop.
    if l_found is initial.
      l_object = lcl_table_display=>create_table( l_tabname ).
      if g_block_mode is initial.
        l_object->g_table_type = 4.
      else.
        l_object->g_table_type = 2.
      endif.
      call method l_object->set_all_events.
    endif.
    call method l_object->output_list.
  endmethod.                    "display_list
***
*   Display table in ALV grid
***
  method display_grid.
    data: l_object  type ref to lcl_table_display,
          l_tabname type tabname,
          l_found   type c.

    l_tabname = in_tabname.
    loop at gt_table_obj into l_object.
      if l_object->g_table = l_tabname.
        l_found = 'X'.
        exit.
      endif.
    endloop.
    if l_found is initial.
      l_object = lcl_table_display=>create_table( l_tabname ).
      if g_block_mode is initial.
        l_object->g_table_type = 4.
      else.
        l_object->g_table_type = 2.
      endif.
      call method l_object->set_all_events.
    endif.
    if g_block_mode is initial.
      call method l_object->output_grid.
    else.
      call method l_object->output_list.
    endif.
  endmethod.                    "display_grid
***
*   Display tables in ALV hierarchy
***
  method display_hier.
    data: l_tabnam1 type tabname,
          l_tabnam2 type tabname,
          lt_fcat1  type slis_t_fieldcat_alv,
          lt_fcat2  type slis_t_fieldcat_alv,
          ls_fcat1  type slis_fieldcat_alv,
          ls_fcat2  type slis_fieldcat_alv.

    l_tabnam1 = in_header.
    l_tabnam2 = in_detail.
    call method lcl_table_display=>get_existing_table
      exporting
        in_tabname = l_tabnam1
      receiving
        out_table  = g_header_table
      exceptions
        not_found  = 1.
    if sy-subrc ne 0.
      g_header_table = lcl_table_display=>create_table( l_tabnam1 ).
      if g_block_mode is initial.
        g_header_table->g_table_type = 1.
      else.
        g_header_table->g_table_type = 3.
      endif.
      call method g_header_table->set_all_events.
    endif.
    call method lcl_table_display=>get_existing_table
      exporting
        in_tabname = l_tabnam2
      receiving
        out_table  = g_detail_table
      exceptions
        not_found  = 1.
    if sy-subrc ne 0.
      g_detail_table = lcl_table_display=>create_table( l_tabnam2 ).
    endif.

*   Set key fields
    if in_level is initial.
      lt_fcat1 = g_header_table->get_alv_fieldcat( ).
      lt_fcat2 = g_detail_table->get_alv_fieldcat( ).
      loop at lt_fcat1 into ls_fcat1.
        ls_fcat1-key = space.
        loop at lt_fcat2 into ls_fcat2
                        where fieldname = ls_fcat1-fieldname.
          ls_fcat2-key = space.
          ls_fcat2-key_sel = 'X'.
          ls_fcat2-tech = 'X'.
          modify lt_fcat2 from ls_fcat2 transporting key.
        endloop.
        if sy-subrc = 0.
          ls_fcat1-key = 'X'.
        endif.
        modify lt_fcat1 from ls_fcat1 transporting key.
      endloop.
      call method g_header_table->set_alv_fieldcat
        exporting
          in_fieldcat = lt_fcat1.
      call method g_detail_table->set_alv_fieldcat
        exporting
          in_fieldcat = lt_fcat2.
    else.
      call method g_header_table->set_alv_keys
        exporting
          in_level = in_level.
      call method g_detail_table->set_alv_keys
        exporting
          in_level = in_level
          in_key   = space.
    endif.

    call method output_hierarchy.
  endmethod.                    "display_hier
***
*   Set block mode
***
  method set_block_mode.
    g_block_mode = in_mode.
  endmethod.                    "set_block_mode
***
*   Set block text
***
  method set_block_text.
    g_block_text = in_text.
  endmethod.                    "set_block_text
***
*   Create new table
***
  method create_table.
    data: l_object type ref to lcl_table_display.

    field-symbols: <local> type standard table.

    assign (in_tabname) to <local>.
    if not <local> is assigned.
      raise create_error.
    endif.

    create object l_object exporting in_data = <local>
                           exceptions casting_error  = 1
                                      empty_fieldcat = 2.
    if sy-subrc ne 0.
      raise create_error.
    endif.
    call method l_object->set_table_name
      exporting
        in_tabname = in_tabname.

*   Default print options
    l_object->gs_prin-no_print_selinfos  = 'X'.
    l_object->gs_prin-no_coverpage       = 'X'.
    l_object->gs_prin-no_print_listinfos = 'X'.

    out_table = l_object.
  endmethod.                    "create_table
***
*   Get existing table
***
  method get_existing_table.
    data: l_object  type ref to lcl_table_display,
          l_tabname type tabname,
          l_repid   type repid,
          l_struc   type tabname,
          l_found   type c.

    l_tabname = in_tabname.
    l_repid   = in_repid.
    l_struc   = in_struc.
    if l_tabname is initial.
      if l_repid is initial and
         l_struc is initial.
        raise no_parameter.
      else.
*       Get last existing table with same definition
        loop at gt_table_obj into l_object.
          if l_object->g_repid = l_repid and
             l_object->g_struc = l_struc.
            l_found = 'X'.
            exit.
          endif.
        endloop.
      endif.
    else.
*     Get last existing table with same name
      loop at gt_table_obj into l_object.
        if l_object->g_table = l_tabname.
          l_found = 'X'.
          exit.
        endif.
      endloop.
    endif.

    if l_found is initial.
      raise not_found.
    else.
      out_table = l_object.
    endif.
  endmethod.                    "get_existing_table
***
*   Create table display
***
  method constructor.
    data: l_object type ref to lcl_table_display.

    data: ls_data  type ref to data.

    data: ob_desc  type ref to cl_abap_structdescr.

    data: l_found  type c,
          l_absol  type char200,
          l_repid  type repid,
          l_struc  type tabname.

    field-symbols: <table> type standard table,
                   <struc> type any.

*   Get data and store it into attribute
    create data me->gt_data like in_data.
    assign me->gt_data->* to <table>.
    <table> = in_data.

*   Get global data definition
    create data ls_data like line of <table>.
    assign ls_data->* to <struc>.
    catch system-exceptions assign_casting_illegal_cast = 1.
      ob_desc ?= cl_abap_typedescr=>describe_by_data( <struc> ).
    endcatch.
    if sy-subrc = 1.
      raise casting_error.
    endif.

*   Get program name and main type used to define table
    l_absol = ob_desc->absolute_name.
    split l_absol at '/TYPE=' into l_repid l_struc.
    shift l_repid up to '='.
    shift l_repid.

    check l_struc np '%_*'.

*   Set attributes
    me->g_repid = l_repid.
    me->g_struc = l_struc.

    me->g_table = l_struc.
    replace 'TY' with 'WT' into me->g_table.

*   Field catalog
    call method lcl_table_display=>get_existing_table
      exporting
        in_repid  = l_repid
        in_struc  = l_struc
      receiving
        out_table = l_object
      exceptions
        not_found = 1.
    if sy-subrc = 0.
      me->gt_fcat = l_object->get_alv_fieldcat( ).
      call method set_table_name
        exporting
          in_tabname = me->g_table.
    else.
      call method fill_fieldcat
        exporting
          repid = l_repid
          struc = l_struc
        changing
          fcat  = me->gt_fcat.
      if me->gt_fcat is initial.
        raise empty_fieldcat.
      endif.
    endif.

*   Keep list of tables
    append me to gt_table_obj.
  endmethod.                    "constructor
***
*   Output list
***
  method output_list.
    call method output_table
      exporting
        mode = 'L'.
  endmethod.                    "output_list
***
*   Output grid
***
  method output_grid.
    call method output_table
      exporting
        mode = 'G'.
  endmethod.                    "output_grid
***
*   Output table
***
  method output_table.
    data: l_object type ref to lcl_table_display.

    data: ls_vari  type disvariant.

    field-symbols: <table> type standard table.

    assign me->gt_data->* to <table>.

    if not g_block_mode is initial.
      read table gt_table_obj into l_object index 1.
      if sy-subrc = 0.
        if l_object->g_table = me->g_table.
          call method init_block_list.
        endif.
      endif.
    endif.

*   Get default user variant
    call method get_default_variant
      changing
        out_variant = ls_vari.

*   Display table contents
    if mode = 'G'.
      call function 'REUSE_ALV_GRID_DISPLAY'
        exporting
          i_callback_program = me->g_repid
          i_grid_title       = me->g_title
          i_grid_settings    = me->gs_sett
          is_layout          = me->gs_layo
          it_fieldcat        = me->gt_fcat
          it_sort            = me->gt_sort
          i_save             = 'U'
          is_variant         = ls_vari
          it_events          = me->gt_evnt
          is_print           = me->gs_prin
        tables
          t_outtab           = <table>
        exceptions
          program_error      = 1
          others             = 2.
      if sy-subrc <> 0.
        raise display_error.
      endif.
      call method refresh_objects.
    else.
      if g_block_mode is initial.
        call function 'REUSE_ALV_LIST_DISPLAY'
          exporting
            i_callback_program = me->g_repid
            is_layout          = me->gs_layo
            it_fieldcat        = me->gt_fcat
            it_sort            = me->gt_sort
            i_save             = 'U'
            is_variant         = ls_vari
            it_events          = me->gt_evnt
            is_print           = me->gs_prin
          tables
            t_outtab           = <table>
          exceptions
            others             = 0.
        if sy-subrc <> 0.
          raise display_error.
        endif.
        call method refresh_objects.
      else.
        call function 'REUSE_ALV_BLOCK_LIST_APPEND'
          exporting
            is_layout                  = me->gs_layo
            it_fieldcat                = me->gt_fcat
            i_tabname                  = me->g_table
            it_events                  = me->gt_evnt
            it_sort                    = me->gt_sort
            i_text                     = g_block_text
          tables
            t_outtab                   = <table>
          exceptions
            program_error              = 1
            maximum_of_appends_reached = 2
            others                     = 3.
        if sy-subrc <> 0.
          raise display_error.
        endif.
      endif.
    endif.
  endmethod.                    "output_table
***
*   Output hierarchy
***
  method output_hierarchy.
    data: l_object type ref to lcl_table_display.

    data: lt_fcat  type slis_t_fieldcat_alv,
          lt_sort  type slis_t_sortinfo_alv,
          ls_fcat  type slis_fieldcat_alv,
          ls_vari  type disvariant,
          ls_keyi  type slis_keyinfo_alv.

    data: l_index  type numc2,
          l_field  type fieldname.

    field-symbols: <head> type standard table,
                   <deta> type standard table,
                   <targ> type any.

    assign g_header_table->gt_data->* to <head>.
    assign g_detail_table->gt_data->* to <deta>.

*   Set key fields as common fields between header and detail
    loop at g_header_table->gt_fcat into ls_fcat
                                   where key = 'X'.
      l_index = l_index + 1.
*     Create link
      concatenate 'HEADER' l_index into l_field.
      assign component l_field of structure ls_keyi to <targ>.
      if sy-subrc = 0.
        <targ> = ls_fcat-fieldname.
        unassign <targ>.
      else.
        exit.
      endif.
    endloop.

    append lines of g_header_table->gt_fcat to lt_fcat.
    append lines of g_detail_table->gt_fcat to lt_fcat.

    append lines of g_header_table->gt_sort to lt_sort.
    append lines of g_detail_table->gt_sort to lt_sort.

    if not g_block_mode is initial.
      read table gt_table_obj into l_object index 1.
      if sy-subrc = 0.
        if l_object->g_table = g_header_table->g_table.
          call method g_header_table->init_block_list.
        endif.
      endif.
    endif.

*   Get default user variant
    call method g_header_table->get_default_variant
      changing
        out_variant = ls_vari.

    if g_block_mode is initial.
      call function 'REUSE_ALV_HIERSEQ_LIST_DISPLAY'
        exporting
          i_callback_program = g_header_table->g_repid
          is_layout          = g_header_table->gs_layo
          it_fieldcat        = lt_fcat
          it_sort            = lt_sort
          i_save             = 'U'
          is_variant         = ls_vari
          it_events          = g_header_table->gt_evnt
          i_tabname_header   = g_header_table->g_table
          i_tabname_item     = g_detail_table->g_table
          is_keyinfo         = ls_keyi
          is_print           = g_header_table->gs_prin
        tables
          t_outtab_header    = <head>
          t_outtab_item      = <deta>
        exceptions
          program_error      = 1
          others             = 2.
      if sy-subrc <> 0.
        raise display_error.
      endif.
      call method refresh_objects.
    else.
      call function 'REUSE_ALV_BLOCK_LIST_HS_APPEND'
        exporting
          is_layout                  = g_header_table->gs_layo
          it_fieldcat                = lt_fcat
          is_keyinfo                 = ls_keyi
          i_header_tabname           = g_header_table->g_table
          i_item_tabname             = g_detail_table->g_table
          it_events                  = g_header_table->gt_evnt
          it_sort                    = lt_sort
          i_text                     = g_block_text
        tables
          t_outtab_header            = <head>
          t_outtab_item              = <deta>
        exceptions
          program_error              = 1
          maximum_of_appends_reached = 2
          others                     = 3.
      if sy-subrc <> 0.
        raise display_error.
      endif.
    endif.
  endmethod.                    "output_hierarchy
***
*   Init block list
***
  method init_block_list.
    data:  ls_evnt1 type slis_alv_event,
           ls_evnt2 type slis_alv_event.

*   Events for whole list display
    concatenate 'F_' slis_ev_pf_status_set '_BLOCK'
           into ls_evnt1-form.
    concatenate 'F_' slis_ev_user_command '_BLOCK'
           into ls_evnt2-form.

*   Initialization of block list
    call function 'REUSE_ALV_BLOCK_LIST_INIT'
      exporting
        i_callback_program       = me->g_repid
        i_callback_pf_status_set = ls_evnt1-form
        i_callback_user_command  = ls_evnt2-form.
  endmethod.                    "init_block_list
***
*   End of block list
***
  method end_block_list.
    data: l_object type ref to lcl_table_display,
          ls_print type slis_print_alv.

    check not g_block_mode is initial.
    if in_print is supplied.
      ls_print = in_print.
    else.
      read table gt_table_obj into l_object index 1.
      ls_print = l_object->gs_prin.
    endif.
    call function 'REUSE_ALV_BLOCK_LIST_DISPLAY'
      exporting
        is_print      = ls_print
      exceptions
        program_error = 1
        others        = 2.
    if sy-subrc <> 0.
      raise display_error.
    endif.
    call method refresh_objects.
  endmethod.                    "end_block_list
***
*   Refresh table of objects
***
  method refresh_objects.
    free: gt_table_obj.
  endmethod.
***
*   Fill field catalog
***
  method fill_fieldcat.
    data: lt_abap   type rsfb_source.

    data: ls_defin  type ty_defin.

    data: lt_dfies  type table of dfies,
          ls_dfies  type dfies,
          ls_dd04v  type dd04v,
          ls_dd01v  type dd01v,
          l_flong   type dfies-lfieldname,
          l_dname   type dfies-domname.

    data: ls_fcat   type slis_fieldcat_alv,
          ls_fcat2  type slis_fieldcat_alv.

    data: l_index   type i,
          l_nbfld   type i.

    free: me->gt_defin.

*   Process data definition
    call method get_definition
      exporting
        repid = repid
        struc = struc
      changing
        abap  = lt_abap.

*   Process sub levels if required
    call method recursive_definition
      exporting
        repid = repid
      changing
        abap  = lt_abap.

    if me->gt_defin is initial.
      raise no_definition.
    endif.

    loop at me->gt_defin into ls_defin.
      clear: ls_fcat.
      move-corresponding ls_defin to ls_fcat.
*     Retrieve info about this field
      free: ls_dfies, ls_dd04v, ls_dd01v, l_dname.
      l_flong = ls_fcat-ref_fieldname.
      set locale language 'E'.
      translate: ls_fcat-ref_tabname   to upper case,
                 ls_fcat-ref_fieldname to upper case,
                 l_flong               to upper case.
      if not ls_fcat-ref_tabname is initial.
*       Try to get info about field in table
        call function 'DDIF_FIELDINFO_GET'
          exporting
            tabname        = ls_fcat-ref_tabname
            fieldname      = ls_fcat-ref_fieldname
            lfieldname     = l_flong
          importing
            dfies_wa       = ls_dfies
          exceptions
            not_found      = 1
            internal_error = 2
            others         = 3.
        if sy-subrc = 0.
          move-corresponding ls_dfies to ls_fcat.
          ls_fcat-fieldname = ls_defin-fieldname.
          move: ls_dfies-keyflag   to ls_fcat-key,
                ls_dfies-scrtext_m to ls_fcat-seltext_l,
                ls_dfies-domname   to l_dname.
        endif.
      else.
*       Try to get info about structure
        ls_defin-ref_tabname = ls_defin-ref_fieldname.
        call function 'DDIF_FIELDINFO_GET'
          exporting
            tabname   = ls_defin-ref_tabname
          tables
            dfies_tab = lt_dfies
          exceptions
            others    = 0.
        if not lt_dfies is initial.
*         Process fields of this structure
          loop at lt_dfies into ls_dfies.
            clear: ls_fcat.
            move-corresponding ls_dfies to ls_fcat.
            if ls_defin-fieldname ne 'INCLUDE'.
              concatenate ls_defin-fieldname ls_fcat-fieldname
                     into ls_fcat-fieldname
                separated by '-'.
            endif.
            move ls_dfies-keyflag to ls_fcat-key.
            move ls_dfies-scrtext_m to ls_fcat-seltext_l.
            ls_fcat-tabname = me->g_table.
            clear: ls_fcat-col_pos,
                   ls_fcat-offset.
            if ls_fcat-ref_tabname is initial.
              ls_fcat-ddictxt = 'L'.
            endif.
*           Display Yes/No fields as checkboxes
            if ls_dfies-domname = 'XFELD'.
              ls_fcat-checkbox = 'X'.
            endif.

*           Add field to field catalog
            append ls_fcat to fcat.
          endloop.
          continue.
        else.
*         Try to get info about data element
          call function 'DDIF_DTEL_GET'
            exporting
              name          = ls_fcat-ref_fieldname
              langu         = sy-langu
            importing
              dd04v_wa      = ls_dd04v
            exceptions
              illegal_input = 1
              others        = 2.
          if sy-subrc = 0.
            move-corresponding ls_dd04v to ls_fcat.
            move: ls_dd04v-scrtext_m to ls_fcat-seltext_l,
                  ls_dd04v-domname   to l_dname.
          else.
*           Finally try to get info about domain
            call function 'DDIF_DOMA_GET'
              exporting
                name          = ls_fcat-ref_fieldname
                langu         = sy-langu
              importing
                dd01v_wa      = ls_dd01v
              exceptions
                illegal_input = 1
                others        = 2.
            if sy-subrc = 0.
              move-corresponding ls_dd01v to ls_fcat.
              move: ls_dd01v-ddtext  to ls_fcat-seltext_l,
                    ls_dd01v-domname to l_dname.
            endif.
          endif.
        endif.
      endif.
*     Table name must be internal table containing data
      ls_fcat-tabname = g_table.
*     No offset
      clear: ls_fcat-offset.
*     Default text is stored in long text
      if ls_fcat-ref_tabname is initial.
        ls_fcat-ddictxt = 'L'.
      endif.
*     Display Yes/No fields as checkboxes
      if l_dname = 'XFELD'.
        ls_fcat-checkbox = 'X'.
      endif.

*     Add field to field catalog
      append ls_fcat to fcat.
    endloop.
*   Positions
    loop at fcat into ls_fcat.
      ls_fcat-row_pos = 1.
      ls_fcat-col_pos = sy-tabix.
      modify fcat from ls_fcat transporting row_pos col_pos.
    endloop.
*   Link between fields
    describe table fcat lines l_nbfld.
    loop at fcat into ls_fcat.
      if sy-tabix ne l_nbfld.
        l_index = sy-tabix + 1.
        read table fcat into ls_fcat2 index l_index.
        if sy-subrc = 0.
          if ls_fcat-datatype = 'CURR'.
*           Currency unit
            if ls_fcat2-datatype = 'CUKY'.
              ls_fcat-cfieldname = ls_fcat2-fieldname.
              ls_fcat-ctabname   = ls_fcat2-tabname.
              modify fcat from ls_fcat.
            else.
              loop at fcat into ls_fcat2
                           from l_index
                          where datatype = 'CUKY'.
*               First currency unit after field
                ls_fcat-cfieldname = ls_fcat2-fieldname.
                ls_fcat-ctabname   = ls_fcat2-tabname.
                modify fcat from ls_fcat.
                exit.
              endloop.
              if sy-subrc ne 0.
*               No currency unit after field, try before
                read table fcat into ls_fcat2
                            with key datatype = 'CUKY'.
                if sy-subrc = 0.
                  ls_fcat-cfieldname = ls_fcat2-fieldname.
                  ls_fcat-ctabname   = ls_fcat2-tabname.
                  modify fcat from ls_fcat.
                else.
*                 Default is EURO
                  ls_fcat-currency = 'EUR'.
                endif.
              endif.
            endif.
          endif.
          if ls_fcat-datatype = 'QUAN'.
*           Quantity unit
            if ls_fcat2-datatype = 'UNIT'.
              ls_fcat-cfieldname = ls_fcat2-fieldname.
              ls_fcat-ctabname   = ls_fcat2-tabname.
              modify fcat from ls_fcat.
            endif.
          endif.
        endif.
      endif.
    endloop.
  endmethod.                    "fill_fieldcat
***
*   Get definition of type from code source
***
  method get_definition.
    data: l_strng type rssource,
          ls_abap type rssource,
          l_fdpos type i,
          l_first type i,
          l_lastr type i.

    data: lt_incl type table of repid,
          ls_incl type repid.

*   Get program code
    read report repid into abap.
    check sy-subrc eq 0.

*   Get first line of definition
    concatenate 'BEGIN OF' struc into l_strng
                            separated by space.
    loop at abap into ls_abap.
      if ls_abap cs l_strng.
        l_fdpos = strlen( l_strng ) + sy-fdpos.
        if ls_abap(1) = '*' or ls_abap(sy-fdpos) cs '"'.
          continue.
        endif.
        if ls_abap+l_fdpos(1) ca ',. "'.
          l_first = sy-tabix.
          exit.
        endif.
      endif.
    endloop.
    if l_first is initial.
*     Table is defined in an include
      call function 'RS_GET_ALL_INCLUDES'
        exporting
          program    = repid
        tables
          includetab = lt_incl
        exceptions
          others     = 1.
      if sy-subrc = 0.
        loop at lt_incl into ls_incl.
*         Try to find definition in this include
          read report ls_incl into abap.
          loop at abap into ls_abap.
            if ls_abap cs l_strng.
              l_fdpos = strlen( l_strng ) + sy-fdpos.
              if ls_abap(1) = '*' or ls_abap(sy-fdpos) cs '"'.
                continue.
              endif.
              if ls_abap+l_fdpos(1) ca ',. "'.
                l_first = sy-tabix.
                exit.
              endif.
            endif.
          endloop.
          if not l_first is initial.
            exit.
          endif.
        endloop.
      endif.
    endif.

*   Get last line of definition
    concatenate 'END OF' struc into l_strng
                          separated by space.
    loop at abap into ls_abap.
      if ls_abap cs l_strng.
        l_fdpos = strlen( l_strng ) + sy-fdpos.
        if ls_abap(1) = '*' or ls_abap(sy-fdpos) cs '"'.
          continue.
        endif.
        if ls_abap+l_fdpos(1) ca ',. "'.
          l_lastr = sy-tabix - l_first.
          exit.
        endif.
      endif.
    endloop.

*   Keep only relevant code lines
    if l_first le 0
    or l_lastr le 0.
      refresh abap.
    else.
      delete abap to l_first.
      delete abap from l_lastr.
    endif.
  endmethod.                    "get_definition
***
*   Get definition of type recursively
***
  method recursive_definition.
    data: lt_token type table of stokex,
          ls_token type stokex,
          lt_state type table of sstmnt,
          ls_state type sstmnt.

    data: ls_defin type ty_defin,
          l_reffld type fieldname.

    data: lt_recu  type rsfb_source.

*   Retrieve tokens
    scan abap-source abap
              tokens into lt_token
          statements into lt_state.

    loop at lt_state into ls_state.
      clear: ls_defin.
*     Field name
      read table lt_token into ls_token
                         index ls_state-from.
      ls_defin-fieldname = ls_token-str.
*     Reference type
      read table lt_token into ls_token
                         index ls_state-to.
      l_reffld = ls_token-str.
*     Check if this type is defined in program
      free: lt_recu.
      call method get_definition
        exporting
          repid = repid
          struc = l_reffld
        changing
          abap  = lt_recu.
      if lt_recu is initial.
        if not g_level is initial.
          concatenate g_level ls_defin-fieldname
                 into ls_defin-fieldname separated by '-'.
          condense ls_defin-fieldname.
        endif.
        if l_reffld cs '-'.
          split l_reffld at '-'
                       into ls_defin-ref_tabname
                            ls_defin-ref_fieldname.
          if ls_defin-ref_tabname = 'SY'.
            ls_defin-ref_tabname = 'SYST'.
          endif.
        else.
          ls_defin-ref_fieldname = ls_token-str.
        endif.
        append ls_defin to me->gt_defin.
      else.
*       Process sub levels
        if me->g_level is initial.
          me->g_level = ls_defin-fieldname.
        else.
          concatenate me->g_level ls_defin-fieldname into me->g_level
                                             separated by '-'.
        endif.
        call method recursive_definition
          exporting
            repid = repid
          changing
            abap  = lt_recu.
        if me->g_level cs '-'.
          shift me->g_level right up to '-'.
          shift me->g_level right.
          shift me->g_level left deleting leading space.
        else.
          clear: me->g_level.
        endif.
      endif.
    endloop.
  endmethod.                    "recursive_definition
***
*   Get fieldcat
***
  method get_alv_fieldcat.
    out_fieldcat = me->gt_fcat.
  endmethod.                    "get_alv_fieldcat
***
*   Set table name
***
  method set_table_name.
    data: l_fcat type slis_fieldcat_alv.

    loop at me->gt_fcat into l_fcat.
      l_fcat-tabname = in_tabname.
      modify me->gt_fcat from l_fcat.
    endloop.
    me->g_table = in_tabname.
  endmethod.                    "set_table_name
***
*   Set title
***
  method set_alv_title.
    me->g_title = in_title.
  endmethod.                    "set_alv_title
***
*   Set fieldcat
***
  method set_alv_fieldcat.
    me->gt_fcat = in_fieldcat.
  endmethod.                    "set_alv_fieldcat
***
*   Set field invisible
***
  method set_alv_fieldnoout.
    data: l_field type fieldname,
          l_noout type c,
          l_tech  type c,
          ls_fcat type slis_fieldcat_alv.

    l_field = in_field.
    if in_noout is supplied.
      l_noout = in_noout.
    else.
      l_noout = 'X'.
    endif.
    if in_tech is supplied.
      l_tech = in_tech.
    endif.

    loop at me->gt_fcat into ls_fcat
                       where fieldname = l_field.
      ls_fcat-no_out = l_noout.
      ls_fcat-tech   = l_tech.
      modify gt_fcat from ls_fcat transporting no_out tech.
    endloop.
  endmethod.                    "set_alv_fieldnoout
***
*   Set field editable
***
  method set_alv_fieldedit.
    data: l_field type fieldname,
          l_edit  type c,
          ls_fcat type slis_fieldcat_alv.

    l_field = in_field.
    if in_edit is supplied.
      l_edit = in_edit.
    else.
      l_edit = 'X'.
    endif.

    loop at me->gt_fcat into ls_fcat
                       where fieldname = l_field.
      ls_fcat-edit = l_edit.
      modify gt_fcat from ls_fcat transporting edit.
    endloop.
  endmethod.                    "set_alv_fieldedit
***
*   Set field text
***
  method set_alv_fieldtext.
    data: l_field type fieldname,
          ls_fcat type slis_fieldcat_alv.

    l_field = in_field.
    loop at me->gt_fcat into ls_fcat
                       where fieldname = l_field.
      ls_fcat-seltext_m = in_ftext.
      ls_fcat-ddictxt = 'M'.
      modify gt_fcat from ls_fcat transporting seltext_m ddictxt.
    endloop.
  endmethod.                    "set_alv_fieldtext
***
*   Set field sum
***
  method set_alv_fieldsum.
    data: l_field type fieldname,
          l_dosum type c,
          ls_fcat type slis_fieldcat_alv.

    l_field = in_field.
    if in_dosum is supplied.
      l_dosum = in_dosum.
    else.
      l_dosum = 'X'.
    endif.

    loop at me->gt_fcat into ls_fcat
                       where fieldname = l_field.
      ls_fcat-do_sum = l_dosum.
      modify gt_fcat from ls_fcat transporting do_sum.
    endloop.
  endmethod.                    "set_alv_fieldsum
***
*   Set line break in field catalog
***
  method set_alv_linebreak.
    data: l_field type fieldname,
          ls_fcat type slis_fieldcat_alv,
          l_tabix type i.

    l_field = in_field.
    read table me->gt_fcat into ls_fcat
                       with key fieldname = l_field.
    if sy-subrc = 0.
      l_tabix = sy-tabix.
    else.
      exit.
    endif.

    loop at me->gt_fcat into ls_fcat
                        from l_tabix.
      ls_fcat-row_pos = ls_fcat-row_pos + 1.
      modify gt_fcat from ls_fcat transporting row_pos.
    endloop.
  endmethod.                    "set_alv_linebreak
***
*   Set settings
***
  method set_alv_settings.
    call method map_structure
      exporting
        source = in_settings
      changing
        destin = me->gs_sett.
  endmethod.                    "set_alv_settings
***
*   Set layout
***
  method set_alv_layout.
    call method map_structure
      exporting
        source = in_layout
      changing
        destin = me->gs_layo.
  endmethod.                    "set_alv_layout
***
*   Set printing options
***
  method set_alv_print.
    call method map_structure
      exporting
        source = in_print
      changing
        destin = me->gs_prin.
  endmethod.                    "set_alv_print
***
*   Set sortings
***
  method set_alv_sorting.
    data: l_desc   type alvdynp-sortdown,
          l_group  type alvdynp-grouplevel,
          l_subtot type alvdynp-subtotals.
    data: ls_sort  type slis_sortinfo_alv,
          l_index  type i.

    if in_desc is supplied.
      l_desc = in_desc.
    endif.
    if in_group is supplied.
      l_group = in_group.
    else.
      l_group = '*'.
    endif.
    if in_subtot is supplied.
      l_subtot = in_subtot.
    else.
      l_subtot = 'X'.
    endif.

    describe table me->gt_sort lines l_index.
    l_index = l_index + 1.

    ls_sort-spos = l_index.
    ls_sort-fieldname = in_field.
    ls_sort-tabname = me->g_table.
    if l_desc is initial.
      ls_sort-up = 'X'.
    else.
      ls_sort-down = 'X'.
    endif.
    ls_sort-group = l_group.
    ls_sort-subtot = l_subtot.

    append ls_sort to me->gt_sort.
  endmethod.                    "set_alv_sorting
***
*   Set key fields
***
  method set_alv_keys.
    data: l_key   type c,
          ls_fcat type slis_fieldcat_alv.

    if in_key is supplied.
      l_key = in_key.
    else.
      l_key = 'X'.
    endif.
    loop at me->gt_fcat into ls_fcat from 1 to in_level.
      ls_fcat-key = l_key.
      modify gt_fcat from ls_fcat transporting key.
    endloop.
  endmethod.                    "set_alv_keys
***
*   Add event
***
  method set_alv_event.
    data: ls_evnt type slis_alv_event.

    loop at gt_evnt into ls_evnt
                   where name = in_name.
      ls_evnt-form = in_form.
      modify gt_evnt from ls_evnt transporting form.
    endloop.
    if sy-subrc ne 0.
      ls_evnt-name = in_name.
      ls_evnt-form = in_form.
      append ls_evnt to gt_evnt.
    endif.
  endmethod.                    "set_alv_event
***
*   Add event
***
  method set_all_events.
    data: lt_trig type table of rtrig,
          ls_evnt type slis_alv_event.

    call function 'REUSE_ALV_EVENTS_GET'
      exporting
        i_list_type     = g_table_type
      importing
        et_events       = gt_evnt
      exceptions
        list_type_wrong = 1
        others          = 2.
    if sy-subrc = 0.
*     Get program form routines
      load report g_repid part 'TRIG' into lt_trig.
*     List of valid form routines
      loop at gt_evnt into ls_evnt.
        concatenate 'F_' ls_evnt-name into ls_evnt-form.
        if not g_block_mode is initial.
          concatenate ls_evnt-form me->g_table into ls_evnt-form
                                       separated by '_'.
        endif.
        read table lt_trig with key exto  = ls_evnt-form
                                    fform = 'X'
                       transporting no fields.
        if sy-subrc = 0.
          modify gt_evnt from ls_evnt transporting form.
        else.
          delete gt_evnt.
        endif.
      endloop.
    endif.

  endmethod.                    "set_all_events
***
*   Map fields from incoming structure into attribute
***
  method map_structure.
    data: ob_desc  type ref to cl_abap_structdescr,
          ls_compo type abap_compdescr.

    field-symbols: <field> type any,
                   <struc> type any.

    ob_desc ?= cl_abap_typedescr=>describe_by_data( destin ).

    loop at ob_desc->components into ls_compo.
      assign component ls_compo-name of structure source to <field>.
      if <field> is assigned.
        assign component ls_compo-name of structure destin to <struc>.
        catch system-exceptions conversion_errors = 1.
          move <field> to <struc>.
        endcatch.
        unassign <field>.
      endif.
    endloop.
  endmethod.                    "map_structure
***
*   Get default variant
***
  method get_default_variant.
    g_variant_level = g_variant_level + 1.

    out_variant-report   = me->g_repid.
    out_variant-handle   = me->g_variant_level.
    out_variant-username = sy-uname.
    call function 'REUSE_ALV_VARIANT_DEFAULT_GET'
      exporting
        i_save     = 'U'
      changing
        cs_variant = out_variant
      exceptions
        others     = 0.
  endmethod.                    "get_default_variant
endclass.                    "lcl_table_display IMPLEMENTATION 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值