How to use Virtual InfoProviders in SAP BI / BW

 How to use Virtual InfoProviders in SAP BI / BW

Why use Virtual InfoProviders
Because sometimes you need the controll about the whole reading process and not only on single lines / virtuel key-figures / virtual characteristics.
Because you need – depending on the selection – control about the selected attributes.
 Cube1
How it all Works
We will create a reusable Class-Framework that will do job.
The function (which defines the virtual infoprovider) calls first the „DEFINE“ Method. „DEFINE“ looks what characteristics and keyfigures are requested by the OLAP process (What does the Query use).
If there is an implementation (naming-convention) of a keyfigure or characteristic the „GET_INSTANCE“ of this implementation is called. The defined characteristics-class  declares what characteristics and keyfigures it do use for further working. The „EXECUTE“ Method of that implementation got the result of the reading and processes it on its own way.
 Class-Chart Image [1]
Where to start
Transaction RSA1
 Create a Cube the usual way:
Go to CTRL+F5
 left_click_cube
Set it to Virtual
 set_virtual
Set a Function implementing parameters like described in the F1 – HELP or below
 set_fuba
Please do a F1-HELP 

1. VirtualProvider, basierend auf Funktionsbaustein

Name des Funktionsbaustein, der als Quelle für den VirtualProvider benutzt wird. Für die Schnittstelle dieses Funktionsbausteins sind verschiedene Varianten vorgegeben, die von den gewählten Optionen für den VirtualProvider abhängen .

Falls RFC Verpacken eingeschaltet ist:

dann Variante 1

Falls Sid-Unterstützung ausgeschaltet ist:

dann Variante 2

Sonst Variante 3

1.1 Variante 1:
IMPORTING
   infocube        LIKE bapi6200-infocube
   keydate         LIKE bapi6200-keydate
   return          LIKE bapiret2
TABLES
   selection       STRUCTURE bapi6200sl
   characteristics STRUCTURE bapi6200fd
   keyfigures      STRUCTURE bapi6200fd
   data            STRUCTURE bapi6100da
EXCEPTIONS
   communication_failure
   system_failure

Diese Variante ist die allgemeinste und einfachste, und in der Funktionsbausteindokumentation des Funktionsbausteins BAPI_INFOCUBE_READ_REMOTE_DATA beschrieben.

1.2 Variante 2:
IMPORTING
  i_infoprov         TYPE rsinfoprov
  i_keydate          TYPE rrsrdate
  i_th_sfc           TYPE rsdri_th_sfc
  i_th_sfk           TYPE rsdri_th_sfk
  i_t_range          TYPE rsdri_t_range
  i_tx_rangetab      TYPE rsdri_tx_rangetab
  i_first_call       TYPE rs_bool
  i_packagesize      TYPE i
  i_maxrows          TYPE i
  i_use_aggregation  TYPE rs_bool
  i_show_statement   TYPE rs_bool
EXPORTING
  e_t_data           TYPE standard table
  e_end_of_data      TYPE rs_bool
  e_t_msg            TYPE rs_t_msg

Diese Variante wird in der Funktionsbausteindokumentation des Funktionsbausteins RSDRI_VPROV_READ_TEMPLATE beschrieben.

Alternativ kann hier auch der Name einer Klasse angegeben werden, die das Interface IF_RSDRV_VPROV_LOC_NOSID_QUERY implementiert. Die Unterscheidung wird anhand des Namens vorgenommen. Es wird von einer Klasse ausgegangen, wenn der Name mit ‚CL‘ beginnt (Klassennamen wie z.B.: ZCL*, YCL* oder die Benutzung von Namensraumpräfixen werden nicht unterstützt). Die Verwendung dieses Interfaces ist ausschließlich SAP-internen Applikationen vorbehalten.
Funktionsbaustein Template – how it could look like
function Z_MY_VIRTUAL1.
*“———————————————————————- 
*“*“Lokale Schnittstelle: 
*“  IMPORTING 
*“     REFERENCE(I_INFOPROV) TYPE  RSINFOPROV 
*“     REFERENCE(I_TH_SFC) TYPE  RSDRI_TH_SFC 
*“     REFERENCE(I_TH_SFK) TYPE  RSDRI_TH_SFK 
*“     REFERENCE(I_T_RANGE) TYPE  RSDRI_T_RANGE OPTIONAL 
*“     REFERENCE(I_TX_RANGETAB) TYPE  RSDRI_TX_RANGETAB OPTIONAL 
*“     REFERENCE(I_FIRST_CALL) TYPE  RS_BOOL OPTIONAL 
*“     REFERENCE(I_PACKAGESIZE) TYPE  I DEFAULT 100000 
*“     REFERENCE(I_KEYDATE) TYPE  RRSRDATE DEFAULT SY-DATUM 
*“     REFERENCE(I_MAXROWS) TYPE  I OPTIONAL 
*“     REFERENCE(I_USE_AGGREGATION) TYPE  RS_BOOL DEFAULT ‚X‘ 
*“     REFERENCE(I_SHOW_STATEMENT) TYPE  RS_BOOL DEFAULT “ 
*“  EXPORTING 
*“     REFERENCE(E_T_DATA) TYPE  STANDARD TABLE 
*“     REFERENCE(E_END_OF_DATA) TYPE  RS_BOOL 
*“     REFERENCE(E_T_MSG) TYPE  RS_T_MSG 
*“———————————————————————-
data: o_zcl_zmakvri01 type ref to zcl_vprov ,
l_infoprov      
 type rsinfoprov value ‚Z<MYBASIS_CUBE_DSO_TO_READ>‘ .
