Skip to Content

You know how the say the best admins, developers (…) are the lazy ones – why? Because the automate everything that makes sense to automate: let repetitive tasks be done by some kind of automation, e.g. a script:

Once you have that, you’re way faster, you don’t make typing errors, and you script defines a kind of standard/best practice you can rely on, without having to think about it.
Of course, your script, template or whatever can and should improve if you gain new knowledge.

That being said, I often have to write a new ABAP-(ALV-)report from scratch:

Select some data
Maybe do something with it
Display in ALV.

This might be a throw-away report just to try something out, or a report to be used productively (or one – maybe silently – turning into the other, I guess you all know those examples).

Say you’d want a report, selecting data from a database tabel (e.g. VBAP), with a select-option on one of this table’s fields (e.g. ERNAM), displaying what was selected in a ALV-Grid (with all features enabled).
Easy, isn’t it? Won’t take you longer that a few minutes, right?!

Guess how long it takes me: 3 seconds! (Time starts, when I can start coding in eclipse, e.g. I have supplied the name of the report, chosen a package and the transport request).

Here’s what I do:
jre_, + Ctrl+space + Enter
VBAP, Tab, ERNAM.
Activate (Ctrl+F3)
Run (F8!).

Did you take the time? It was fast, wasn’t it? 😉

And it’s not a quick-and-dirty style of writing (you know, just start coding with select * from … without caring to even create forms or methods), but a very nice one, according to whatever my standards are (e.g. everything in local classes, respecting naming conventions, strong (=non-generic) typing… etc.).

So, you already know how I did that: I create myself a report-template in AdT, with variables for the table- and field-name.

This is where it is defined:

 

The custom variables make it flexible:

And this is it’s full code for your inspiration:

*REPORT  generic

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}.

*Sel-Screen:
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.                    "lcl_report DEFINITION



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.                    "process_data

  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.                    "display_data


  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.                    "lcl_report IMPLEMENTATION



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

 

Takaway: action you can take:
Invest a little time to create a very nice template.
From now one, use it whenever it is applicable.

If you spot an error, or a chance for improvement, not only correct the report you just wrote, but also adjust your template accordingly.
-> All further uses will benefit from that!

 

If you start dirty, you might stay dirty.
So start clean right away!

 

Constraints/further ideas/notes:

– You can put as much coding as you like in the template, but it will end up in only one report – structuring with includes (_sel, _top etc.) isn’t easily possible.
– Your template doesn’t have to be a whole report, it could also be a method you often code. (I have one where I simply pass in a (any) internal table, and it displays it in ALV).
– I the current unit-testing-hype  it might be worth to think about to also have a temple (=jump-start) for the test class.
– The template is in Eclipse, so I can use it in any system I access! (As opposed to those old templates in SE80 – I admit, I never made to much use of them!)
– (You can probably share your template with your colleagues (and profit from their improvements to it) somehow e.g. with using git).

Now over to you:
How do you avoid repetitive tasks, while improving quality? Do you, too, use dedicated templates, or do you just copy and adept from another (well written) productive program?

Your input is most welcome!

 

Joachim

To report this post you need to login first.

16 Comments

