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.


    DATA: lo_factory        TYPE REF TO          if_fdt_factory.
    DATA: lt_table_data     TYPE                 if_fdt_decision_table=>ts_table_data.
    DATA: lo_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.

    TYPES: BEGIN 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 c 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 1 INTO DATA(ls_fdt) .
    DATA(lv_appl_id)  =  ls_fdt-id.

* Generic factory instance
    lo_factory = cl_fdt_factory=>if_fdt_factory~get_instance( lv_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 1 INTO ls_fdt .
    DATA(lv_decision_tab_guid)  =  ls_fdt-id.

* Get Expression
    lo_dec_table ?= lo_factory->get_expression( iv_id = lv_decision_tab_guid ).

* Get BRF Columns
    lo_dec_table->get_columns( IMPORTING ets_column = DATA(lt_column) ).

* Get BRF Rows
    lo_dec_table->get_rows( IMPORTING ets_row_data = DATA(lt_rowdata) ).

* Get the expression using decision table guid
    lo_decision_table ?= lo_factory->get_expression( iv_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).
      CLEAR: ls_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.
    CLEAR: ls_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_dec) = ls_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_tabix) = sy-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.

DATA: lt_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.

DATA: lv_field(10) TYPE c 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 1 OF STRUCTURE <lfs_dec_wa> TO FIELD-SYMBOL(<lfs_name>).
    ASSIGN COMPONENT 2 OF STRUCTURE <lfs_dec_wa> TO FIELD-SYMBOL(<lfs_low>).
    ASSIGN COMPONENT 3 OF STRUCTURE <lfs_dec_wa> TO FIELD-SYMBOL(<lfs_high>).

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

ENDIF.

No comments:

Post a Comment

AI-Powered Warehouse Temperature Automation Using IoT and SAP

  Overview In this project, we present a smart, scalable solution that leverages  AI ,  IoT , and  SAP technologies  to automate and optim...