create object o_zcl_zmyvri01 . call method o_zcl_zmyvri01-> define
 exporting
i_infoprov       
 = l_infoprov
i_th_sfc         
 = i_th_sfc
i_th_sfk         
 = i_th_sfk
i_t_range        
 = i_t_range
i_tx_rangetab    
 = i_tx_rangetab
i_keydate        
 = i_keydate
i_maxrows        
 = i_maxrows
i_use_aggregation
 = i_use_aggregation
.
 call method o_zcl_zmyvri01-> read
*  EXPORTING 
*    I_PACKAGESIZE    = I_PACKAGESIZE 
*    I_SHOW_STATEMENT = I_SHOW_STATEMENT 
 importing
e_t_data        
 = e_t_data
e_end_of_data   
 = e_end_of_data
e_t_msg         
 = e_t_msg
 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.endfunction.
 
Implement the generic classes like below
Get-Commands for Virtual Provider class
class zcl_virtual_command_factory definition 
 public
final
 create public .*“* public components of class ZCL_VIRTUAL_COMMAND_FACTORY 
*“* do not include other source files here!!! 
public section.  class-methods get_list
 importing 
!i_t_range
 type rsdri_t_range
 exporting 
!e_command_list
 type zt_command_list
 changing 
!c_th_sfc
 type rsdri_th_sfc
!c_th_sfk
 type rsdri_th_sfk .
*“* protected components of class ZCL_VIRTUAL_COMMAND_FACTORY 
*“* do not include other source files here!!! 
protected section.
*“* private components of class ZCL_VIRTUAL_COMMAND_FACTORY 
*“* do not include other source files here!!! 
private section.
endclass.class zcl_virtual_command_factory implementation. * <SIGNATURE>—————————————————————————————+
* | Static Public Method ZCL_VIRTUAL_COMMAND_FACTORY=>GET_LIST 
* +————————————————————————————————-+
* | [—>] I_T_RANGE                      TYPE        RSDRI_T_RANGE 
* | [<—] E_COMMAND_LIST                 TYPE        ZT_COMMAND_LIST 
* | [<–>] C_TH_SFC                       TYPE        RSDRI_TH_SFC 
* | [<–>] C_TH_SFK                       TYPE        RSDRI_TH_SFK 
* +————————————————————————————–</SIGNATURE>
method get_list.
 data: wa_sfc type rsdri_s_sfc,
wa_sfk
 type rsdri_s_sfk,
classname
 type string,
i_zci_command
 type ref to zci_virtual_object_command
.
 “ Creates a command-list for virtual infoobjects.
 loop at c_th_sfc into wa_sfc.
 concatenate ‚ZCL_VI_‘ wa_sfc chanm into classname. „Namingconvention for the class ZCL_VI_<InfoObject>
 try.            
 call method (classname) =>get_instance
 exporting 
i_t_range
 = i_t_range
 importing 
e_self   
 = i_zci_command
 changing 
c_th_sfc 
 = c_th_sfc
c_th_sfk 
 = c_th_sfk.
 append i_zci_command to e_command_list.
 clear i_zci_command.
 catch cx_sy_dyn_call_error.
 endtry. 
 endloop.  “  
 loop at c_th_sfk into wa_sfk.
 concatenate ‚ZCL_VI_‘ wa_sfk kyfnm into classname. 
 try.            
 call method (classname) =>get_instance
 exporting 
i_t_range
 = i_t_range
 importing 
e_self   
 = i_zci_command
 changing 
c_th_sfc 
 = c_th_sfc
c_th_sfk 
 = c_th_sfk.
 append i_zci_command to e_command_list.
 clear i_zci_command.
 catch cx_sy_dyn_call_error.
 endtry. 
 endloop.
endmethod.
endclass.
 
Virtual InfoProvider — Main-Class
 
class zcl_vprov definition 
 public
 create public .public section.
*“* public components of class ZCL_VPROV 
*“* do not include other source files here!!!   class-methods get_info_from_chanm
 importing 
!i_chanm
 type rsdri_s_sfcchanm
 exporting 
!e_typenm
 type string
!e_zalias
 type string
 exceptions 
er_zalias .
 class-methods get_info_from_kyfnm
 importing 
!i_kyfnm
 type rsdri_s_sfkkyfnm
 exporting 
!e_typenm
 type string
!e_zalias
 type string
 exceptions 
er_zalias .
 class-methods get_alias_from_chanm
 importing 
!i_chanm
 type rsdri_s_sfcchanm
returning
 value (r_zalias) type string
 exceptions 
er_zalias .
 class-methods get_alias_from_kyfnm
 importing 
!i_kyfnm
 type rsdri_s_sfkkyfnm
returning
 value (e_zalias) type string
 exceptions 
er_zalias .
 methods get_norm_struct
returning
 value (e_alias_struct) type ref to cl_abap_structdescr .
 methods define
 importing 
!i_infoprov
 type rsinfoprov
!i_th_sfc
 type rsdri_th_sfc
!i_th_sfk
 type rsdri_th_sfk
!i_t_range
 type rsdri_t_range
!i_tx_rangetab
 type rsdri_tx_rangetab
 value (i_keydate) type rrsrdate default sydatum
 value (i_maxrows) type i
 value (i_use_aggregation) type rs_bool default rs_c_true
!i_th_sfc_add
 type rsdri_th_sfc optional .
 methods read
 importing 
 value (i_packagesize) type i default 100000
 value (i_show_statement) type rs_bool default rs_c_false
 exporting 
!e_t_data
 type standard table 
!e_end_of_data
 type rs_bool
!e_t_msg
 type rs_t_msg
 exceptions 
error .
*“* protected components of class ZCL_VPROV 
*“* do not include other source files here!!! 
protected section.  data infoprov type rsinfoprov .
 data th_sfc type rsdri_th_sfc .
 data th_sfk type rsdri_th_sfk .
 data t_range type rsdri_t_range .
 data keydate type rrsrdate .
 data maxrows type i . 
 data use_aggregation type rs_bool .
 data infoprov_th_sfc type rsdri_th_sfc .
 data infoprov_th_sfk type rsdri_th_sfk .
 data infoprov_t_range type rsdri_t_range .
 data t_alias_mapping type zwht_alias_mapping .
 data t_command_list type zt_command_list .  methods modify_range_tables .
*“* private components of class ZCL_VPROV 
*“* do not include other source files here!!! 
private section. data t_data type t_cube_struct .

methods set_new_cha
 changing 
!itab
 type ref to data . 
endclass.class zcl_vprov implementation. * <SIGNATURE>—————————————————————————————+
* | Instance Public Method ZCL_VPROV->DEFINE 
* +————————————————————————————————-+
* | [—>] I_INFOPROV                     TYPE        RSINFOPROV 
* | [—>] I_TH_SFC                       TYPE        RSDRI_TH_SFC 
* | [—>] I_TH_SFK                       TYPE        RSDRI_TH_SFK 
* | [—>] I_T_RANGE                      TYPE        RSDRI_T_RANGE 
* | [—>] I_TX_RANGETAB                  TYPE        RSDRI_TX_RANGETAB 
* | [—>] I_KEYDATE                      TYPE        RRSRDATE (default =SY-DATUM)
* | [—>] I_MAXROWS                      TYPE        I 
* | [—>] I_USE_AGGREGATION              TYPE        RS_BOOL (default =RS_C_TRUE)
* | [—>] I_TH_SFC_ADD                   TYPE        RSDRI_TH_SFC(optional)
* +————————————————————————————–</SIGNATURE>
method define.
*——————————————————————–* 
 “ set Attributes 
infoprov
 = i_infoprov .
keydate
 = i_keydate .
maxrows
 = i_maxrows .
th_sfc
 = i_th_sfc .
th_sfk
 = i_th_sfk .
t_range
 = i_t_range .
use_aggregation
 = i_use_aggregation .
*——————————————————————–*

call method zcl_virtual_command_factory=> get_list
 exporting 
i_t_range     
 = i_t_range
 importing 
e_command_list
 = me->t_command_list
 changing 
c_th_sfc      
 = th_sfc
c_th_sfk      
 = th_sfk.

*——————————————————————–*

modify_range_tables( ) .
*——————————————————————–*

endmethod.
* <SIGNATURE>—————————————————————————————+
* | Static Public Method ZCL_VPROV=>GET_ALIAS_FROM_CHANM 
* +————————————————————————————————-+
* | [—>] I_CHANM                        TYPE        RSDRI_S_SFC-CHANM 
* | [<-()] R_ZALIAS                       TYPE        STRING 
* | [EXC!] ER_ZALIAS 
* +————————————————————————————–</SIGNATURE>
method get_alias_from_chanm.

* just a returning wrapper! 
 call method zcl_vprov=> get_info_from_chanm
 exporting 
i_chanm  
 = i_chanm
 importing 
*    e_typenm  = 
e_zalias 
 = r_zalias
 exceptions 
er_zalias
 = 1
 others    = 2
.
 if sy subrc <> 0.
 raise er_zalias.
 endif.endmethod.

* <SIGNATURE>—————————————————————————————+
* | Static Public Method ZCL_VPROV=>GET_ALIAS_FROM_KYFNM 
* +————————————————————————————————-+
* | [—>] I_KYFNM                        TYPE        RSDRI_S_SFK-KYFNM 
* | [<-()] E_ZALIAS                       TYPE        STRING 
* | [EXC!] ER_ZALIAS 
* +————————————————————————————–</SIGNATURE>
method get_alias_from_kyfnm.
*  * just a wraopper for returning 
 call method zcl_vprov=> get_info_from_kyfnm
 exporting 
i_kyfnm  
 = i_kyfnm
 importing 
*     e_typenm  = 
e_zalias 
 = e_zalias
 exceptions 
er_zalias
 = 1
 others    = 2
.
 if sy subrc <> 0.
 raise er_zalias.
 endif.endmethod.* <SIGNATURE>—————————————————————————————+
* | Static Public Method ZCL_VPROV=>GET_INFO_FROM_CHANM 
* +————————————————————————————————-+
* | [—>] I_CHANM                        TYPE        RSDRI_S_SFC-CHANM 
* | [<—] E_TYPENM                       TYPE        STRING 
* | [<—] E_ZALIAS                       TYPE        STRING 
* | [EXC!] ER_ZALIAS 
* +————————————————————————————–</SIGNATURE>
method get_info_from_chanm.
 data: l_moff  type i , 
l_len  
 type i , 
l_typenm
 type string,
l_zalias
 type string ,
l_chanm
 type string ,
l_nav
 type c length 2 .
*——————————————————————–* 
“ Import
l_chanm
 = i_chanm .
*——————————————————————–* 
“ Calculaction
  find ‚__‘ in l_chanm “ navi-attribute ? 
match offset l_moff .
 if sy subrc = 0 . “ take navi-attribute infoobject-name 
l_moff
 = l_moff + 2 .
l_len
 = strlen( l_chanm )  l_moff .
l_chanm
 = l_chanm+l_moff(l_len ) .
l_nav
 = ‚__‘ .
 endif .

if strlen( l_chanm ) <= 17 . 
 concatenate ‚Y‘ l_nav l_chanm into l_zalias . „zalias 
 else .
 raise er_zalias .
 endif .

if l_chanm( 1) = ‚0‘ . “ 0CALMONTH ? type is /BI0/OICALMONTH 
l_len
 = strlen( l_chanm )  1 . 
 concatenate ‚/BI0/OI‘ l_chanm+1( l_len) into l_typenm .
 else.
 concatenate ‚/BIC/OI‘ l_chanm into l_typenm .
 endif .*——————————————————————–* 
“ Export
e_typenm
 = l_typenm .
e_zalias
 = l_zalias .

endmethod.

* <SIGNATURE>—————————————————————————————+
* | Static Public Method ZCL_VPROV=>GET_INFO_FROM_KYFNM 
* +————————————————————————————————-+
* | [—>] I_KYFNM                        TYPE        RSDRI_S_SFK-KYFNM 
* | [<—] E_TYPENM                       TYPE        STRING 
* | [<—] E_ZALIAS                       TYPE        STRING 
* | [EXC!] ER_ZALIAS 
* +————————————————————————————–</SIGNATURE>
method get_info_from_kyfnm.
 data: l_moff  type i , 
l_len  
 type i , 
l_typenm
 type string,
l_zalias
 type string ,
l_kyfnm
 type string .
*——————————————————————–* 
 “ Import 
l_kyfnm
 = i_kyfnm .
*——————————————————————–* 
 “ Berechnung 
 if l_kyfnm( 1) = ‚0‘ . “ für 0* usw. type ist /BI0/OI* 
l_len
 = strlen( l_kyfnm )  1 . 
 concatenate ‚/BI0/OI‘ l_kyfnm+1( l_len) into l_typenm .
 else.
 concatenate ‚/BIC/OI‘ l_kyfnm into l_typenm .
 endif .
 if strlen( l_kyfnm ) <= 17 . 
 concatenate ‚Y‘ l_kyfnm into l_zalias .
 else .
 raise er_zalias .
 endif .
*——————————————————————–* 
 “ Export 
e_typenm
 = l_typenm .
e_zalias
 = l_zalias .

endmethod.

* <SIGNATURE>—————————————————————————————+
* | Instance Public Method ZCL_VPROV->GET_NORM_STRUCT 
* +————————————————————————————————-+
* | [<-()] E_ALIAS_STRUCT                 TYPE REF TO CL_ABAP_STRUCTDESCR
* +————————————————————————————–</SIGNATURE>
method get_norm_struct.
 field-symbols: <sfc> type rsdri_s_sfc ,
<sfk>
 type rsdri_s_sfk .
 data: l_typenm type string ,
l_zalias
 type string ,
l_comp_tab
 type abap_component_tab ,
wa_comp_tab
 type line of abap_component_tab ,
wa_sfc
 type rsdri_s_sfc ,
wa_sfk
 type rsdri_s_sfk ,
wa_alias_mapping
 type line of zwht_alias_mapping .

data: l_nm type string .
 data: l_len type i . 
 data: l_moff type i .

loop at th_sfc assigning <sfc>.
get_info_from_chanm
( 
 exporting 
i_chanm 
 = <sfc>chanm
 importing 
e_typenm
 = l_typenm
e_zalias
 = l_zalias )
.
wa_comp_tab
 name = l_zalias .
wa_comp_tab
 type ?= cl_abap_typedescr=> describe_by_name( l_typenm ) .
 append wa_comp_tab to l_comp_tab .
 clear wa_sfc .
wa_sfc
 chaalias = l_zalias .
 modify infoprov_th_sfc from wa_sfc transporting chaalias
 where chanm = <sfc> chanm .
 if sy subrc <> 0. “ weiter 
 endif . 
 if <sfc> chaalias is not initial .
 clear wa_alias_mapping .
