Skip to Content
Personal Insights

Cleaning up my AdT report template – Part 2 – more CleanAbap

[For a short time (less’ than a day!), this used to be part of my blog https://blogs.sap.com/2020/06/17/cleaning-up-my-adt-report-template-get-rid-of-empty-lines/ – I now decided, that that can stand for itself (“just” deleting empty lines is something – that was the point I was going to make). So I move the “more refactoring” part to here. ]

Next up, I remove un-needed comments, some more empty lines, white space and a line-break:

Types: gty_data type ${my_table} ,
       gty_tab_data TYPE STANDARD TABLE OF gty_data.
*data, solely for select-options.
data: gso_${my_table} type ${my_table}.

SELECTION-SCREEN BEGIN OF BLOCK sel_opt WITH FRAME TITLE text-t01.
SELECT-Options: so_${my_table_field} for gso_${my_table}-${my_table_field}.
SELECTION-SCREEN END OF BLOCK sel_opt.
SELECTION-SCREEN BEGIN OF BLOCK mode WITH FRAME TITLE text-t02.
PARAMETERS: pa_disp TYPE flag RADIOBUTTON GROUP mode DEFAULT 'X',
            pa_proc TYPE flag RADIOBUTTON GROUP mode.
SELECTION-SCREEN END OF BLOCK mode.

CLASS lcl_report DEFINITION.
  PUBLIC SECTION.
    class-METHODS: init. 
    METHODS: get_data CHANGING ct_data TYPE gty_tab_data,
             display_data CHANGING ct_data TYPE gty_tab_data,
             process_data IMPORTING it_data TYPE gty_tab_data.
ENDCLASS.

CLASS lcl_report IMPLEMENTATION.
  METHOD process_data.
    FIELD-SYMBOLS: <data> LIKE LINE OF it_data.

    CHECK it_data IS NOT INITIAL.
    LOOP AT it_data ASSIGNING <data>.
*do something
    ENDLOOP.
  ENDMETHOD.                    

  METHOD display_data.
    DATA: lr_alv          TYPE REF TO cl_salv_table.
    DATA: lr_functions    TYPE REF TO cl_salv_functions_list,
          lr_layout       TYPE REF TO cl_salv_layout,
          ls_key          TYPE salv_s_layout_key.
    TRY.
        CALL METHOD cl_salv_table=>factory
          EXPORTING
            list_display = if_salv_c_bool_sap=>false
          IMPORTING
            r_salv_table = lr_alv
          CHANGING
            t_table      = ct_data.
        ##NO_HANDLER.
      CATCH cx_salv_msg .
    ENDTRY.

    lr_layout = lr_alv->get_layout( ).
    ls_key-report = sy-repid.
    lr_layout->set_key( ls_key ).
    lr_layout->set_default( abap_true ).
    lr_layout->set_save_restriction( if_salv_c_layout=>restrict_none ).
    lr_functions = lr_alv->get_functions( ).
    lr_functions->set_all( abap_true ).
    CALL METHOD lr_alv->display.
  ENDMETHOD.

  METHOD get_data.      
	select * from ${my_table} into CORRESPONDING FIELDS OF table ct_data UP TO 500 ROWS
    where ${my_table_field} in so_${my_table_field}.              
  ENDMETHOD.

method init.
  DATA: lt_data TYPE gty_tab_data,
        lo_report TYPE REF TO lcl_report.
  CREATE OBJECT lo_report.
	lo_report->get_data( CHANGING ct_data = lt_data ).
  check lt_data is not initial.

  CASE abap_true.
    WHEN pa_disp.
      lo_report->display_data( changing ct_data = lt_data ).
    WHEN pa_proc.
      lo_report->process_data( EXPORTING it_data = lt_data ).
  ENDCASE.
endmethod. 
ENDCLASS. 

START-OF-SELECTION.
  lcl_report=>init( ).

Then, I used some inline-declarations and went into refactoring the display_data method.

What I noted:

There’s no good editing in the template editor – it’s just text.
With “no good editing” I mean I miss all the cool features I have when editing ABAP-code ( e.g. format code, comment out, syntax check).

So what I did was:

1. Make the template into a report. ( Setting ${my_table} with MARA and ${my_table_field} with MATNR)
2. Refactor that report. (utilizing all the features I need).
3. Serach-and-replace to get back ${my_table} and ${my_table_field} in their places.
4. Copy into the template.

And this is what it looks now:

Types: gty_data type ${my_table} ,
       gty_tab_data TYPE STANDARD TABLE OF gty_data.
*solely for select-options.
data: gso_${my_table} type ${my_table}.

SELECTION-SCREEN BEGIN OF BLOCK sel_opt WITH FRAME TITLE text-t01.
    SELECT-Options: so_${my_table_field} for gso_${my_table}-${my_table_field}.
    SELECTION-SCREEN END OF BLOCK sel_opt.
    SELECTION-SCREEN BEGIN OF BLOCK mode WITH FRAME TITLE text-t02.
    PARAMETERS: pa_disp TYPE flag RADIOBUTTON GROUP mode DEFAULT 'X',
                pa_proc TYPE flag RADIOBUTTON GROUP mode.
SELECTION-SCREEN END OF BLOCK mode.

CLASS lcl_report DEFINITION.
PUBLIC SECTION.
  CLASS-METHODS: init.
  METHODS: get_data CHANGING ct_data TYPE gty_tab_data,
    display_data CHANGING ct_data TYPE gty_tab_data,
    process_data IMPORTING it_data TYPE gty_tab_data.
ENDCLASS.

CLASS lcl_report IMPLEMENTATION.
  METHOD process_data.
    LOOP AT it_data ASSIGNING FIELD-SYMBOL(<data>).
*do something
    ENDLOOP.
  ENDMETHOD.

  METHOD display_data.
    TRY.
        cl_salv_table=>factory( IMPORTING  r_salv_table   = data(lr_alv)
                                CHANGING   t_table        = ct_data  ).
      CATCH cx_salv_msg.
    ENDTRY.

    lr_alv->get_layout( )->set_key( VALUE #( report = sy-repid ) ).
    lr_alv->get_layout( )->set_default( abap_true ).
    lr_alv->get_layout( )->set_save_restriction( if_salv_c_layout=>restrict_none ).
    lr_alv->get_functions( )->set_all( abap_true ).
    CALL METHOD lr_alv->display.
  ENDMETHOD.

  METHOD get_data.
    select * from ${my_table} into CORRESPONDING FIELDS OF table ct_data UP TO 500 ROWS
    where ${my_table_field} in so_${my_table_field}.
  ENDMETHOD.

METHOD init.
  DATA: lt_data   TYPE gty_tab_data,
        lo_report TYPE REF TO lcl_report.
  CREATE OBJECT lo_report.
  lo_report->get_data( CHANGING ct_data = lt_data ).
  CHECK lt_data IS NOT INITIAL.

  CASE abap_true.
    WHEN pa_disp.
      lo_report->display_data( CHANGING ct_data = lt_data ).
    WHEN pa_proc.
      lo_report->process_data( EXPORTING it_data = lt_data ).
  ENDCASE.
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  lcl_report=>init( ).

 

For now, I’ll leave it at this!

Final thoughts and recap:

– Quick wins by removing empty lines
– when you get into more refactoring, it does get time-consuming (-> know when to stop)
– Time you invest in a template hopefully pays manyfold (-> every time you use it)
– Editing AdT-templates is not comfortable (no tooling) -> workaround via ABAP-code
– Just writing “${my_template_variable} in template text actually works fine! (Not sure if allays was)

– I have not done any re-naming
– Maybe I should explain (and question) my display_data method some time? [Edit: ok, did that! ]
– There is the general question if “ABAP report” is the right starting point to do anything today.

Questions and comments welcome!

3 Comments
You must be Logged on to comment or reply to a post.
  • Having done this with an up-to date S/4HANA Backend (19109) it only later occurred to me that I might have broken compatibility with the “old world” (-> SAP ERP / ecc).

    So I check now, and: OK, it’s fine! (with SAP_BASIS 750 0011)

    …Yes, SAP_BASIS 750, is the “old world” to me; but also yes: some of our customer systems are older – I didn’t check with them.

    But it wouldn’t be a problem, either: I have kept the original template as it is and create a now one (via down- and up-load) to fiddle with.

     

  • I love these blogs.   They put everything in perspective.  Make small changes while making modifications to code.   Each time there is a change do a little more.   That would make the changes less costly.   It might cause a little longer testing.  The key here is “little”.  That is huge for me.  When making a change, I usually have 100 other things going on.  I see the code that needs some help – and think I don’t have time for a rewrite.  But I would have time to make small changes.

    Before and after pictures are great!