You are on page 1of 8

www.biportal.

org

Implement Performing Virtual Key Figures in BW 7.3 and BO4

Contents
1. Reporting Scenario requiring VKF ................................................................................................... 1
2. Create a Key Figure (VKF) and add it to the infocube, multiprovider ............................................. 2
3. Create Classic BAdi Implementation with appropriate parameters and code in the methods ...... 3
4. Create a query with the VKF and debug it ...................................................................................... 6
5. Identify position(s) of parameters and update the ABAP code ...................................................... 6
6. Create a BO4 Webi /OLAP Analysis report based on the BEx query via BICS ................................. 7
7. Possible impact on other queries and performance....................................................................... 7

1. Reporting Scenario requiring VKF

First of all I do not advise using Virtual Key Figures (VKF) unless you really have to. The reason for
that is twofold: they are difficult to maintain, and they may impact query performance dramatically.

However, there are certain reporting scenarios where it is impossible to deliver a proper BI reporting
solution without a VKF. For example, we have a Credit Limit set as an attribute of 0Customer and it is
periodically updated. We also want to display Credit Limit in the reports as a Key Figure in order to
apply currency conversions, aggregations by maximum value, etc. Having KF as an attribute of an
infoobject does not give us these capabilities. At the same time if we copy the Credit Limit to the
transactional object (Infocube) we would have to fully refresh it every time as the Credit Limit values
get updated for each customer. Full cube refresh is not a great option in case of big data volumes.

This scenario leads us to a solution where we have to introduce a VKF and populate it at the report
run time based on the current Credit Limit values from the Customer master data.

Here is a link to the document describing this process step by step:


http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/60e36c72-a956-2d10-15a0-
e76055c316cb?QuickLink=index&overridelayout=true&48232482841452

In this post I will show how the scenario described above has been implemented and tested using
BO4 frontend tools, addressing possible performance risks.

1
www.biportal.org

2. Create a Key Figure (VKF) and add it to the infocube,


multiprovider

Add the VKF to the infocube(s) and multiprovider(s) where it is going to be used. In the
transformation to the cube the VKF does not have to be mapped.

The runtime scenario will look as follows:

2
www.biportal.org

3. Create Classic BAdi Implementation with appropriate


parameters and code in the methods
In TC SE19 choose BAdi RSR_OLAP_BADI:

You have to create your own implementation based on it and link it to relevant infoprovider(s).

Go to the implementation class (in my case ZCL_IM_VAR_IMPL_AR):

In the Attributes tab you have to enter Input/ Output parameters as well as internal tables that you
want to use at the run time.

3
www.biportal.org

class ZCL_IM_VAR_IMPL_AR definition


public
final
create public .

public section.
interfaces IF_EX_RSR_OLAP_BADI .
types:
begin of ty_cust,
CUSTOMER TYPE /BI0/OICUSTOMER,
/BIC/CDM_LIMI1 TYPE /BIC/OICDM_LIMI1,
/BIC/ZCUR TYPE /BIC/OIZCUR,
end of ty_cust .
data P_KYF_CDM_LIMVK type I .
data P_CHA_0DEBITOR type I .
data P_CHA_ZCUR type I .
data:
T_CUST type HASHED TABLE OF ty_cust WITH UNIQUE KEY customer .

______________________________________________________________________________

Here is the code for each method in the Implementation Class:

method IF_EX_RSR_OLAP_BADI~DEFINE.
DATA: l_s_chanm TYPE rrke_s_chanm,
l_kyfnm TYPE rsd_kyfnm.
FIELD-SYMBOLS:
<l_s_chanm> TYPE rrke_s_chanm.
CASE i_s_rkb1d-infocube.
WHEN 'FIAR_M03' OR 'FIAR_C03'.
l_s_chanm-chanm = '0DEBITOR'.
l_s_chanm-mode = rrke_c_mode-read.
APPEND l_s_chanm to c_t_chanm.
l_s_chanm-chanm = 'ZCUR'.
l_s_chanm-mode = rrke_c_mode-chng_w_sel.
APPEND l_s_chanm to c_t_chanm.
APPEND 'CDM_LIMVK' TO c_t_kyfnm.
ENDCASE.
endmethod.

4
www.biportal.org

______________________________________________________________________________