wa_alias_mapping
 name = <sfc> chanm .
wa_alias_mapping
 alias = <sfc> chaalias .
wa_alias_mapping
 zalias = l_zalias .
 append wa_alias_mapping to t_alias_mapping .
 endif . 
 endloop .

loop at th_sfk assigning <sfk>.
get_info_from_kyfnm
( 
 exporting 
i_kyfnm 
 = <sfk>kyfnm
 importing 
e_typenm
 = l_typenm
e_zalias
 = l_zalias )
.
wa_comp_tab
 name = l_zalias .
wa_comp_tab
 type ?= cl_abap_typedescr=> describe_by_name( l_typenm ) .
 append wa_comp_tab to l_comp_tab .
 clear wa_sfk .
wa_sfk
 kyfalias = l_zalias .
 modify infoprov_th_sfk from wa_sfk transporting kyfalias
 where kyfnm = <sfk> kyfnm .
 if sy subrc <> 0. “ weiter 
 endif . 
 if <sfk> kyfalias is not initial .
 clear wa_alias_mapping .
wa_alias_mapping
 name = <sfk> kyfnm .
wa_alias_mapping
 alias = <sfk> kyfalias .
wa_alias_mapping
 zalias = l_zalias .
 append wa_alias_mapping to t_alias_mapping .
 endif . 
 endloop .  e_alias_struct

= cl_abap_structdescr=>create ( p_components = l_comp_tab ) .endmethod.

* <SIGNATURE>—————————————————————————————+
* | Instance Protected Method ZCL_VPROV->MODIFY_RANGE_TABLES 
* +————————————————————————————————-+
* +————————————————————————————–</SIGNATURE>
method modify_range_tables.
 data: wa_sfc type rsdri_s_sfc ,
wa_sfk
 type rsdri_s_sfk ,
l_infoprov_struct_name
 type string ,
ddic
 type dd_x031l_table, „Datadictonary for later use
wa_ddic
 type line of dd_x031l_table ,
descr_ref
 type ref to cl_abap_structdescr .
 field-symbols:
<sfc_zeile>
 type rsdri_s_sfc,
<sfk_zeile>
 type rsdri_s_sfk,
<range_zeile>
 type rsdri_s_range .

concatenate ‚/BIC/V‘ infoprov ‚J‘ into l_infoprov_struct_name .
descr_ref ?= cl_abap_structdescr
=> describe_by_name( l_infoprov_struct_name ).
 „Struktur-Objekt der zu lesenden Objekte lesen 
ddic
 = descr_ref-> get_ddic_object( ) . “ DDic Beschreibung auslesen 
*——————————————————————–* 
 “ Merkmale, die nicht in INFOPROV sind, aus INFOPROV_th_sfc löschen 
infoprov_th_sfc
 = th_sfc .
 loop at infoprov_th_sfc assigning <sfc_zeile> .
 read table ddic with key fieldname = <sfc_zeile> chanm
 into wa_ddic transporting fieldname .
 if sy subrc <> 0 .
 find ‚__‘ in <sfc_zeile> chanm .
 if sysubrc <> 0 .
 delete infoprov_th_sfc where chanm = <sfc_zeile> chanm .
 endif . 
 endif . 
 endloop .
*——————————————————————–* 
 “ Kennzahlen, die nicht in INFOPROV sind, aus INFOPROV_th_sfk löschen 
infoprov_th_sfk
 = th_sfk .

delete infoprov_th_sfk where kyfnm = ‚1ROWCOUNT‘. 
 delete th_sfk where kyfnm = ‚1ROWCOUNT‘.

loop at infoprov_th_sfk assigning <sfk_zeile> .
 read table ddic with key fieldname = <sfk_zeile> kyfnm
 into wa_ddic transporting fieldname .
 if sy subrc <> 0 .
 find ‚__‘ in <sfk_zeile> kyfnm .
 if sysubrc <> 0 .
 delete infoprov_th_sfk where kyfnm = <sfk_zeile> kyfnm .
 endif . 
 endif . 
 endloop .*——————————————————————–* 
 “ 
infoprov_t_range
 = t_range .
 loop at infoprov_t_range assigning <range_zeile> .
 read table ddic with key fieldname = <range_zeile> chanm
 into wa_ddic transporting fieldname .
 if sy subrc <> 0 .
 find ‚__‘ in <range_zeile> chanm .
 if sysubrc <> 0 .
 delete infoprov_t_range where chanm = <range_zeile> chanm .
 endif . 
 endif . 
 endloop .endmethod.

* <SIGNATURE>—————————————————————————————+
* | Instance Public Method ZCL_VPROV->READ 
* +————————————————————————————————-+
* | [—>] I_PACKAGESIZE                  TYPE        I (default =100000)
* | [—>] I_SHOW_STATEMENT               TYPE        RS_BOOL (default =RS_C_FALSE)
* | [<—] E_T_DATA                       TYPE        STANDARD TABLE 
* | [<—] E_END_OF_DATA                  TYPE        RS_BOOL 
* | [<—] E_T_MSG                        TYPE        RS_T_MSG 
* | [EXC!] ERROR 
* +————————————————————————————–</SIGNATURE>
method read.
 type-pools: rsdrc, abap .
 data:  c_first_call type  rs_bool ,
