0% found this document useful (0 votes)
291 views

BADI Snippets

The document provides code snippets for interacting with SAP BPC data from ABAP. Snippet 1 reads dimension master data. Snippet 2 reads child members of a parent node. Snippet 3 reads application transaction data and loads it into a dynamic table. Snippet 4 writes data back to the application. Snippet 5 reads all parent nodes for a given base member from a dimension hierarchy.

Uploaded by

sivakumar7
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
291 views

BADI Snippets

The document provides code snippets for interacting with SAP BPC data from ABAP. Snippet 1 reads dimension master data. Snippet 2 reads child members of a parent node. Snippet 3 reads application transaction data and loads it into a dynamic table. Snippet 4 writes data back to the application. Snippet 5 reads all parent nodes for a given base member from a dimension hierarchy.

Uploaded by

sivakumar7
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

Applies to: 1) SAP BPC projects migrating from MS version to 7.X NW version. 2) New development on SAP BPC 7.

X NW version.

Summary: The article explains few code snippets which interface with the backend SAP BI system to retrieve or write-back the required BPC data.

Prerequisites: Nascent knowledge of SAP BPC 7.X NW tool, in particular the coding conventions applicable in *.LGF file. Understanding of basic Object-oriented (OOPS) ABAP.

Introduction: A LGF level logic which is required to process large volume of application records will in most likeliness perform better when implemented in ABAP rather than employing the same logic through *.LGF file completely. The ABAP level logic is invoked by calling the BAdI. For more information on BAdI, please refer the following link: SAP Library - Enhancement Framework

To save the extra time overhead in read of application data whenever QUERY is set to ON in START_BADI... END_BADI construct, this parameter can be set to OFF and an equivalent ABAP logic can then fetch the application data. This way the code executes much faster. This kind of code snippet and few more are described below.

Code Snippet # 1

The below code reads a certain dimension's master data

DATA: lo_dim TYPE REF TO cl_uja_dim, lr_dim_data TYPE REF TO if_uja_dim_data, lt_attr_name TYPE uja_t_attr_name, lt_sel TYPE uj0_t_sel, ls_sel TYPE uj0_s_sel, lr_data TYPE REF TO data, ls_emp TYPE REF TO data. FIELD-SYMBOLS: <lt_emp> TYPE STANDARD TABLE, <ls_emp> TYPE ANY. ***Construct to generate the EMPLOYEE data from dimension library REFRESH: lt_attr_name, lt_sel. CLEAR: ls_sel. TRY .

CREATE OBJECT lo_dim EXPORTING i_appset_id = i_appset_id i_dimension = 'EMPLOYEE'. CATCH cx_uja_admin_error . ENDTRY. lr_dim_data = lo_dim. " Append the list of attribute(s) for which the master data is generated APPEND: 'ID' TO lt_attr_name. " Bind the condition data to lt_sel table, this will become selection criteria " analogous to the WHERE clause of a DB SELECT statement ls_sel-dimension = 'EMPLOYEE'. ls_sel-attribute = 'CALC'. ls_sel-sign = 'I'. ls_sel-option = 'EQ'. ls_sel-low = 'N'. APPEND ls_sel TO lt_sel. " GET DIMENSION MEMBERS TRY. CALL METHOD lr_dim_data->read_mbr_data EXPORTING it_attr_list = lt_attr_name "attribute list it_sel = lt_sel "condition data IMPORTING er_data = lr_data. "reference of master data table CATCH cx_uja_admin_error . ENDTRY. "Assign the referenced memory area to a field-symbol ASSIGN lr_data->* TO <lt_emp>. CREATE DATA ls_emp LIKE LINE OF <lt_emp>. ASSIGN ls_emp->* TO <ls_emp>. ***End of construct

Points to note: read_mbr_data method reads the relevant master data from dimension library. In addition tolt_attr_name and lt_sel, developer has options to give a particular hierarchy, or specify if only base members are required to be pulled. Code Snippet # 2 The below code reads child members of a parent node from the hierarchy of dimension's master data

DATA: lo_dim TYPE REF TO cl_uja_dim, lr_dim_data TYPE REF TO if_uja_dim_data, lt_base_en TYPE uja_t_dim_member. TRY. CREATE OBJECT lo_dim

EXPORTING i_appset_id = i_appset_id i_dimension = 'ENTITY'. CATCH cx_uja_admin_error. ENDTRY. lr_dim_data = lo_dim.

"GET THE CHILD NODES CALL METHOD lr_dim_data->get_children_mbr EXPORTING i_parent_mbr = 'ENT_PAR01' if_only_base_mbr = 'X' IMPORTING et_member = lt_base_en. Points to note: If if_only_base_mbr parameter is left blank then all the intermediate hierarchy level nodes are fetched inlt_base_en.

Code Snippet # 3

The below code reads an applications transaction data and puts in a dynamic internal table

DATA: lt_sel TYPE uj0_t_sel, ls_sel TYPE uj0_s_sel, ls_cv TYPE ujk_s_cv, lo_appl TYPE REF TO cl_uja_application, lt_appl_dim TYPE uja_t_appl_dim, ls_appl_dim LIKE LINE OF lt_appl_dim, lt_dim_name TYPE ujq_t_dim, ls_dim_name LIKE LINE OF lt_dim_name, lo_model TYPE REF TO if_uj_model, lo_dataref TYPE REF TO data. FIELD-SYMBOLS: <lt_tx_data> TYPE STANDARD TABLE.

*** Get structure of application data table**** CREATE OBJECT lo_appl EXPORTING i_appset_id = i_appset_id "input parameter of method i_application_id = i_appl_id. "input parameter of method

* Getting all dimensions for the given application and appset REFRESH lt_appl_dim.

lo_appl->get_appl_dim( EXPORTING i_appl_id = i_appl_id IMPORTING et_appl_dim = lt_appl_dim ). * populate internal table for SQE call REFRESH lt_dim_name. LOOP AT lt_appl_dim INTO ls_appl_dim. ls_dim_name = ls_appl_dim-dimension. APPEND ls_dim_name TO lt_dim_name. ENDLOOP. * Including MEASURES dimension in table structure ls_dim_name = 'MEASURES'. APPEND ls_dim_name TO lt_dim_name. SORT lt_dim_name. * Get the structure of the result TRY. lo_model = cl_uj_model=>get_model( i_appset_id ). lo_model->create_tx_data_ref( EXPORTING i_appl_name = i_appl_id i_type = 'T' it_dim_name = lt_dim_name if_tech_name = space IMPORTING er_data = lo_dataref ). CATCH cx_uj_static_check. ENDTRY. * Assigning the structure to table ASSIGN lo_dataref->* TO <lt_tx_data>. "Generating application data with below filter set REFRESH lt_sel. CLEAR ls_sel. ls_sel-dimension = 'RPTCURRENCY'. ls_sel-low = 'LC'. APPEND ls_sel TO lt_sel. " Reading the time values passed from the LGF script that calls this BAdI ls_sel-dimension = 'TIME'. READ TABLE it_cv INTO ls_cv WITH KEY dimension = 'TIME'. IF sy-subrc = 0. LOOP AT ls_cv-member INTO ls_dim_member. ls_sel-low = ls_dim_member. APPEND ls_sel TO lt_sel. CLEAR ls_dim_member. ENDLOOP. ENDIF. REFRESH <lt_tx_data>.

TRY. "module call to populate the data records CALL FUNCTION 'UJQ_RUN_RSDRI_QUERY' EXPORTING i_appset_id = i_appset_id i_appl_id = i_appl_id it_dim_name = lt_dim_name if_check_security = abap_false it_sel = lt_sel "condition data IMPORTING et_data = <lt_tx_data>. CATCH cx_ujq_exception. ENDTRY. Points to note: UJQ_RUN_RSDRI_QUERY reads the application data only for the base level values of the dimensions and the function module cant fetch the aggregated transaction data at parent level

Code Snippet # 4 The below code push (write) the data back to the application

DATA: l_count TYPE i, l_incr TYPE i, l_index1 TYPE p, l_index2 TYPE p. DATA: rf_context_ro lo_wb_main_int context_ro wa_cl_uje_user wa_user wa_work_status gi_message log lt_dataref ls_dataref lo_ref

TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE

REF REF REF REF

if_uj_context, cl_ujr_write_back, if_uj_context, cl_uje_user, uj0_s_user, ujr_s_work_status, uj0_t_message, string, REF TO data, REF TO data, REF TO cx_root.

TO TO TO TO

***Logic to process the ct_data*** " The logic processes ct_data, ct_data is refreshed and the generated output is appended back to ct_data " If write is set to OFF in the call to BAdI, " the new ct_data will now be required to be written back explicitly through ABAP ***Logic to process the ct_data ends*** IF ct_data[] IS NOT INITIAL. " Check to make sure the buffer is not empty * Get the current context details CALL METHOD cl_uj_context=>get_cur_context RECEIVING ro_context = context_ro. context_ro->switch_to_srvadmin( ). * Assign the user details wa_user = context_ro->ds_user. TRY. CALL METHOD cl_uj_context=>set_cur_context EXPORTING i_appset_id = i_appset_id is_user = wa_user i_appl_id = i_appl_id i_module_name = context_ro->d_calling_module. CATCH cx_uj_obj_not_found .

