Sunday, 4 May 2008

Writing a Virtual Characteristic or Key figure

Writing a Virtual characteristic is one which i really struggled to get on - more because of lack of material than the complexity itself.

Here, i have documented my approach to write one - hope it is a good reference for some one planning to write one.

CAUTION: Virtual char and KFs seriously impact the performance of the query; therefore use them with discretion.
---------------------------------------

Need for virtual char & KFs:

To do calculation/manipulation of char or KFs at query run-time

Walk-through:

We’ll go through the virtual char & KFs using this example.

‘Calc Date’ is an IO that holds the below logic

If Current Date > Revised Promise Date Then

Calc Date = ‘PD’

Else

Calc Date = Revised Promise Date

We shall see how this is implemented using virtual characteristics.

Step 1: Creation of dummy IO

Create a ‘dummy’ info object (without any mapping) that would be the holder for Calc Date

I created IO - ZCRPDTCLC.

Step 2: Associating IO to data target

Add this info object to the data target that would be used for reporting.

I added ZCRPDTCLC under DSO ZPP_DS06 and again to ZPU_M03 MP.

The next steps would involve writing the code for calculating Calc Date.

The code is written in 3 modules.

ZXRSRTOP - Global declaration of variables is done here

ZXRSRU02 - Mode of access for each of the IOs used in the exit is defined here.

ZXRSRZZZ - Association of the global variable to the actual IO is done here.

The exit logic is also written here.

Step 3: Global declaration of variables

Go to ZXRSRTOP module in ABAP editor (tcode se38)

In the ‘Include for Virtual Char’ block (it could be in other blocks also, code written here to make it more organized), declare global variables for Calc Date and Revised Promise Date (these are the objects that will be used in the calculation)

The global variables declared should be in the format –

g_pos__

Data type should be number.

Eg:

Data:

g_pos_ZPP_DS06_ZCRPDTCLC TYPE I,

g_pos_ZPP_DS06_ZCRPDT TYPE I.

Step 4: Defining mode of access for the IO.

Go to ZXRSRU02 module in ABAP editor (tcode se38)

There will be a single CASE block for structure i_s-rkb1d

Eg:

CASE i_s_rkb1d-infocube.

ENDCASE

This structure ‘i_s_rkb1d’ has all details regarding the query like query tech name, data target, etc.

Thereby, i_s_rkb1d-infocube will contain the data target for each query.

CASE i_s_rkb1d-infocube.

WHEN 'ZPP_DS06'.

* Fields to read

g_t_chanm-mode = rrke_c_mode-read.

g_t_chanm = 'ZCRPDT'.

APPEND g_t_chanm to e_t_chanm.

* Fields to write

g_t_chanm-mode = rrke_c_mode-no_selection.

g_t_chanm-chanm = 'ZCRPDTCLC'.

APPEND g_t_chanm to e_t_chanm.

ENDCASE.

We check the info cube attribute for the corresponding data target related to our query.

‘rrke_c_mode’ is the structure that defines the mode of access for each IO (read mode, write mode).

‘g_t_chanm’ is the structure that will hold the name of characteristics that will be used

‘g_t_kyfnm’ is the structure that will hold the name of key figures that will be used

In our example, we use only characteristics and hence only ‘g_t_kyfnm’ structure.

The rest of the code should be self-explanatory.

For each new object, you assign its tech name to ‘g_t_chanm_chanm’ object and append it to ‘e_t_chanm’ which is the output structure.

Similarly for key figures, ‘e_t_kyfnm’ is the output structure.However for key figures, there is no structure to set the mode of access (mode of access – read/write by default).

Another example to drive the point home:

* Characteristics and Units

g_t_chanm-mode = rrke_c_mode-read.

g_t_chanm-chanm = '0MATERIAL'. append g_t_chanm to e_t_chanm.

g_t_chanm-chanm = '0PLANT'. append g_t_chanm to e_t_chanm.

g_t_chanm-mode = rrke_c_mode-no_selection.

g_t_chanm-chanm = 'PR_ID1'. append g_t_chanm to e_t_chanm.

g_t_chanm-chanm = 'PR_ID2'. append g_t_chanm to e_t_chanm.

g_t_chanm-chanm = 'PR_YEAR1'. append g_t_chanm to e_t_chanm.

g_t_chanm-chanm = 'PR_YEAR2'. append g_t_chanm to e_t_chanm.

g_t_chanm-chanm = 'PR_CURR1'. append g_t_chanm to e_t_chanm.

g_t_chanm-chanm = 'PR_CURR2'. append g_t_chanm to e_t_chanm.

* Key Figures