r_new_tabd  
 type ref to cl_abap_tabledescr,
r_itab      
 type ref to data ,
r_f_itab    
 type ref to data ,
r_new_str   
 type ref to cl_abap_structdescr .

field-symbols: <itab>      type standard table ,
<f_itab>   
 type standard table .  r_new_str

= get_norm_struct( ) . 
r_new_tabd
 = cl_abap_tabledescr=> create( p_line_type = r_new_str ) . 
 create data r_itab type handle r_new_tabd .
 assign r_itab-> * to <itab> .

create data r_f_itab type handle r_new_tabd .
 assign r_f_itab-> * to <f_itab> .

while e_end_of_data = “ .
 call function ‚RSDRI_INFOPROV_READ‘
 exporting 
i_infoprov   
 = infoprov
i_th_sfc     
 = infoprov_th_sfc
i_th_sfk     
 = infoprov_th_sfk
i_reference_date
 = keydate
i_t_range    
 = infoprov_t_range
i_packagesize
 = i_packagesize
 importing 
e_t_data     
 = <itab>
e_end_of_data
 = e_end_of_data
 changing 
c_first_call 
 = c_first_call.
 if sy subrc ne 0. 
e_end_of_data
 = ‚X‘.
 raise error.
 else . 
 insert lines of <itab> into table <f_itab> .
 endif. 
 endwhile .
*——————————————————————–*

set_new_cha( changing itab = r_f_itab ) .

*——————————————————————–* 
 field-symbols: <f_itab_zeile> type any , 
<sfc_zeile>
 type rsdri_s_sfc ,
<c_t_data>
 like e_t_data,
<sfk_zeile>
 type rsdri_s_sfk ,
<alias_mapping_zeile>
 type line of zwht_alias_mapping ,
<new_line>
 type any ,
<q>       
 type any , „quelle
<z>       
 type any . „ziel

data: new_line     type ref to data , 
c_t_data
 type ref to data, 
wa_sfc
 type rsdri_s_sfc,
wa_sfk
 type rsdri_s_sfk
.
create data c_t_data like e_t_data.
assign c_t_data-> * to <c_t_data>.

loop at <f_itab> assigning <f_itab_zeile> .
 create data new_line like line of e_t_data .
 assign new_line->* to <new_line> .
 append <new_line> to <c_t_data> assigning <new_line> .
 loop at t_alias_mapping assigning <alias_mapping_zeile> .
 assign component <alias_mapping_zeile>alias of structure <new_line> to <z> .
 assign component <alias_mapping_zeile>zalias of structure <f_itab_zeile> to <q> .
<z>
 = <q> .
 endloop . 
 endloop .
e_t_data[]
 = <c_t_data>[].

endmethod.

* <SIGNATURE>—————————————————————————————+
* | Instance Private Method ZCL_VPROV->SET_NEW_CHA 
* +————————————————————————————————-+
* | [<–>] ITAB                           TYPE REF TO DATA 
* +————————————————————————————–</SIGNATURE>
method set_new_cha.

“ generierte Kommandos für virtuelle Merkmale und Kennzahlen durchlaufen
 data: c_command type ref to zci_virtual_object_command.

loop at me-> t_command_list into c_command.
 call method c_command->execute
 changing 
c_t_data
 = itab .
 endloop.endmethod.
endclass.

Interface Virtual Command Object
*“* components of interface ZCI_VIRTUAL_OBJECT_COMMAND 
interface zci_virtual_object_command
 public .  class-methods get_instance
 importing 
!i_t_range
 type rsdri_t_range
 exporting 
!e_self
 type ref to zci_virtual_object_command
 changing 
!c_th_sfc
 type rsdri_th_sfc
!c_th_sfk
 type rsdri_th_sfk .
 methods execute
 changing 
!c_t_data
 type ref to data . 
endinterface.
 
Example-Objekt  Top A,B,C depending on selection
 
class zcl_vi_zmakm001 definition 
 public
final
 create public .*“* public components of class ZCL_VI_ZMYM001 
*“* do not include other source files here!!! 
public section.  interfaces zci_virtual_object_command .  aliases execute
 for zci_virtual_object_command~execute .
 aliases get_instance
 for zci_virtual_object_command~get_instance .  data c_th_sfc type rsdri_th_sfc .
 data c_th_sfk type rsdri_th_sfk .
*“* protected components of class ZCL_VI_ZMYM001 
*“* do not include other source files here!!! 
protected section. data i_t_range type rsdri_t_range .
*“* private components of class ZCL_VI_ZMYM001 
*“* do not include other source files here!!! 
private section.

constants z0calmonth type string value ‚0CALMONTH‘. „#EC NOTEXT
endclass.

class zcl_vi_zmym001 implementation.

