(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
Okumaya devam et...
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
Okumaya devam et...
Ekli dosyalar
Moderatörün son düzenlenenleri: