report zab_select_configuration.
data: gt_zconf type standard table of zconf.
data: gs_zconf_static type zconf.
data: gs_zconf_dynamic type zconf.
data: gs_zconf_source type zconf.
data: gt_sflight type standard table of sflight.
field-symbols: <sf> type sflight.
"select our configuration
select * into corresponding fields of table gt_zconf
from zconf.
"select sample data to check
select * up to 100 rows into corresponding fields of table gt_sflight
from sflight.
loop at gt_sflight assigning <sf>.
" static version where you manually check key fields and at each change of
" your configuration table structure you have to adjust it
clear gs_zconf_static.
perform select_configuration_static using <sf>-carrid
<sf>-planetype
changing gs_zconf_static.
" dynamic verision, once done never changed again
clear: gs_zconf_dynamic, gs_zconf_source.
move-corresponding <sf> to gs_zconf_source.
perform select_configuration_dynamic using gs_zconf_source
changing gs_zconf_dynamic.
*--------------------------------------------------------------------*
* do your coding here with configuration in gs_zconf_static or
* gs_zconf_dynamic
*--------------------------------------------------------------------*
endloop.
*&---------------------------------------------------------------------*
*& Form select_configuration_static
*&---------------------------------------------------------------------*
form select_configuration_static using f_carrid type s_carrid
f_planetype type s_planetye
changing f_zconf type zconf.
field-symbols: <conf> type zconf.
data: f_current_score type i.
data: f_best_score type i.
"loop at our configuration table
loop at gt_zconf assigning <conf>.
clear f_current_score. "clear previous score
if f_carrid eq <conf>-carrid.
"if the fields are same then we add 20 to score
add 20 to f_current_score.
elseif <conf>-carrid is initial.
"if the configuration field is empty this means this is valid for all
"we add 10
add 10 to f_current_score.
else.
"if the fields are different and configuration is not valid for all
"then we go to next line of configuration
continue.
endif.
"same rules applies here but as this is second key then the score is lower
if f_planetype eq <conf>-planetype.
add 2 to f_current_score.
elseif <conf>-planetype is initial.
add 1 to f_current_score.
else.
continue.
endif.
"check if we have bigger score than before and if yes then we change
"our configuration structure
if f_current_score > f_best_score.
f_best_score = f_current_score.
f_zconf = <conf>.
endif.
endloop.
endform. "select_configuration_static
*&---------------------------------------------------------------------*
*& Form select_configuration_dynamic
*&---------------------------------------------------------------------*
form select_configuration_dynamic using f_sour_conf type zconf
changing f_resu_conf type zconf.
field-symbols: <source> type any,
<config> type any,
<conf> type zconf,
<dfies> type dfies.
data: f_keys_number type i.
data: f_score type i.
data: f_current_score type i.
data: f_best_score type i.
data: fo_conf_str type ref to cl_abap_structdescr.
data: ft_ddfields type ddfields.
data: f_continue type c.
"we create structure object for our customization table
fo_conf_str ?= cl_abap_elemdescr=>describe_by_name( 'ZCONF' ).
"lets get fields for table
fo_conf_str->get_ddic_field_list(
* exporting
* p_langu = SY-LANGU
* p_including_substructres = ABAP_FALSE
receiving
p_field_list = ft_ddfields
exceptions
not_found = 1
no_ddic_type = 2
others = 3
).
if sy-subrc eq 0.
* Implement suitable error handling here
endif.
"check it there was no problem before
check ft_ddfields[] is not initial.
"get the number of key fields
loop at ft_ddfields assigning <dfies> where keyflag eq 'X'.
add 1 to f_keys_number.
endloop.
"loop at our configuration table
loop at gt_zconf assigning <conf>.
clear f_current_score. "clear score.
"we will check key fields only
do f_keys_number times.
"assign key field of configuration
assign component sy-index of structure <conf> to <config>.
if sy-subrc ne 0. exit. endif.
"assign key field of source
assign component sy-index of structure f_sour_conf to <source>.
if sy-subrc ne 0. exit. endif.
"prepare score value
f_score = 1.
do ( f_keys_number - sy-index + 1 ) times.
"we do power of 10, the lower key field position the higher score
f_score = 10 * f_score.
enddo.
if <config> eq <source>.
"if the fields are same then we add 2 times score
do 2 times.
add f_score to f_current_score.
enddo.
elseif <config> is initial.
"if the configuration field is empty this means this is valid for all
"so we add score
add f_score to f_current_score.
else.
"there is no match and configuration is not empty
"so we have to go to next line of configuration
f_continue = 'X'.
exit.
endif.
enddo.
"check if we have to continue or not
if f_continue eq 'X'.
clear f_continue.
continue.
endif.
"check if we have bigger score than before and if yes then we change
"our configuration structure
if f_current_score > f_best_score.
f_best_score = f_current_score.
f_resu_conf = <conf>.
endif.
endloop.
endform. "select_configuration_dynamic
How to select proper configuration entry
When you will want to create a customization table for your program but you want to do it that way that you want to have many key fields and some of them can be empty which would mean that this is valid for all entries then you have to do some little coding to handle it as you just cannot check only if key fields are same as in your checked structure. There is a way to do it and the method described can be used in all programing languages. I will show you two ways - static and dynamic.
In static one I will hard code key field names in the code which makes that you have to rewrite the code each time you change the structure of your configuration table.
Dynamic way when done once then doesn't have to be redesign as I will use cl_abap_elemdescr and cl_abap_structdescr to get key fields.
Ok, firstly we need to create our configuration table in dictionary using SE11. As sample I will create table only with two key fields on a base whom I will check the configuration.
After we need to create some entries in out table. I assume that if key field is empty then it's valid for all entries checked. For example bellow you can find picture with some dummy configuration entries. First line has both key fields empty so this means that if no other configuration will be found for specific airline and/or plane type then I will use this line. So this is kind of default configuration. Using initial fields gives us the possibility to store defaults also for part of the key, like in second line where airline is empty but the plane type is filled. In this case if we will not find configuration for our airline and plane type 747-400 then I will use this line for configuration. Third line shows example where we've set first key but second one is empty. This means that this line is valid for all plane type in airline AA for which there is no direct configuration.
Now let's go to ABAP. In the example of the code which you'll find bellow you can find two forms select_configuration_static and select_configuration_dynamic. This two forms will give you same result but they are done in different way. In fact you could also make dynamic version more dynamic by adding table parameter with your customization table and it's name then you could store it as a FM or method in a class so you could reuse it without any rework. But to make it more understandable I keep it that way.
Enjoy!