append '0QUANT_B' to e_t_kyfnm.

append 'AMOUNT1' to e_t_kyfnm.

append 'AMOUNT2' to e_t_kyfnm.

For ‘g_t_kyfnm’ we need not set any mode.

Step 5: Writing the logic for virtual char/KF

Go to ZXRSRZZZ module in ABAP editor (tcode se38)

Here, create a new form for the data target being used.

Form name should be begin with ‘USER_’ followed by the data target’s name.

C_S_DATE is the structure that would hold the data in the query.

To access the IOs in the code, we have to create field symbols that act as aliases.

Then the global variables created are associated to these aliases using the ASSIGN statement.

The rest of the code involves the implementation logic as in the snippet below.

FORM USER_ZPP_DS06 USING I_S_RKB1D TYPE RSR_S_RKB1D

CHANGING C_S_DATE TYPE ANY.

DATA: L_DATE TYPE SCAL-DATE.

DATA: L_WEEK TYPE SCAL-WEEK.

CONSTANTS: PAST_DUE(2) TYPE C VALUE 'PD'.

FIELD-SYMBOLS: , .

ASSIGN COMPONENT g_pos_ZPP_DS06_ZCRPDT OF STRUCTURE C_S_DATE TO .

ASSIGN COMPONENT g_pos_ZPP_DS06_ZCRPDTCLC OF STRUCTURE C_S_DATE TO .

L_DATE = SY-DATUM. "Today's Date

CALL FUNCTION 'DATE_GET_WEEK'

EXPORTING

DATE = L_DATE

IMPORTING

WEEK = L_WEEK.

IF L_WEEK GT . "If Current Week is greater than Revised Promise Date, Calc_Date holds "PD"

= PAST_DUE.

ELSE. "Calc_Date holds Revised Promise Date

= .

ENDIF.

ENDFORM.


Overall Program Flow for Calc Date

ZXRSRTOP

Data:

g_pos_ZPP_DS06_ZCRPDTCLC TYPE I,

g_pos_ZPP_DS06_ZCRPDT TYPE I.

ZXRSRU02

CASE i_s_rkb1d-infocube.

WHEN 'ZPP_DS06'.

* Fields to read

g_t_chanm-mode = rrke_c_mode-read.

g_t_chanm = 'ZCRPDT'.

APPEND g_t_chanm to e_t_chanm.

* Fields to write

g_t_chanm-mode = rrke_c_mode-no_selection.

g_t_chanm-chanm = 'ZCRPDTCLC'.

APPEND g_t_chanm to e_t_chanm.

ENDCASE.

ZXRSRZZZ

FORM USER_ZPP_DS06 USING I_S_RKB1D TYPE RSR_S_RKB1D

CHANGING C_S_DATE TYPE ANY.

DATA: L_DATE TYPE SCAL-DATE.

DATA: L_WEEK TYPE SCAL-WEEK.

CONSTANTS: PAST_DUE(2) TYPE C VALUE 'PD'.

FIELD-SYMBOLS: , .

ASSIGN COMPONENT g_pos_ZPP_DS06_ZCRPDT OF STRUCTURE C_S_DATE TO .

ASSIGN COMPONENT g_pos_ZPP_DS06_ZCRPDTCLC OF STRUCTURE C_S_DATE TO .

L_DATE = SY-DATUM. "Today's Date

CALL FUNCTION 'DATE_GET_WEEK'

EXPORTING

DATE = L_DATE

IMPORTING

WEEK = L_WEEK.

IF L_WEEK GT . "If Current Week is greater than Revised Promise Date, Calc_Date holds "PD"

= PAST_DUE.

ELSE. "Calc_Date holds Revised Promise Date

= .

ENDIF.

ENDFORM.



7 comments:

Anonymous said...

Nice one.How does it work in case of multiprovider??There is no abap code written for checking multiprovider mentioned in your example.
Cheers,

Juan R. Malpica said...

Thanks a lot. Good one!
I'm using it for a Multiprovider and works fine. Actually, the code is exactly the same than for a standard cube.

Does anyone know how to use it for navigational attributes???

Thanks again.

seimen said...

Thanks buddy, Nice post to kick start for new bie...

Unknown said...

Finally a clear explanation. Thank you!

Anonymous said...

Do you know if it is possible to index a cube having a virtual characteristic in BWA?

Thanks

Martin L said...

At the moment of determining the value for a virtual char, do I have access to values of other chars in same record of the info provider? this code is executed after or before applying query restrictions? If it is done after, can this code be based on resultset?.
I need to determine a value based on two other characteristics in the cube but depending of course of the input variables.

SAP Singapore said...

There's an ABAP code on his other post