Skip to Content

(Note: first I thought about asking this question, but now I think I found the answer myself, so this became a blog!

tl;dr: the answer is CDS + extend view! 🙂

)

[I write this from a partners point of view, but it applies to anyone writing code that might be extended in another system down the line].

 

I wrote a cool program to display a material list:

(get data is at the very end)

*&---------------------------------------------------------------------*
*& Report zz_jre_select_enahnce
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zz_jre_select_enahnce.

Types: gty_data type mara ,
       gty_tab_data TYPE STANDARD TABLE OF gty_data .

*data, solely for select-options.
data: gso_mara type mara.

*Sel-Screen:
SELECTION-SCREEN BEGIN OF BLOCK sel_opt WITH FRAME TITLE text-t01.
SELECT-Options: so_matnr for gso_mara-matnr.
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.
    METHODS: display_data CHANGING ct_data TYPE gty_tab_data.
    METHODS: 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
ENDCLASS.                    "lcl_report IMPLEMENTATION



START-OF-SELECTION.
  PERFORM start_of_selection.

FORM start_of_selection.

  DATA: lt_data TYPE gty_tab_data,
        lo_report TYPE REF TO lcl_report.

*by using a form-routine to get_data we can just use paramters and
*select-options inside.
  PERFORM get_data CHANGING lt_data.

  check lt_data is not initial.

  CREATE OBJECT lo_report.

  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.
ENDFORM.                    "start_of_selection


FORM get_data  CHANGING PT_DATA TYPE gty_tab_data.

select
 matnr,
 ernam,
 ersda
 from mara into CORRESPONDING FIELDS OF table @pt_data UP TO 500 ROWS
  where matnr in @so_matnr
  .
ENDFORM.

 

 

But I also want to give customers the chance to enhance it, adding more fields to the select.

What’s the best way to do it?

 

This would be nice but doesn’t work:

FORM get_data_static_list  CHANGING PT_DATA TYPE gty_tab_data.

select
 matnr,
 ernam,
 ersda
*[enhancement-spot here would be nice, but is not possibel ]
 from mara into CORRESPONDING FIELDS OF table @pt_data UP TO 500 ROWS
  where matnr in @so_matnr
  .
ENDFORM.

 

Put the whole select into an enhancement-section:

FORM get_data_eh_sect  CHANGING PT_DATA TYPE gty_tab_data.

ENHANCEMENT-SECTION ZZ_JRE_SELECT_ENAHNCE_SEL1 SPOTS ZZ_JRE_SELECT_ENAHNCE_SEL .
select
 matnr,
 ernam,
 ersda
 from mara into CORRESPONDING FIELDS OF table @pt_data UP TO 500 ROWS
  where matnr in @so_matnr
  .
END-ENHANCEMENT-SECTION.
ENDFORM.

Valid choice, but it gives more freedom/options then I wanted to give (the whole select can be replaced/altered, not just fields added) . I agree that this can be view an advantage as well.

 

Build the field list dynamically and provide an enhancement point to add more fields to it;

FORM get_data_dynamic_list_enhp  CHANGING PT_DATA TYPE gty_tab_data.

data lt_fields type table of string.
lt_fields = value #(
( ` MATNR  ,`)
( ` ERNAM  ,`)
( ` ERSDA   `)
).

*ENHACEMENT-Point HERE;
ENHANCEMENT-POINT ZZ_JRE_SELECT_ENAHNCE_SEL2 SPOTS ZZ_JRE_SELECT_ENAHNCE_SEL .

*ADD:
* ,
* [yourFild_1],
*....
*[yourfild_D]

select
 (lt_fields)
 from mara into CORRESPONDING FIELDS OF table @pt_data UP TO 500 ROWS
  where matnr in @so_matnr
  .
ENDFORM.

Valid, too; you could not only add to but also remove from the fields list..
But: we lose all static checks, which I think is a big drawback.
(e.g. misspelling a fieldname will not give a syntax-error (which would be easy to find and solve) but cause trouble at runtime. )

 

My solution:

 

Move the field list to a CDS View and select * from it:

@AbapCatalog.sqlViewName: 'ZZ_MARA1'
@AbapCatalog.compiler.compareFilter : true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Select from MARA for Demo'
define view zz_jre_sel_mara as select from mara {
    matnr,
    ernam,
    ersda
}

 

FORM get_data_from_cds  CHANGING PT_DATA TYPE gty_tab_data.

select
 *
 from zz_jre_sel_mara into CORRESPONDING FIELDS OF table @pt_data UP TO 500 ROWS
  where matnr in @so_matnr
  .
ENDFORM.

 

The CDS-view can be extended with a – well – extend view:

@AbapCatalog.sqlViewAppendName: 'ZZ_MARA11'
@EndUserText.label: 'Extending zz_jre_sel_mara 1'
extend view zz_jre_sel_mara with zz_jre_sel_mara_ext1 {
    mara.meins
// mara.[yy_yourfield_1]
// mara.[yy_yourfield_2]    
}

 

 

