Tuesday, May 12, 2026

Utility Class for reading a decision table

 In order to read a BRF Decision table a utility class can be created.

The Class STATIC Method BRF_READ_TABLE can have the following parameters:

IV_APP TYPE IF_FDT_TYPES=>NAME Application Name

IV_DEC TYPE IF_FDT_TYPES=>NAME Decision Table Name

ET_DYN_OUT TYPE REF TO DATA Export Dynamic Internal Table

The Method can be coded as below:

  METHOD brf_read_table.


    DATAlo_factory        TYPE REF TO          if_fdt_factory.
    DATAlt_table_data     TYPE                 if_fdt_decision_table=>ts_table_data.
    DATAlo_decision_table TYPE REF TO          cl_fdt_decision_table,
          lo_dec_table      TYPE REF TO          if_fdt_decision_table.

    DATA:
      lo_element          TYPE REF TO          cl_fdt_element,
      ls_fdt_dec_tab_stru TYPE cacs_s_fdt_dec_tab_struc,
      lt_dec_tab_struct   TYPE cacs_tt_fdt_dec_tab_struc,

      ls_ddic_info        TYPE dd04v,
      ls_fcat_dec_tab     TYPE lvc_s_fcat,
      lt_fcat_dec_tab     TYPE lvc_t_fcat,
      lv_tab_name         TYPE ddobjname.

    FIELD-SYMBOLS:
                   <fs_data> TYPE REF TO data.

    TYPESBEGIN OF ts_result_data,
             row_no    TYPE int4,
             col_no    TYPE int4,
             value     TYPE string,
             is_result TYPE abap_bool,
           END OF ts_result_data ,

           BEGIN OF ts_dt_column,
             col_name  TYPE string,
             col_type  TYPE string,
             col_no    TYPE int4,
             object_id TYPE if_fdt_types=>id,
           END OF ts_dt_column .

    DATA lt_rule_res_data TYPE TABLE OF ts_result_data,
           ls_rule_res_data TYPE ts_result_data,
           lv_value         TYPE string,
           lt_range         TYPE if_fdt_range=>ts_range,
           ls_range         LIKE LINE OF lt_range,
           lv_result_type   TYPE LENGTH 1,
           lv_comp_count    TYPE i,
           ls_timepoint     TYPE if_fdt_types=>element_timepoint,
           ls_dyn_line      TYPE REF TO data,
           lv_rown_count    TYPE i.
*            lt_fcat_dec_tab   TYPE lvc_t_fcat.

    FIELD-SYMBOLS:
      <fs_result>       TYPE data,
      <fs_dyntable>     TYPE table,
      <fs_struct_tab>   TYPE any,
      <fs_dataa>        TYPE any,
*                 <fs_data> TYPE REF TO data.
      <fs_fcat_dec_tab> TYPE lvc_s_fcat.

    CHECK iv_app IS NOT INITIAL.
    CHECK iv_dec IS NOT INITIAL.

* Get Application GUID
    CALL METHOD cacsbr_cl_icm_fdt_helper=>get_fdt_guid
      EXPORTING
        io_factory  lo_factory
        id_obj_name iv_app " Application Name
        id_obj_type 'AP'
      IMPORTING
        et_obj_ids  DATA(lt_fdt_ids).

    CHECK lt_fdt_ids[] IS NOT INITIAL"No application found so quit

    READ TABLE lt_fdt_ids INDEX INTO DATA(ls_fdt.
    DATA(lv_appl_id)  =  ls_fdt-id.

* Generic factory instance
    lo_factory cl_fdt_factory=>if_fdt_factory~get_instancelv_appl_id ).

    CLEAR lt_fdt_ids.
* Get Decision Table GUID
    CALL METHOD cacsbr_cl_icm_fdt_helper=>get_fdt_guid
      EXPORTING
        io_factory  lo_factory
        id_obj_name iv_dec " Decision Table Name
        id_obj_type 'EX'
      IMPORTING
        et_obj_ids  lt_fdt_ids.

    CHECK lt_fdt_ids[] IS NOT INITIAL" No Decision Table found so quit

    READ TABLE lt_fdt_ids INDEX INTO ls_fdt .
    DATA(lv_decision_tab_guid)  =  ls_fdt-id.

* Get Expression
    lo_dec_table ?= lo_factory->get_expressioniv_id lv_decision_tab_guid ).

* Get BRF Columns
    lo_dec_table->get_columnsIMPORTING ets_column DATA(lt_column).