method IF_EX_RSR_OLAP_BADI~INITIALIZE.
CASE i_s_rkb1d-COMPID. " different offset for each query
WHEN 'FIAR_QUERY1'.
IF t_cust IS INITIAL.
SELECT CUSTOMER /BIC/CDM_LIMI1 /BIC/ZCUR
FROM /BI0/PCUSTOMER INTO TABLE t_cust
WHERE OBJVERS = 'A' AND /BIC/CDM_LIMI1 NE 0.
ENDIF.
p_kyf_CDM_LIMVK = 36.
p_cha_0DEBITOR = 21.
P_CHA_AZCS1100 = 30.
WHEN ' FIAR_QUERY2'.
IF t_cust IS INITIAL.
SELECT CUSTOMER /BIC/CDM_LIMI1 /BIC/ZCUR
FROM /BI0/PCUSTOMER INTO TABLE t_cust
WHERE OBJVERS = 'A' AND /BIC/CDM_LIMI1 NE 0.
ENDIF.
p_kyf_CDM_LIMVK = 38.
p_cha_0DEBITOR = 22.
P_CHA_AZCS1100 = 32.
ENDCASE.
endmethod.

______________________________________________________________________________

method IF_EX_RSR_OLAP_BADI~COMPUTE.
FIELD-SYMBOLS <fs_CDM_LIMVK> TYPE ANY.
FIELD-SYMBOLS <fs_0DEBITOR> TYPE ANY.
FIELD-SYMBOLS <fs_ZCUR> TYPE ANY.
FIELD-SYMBOLS <cust> TYPE ty_cust.

CASE i_s_rkb1d-COMPID. " Calculate only for queries with VKF


WHEN 'FIAR_QUERY1' OR ' FIAR_QUERY2'.

ASSIGN COMPONENT p_kyf_CDM_LIMVK OF STRUCTURE c_s_data TO <fs_CDM_LIMVK


>.
ASSIGN COMPONENT P_CHA_0DEBITOR OF STRUCTURE c_s_data TO <fs_0DEBITOR>.
ASSIGN COMPONENT P_CHA_ZCUR OF STRUCTURE c_s_data TO <fs_ZCUR>.

READ TABLE t_cust ASSIGNING <cust>


WITH TABLE KEY CUSTOMER = <fs_0DEBITOR>.
IF sy-subrc = 0.
<fs_CDM_LIMVK> = <cust>-/BIC/CDM_LIMI1.
<fs_ZCUR> = <cust>-/BIC/ZCUR.
ELSE. <fs_CDM_LIMVK> = 0.
ENDIF.
ENDCASE.
endmethod.

5
www.biportal.org

4. Create a query with the VKF and debug it


Query structure has to be defined prior to debugging as object positions change when query
structure changes.

In the COMPUTE method you should analyze C_S_DATA object for your query:

5. Identify position(s) of parameters and update the ABAP code


All Input and output parameters have to be identified in the C_S_DATA structure either by name or
by value. This process has to be carried out for each query separately.

Sequentual numbers of relevant components have to be updated in the INITIALIZE method:

p_kyf_CDM_LIMVK = 38.
p_cha_0DEBITOR = 22.
P_CHA_AZCS1100 = 32.

6
www.biportal.org

6. Create a BO4 Webi /OLAP Analysis report based on the BEx


query via BICS

One of the purposes of the VKF in this case is to be able to perform currency conversion on master
data attributes (Credit Limit). When running the report please specify the target currency in the
prompt:

After execution all Key Figures in the report have been converted to the target currency from the
prompt. During report execution Credit Limit VKF is been read from 0Customer master data
attributes:

It has been verified that VKFs work correctly with all BO4 tools (BO Analysis, Webi, OLAP Analysis,
etc.)

7. Possible impact on other queries and performance


It is extremely important to make sure the code used in the VKF calculation is optimized and is
properly placed. In the case above we read master data to the internal table only once at the query
launch in the INITIALIZE method:

IF t_cust IS INITIAL.
SELECT CUSTOMER /BIC/CDM_LIMI1 /BIC/ZCUR

7
www.biportal.org

FROM /BI0/PCUSTOMER INTO TABLE t_cust


WHERE OBJVERS = 'A' AND /BIC/CDM_LIMI1 NE 0.
ENDIF.

Please note, we use a HASHED internal table with a Unique key for attribute lookups. The lookup is
done for every line from the cube used in the report calculation, therefore it is critical to have this
code done the most optimal way. We have to READ data using WITH TABLE KEY for best
performance results:

READ TABLE t_cust ASSIGNING <cust>


WITH TABLE KEY CUSTOMER = <fs_0DEBITOR>.

We also have to make sure we read master data tables only in those queries where the VKF is used.
Therefore, we have to do query name checks in the INITIALIZE method:

CASE i_s_rkb1d-COMPID. " different offset for each query


WHEN 'FIAR_QUERY1'.

Similar check needs to be done in the COMPUTE method:

CASE i_s_rkb1d-COMPID. " Calculate only for queries with VKF


WHEN 'FIAR_QUERY1' OR ' FIAR_QUERY2'.

If we do not check for query names the code will be executed for all queries based on the
infoproviders mentioned in the BAdi parameters. This will badly impact performance of all these
queries and may corrupt results.

You might also like