(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