You must be Logged on to comment or reply to a post.

  1. Bärbel Winkler

    Thanks for the tip, Joachim!

    I’m a big fan of templates and have been using them in SE38/SE80 for anything from just header comments in a program (either in German or English) to fairly complete program frames where I then just have to modify or add definition sections, data retrieval routines and any processing needed to get the output data (usually as an ALV) in the required format.

    Personally, I’ve always prefered starting a new program from scratch via a template instead of as a copy of an already existing program. The latter usually brings with it a lot of “baggage” of unwanted code and I’ve seen more than my fair share of obviously copied and then never cleaned up programs. Another advantage of working with templates is, that the programs have a very similar look & feel which makes them a lot easier to “grasp” for myself as well as others.

    It’s also helpful to know that and how I can create my own patterns in Eclipse with the added bonus of parameters. What I never much liked with the patterns via the SAP-GUI is that they are not readily available to down- and upload in bulk and just get lost in the ether when a new GUI-version gets installed (after getting caught by this once, I now also have “my” patterns in a simple txt-file for safe-keeping).

    Cheers

    Bärbel

    (2) 
    1. Ganesh pandian

      Instead of saving templates in a txt file save all your templates in a Onenote file, much safer and much easier to search as well, Just a suggesion 🙂

      (0) 
      1. Bärbel Winkler

        Although I’m using OneNote for other stuff I prefer Notepad for code-snippets as copying & pasting from programs like OneNote can introduce unwanted formatting via HTML (at least I encountered that with code copied from Word – you don’t necessarily see it but it can cause syntax errors nonetheless).

         

        (1) 
      2. Joachim Rees Post author

        I do like text-files on my local hard-disk – they are easy to write, easy to read(e.g. Notepad opens very fast) and so small and thus very easy to backup

        -> The backup file (I use a simple *.Zip) is:

        1. very fast created
        2. very small, thus:

        2.1 can be stored nearly anywhere (old USB-stick, phone, e-mail-attachment …)

        2.2 can be stored away very fast.

         

         

        Also textfiles are very inter-operable:

        – the probably have the best chance of still being readable in 20+ years

        – can easily be shared/used across platforms(Linux,MacOs,Win…)

        – can easily be versioned with git

        – ….

         

         

        So: ‘yay’ for textfiles! 🙂

        But of course it’s ok for everyone to find solutions best fitting to them – and great that we share them here!

         

        Best

        Joachim

        (0) 
  2. Nabheet Madan

    Cool tip. Thanks Joachim Rees In our GUI editor we have been using it for normally for header templates for developments.I believe this can be quite effective in the ABAP unit testing framework where basic set up is normally the same.

    (0) 
    1. Suhas Saha

      I believe this can be quite effective in the ABAP unit testing framework where basic set up is normally the same.

      Did you check the default template “testClass”?

      (0) 
      1. Nabheet Madan

        I actually was not much aware about it.  This blog explain clearly about how to use patterns testclass being one of them. Thanks for sharing the same(getting used to eclipse:))

         

         

        (0) 
  3. Florian Henninger

    Hi Joachim,could have a little more new syntax;-)

    Nice use case for the templates. Do not really see the case for me at all, because I really try to stay away from any report and do use instead of that today idata’s in combination with the smart templates. So what’s the use-case behind that in your daily work?

    The method with the any and show an ALV I also do not get at all? Why not just make use of the SE16H with all the additional possibilities.

    No matter what, I like the idea behind and maybe we need to talk a little longer about it when meeting for a coffee break:-)

    ~Florian

    (0) 
    1. Joachim Rees Post author

      Hi Florian,

      wow, thanks for your Feedback!
      That’s a lot of points you mention, let me try to get through them

      1. More New Syntax:

      Not sure if I see all the points you mean with that:

      I could do some more inline-declaration, e.g. in method init, agreed. Are there other points you spotted?

      (Also, I might use the template on an System >7.40, where things wouldn’t work – but I could just have another template for that, or manually adapt to this seldom cases. I agree that templates should represent the current/newest best practices.)

      2. May use-case in “daily” work:
      mainly “try-something-out”-reports, for example like that one on new SQL-Syntax  (you can tell I still used FORM in my template back then *shameOnMe* 😉 )

       

      Without a template, I would just start typing into the empty editor.

      With my template, I already have nice, running report, on which I can build.

      3. Method to display “any table”:

      Uh, after re-reading that part, I see how this is confusing. I updated it to “internal table”, as my intention is of course not to re-create se16(*).

       

      Let me just show the method:

       

      "Definition:
      METHODS display_data_generic CHANGING ct_data TYPE table.
      
      "Implementation
        METHOD display_data_generic.
      
          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.
      
      

       

      …and I use it to “nicely” look at the data I selected/processes. (As opposed to only being able to look at it in the Debugger).

      A good use case example is again the link I provided above. (There it’s still called “FORM display_data ” but you get the point!)

       

      4. And finally: coffee break: always a good idea! 🙂

      Btw: Caroleigh Deneen  how about the “catch a mentor”-mission, will we get that one back soon? 😉

       

      best

      Joachim

      (1) 
      1. Florian Henninger

        Recoginzed it because of the into-clause is not the last statement of the select and the missing inline decs.

        The try-out in my daily work point is that I do not see a big benefit to have the “play”-programs a lot people do. I take one or two new elements and build it in productive code (if the system fits) and that takes some more time to finish it, but ends up that I really can use it for future developments. And as I’m not working to maintain systems it should be possible to stick to the new learned syntax:-)

         

        (1) 
      2. Caroleigh Deneen

        Yes, that was the plan before the mission set was put on pause. Now that we are back and some time has gone by, we will re-visit and let you know as we get closer to the event.

        (1) 
  4. Michelle Crapo

    Excellent idea. My “quick and dirty” programs will become very easy to write. I like that you used a simple approach first. It keeps it simple enough for me to follow.

    What do I do now? Well I do copy some of my code. Sometimes I do have a template for it.  If I am really reusing the code I try to create a class or function module.

    Michelle

    (0) 
    1. Joachim Rees Post author

       My “quick and dirty” programs will become very easy to write.

      exactly! And, as an added bonus, they will be of very high (formal) quality, as you do the typing once in the template, and the profit with every use.

      Do share your experience with it, if you like!

      best
      Joachim

      (0) 

Leave a Reply