Monday, 29 October 2018

ABAP Recursive Code to Identify root nodes in Hierarchy fromTable Data

I have come across a scenario where I need to find out the root entry from a hierarchy. I would like to share the approach which I followed for the same. It might not be the best one but hope will help you in one or the other way.

Consider the test data for our case:


Here First Column is the Child Node and Second Column is Parent Node.

Problem Statement: We need to identify the final child nodes for Parent ‘1’ and ‘2’.

For e.g: For parent 1 root nodes are A and B. And again for A the root node are C, D out of which D is final root node and for C we have again two child nodes M and N which are at end the root nodes.

Same way we need to identify all the root nodes.

ABAP Code For the same:

*&---------------------------------------------------------------------*
*& Report ZAM_RECURSIVE_TEST
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zam_recursive_test.
TYPES: BEGIN OF ty_data,      "To hold test data
         field1 TYPE char1,   "Child
         field2 TYPE char2,   "Parent
       END OF ty_data,

       BEGIN OF ty_out,      "To Filter
         field1 TYPE char1,
       END OF ty_out,

       BEGIN OF ty_sel,      "Range Table
         sign TYPE TVARV_SIGN,
         opti TYPE TVARV_OPTI,
         low  TYPE char32,
         high TYPE char32,
       END OF ty_sel.

TYPES tt_data TYPE TABLE OF ty_data WITH EMPTY KEY.

DATA: it_data TYPE TABLE OF ty_data,
      wa_data TYPE ty_data,
      it_rec  TYPE tt_data,
      wa_rec  TYPE ty_data,
      it_out  TYPE TABLE OF ty_out,
      it_sel  TYPE TABLE OF ty_sel,
      wa_sel  TYPE ty_sel.

"Create Test Data
wa_data-field1 = 'A'. wa_data-field2 = '1'.
APPEND wa_data TO it_data.
wa_data-field1 = 'B'. wa_data-field2 = '1'.
APPEND wa_data TO it_data.
wa_data-field1 = 'C'. wa_data-field2 = 'A'.
APPEND wa_data TO it_data.
wa_data-field1 = 'D'. wa_data-field2 = 'A'.
APPEND wa_data TO it_data.
wa_data-field1 = 'E'. wa_data-field2 = 'B'.
APPEND wa_data TO it_data.
wa_data-field1 = 'K'. wa_data-field2 = '2'.
APPEND wa_data TO it_data.
wa_data-field1 = 'L'. wa_data-field2 = 'K'.
APPEND wa_data TO it_data.
wa_data-field1 = 'M'. wa_data-field2 = 'C'.
APPEND wa_data TO it_data.
wa_data-field1 = 'N'. wa_data-field2 = 'C'.
APPEND wa_data TO it_data.
wa_data-field1 = 'O'. wa_data-field2 = 'E'.
APPEND wa_data TO it_data.
wa_data-field1 = 'P'. wa_data-field2 = 'B'.
APPEND wa_data TO it_data.
"Sort Test Data
SORT it_data by field2.
"Fetch Data for Parent 1
it_rec = VALUE tt_data( FOR wa_rec2 IN it_data WHERE ( field2 = '1' ) ( CORRESPONDING #( wa_rec2 ) )  ) .
"Call recursive code
PERFORM f_fetch TABLES it_rec.
"Fetch Data for Parent 2
it_rec = VALUE tt_data( FOR wa_rec2 IN it_data WHERE ( field2 = '2' ) ( CORRESPONDING #( wa_rec2 ) )  ) .
"Call recursive code
PERFORM f_fetch TABLES it_rec.

"Write Data
WRITE /: 'Original Data'.
WRITE /: 'Node'.
WRITE: '     Parent'.
LOOP AT it_data into wa_data.
"Loop on Original Data
  WRITE /: wa_data-field1.
  WRITE '       '.
  WRITE wa_data-field2.
ENDLOOP.

DATA ls_out TYPE ty_out.
WRITE /: '----------------------------------------------'.
WRITE /: 'Children Nodes Identified'.
LOOP AT it_out INTO ls_out.
"Loop for Children Node
WRITE /: ls_out-field1.
wa_sel-sign = 'I'.
wa_sel-opti = 'EQ'.
wa_sel-low = ls_out-field1.
APPEND wa_sel TO it_sel.
ENDLOOP.

WRITE /: '----------------------------------------------'.
WRITE /: 'Complete Details for Children Nodes'.
WRITE /: 'Node'.
WRITE: '     Parent'.

LOOP AT it_data into wa_data where field1 IN it_sel.
"Loop on Children complete data
  WRITE /:  wa_data-field1.
  WRITE '       '.
  WRITE wa_data-field2.
ENDLOOP.


FORM f_fetch TABLES pt_rec TYPE tt_data.
  DATA: ls_rec   TYPE ty_data,
        wa_data2 TYPE ty_data,
        ls_out   TYPE ty_out,
        lv_lines TYPE i.
  LOOP AT pt_rec INTO ls_rec.
    READ TABLE it_data INTO wa_data2 WITH KEY field2 = ls_rec-field1 BINARY SEARCH.
    IF sy-subrc IS INITIAL.
      DATA(it_pass) = VALUE tt_data( FOR wa_rec2 IN it_data WHERE ( field2 = ls_rec-field1 ) ( CORRESPONDING #( wa_rec2 ) )  ) .
      DESCRIBE TABLE it_pass LINES lv_lines.
      IF lv_lines GE 1.
        PERFORM f_fetch TABLES it_pass.
      ELSE.
        CLEAR: ls_rec,it_pass.
        ls_rec-field1 = wa_data2-field1.
        APPEND ls_rec TO it_pass.
        PERFORM f_fetch TABLES it_pass.
      ENDIF.

    ELSE.
      ls_out-field1 = ls_rec-field1.
      APPEND ls_out TO it_out.
    ENDIF.
  ENDLOOP.

ENDFORM.

Output :

No comments:

Post a Comment