Skip to Content
Personal Insights
Author's profile photo Joachim Rees

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!

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Joachim Rees
      Joachim Rees
      Blog Post Author

      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.

       

      Author's profile photo Michelle Crapo
      Michelle Crapo

      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!

      Author's profile photo Joachim Rees
      Joachim Rees
      Blog Post Author

      Hey Michelle, thanks very much for your kind feedback!

      Glad you like it!

      Author's profile photo Joachim Rees
      Joachim Rees
      Blog Post Author

      Also, I love the phrase "code that needs some help" ! Thanks for that!