generic variant function
hello
sap vc is a powerfull tool. i like it, to design the vc the way that the logic is stored in decision tables, for instance a list of allowed options for a characteristic. so the end user just has to maintain the table when new master data is created, and does not have to create new dependencies.
there is a command call ‘table’ which allows access to variant tables. ( i think you already know)
sometimes there is a disadvantage that you have to create severall dependencies in order to pass the right selection criterias
my target was to create just one global dependency to cover all, which simplifies the maintenance of the configurator
i designed a generic variant function which reads data from the current configuration and with the possibility to use a cached access to variant table data.
dependency:
000010 | Function Z_PRE_COND_00 |
000020 | (GLOBAL_TABLENAME = ‘MYVARIANTTABLE’, |
000030 | OBJECT_CAWN_ATINN = mdata $self.CAWN_ATINN, |
000040 | OBJECT_CAWN_ATWRT = mdata $self.CAWN_ATWRT ) |
______ | ________________________________________________________________________ |
the two characteristics CAWN_ATINN and CAWN_ATWRT are Object Characteristic with a link to the Table CAWN
this is used to find the name of the currently selected characteristic-value
Variant Table /NCU62
Variant Function /NCU66:
Example: Table POWER
Characteristics
PRODUCT
POWER
you see a list of allowed POWER values for the PRODUCT
so the global dependency/function validates, if only allowed POWER values for the selected PRODUCT are entered
we can use the same characteristic POWER for all PRODUCTS, but with different allowed values
>> search for entries with same characteristics/values as current configuration!
FUNCTION z_pre_cond_00.
*”———————————————————————-
*”*”Lokale Schnittstelle:
*” IMPORTING
*” REFERENCE(GLOBALS) TYPE CUOV_00
*” TABLES
*” QUERY STRUCTURE CUOV_01
*” MATCH STRUCTURE CUOV_01
*” EXCEPTIONS
*” FAIL
*” INTERNAL_ERROR
*”———————————————————————-
DATA it_imp_values TYPE STANDARD TABLE OF api_val_i.
DATA its_imp_values TYPE SORTED TABLE OF api_val_i “MDW01
WITH UNIQUE KEY atnam atwtb atinn. “must be unique!
FIELD-SYMBOLS <imp_values> TYPE api_val_i.
DATA wa_imp_values TYPE api_val_i.
DATA it_imp_char TYPE STANDARD TABLE OF api_char.
DATA its_imp_char TYPE SORTED TABLE OF api_char “MDW01
WITH UNIQUE KEY atnam. “must be unique!
FIELD-SYMBOLS <fs_char> TYPE api_char.
DATA wa_imp_char TYPE api_char.
FIELD-SYMBOLS <fs_values> TYPE api_value.
DATA wf_atinn LIKE cabn-atinn.
DATA wf_atwrt LIKE cuov_01-atwrt.
DATA it_char TYPE TABLE OF api_char.
FIELD-SYMBOLS <fs_chk_char> TYPE api_char.
TYPE-POOLS: cullt.
DATA: wf_tablename TYPE tablstruct-var_tab.
DATA: it_vc_table TYPE TABLE OF vtentries.
DATA: it_vc_tab_char TYPE TABLE OF vtchars.
DATA: self_instance TYPE cullt_instance_nr VALUE 1.
DATA: parent_instance TYPE cullt_instance_nr VALUE 2.
DATA: instance TYPE cullt_instance.
DATA: wa_properties TYPE LINE OF cullt_properties.
DATA: characteristics LIKE STANDARD TABLE OF bapicuch01.
DATA: characteristics_value LIKE STANDARD TABLE OF bapicuvl01.
DATA: wa_characteristics_value LIKE bapicuvl01.
DATA: wf_instance LIKE capiparms-instance.
DATA it_exp_values_error TYPE STANDARD TABLE OF api_val_i.
DATA wa_exp_values_error TYPE api_val_i.
DATA wa_exp_values TYPE api_value.
DATA it_exp_values TYPE STANDARD TABLE OF api_value.
DATA its_exp_values TYPE SORTED TABLE OF api_value “MDW01
WITH NON-UNIQUE KEY atnam atwrt.
DATA: ls_cabn TYPE cabn,
ls_cawn TYPE cawn.
* data: wf_atinn like cawn-atinn.
DATA: wf_atnam LIKE cabn-atnam.
DATA: wa_char LIKE LINE OF it_char.
DATA: wf_atflv LIKE cawn-atflv.
DATA: wf_tabix TYPE vtentries-vtlineno.
DATA: wf_found.
DATA: wf_row_fields_match.
*..initialize table with export parameters………………………..*
REFRESH match.
*..get value of input characteristic
CALL FUNCTION ‘CUOV_GET_FUNCTION_ARGUMENT’
EXPORTING
argument = ‘GLOBAL_TABLENAME’
IMPORTING
sym_val = wf_atwrt
TABLES
query = query
EXCEPTIONS
arg_not_found = 01.
IF sy-subrc <> 0.
RAISE internal_error.
ENDIF.
wf_tablename = wf_atwrt.
*..get value of input characteristic salesorganisation
CALL FUNCTION ‘CUOV_GET_FUNCTION_ARGUMENT’
EXPORTING
argument = ‘OBJECT_CAWN_ATINN’
IMPORTING
num_val = wf_atflv
TABLES
query = query
EXCEPTIONS
arg_not_found = 01.
wf_atinn = wf_atflv.
*..get value of input characteristic salesorganisation
CALL FUNCTION ‘CUOV_GET_FUNCTION_ARGUMENT’
EXPORTING
argument = ‘OBJECT_CAWN_ATWRT’
IMPORTING
sym_val = wf_atwrt
TABLES
query = query
EXCEPTIONS
arg_not_found = 01.
IF sy-subrc <> 0.
RAISE internal_error.
ENDIF.
* read current configuration values
CLEAR it_char.
CALL FUNCTION ‘CEI0_DDB_HAS_CHARACTERISTICS’
TABLES
exp_characteristics = it_char
EXCEPTIONS
not_found = 1
no_characteristic_in_ddb = 2
OTHERS = 3.
READ TABLE it_char INTO wa_char WITH KEY atinn = wf_atinn. ” binary search.
IF sy-subrc = ‘0’.
wf_atnam = wa_char-atnam.
ENDIF.
IF NOT it_char[] IS INITIAL.
* it_imp_char = its_imp_char. “sorted-> standard table
* select values
CALL FUNCTION ‘CEI0_DDB_HAS_VALUES’
EXPORTING
assigned_values = ‘X’
allowed_values = ‘ ‘
valid_values = ‘ ‘
inconsistent_values = ‘ ‘
first_assigned_value = ‘ ‘
default_values = ‘ ‘
incl_author = ‘X’
TABLES
imp_characteristics = it_imp_char
exp_values = it_exp_values
EXCEPTIONS
not_found = 1
OTHERS = 2.
SORT it_exp_values BY atnam atwrt.
ELSE.
* if CEI0_DDB_HAS_CHARACTERISTICS gives no values, use other function: (depends on vc-transaction/low-level configurator)
** example values from cs11
* this is not needed for input-screen related dependencies, but useful if you are working with procedures
CALL FUNCTION ‘CULL_GET_INSTANCE’
EXPORTING
instance_nr = parent_instance
IMPORTING
instance = instance
EXCEPTIONS
unknown_instance = 1
OTHERS = 2.
REFRESH it_exp_values.
LOOP AT instance-properties INTO wa_properties.
CLEAR wa_exp_values-atnam.
wa_exp_values-atinn = wa_properties-characteristic.
READ TABLE gt_cabn INTO ls_cabn WITH TABLE KEY atinn = wa_exp_values-atinn.
IF sy-subrc <> ‘0’.
SELECT SINGLE *
FROM cabn
INTO ls_cabn
WHERE atinn = wa_exp_values-atinn.
INSERT ls_cabn INTO TABLE gt_cabn.
ENDIF.
wa_exp_values-atnam = ls_cabn-atnam.
*wa_exp_values-ATBEZ = wa_properties-characteristic
wa_exp_values-atwrt = wa_properties-value-atwrt.
* if wa_properties-value-atwrt is initial
* and wa_properties-value-atflv <> 0.
IF ls_cabn-atfor <> ‘CHAR’.
* nicht immer usr01 sondern via set country…
IF usr01-bname <> ‘ ‘.
usr01-bname = sy-uname.
DATA: w_zahl TYPE p DECIMALS 1, w_string(10).
WRITE: w_zahl TO w_string.
IF w_string CA ‘,’.
usr01-dcpfm = ‘ ‘.
ELSE.
usr01-dcpfm = ‘X’.
ENDIF.
ENDIF.
MOVE-CORRESPONDING ls_cabn TO ls_cawn.
ls_cawn-atawe = ls_cabn-msehi. CLEAR ls_cabn-msehi.
ls_cawn-spras = sy-langu.
MOVE-CORRESPONDING wa_properties-value TO ls_cawn.
CALL FUNCTION ‘CTCV_PREPARE_VALUES_TO_DISPLAY’
EXPORTING
align = ‘NO’
decimalpoint = usr01-dcpfm
shift = ‘L’
single = ‘NO’
string_without_operand = ‘NO’
string_without_unit = ‘NO’
structure_cabn = ls_cabn
structure_cawn = ls_cawn
IMPORTING
string = wa_exp_values-atwrt.
ENDIF.
*wa_exp_values-ATWTB = wa_properties-
wa_exp_values-ataut = wa_properties-author.
APPEND wa_exp_values TO it_exp_values.
ENDLOOP.
ENDIF.
* get vc table
CALL METHOD zcl_ml_vc_table_cache=>get_table_content
EXPORTING
tablename = wf_tablename
IMPORTING
it_vc_tab_char = it_vc_tab_char[]
it_vc_table = it_vc_table[].
IF NOT it_vc_tab_char IS INITIAL.
* search dynamic table-entry:
SORT it_exp_values BY atnam atwrt .
SORT it_vc_table BY vtlineno vtcharact vtvalue.
FIELD-SYMBOLS: <wa_vc_value> LIKE LINE OF it_vc_table.
FIELD-SYMBOLS: <wa_vc_char> LIKE LINE OF it_vc_tab_char.
wf_found = ‘ ‘.
DO.
UNPACK sy-index TO wf_tabix .
READ TABLE it_vc_table TRANSPORTING NO FIELDS
WITH KEY vtlineno = wf_tabix.
IF sy-subrc <> ‘0’. EXIT. ENDIF.
wf_row_fields_match = ‘X’.
LOOP AT it_vc_tab_char ASSIGNING <wa_vc_char>. “table structure
READ TABLE it_exp_values INTO wa_exp_values
WITH KEY atnam = <wa_vc_char>-charact BINARY SEARCH.
* Loop/multiple characteristics?
IF sy-subrc <> ‘0’. CLEAR wa_exp_values. ENDIF.
IF <wa_vc_char>-charact = wf_atnam.
wa_exp_values-atwrt = wf_atwrt.
DATA: wf_atzhl LIKE cawn-atzhl.
SELECT SINGLE atzhl FROM cawnt INTO wf_atzhl
WHERE atinn = wf_atinn AND atwtb = wf_atwrt
AND spras = sy-langu.
IF sy-subrc = ‘0’.
SELECT SINGLE atwrt FROM cawn INTO wa_exp_values-atwrt
WHERE atinn = wf_atinn
AND atzhl = wf_atzhl.
ENDIF.
CLEAR sy-subrc.
ENDIF.
* If sy-subrc = ‘0’.
* or vc_table-index = 1?
* empty value?
READ TABLE it_vc_table TRANSPORTING NO FIELDS
WITH KEY vtlineno = wf_tabix
vtcharact = <wa_vc_char>-charact
vtvalue = wa_exp_values-atwrt
BINARY SEARCH.
IF sy-subrc <> 0.
CLEAR wf_row_fields_match.
EXIT. “next line
ENDIF.
ENDLOOP.
IF wf_row_fields_match = ‘X’. wf_found = ‘X’. EXIT. ENDIF.
ENDDO.
IF wf_found = ‘ ‘.
RAISE fail. “no entry found, let the selection condition fail
ENDIF.
*..add result to the table of output characteristics for procedures:
*.. pseudo output
* CALL FUNCTION ‘CUOV_SET_FUNCTION_ARGUMENT’
* EXPORTING
* argument = ‘OUT_CHAR’
* vtype = ‘CHAR’
* sym_val = value
* TABLES
* match = match
* EXCEPTIONS
* existing_value_replaced = 01.
* set a numeric output value
*data: wf_atflv like match-atflv.
*CALL FUNCTION ‘CONVERSION_EXIT_FLOAT_INPUT’
* EXPORTING
* INPUT = wa_exp_values-atwrt
* IMPORTING
* OUTPUT = wf_atflv.
* CALL FUNCTION ‘CUOV_SET_FUNCTION_ARGUMENT’
* EXPORTINg
* argument = query-varnam
* vtype = ‘NUM’
** sym_val = wa_exp_values-atwrt
* num_val = wf_atflv
* TABLES
* match = match
* EXCEPTIONS
* existing_value_replaced = 01.
ELSE.
RAISE fail. “table not found
ENDIF.
ENDFUNCTION.
Class ZCL_ML_VC_TABLE_CACHE class to read and cache variant tables
class ZCL_ML_VC_TABLE_CACHE definition
public
final
create public .
*”* public components of class ZCL_ML_VC_TABLE_CACHE
*”* do not include other source files here!!!
public section.
data:
begin of table_list,
table_name type tabname,
tableobj type ref to ZCL_ML_VC_TABLE_CACHE,
end of table_list .
dataTABLE_STRUCTURE type ZML_VTCHARS . “table type of vtchars
data TABLE_CONTENT type ZML_VTENTRIES . “table type of vtentries
class-data:
TABLE_NAMES like table of table_list .
data TABLE_NAME type TABLENAME .
methods CONSTRUCTOR
importing
!TABLENAME type APITABL optional .
class-methods GET_TABLE_CONTENT
importing
value(TABLENAME) type APITABL optional
exporting
!IT_VC_TAB_CHAR type ZML_VTCHARS “table type of VTCHARS
!IT_VC_TABLE type ZML_VTENTRIES . “table type of VTENTRIES
Importing-Parameter
TABLENAME TYPE APITABL OPTIONAL (Tabellenname)
method CONSTRUCTOR.
* data: wf_tablename type CAPIPARMS-VAR_TAB.
if tablename <> ‘ ‘.
* wf_tablename = tablename.
CALL FUNCTION ‘CARD_TABLE_READ_STRUCTURE’
EXPORTING
VAR_TAB = tablename
* CHANGE_NO =
* DATE =
* LANGUAGE =
* IMPORTING
* BASIC_DATA =
* RETURN =
TABLES
* DESCRIPTIONS =
CHARACTERISTICS = me->table_structure[]
* VALUE_ASSIGNMENT_ALT =
EXCEPTIONS
ERROR = 1
OTHERS = 2
.
if sy-subrc = ‘0’.
* Lesen der Tabelleneinträge
CALL FUNCTION ‘CARD_TABLE_READ_ENTRIES’
EXPORTING
VAR_TABLE = tablename
* CHANGE_NO =
* DATE =
TABLES
VAR_TAB_ENTRIES = me->table_content[]
EXCEPTIONS
ERROR = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
endif.
data: line like line of ZCL_ML_VC_TABLE_CACHE=>table_names.
line-table_name = tablename.
line-tableobj = me.
append line to ZCL_ML_VC_TABLE_CACHE=>table_names.
endif.
endmethod.
GET_TABLE_CONTENT
Beschreibung:
Statische Methode
Importing-Parameter
VALUE(TABLENAME) TYPE APITABL OPTIONAL (Tabellenname)
Exporting-Parameter
IT_VC_TAB_CHAR TYPE ZML_VTCHARS (tabellentyp vtchars)
IT_VC_TABLE TYPE ZML_VTENTRIES (tabellentyp vtentries)
method GET_TABLE_CONTENT.
data: line like line of ZCL_ML_VC_TABLE_CACHE=>table_names.
data:
begin of table_list,
table_name type tabname,
tableobj type ref to ZCL_ML_VC_TABLE_CACHE,
end of table_list .
data: lo_table_cache type ref to ZCL_ML_VC_TABLE_CACHE.
field-symbols: <line> type any.
read table ZCL_ML_VC_TABLE_CACHE=>table_names into line
with key table_name = tablename.
if sy-subrc <> ‘0’.
create object lo_table_cache
EXPORTING
tablename = tablename.
else.
lo_table_cache = line-tableobj.
endif.
it_vc_tab_char[] = lo_table_cache->table_structure[].
it_vc_table[] = lo_table_cache->table_content[].
endmethod.
you can use it in preconditions/selection conditions and/or procedures.
of course you can also access a data dictionary table and create a table maintenance dialog, then you don’t need the access routines/class to variant tables at all
maybe you have similar requirements/ideas and this is of use for you.
Hi Jorg,
Excellent ! This is a very useful approach. I have one question though.
Should you create the characteristics with all the possible values or can we just create the characteristics without values and use them in the function ?
best regards,
Rishi
hi rishi
sorry i just saw your comment now
if you assign values to characteristics, the Default F4 Value Help will work for the user, if you don't do you, you will have to implement a userexit to determine the allowed values when the user presses f4. i did this once for a Project using CMOD for CCUCEI0H (EXIT_SAPLCEI0_022, INCLUDE ZXCEI0U14)
Hi ,
found this blog while browsing indeed global functions as described; have a questions regarding some z-objects mentioned in the post like:
tableobj type ref to ZCL_ML_VC_TABLE_CACHE
and
type like zml_vtchars etc..
have you (data) definitions of these z-objects ZCL_ML_VC_TABLE_CACHE assuming structure type zml_vtchars refers to standard type vtchars?