ENDTRY. wa_work_status-module_id = cl_ujk_model=>g_module_id. DESCRIBE TABLE ct_data LINES l_count. l_incr = 0. DO . "40000 number based on PACKAGE_SIZE parameter of UJR_PARAM table l_index1 = 40000 * l_incr + 1. l_incr = l_incr + 1. l_index2 = 40000 * l_incr. IF l_count < l_index2. " lt_tab_1 declared static internal table having identical structure as that of ct_data REFRESH lt_tab_1. APPEND LINES OF ct_data FROM l_index1 TO l_count TO lt_tab_1. ELSE. REFRESH lt_tab_1. APPEND LINES OF ct_data FROM l_index1 TO l_index2 TO lt_tab_1. ENDIF. SORT lt_tab_1. " System takes less time to write to application when the data is sorted TRY. CREATE OBJECT lo_wb_main_int. CALL METHOD lo_wb_main_int->write_back_int EXPORTING is_work_status = wa_work_status i_default_logic = abap_false i_bypass_badi = 'X' i_sign_trans = abap_false it_array = lt_tab_1 i_appl_id = i_appl_id i_appset_id = i_appset_id IMPORTING et_message = gi_message es_status_records = l_status_records. CATCH cx_uj_static_check INTO lo_ref. ENDTRY. IF l_count < l_index2. "Exit the do.. enddo, as the last package is written to the application EXIT. ENDIF. ENDDO. ENDIF.

Points to note: Whenever the data is in process of writing back to application or commiting to DB, the system (based on the filter setting in write-back BAdI) triggers the write-back BAdI. Also the default logic is triggered after the entire process of data save is complete. If this trigger of extra logic is not required, then the write_back_intmethod has i_default_logic and i_bypass_badi as input parameters which can be used to specify to system whether the write-back or the default part should be triggered or not.

Code Snippet # 5 The logic in code snippet # 2 pulls all the base members, immaterial of the level of base members, for a specified parent. Likewise, there is often times a need to read all parents at different levels for a certain base level member. The below code reads all the ascendants for a specified base member from the hierarchy of dimension's master data.

DATA: lo_dim TYPE REF TO cl_uja_dim, lr_dim_data TYPE REF TO if_uja_dim_data, lr_hier_en_data TYPE REF TO if_uja_hier, lt_mbr_name TYPE uja_t_dim_member, lt_mbr_node TYPE uja_t_mbr_node. ***Construct to read all ascendants (parents) of a base member TRY. CREATE OBJECT lo_dim EXPORTING i_appset_id = i_appset_id i_dimension = 'ENTITY'. CATCH cx_uja_admin_error. ENDTRY. lr_dim_data = lo_dim. "get_hier_of_mbr will generate a reference to (BI backend type information of) ENT_BAS01 base member CALL METHOD lr_dim_data->get_hier_of_mbr EXPORTING i_member = 'ENT_BAS01' RECEIVING ro_hier = lr_hier_en_data. "BPC's interface for ENTITY hierarchy CALL METHOD lr_hier_en_data->get_parents EXPORTING i_member = 'ENT_BAS01' if_self = 'X' if_parent_after = 'X' IMPORTING et_mbr_name = lt_mbr_name et_mbr_node = lt_mbr_node. ***End of construct Points to note: lt_mbr_name reads all the hierarchy nodes in an array format. For example: if ENT_BAS01 is at level 4 of the heirarchy with root node being level 1, then lt_mbr_name will have 4 entries containing "ENT_BAS01 and the 3 upper level parents". lt_mbr_node will consist all the hierarchy like information of lt_mbr_name.lt_mbr_node contains columns as MEMBER, PARENT, TLEVEL describing the linkage of base node to its parent(s) within the hierarchy.

Conclusion: The above 4 snippets are of most utility in a typical BPC 7.X NW project. One can explore the CL_UJA_DIM, CL_UJA_APPLICATION, and CL_UJR_WRITE_BACK interfaces (SE24) and implement different methods from it to further customize the requirement in addition to the described code snippets. 2 common parameters in all 4 codes are i_appset_id & i_appl_id and they are the input parameters present in the method of invoked BAdI, specifying the appset and application which triggered the logic originally.

Note: All the ABAP mentioned in this article can be directly utilized in any BPC7.X NW project, but it will require a further change and proper testing to suit the client's requirement.

You might also like