* Get BRF Rows
    lo_dec_table->get_rowsIMPORTING ets_row_data DATA(lt_rowdata).

* Get the expression using decision table guid
    lo_decision_table ?= lo_factory->get_expressioniv_id lv_decision_tab_guid ).

* Get the decision table data based on above expression guid
    lo_decision_table->if_fdt_decision_table~get_table_data(
      IMPORTING
        ets_data     lt_table_data
    ).

    LOOP AT lt_column INTO DATA(ls_column).
      CALL METHOD cl_fdt_services=>get_texts_for_id
        EXPORTING
          iv_id        ls_column-object_id
          iv_timestamp ''
        IMPORTING
          ev_name      DATA(lv_column_name).

      lo_element ?= lo_factory->get_data_object(  iv_id  ls_column-object_id
          iv_data_object_type if_fdt_constants=>gc_data_object_type_element ).
      CALL METHOD lo_element->if_fdt_data_object~get_ddic_binding
        RECEIVING
          rv_ddic_typename DATA(lv_tabname).
      IF lv_tabname IS INITIAL.
        lv_tabname 'CHAR255'.
      ENDIF.

      MOVE ls_column-col_no         TO ls_fdt_dec_tab_stru-column_num.
      MOVE lv_column_name           TO ls_fdt_dec_tab_stru-column_name.
      MOVE lv_tabname               TO ls_fdt_dec_tab_stru-col_data_type.
      MOVE ls_column-is_optional    TO ls_fdt_dec_tab_stru-is_optional.
      MOVE ls_column-input_required TO ls_fdt_dec_tab_stru-is_required.
      MOVE ls_column-is_result      TO ls_fdt_dec_tab_stru-is_result.
      MOVE ls_column-ui_mode        TO ls_fdt_dec_tab_stru-is_ui_mode.
      APPEND ls_fdt_dec_tab_stru    TO  lt_dec_tab_struct.
    ENDLOOP.


** table creation
    LOOP AT lt_dec_tab_struct INTO DATA(ls_dec_tab_struct).
      lv_tab_name ls_dec_tab_struct-col_data_type.
      CALL FUNCTION 'DDIF_DTEL_GET'
        EXPORTING
          name     lv_tab_name
          state    'A'
          langu    sy-langu
        IMPORTING
          dd04v_wa ls_ddic_info.

      ls_fcat_dec_tab-fieldname ls_dec_tab_struct-column_name.
      ls_fcat_dec_tab-col_pos   ls_dec_tab_struct-column_num.
      ls_fcat_dec_tab-tabname   ls_dec_tab_struct-col_data_type.
      ls_fcat_dec_tab-outputlen ls_ddic_info-leng.
      APPEND ls_fcat_dec_tab TO lt_fcat_dec_tab.
    ENDLOOP.

    ASSIGN et_dyn_out TO <fs_data>"Dynamic table out type ref to DATA

* Create Dynamic Table
    CALL METHOD cl_alv_table_create=>create_dynamic_table
      EXPORTING
        it_fieldcatalog           lt_fcat_dec_tab
      IMPORTING
        ep_table                  <fs_data>
      EXCEPTIONS
        generate_subpool_dir_full 1
        OTHERS                    2.
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

*  Get the values inside the table  from BRF plus
    LOOP AT lt_table_data INTO DATA(ls_table_data).
      CLEARls_rule_res_data,lv_value.
      IF ls_table_data-r_value IS NOT INITIAL.
        ASSIGN ls_table_data-r_value->TO <fs_result>.
*       Not a date field. Hence get the value directly.
        lv_value <fs_result>.

        UNASSIGN <fs_result>.
      ELSEIF ls_table_data-ts_range IS NOT INITIAL.
        lt_range ls_table_data-ts_range.
        READ TABLE lt_range INTO ls_range INDEX 1.
        IF  sy-subrc  0.
          ASSIGN ls_range-r_low_value->TO <fs_result>.
          IF <fs_result> IS ASSIGNED .
            DESCRIBE FIELD <fs_result> TYPE lv_result_type COMPONENTS lv_comp_count.
            IF lv_result_type 'u'" Flat Structure
*         If the result is a flat struc, then it should be a time point (date field)
              ls_timepoint <fs_result>.
              lv_value ls_timepoint-date.
            ELSE.
*         Not a date field. Hence get the value directly.
              lv_value <fs_result>.
            ENDIF.
            UNASSIGN <fs_result>.
          ELSE.