And this it to show it actually works:

-> Indeed, MARA-MEINS is selected together with the other fields!

Ho do you tackle this problem? Do you (have to) care about your field lists being extendable?

best
Joachim

To report this post you need to login first.

15 Comments

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

  1. Michelle Crapo

    I like it.   It’s very clean code.   It’s interesting to see it in “normal” (old) ABAP first.  For me as I havenn’t had a chance to use CDS, it looks like you can use the view within an ABAP program, Correct?

    Thank you!

    Michelle

    (And I haven’t taken the time to read about it)

    (0) 
    1. Joachim Rees Post author

      Hey Michelle,

      thanks for your Feedback!
      And yes, your’re right, you can read from the CDS-view from an ABAP programm (just as you read from a ‘normal’ table).

      Best
      Joachim

       

      (1) 
  2. Umar Abdullah

    Joachim Rees  , Good Work. I believe that you want to explain View extensibility and also it would have been very nice if you had written method for fetching data also.

    (0) 
    1. Joachim Rees Post author

      Hey Umar ,

      thanks for your kind feedback!
      Your point is, that I should have used a method instead of a form to fetch the data?! Yes, you’re right; that’s part of my laziness. (and my template still works like that…)

      In Demo/throw-away- reports I tend to still use FORM get_data as this lets me access select-options right away (as opposed to a method of a local class, where I would need to pass them with parameters, and also type the parameters…).

       

      best
      Joachim

      (0) 
      1. Christian Guenter

        Hey Joachim,

        you can also access select-options in methods of local classes as you can do within form routines. No need to explicitly pass them to the method. Of course that doesn’t mean you should always do that 😉

        Btw. I use local classes for even the smallest of my test reports mainly because the refactorings within ABAP in Eclipse work much better.

        Regards Christian

        (1) 
        1. Joachim Rees Post author

          Hi Christian,

          thanks a lot for pointing this out!
          Seems I have been the victim of a misconception for quite some time! (Was it maybe different in past releases?)

          So I can use local-class only with now drawback at all – great! I’ll try to edit my (throw-away) report-temple accordingly.

          best
          Joachim

          PS: I tried it out, indeed, no problem at all: 

          (2) 
          1. Umar Abdullah

             

            Hi Christian / Joachim,

             

            Yes I tried using select option directly in the method. It works where as in the previous version it was not possible to use Select-option directly in the methods.Thanks.

             

            (0) 
            1. Joachim Rees Post author

              Hey Umar,
              thanks a lot for your input – so I havn’t been “all wrong”, but just missed an update.

              Anyway we know now, great!

              (0) 
        2. BĂ€rbel Winkler

          Thanks for this clarification, Christian! The perceived need to first move the sel-screen fields into an itab for rsparams (and all that entails) was quite a deterrent for me to write more programs (of the simple/straightforward kind I usually do) with ABAP-OO and local classes. No longer having to do this, will make it much easier.

          Cheers

          Baerbel

           

          (2) 
  3. Peter Inotai

    CDS is a nice option. Only problem that you need at least 7.40 release and most of us don’t have it. 🙁

    SELECT (select) INTO TABLE <itab> FROM (from).  approach is also an option like in demo report DEMO_DYNAMIC_SQL. and list of fields can come from wherever you want to (cust table etc).

    Peter

     

    (1) 
    1. Joachim Rees Post author

      Hi Peter,

      yeah, I’m lucky to have an up-to-date environment available!

      I do like the idea of the fields list (or a list of additional fields) coming  from a customizing table: that way, fields can be added without even having to touch the code. (Which mitigates the drawback of not having static checks, I think).

       

      Thanks for your input!

      Joachim

      (1) 
      1. Peter Inotai

        “Which mitigates the drawback of not having static checks, I think.” 

        Yes, you’re totally right. It has to be somehow validated before the select.

        (1) 
  4. Alejandro Sensejl

    I assume from typing of

    gty_tab_data TYPE STANDARD TABLE OF gty_data

    that it’s declaration is part of your report.

    What about using syntax SELECT * … INTO CORRESPONDING FIELDS OF TABLE and placing the enhancement section in the declaration of gty_data?

    Something like this…

    TYPES: BEGIN OF gty_data,
             field1 type type1,
             field2 type type2
    *ENHACEMENT-POINT HERE;
           END   OF gty_data.

    TYPES:

    BEGIN OF gty_data,

     

     

     

    (0) 
    1. Joachim Rees Post author

      Hi Alejandro,

      very good idea you propose here, I thing this would work very fine!
      (And: usually (in a real-world example) you would have to extend the type somehow anyway, as otherwise it wouldn’t contain your [yy_yourfield_1]!)

      I quickly thought about that when writing my blog, but the I let it go again, so good that you point it out here!

      Thanks!
      Joachim

       

      (0) 

Leave a Reply