* <SIGNATURE>—————————————————————————————+
* | Instance Public Method ZCL_VI_ZMYM001->ZCI_VIRTUAL_OBJECT_COMMAND~EXECUTE
* +————————————————————————————————-+
* | [<–>] C_T_DATA                       TYPE REF TO DATA 
* +————————————————————————————–</SIGNATURE>
method zci_virtual_object_command~ execute.
 
 field-symbols:
<c_t_data>
 type standard table,
<line_of_data>
 type any .

assign c_t_data-> * to <c_t_data>.
 if sy subrc ne 0. 
*    raise not_compatible_exception. 
 endif.

data: zvolume type rsdri_s_sfk,
zcountry
 type rsdri_s_sfc,
zneo_m024
 type rsdri_s_sfc,
calmonth
 type rsdri_s_sfc,
zmakm001
 type rsdri_s_sfc,
alias
 type string.„,
“ Für dynamischen sort 
*        sort_tab TYPE abap_sortorder_tab, 
*        sort_line TYPE abap_sortorder.

„!!! ACHTUNG REIHENFOLGE VERÄNDERT SORTIERUNG UND DAMIT LOGIK!!!!!!!

“ Für jeden Monat seperat. 
calmonth
chanm = z0calmonth.
 call method zcl_vprov=> get_info_from_chanm(
 exporting i_chanm   = calmonth chanm
 importing e_zalias  = alias ).
calmonth
chaalias = alias. clear alias.
*  sort_line-name = calmonth-chaalias. sort_line-descending = “. „Absteigend! Neueste zuerst – default
*  APPEND sort_line TO sort_tab. CLEAR sort_line.

“ Nach Martklassifizierung 
zneo_m024
chanm = zzneo_m024.
 call method zcl_vprov=> get_info_from_chanm(
 exporting i_chanm   = zneo_m024 chanm
 importing e_zalias  = alias ).
zneo_m024
chaalias = alias. clear alias.
*  sort_line-name = zneo_m024-chaalias. sort_line-descending = “. „Aufsteigend! A Markt zuerst
*  APPEND sort_line TO sort_tab. CLEAR sort_line.

“ Nach Volumen 
zvolume
kyfnm = zzvolumen.
 call method zcl_vprov=> get_info_from_kyfnm(
 exporting i_kyfnm = zvolume kyfnm
 importing e_zalias  = alias ).
zvolume
kyfalias = alias. clear alias.
*  sort_line-name = zvolume-kyfalias. sort_line-descending = ‚X‘. „Absteigend! Größte zuerst – default
*  APPEND sort_line TO sort_tab. CLEAR sort_line.

“ Nach Land – ist eigentlich nur für den Ausschluss DE|IT in A-Markt interessant
zcountry
chanm = zzcountry.
 call method zcl_vprov=> get_info_from_chanm(
 exporting i_chanm   = zcountry chanm
 importing e_zalias  = alias ).
zcountry
chaalias = alias. clear alias.
*  sort_line-name = zcountry-chaalias. sort_line-descending = “. „Aufsteigend! A Markt zuerst
*  APPEND sort_line TO sort_tab. CLEAR sort_line.

„““ Sortieren 
*  SORT <c_t_data> BY (sort_tab).

“ Virtuelles Merkmal zuweisen 
zmakm001
chanm = zzmakm001.
 call method zcl_vprov=> get_info_from_chanm(
 exporting i_chanm   = zmakm001 chanm
 importing e_zalias  = alias ).
zmakm001
chaalias = alias. clear alias.

„*************************************************************** 
 „Selektion für zmakm001 übernehmen 
 data: sel_tab type range of /bic/oizmakm001,
wa_sel_tab
 like line of sel_tab,
_range
 type rsdri_s_range.

loop at me-> i_t_range into _range where chanm = ‚ZMAKM001‘ .
 move-corresponding _range to wa_sel_tab.
wa_sel_tab
 option = _range compop.
 append wa_sel_tab to sel_tab.
 endloop.
 „***************************************************************

„*************************************************************** 
 field-symbols: <act_month> type any, 
<zneo_m024>
 type any,
<country>
 type any,                 <l_month>

type any,
<l_zneo_m024>
 type any,                 <zmakm001>

type any,
<zvolumen>
 type any.

“ Gruppensumme Monat, Markt Land, Exposure bilden 
 data: t_gruppensumme type ztszmakm001,
wa_grs 
 type zszmakm001.
 loop at <c_t_data> assigning <line_of_data>.
 assign component calmonthchaalias of structure <line_of_data> to <act_month>.
 assign component zneo_m024chaalias of structure <line_of_data> to <zneo_m024>.
 assign component zcountrychaalias of structure <line_of_data> to <country>.
 assign component zvolumekyfalias of structure <line_of_data> to <zvolumen>.
wa_grs
 0calmonth = <act_month>.
wa_grs
 zneo_m024 = <zneo_m024>.
wa_grs
 zcountry = <country>.
wa_grs
 zvolumen = <zvolumen>.
 collect wa_grs into t_gruppensumme.
unassign: <act_month>, <zneo_m024>, <country>, <zvolumen>.
 clear wa_grs.
 endloop.
 “ Nach Maximum sortieren 
 sort t_gruppensumme by 0calmonth
zneo_m024
*                         zcountry 
zvolumen
 descending.

