Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
AlexPfeil
Advisor
Advisor

Introduction


In a customer project we defined quite some AIF Value Mappings and noticed that Users can insert any Data into the Value Mapping Table. We wanted to limit the possible entries to the fixed Vales or Values in the Value Table of the Domain of the Data Element used in the Value Mapping Definition.

Example


Let´s say we have

"BUKRS" and Internal Field "XFELD":


Value Mapping Definition


 

The Domains we use have a Value Table (BUKRS) and Fixed Values (XFELD):


Value table


 


Fixed Values


 

 

Our Objective: Validate all Entries based on Value Table (Key Field with same Domain as Key) and Fixed Values (Or Value Ranges)

Implementation Steps


Solution: Implement BaDI "/AIF/VMAP" in SE19


Create BaDI Implementation


In Implementation for /AIF/IF_VMAP_MAIN~BEFORE_SAVE we can validate the maintained Values.

The maintained Values are persisted in the Global Table "'(/AIF/VALUE_MAPPING)LT_TABLE->*' ". We assign it to a Field Symbol:
DATA: lt_dbfields             TYPE dfies_tab,
lt_allowed_content TYPE cim_t_string,
lv_maintained_value_str TYPE string.

FIELD-SYMBOLS: <lt_maintained_values> TYPE ANY TABLE,
<lt_columns> TYPE ANY TABLE.

ASSIGN ('(/AIF/VALUE_MAPPING)LT_TABLE->*') TO <lt_maintained_values>.

The used Data Elements can be retrieved from the vmap manager instance:
DATA(lt_columns) = vmap_manager->get_column_types( ).

Then we loop thorugh the column, get their type, domain, Fixed Valued Indicator and Value Table and, if there is a Value Table, get the allowed Values from there
IF <lt_columns> IS ASSIGNED.
LOOP AT <lt_columns> ASSIGNING FIELD-SYMBOL(<ls_column>).
"Get Names of Column Types
ASSIGN COMPONENT 'NAME'
OF STRUCTURE <ls_column>
TO FIELD-SYMBOL(<lv_column_name>).

IF <lv_column_name> IS ASSIGNED.
CASE <lv_column_name>. "Only these columns are relevant
WHEN 'EXT_VALUE'
OR 'INT_VALUE'
OR 'EXT_VALUE1'
OR 'EXT_VALUE2'
OR 'EXT_VALUE3'
OR 'EXT_VALUE4'
OR 'EXT_VALUE5'.

ASSIGN COMPONENT 'TYPE'
OF STRUCTURE <ls_column>
TO FIELD-SYMBOL(<lv_column_type>).

IF <lv_column_type> IS ASSIGNED "These Data Elements are used if no Data Element is provided in /AIF/CUST
AND <lv_column_type> <> '/AIF/VMAP_EXTVAL'
AND <lv_column_type> <> '/AIF/VMAP_INTVAL'.

SELECT domname "Get Domain for Data Element
FROM dd04l INTO @DATA(lv_domain_name) UP TO 1 ROWS
WHERE rollname = @<lv_column_type>.
ENDSELECT.

IF lv_domain_name IS NOT INITIAL.
SELECT valexi, entitytab "Get Fixed Valued Indicator and Value Table
FROM dd01l INTO @DATA(ls_domain_data) UP TO 1 ROWS
WHERE domname = @lv_domain_name.
ENDSELECT.
IF sy-subrc IS NOT INITIAL.
CLEAR ls_domain_data.
ENDIF.
ENDIF.

IF ls_domain_data IS NOT INITIAL.
IF ls_domain_data-entitytab IS NOT INITIAL.
"Get DB Table Data
CALL FUNCTION 'DDIF_FIELDINFO_GET'
EXPORTING
tabname = ls_domain_data-entitytab
TABLES
dfies_tab = lt_dbfields.

"Get the Field with the same Domain
LOOP AT lt_dbfields ASSIGNING FIELD-SYMBOL(<ls_dbfield>)
WHERE domname = lv_domain_name
AND keyflag = abap_true.
DATA(lv_fieldname) = <ls_dbfield>-fieldname.
ENDLOOP.
IF sy-subrc IS NOT INITIAL.
CLEAR lv_fieldname.
ENDIF.
"Select
IF lv_fieldname IS NOT INITIAL.
SELECT (lv_fieldname)
FROM (ls_domain_data-entitytab)
INTO TABLE @lt_allowed_content.
ENDIF.
ENDIF

Then we loop through the maintained Values and check if the data corresponds to the allowed data in the value table. If the domain is defined as domain with fixed values (indicator "valexi"), we check this with a Function Module FM_DOMAINVALUE_CHECK
LOOP AT <lt_maintained_values> ASSIGNING FIELD-SYMBOL(<ls_maintained_values>).
ASSIGN COMPONENT <lv_column_name> OF STRUCTURE <ls_maintained_values> TO FIELD-SYMBOL(<lv_maintained_value>).
IF <lv_maintained_value> IS ASSIGNED.
lv_maintained_value_str = <lv_maintained_value>.
ENDIF.
IF lv_maintained_value_str <> '*' AND lv_maintained_value_str IS NOT INITIAL. "Values "*" and "" are always allowed.
IF ls_domain_data-valexi IS NOT INITIAL.
"Check against Fix Values / Intervals
CALL FUNCTION 'FM_DOMAINVALUE_CHECK'
EXPORTING
i_domname = lv_domain_name
i_domvalue = CONV val_single( lv_maintained_value_str )
EXCEPTIONS
input_error = 1
value_not_allowed = 2
OTHERS = 3.
IF sy-subrc <> 0.
MESSAGE e003(xxxxx) WITH <lv_maintained_value> lv_domain_name.
ENDIF.
ELSEIF ls_domain_data-entitytab IS NOT INITIAL.
"Check against DB Table we derived before
LOOP AT lt_allowed_content ASSIGNING FIELD-SYMBOL(<lv_data>)
WHERE table_line = <lv_maintained_value>.
ENDLOOP.

IF sy-subrc IS NOT INITIAL.
MESSAGE e002(xxxxx) WITH <lv_maintained_value> lv_fieldname lv_domain_name ls_domain_data-entitytab .
ENDIF.
ENDIF.
ENDIF.
CLEAR lv_maintained_value_str.
ENDLOOP.
ENDIF.
ENDIF.
ENDCASE.
ENDIF.
CLEAR lv_domain_name.
CLEAR lv_fieldname.
CLEAR ls_domain_data.
ENDLOOP.
ENDIF.
ENDIF.
ENDIF.

The Message Class used has to be maintained of course.

Let´s Test in /AIF/VMAP:

With correct Values


With BUKRS = "XXXX" (not existent on T001):


With XFELD = "F" (Only "X" and "" are allowed)



Conclusion


Conclusion: This way we can validate Values maintained in AIF Value Mappings. But be careful: some Domains have huge Value Tables defined (e.g. FDNAME, Table DD03L with 15.351.250 entries), this can have quite a big impact on the runtime.