*         No Data in respective field
            lv_value ''.
          ENDIF.
        ENDIF.
      ENDIF.
      ls_rule_res_data-col_no ls_table_data-col_no.
      ls_rule_res_data-row_no ls_table_data-row_no.
      ls_rule_res_data-value lv_value.

      CLEAR  ls_column.
      READ TABLE lt_column INTO ls_column WITH KEY col_no ls_table_data-col_no.
      ls_rule_res_data-is_result ls_column-is_result.
      APPEND ls_rule_res_data TO lt_rule_res_data.
      CLEAR ls_rule_res_data.
    ENDLOOP.

    SORT lt_rule_res_data BY row_no ASCENDING col_no ASCENDING.
    CLEARls_rule_res_data.

    DESCRIBE TABLE lt_column LINES DATA(lv_count_col).
    DESCRIBE TABLE lt_rule_res_data LINES DATA(lv_rows_count).
    READ TABLE lt_rule_res_data INDEX lv_rows_count INTO ls_rule_res_data.
    DATA(lv_row_cnt_decls_rule_res_data-row_no.

*----------------------------------------------------------------------------------
* Fill the dynamic table with values
    ASSIGN <fs_data>->TO <fs_dyntable>.

* Create dynamic work area and assign to Field Symbol
    CREATE DATA ls_dyn_line LIKE LINE OF <fs_dyntable>.
    ASSIGN ls_dyn_line->TO <fs_struct_tab>.
    UNASSIGN <fs_dataa>.

    lv_rown_count 0.

    WHILE lv_rown_count < lv_row_cnt_dec.
      lv_rown_count lv_rown_count + 1.
      READ TABLE lt_rule_res_data WITH KEY row_no lv_rown_count TRANSPORTING NO FIELDS BINARY SEARCH.
      IF sy-subrc <> 0.
        CONTINUE.
      ENDIF.
      DATA(lv_tabixsy-tabix.

      LOOP AT lt_rule_res_data FROM lv_tabix INTO ls_rule_res_data.
        IF ls_rule_res_data-row_no <> lv_rown_count.
          EXIT.
        ENDIF.

        READ TABLE lt_fcat_dec_tab ASSIGNING <fs_fcat_dec_tab> WITH KEY col_pos ls_rule_res_data-col_no.
        DATA(lv_field=     <fs_fcat_dec_tab>-fieldname.
        ASSIGN COMPONENT lv_field OF STRUCTURE <fs_struct_tab> TO <fs_dataa>.
        <fs_dataa> ls_rule_res_data-value.

      ENDLOOP.
      APPEND <fs_struct_tab> TO <fs_dyntable>.

      IF <fs_dataa> IS ASSIGNED.
        UNASSIGN <fs_dataa>.
      ENDIF.
    ENDWHILE.

  ENDMETHOD.

Once the class is ready it can be programmatically called:

REPORT zgb_test_brf.

DATAlt_dec_tab TYPE REF TO data.
FIELD-SYMBOLS <lfs_dec_tab> TYPE ANY TABLE.

CALL METHOD ZCL_PTPI0935_UTIL=>read_brf_decision_table
  EXPORTING
    iv_app     'ZGB_BRF_APPLICATION'
    iv_dec     'MY_BRF_TABLE'
  IMPORTING
    et_dyn_out lt_dec_tab.

DATAlv_field(10TYPE VALUE 'NAME'.

IF lt_dec_tab IS NOT INITIAL.
  ASSIGN lt_dec_tab->TO <lfs_dec_tab>.

  LOOP AT <lfs_dec_tab> ASSIGNING FIELD-SYMBOL(<lfs_dec_wa>).
    ASSIGN COMPONENT OF STRUCTURE <lfs_dec_wa> TO FIELD-SYMBOL(<lfs_name>).
    ASSIGN COMPONENT OF STRUCTURE <lfs_dec_wa> TO FIELD-SYMBOL(<lfs_low>).
    ASSIGN COMPONENT OF STRUCTURE <lfs_dec_wa> TO FIELD-SYMBOL(<lfs_high>).

    WRITE:/ <lfs_name><lfs_low><lfs_high>.
  ENDLOOP.

ENDIF.

No comments:

Post a Comment

Search SAPMV45A includes for Constants and Statics

 This report can find CONSTANTS and STATICS in SAPMV45A Z-includes. We know that Constants and Statics consume global variables so identifyi...