“ Nur Maximum behalten – bei A Markt DE und IT rauswerfen 
 data: l_month like wa_grs0calmonth,
amonth
 like wa_grs0calmonth,
l_m024
 like wa_grszneo_m024,
a_m024
 like wa_grszneo_m024.

loop at t_gruppensumme into wa_grs.
amonth
 = wa_grs0calmonth.
a_m024
 = wa_grszneo_m024.
 if ( wa_grs zneo_m024 eq ‚A‘ ) and 
 ( wa_grszcountry eq ‚DE‘ or wa_grszcountry eq ‚IT‘ ). 
 delete t_gruppensumme.
 continue. 
 endif. 
 if ( amonth eq l_month ) and ( l_m024 eq a_m024 ). 
 delete t_gruppensumme index sy tabix.
 else. 
l_month
 = amonth.
l_m024
 = a_m024.
 endif. 
 endloop.

data: l_line like sytabix.
 “ Zuweisen der Ergebniss-Länder 
 loop at <c_t_data> assigning <line_of_data>.
l_line
 = sytabix.
 “ Zur Veränderung 
 assign component zmakm001chaalias of structure <line_of_data> to <zmakm001>.
 “ Zum lesen: 
 assign component calmonthchaalias of structure <line_of_data> to <act_month>.
 assign component zneo_m024chaalias of structure <line_of_data> to <zneo_m024>.
 assign component zcountrychaalias of structure <line_of_data> to <country>.

read table t_gruppensumme with
 table key 0calmonth = <act_month>
zneo_m024
 = <zneo_m024>
zcountry 
 = <country>
 transporting no fields. „Read Table verändert sy-tabix 
 if sy subrc eq 0. 
 concatenate <zneo_m024> ‚J‘ into <zmakm001>.
 endif.

if      ( sel_tab is not initial )
 and ( <zmakm001> not in sel_tab ). “ Filterkriterien überprüfen 
 delete <c_t_data> index l_line. “ Wenn nicht in Selektion – dann löschen*      Innerhalb einer LOOP -Schleife kann der Zusatz INDEX weggelassen werden.
*      Dann wird die aktuelle Tabellenzeile der LOOP-Schleife gelöscht. 
*      Wenn aber die aktuelle Zeile im gleichen Schleifendurchgang schon 
*      einmal gelöscht wurde, ist das Verhalten undefiniert.

endif. 
 endloop.
 „*************************************************************** endmethod.* <SIGNATURE>—————————————————————————————+
* | Static Public Method ZCL_VI_ZMAKM001=>ZCI_VIRTUAL_OBJECT_COMMAND~GET_INSTANCE
* +————————————————————————————————-+
* | [—>] I_T_RANGE                      TYPE        RSDRI_T_RANGE 
* | [<—] E_SELF                         TYPE REF TO ZCI_VIRTUAL_OBJECT_COMMAND
* | [<–>] C_TH_SFC                       TYPE        RSDRI_TH_SFC 
* | [<–>] C_TH_SFK                       TYPE        RSDRI_TH_SFK 
* +————————————————————————————–</SIGNATURE>
method zci_virtual_object_command~ get_instance.
 „Top ABC benötigt: 
 “ ZCOUNTRY Land 
 “ ZCOUNTRY__ZNEO_M024 Markt-Klassifizierung als Navigationselement an Land ?0country?
 “ ZVOLUMEN – Kennzahl

data: wa_ type rsdri_s_sfc.

“ Eigentlich sollte Monat immer vorhanden sein – aber zur späteren Codesicherheit:
 read table c_th_sfc into wa_ with key chanm = z0calmonth.
 if sy subrc ne 0. 
wa_
 chanm = z0calmonth.
 insert wa_ into table c_th_sfc.
 endif.

„Land 
 clear wa_. “ Wichtig da sonst ein falsches Mapping gebildet werden kann und die Query
 “ ein leeres Ergebnis zurückliefert. 
 read table c_th_sfc into wa_ with key chanm = zzcountry.
 if sy subrc ne 0. 
wa_
 chanm = zzcountry.
 insert wa_ into table c_th_sfc.
 endif.
 clear wa_.

„Markt-Klassifizierung 
 clear wa_. “ Wichtig da sonst ein falsches Mapping gebildet werden kann und die Query
 “ ein leeres Ergebnis zurückliefert. 
 read table c_th_sfc into wa_ with key chanm = zzneo_m024.
 if sy subrc ne 0. 
wa_
 chanm = zzneo_m024.
 insert wa_ into table c_th_sfc.
 endif.

„Exposure 
 data: wak_ type rsdri_s_sfk.
 read table c_th_sfk into wak_ with key kyfnm = zzvolumen.
 if sy subrc ne 0. 
wak_
 kyfnm = zzvolumen.
 insert wak_ into table c_th_sfk.
 endif.
 clear wak_.

data: self type ref to zcl_vi_zmakm001.
 create object self.  self

->c_th_sfc = c_th_sfc.
self
->c_th_sfk = c_th_sfk.
self
->i_t_range = i_t_range.

e_self

= self.

endmethod.
endclass.

 
How to use Virtual InfoProviders in SAP BI / BW