Skip to Content

Hi All,

recently i got a scenario to biuld a Multilevel Employee Hierarchy report, i posted it on SCN because i was not getting how could i achieve it through custom program (There are some function modules available for the same purpose e.g. RH_STRUC_GET, but alone it was not fulfilling my requirements). Although it is something like as in standard transaction PPOME, but what i was expecting  is something different from what you can see in PPOME transaction. After posted the query on SCN , i was not able to get a single reply (strange for me , i don’t know why). Then i decided to create a Custom Program to show Multilevel Hierarchy Report for Employees, in which you can see all those employee under any level along with its designation , Name, its id, and so on. I have hided the name of Concerned person in this screenshot, and anyone can edit this program to make a good use of Custom Multilevel Hierarchy report.

Although i have searched for the same on SCN, but i got all the answer which was related to the Hierarchy of one person. And it was not my requirement. So, here i am posting this whole code alongwith the screenshot of Output, so that it will benifit all those members or new persons who wants to create a Multilevel Hierarchy Report.

(There may be some correction in this program, which might help in creating a more benificial list, i will appreciate all those suggestions which will come to me to add within my custom code.)

Step By Step Process i have implemented in getting this List.

Let us assume that i have to show all the concerned person under CMD, let us assume that will have many GM, HR head, Purchase Head, Sales Head like persons who are directly reporting to the CMD, again for each department head we will have persons with different positions, and this hierarchy will be from Top – To – Bottom and can be spreaded upto any level. Now the problem is through RH_STRUC_GET we can get all the concerned person details which has a immediate reporting structure.

A user needs to see the hierarchy details at any level, means he could see either starting for a GM , or for a Executive.

Checking for initial entry, if a avalid person has been entered or not.

AT SELECTION-SCREEN.

   IF p_pernr IS NOT INITIAL.

    SELECT SINGLE pernr

       FROM pa0001

       INTO lv_pernr

       WHERE pernr EQ p_pernr

       AND   endda EQ 99991231.

     IF sysubrc IS NOT INITIAL.

       MESSAGE ‘Please enter a valid Employee Code’  TYPE ‘E’.

     ENDIF.

   ENDIF.

Now with the use of RH_STRUC_GET i get all the employees that are directly or indirectly reporting to the concerned person for which i need to see the hierarchy, in tables parameters we will have three tables namely

it_result_tab   -> which shows the result of all objid which are directly or indirectly related to a concerned person

it_result_object -> which shows the designation of all employee with other details

it_result_struc   -> contains the level of each employee with other details

Now getting all the employees details through RH_STRUC_GET

FORM get_data .

   CLEAR lv_objid.

   SELECT SINGLE plans

     INTO lv_objid

     FROM pa0001

     WHERE pernr = p_pernr

     AND endda = ‘99991231’.

   CALL FUNCTION ‘RH_STRUC_GET’

     EXPORTING

       act_otype      = ‘S’

       act_objid      = lv_objid

       act_wegid      = ‘B002’

       act_plvar      = ’01’

       act_begda      = pm_datuv

       act_endda      = pm_datuv

     TABLES

       result_tab     = it_result_tab

       result_objec   = it_result_objec

       result_struc   = it_result_struc

     EXCEPTIONS

       no_plvar_found = 1

       no_entry_found = 2

       OTHERS         = 3.

ENDFORM.  

Now as we will have a table it_result_struc having levels of all employee, so getting the related details of employees.

FORM preapare_final_table .

   LOOP AT  it_result_struc INTO wa_result_struc .

     MOVE-CORRESPONDING wa_result_struc TO it_struct.

     SELECT SINGLE pernr

                   ename

                   bukrs

                   werks

                   btrtl

                   persk

                   kostl

       FROM pa0001

       INTO (it_structpernr ,

             it_structename,

             it_structbukrs,

             it_structwerks,

             it_structbtrtl,

             it_structpersk,

             it_structkostl )

       WHERE endda = 99991231

       AND plans = it_structobjid.

     SELECT SINGLE ptext

       FROM t503t

       INTO it_structptext

       WHERE persk = it_structpersk.

     SELECT SINGLE btext

       FROM t001p

       INTO it_structbtext

       WHERE werks = it_structwerks

         AND btrtl = it_structbtrtl.

     SELECT SINGLE ltext

       FROM cskt

       INTO  it_structltext

       WHERE spras  = ‘E’

       AND kostl = it_structkostl.

     SELECT SINGLE plstx

       FROM t528t

       INTO it_structplstx

       WHERE sprsl = ‘E’

         AND plans = it_structobjid.

     APPEND it_struct.

     CLEAR it_struct.

   ENDLOOP.

   IF so_bukrs[] IS NOT INITIAL.

     DELETE it_struct WHERE bukrs NOT IN so_bukrs.

   ENDIF.

   IF so_werks[] IS NOT INITIAL.

     DELETE it_struct WHERE werks NOT IN so_werks.

   ENDIF.

   IF so_btrtl[] IS NOT INITIAL.

     DELETE it_struct WHERE btrtl NOT IN so_btrtl.

  ENDIF.

   IF so_persk[] IS NOT INITIAL.

     DELETE it_struct WHERE persk NOT IN so_persk.

  ENDIF.

   IF so_kostl[] IS NOT INITIAL.

     DELETE it_struct WHERE kostl NOT IN so_kostl.

  ENDIF.

   DELETE it_struct WHERE pernr IS INITIAL.

  READ TABLE it_struct WITH KEY pernr = p_pernr.

   IF sysubrc IS NOT INITIAL.

    SELECT SINGLE pernr

                   ename

                   bukrs

                   werks

                   btrtl

                   persk

                   kostl

                   plans

       FROM pa0001

       INTO (it_structpernr,

             it_structename,

             it_structbukrs,

             it_structwerks,

             it_structbtrtl,

             it_structpersk,

             it_structkostl,

             it_structobjid )

       WHERE endda = ‘99991231’

         AND plans = lv_objid.

     SELECT SINGLE ptext

       FROM t503t

       INTO it_structptext

       WHERE persk = it_structpersk.

     SELECT SINGLE btext

       FROM t001p

       INTO it_structbtext

       WHERE werks = it_structwerks

         AND btrtl = it_structbtrtl.

     SELECT SINGLE ltext

       FROM cskt

       INTO  it_structltext

       WHERE spras  = ‘E’

       AND kostl = it_structkostl.

     SELECT SINGLE plstx

       FROM t528t

       INTO it_structplstx

       WHERE sprsl = ‘E’

         AND plans = it_structobjid.

     it_structlevel = 0.

     INSERT it_struct INDEX 1.

     DELETE ADJACENT DUPLICATES FROM it_struct COMPARING pernr.

  ENDIF.

ENDFORM.                   

Now we have all the data in our internal table it_struct, including level of each employee , here level refers to the hierarchy level of each employee w.r.t. to higher person for which we want to see the reporting hierarchy.

So, we have to go for each level separately and see haow many are reporting them directly, and the same will be checked for each entry.

FORM prepare_relationship .

   LOOP AT it_struct INTO wa_struct.

     lv_index = sytabix 1.

     IF sytabix EQ 1.

       MOVE wa_structpernr TO ts1_pernrpernr.

       APPEND ts1_pernr TO gt_pernr.

       CONTINUE.

     ELSE.

       PERFORM get_heir USING  wa_struct

                        CHANGING lv_index

                          gt_pernr.

    ENDIF.

   ENDLOOP.


LOOP AT gt_pernr INTO wa_person.

     CLEAR lv_counter.

     lv_index1 = sytabix + 1 .

     LOOP AT gt_pernr INTO wa_person1 FROM lv_index1.

       IF wa_person1level GT wa_personlevel .

         lv_counter = lv_counter + 1.

       ELSEIF  wa_person1level EQ wa_personlevel .

         EXIT.

       ENDIF.

     ENDLOOP.

     MOVE wa_personpernr TO gt_pernr3pernr.

     IF lv_counter IS INITIAL.

       lv_counter 1.

    ENDIF.

     MOVE  lv_counter TO gt_pernr3count.

     APPEND gt_pernr3.

   ENDLOOP.

   gt_pernr2[] = gt_pernr[].

   SORT gt_pernr2 BY f_pernr.

   LOOP AT gt_pernr2.

     MOVE gt_pernr2f_pernr TO it_pernrpernr.

     MOVE 1 TO it_pernrcount.

     COLLECT it_pernr.

   ENDLOOP.

ENDFORM.   

FORM get_heir   USING    wa_struct  TYPE ty_pernr

                CHANGING lv_index  TYPE sytabix

                         gt_pernr    TYPE tt_bom.

   READ TABLE it_struct INTO wa_struct1 INDEX lv_index.

   IF sysubrc IS INITIAL.

     IF wa_structlevel > wa_struct1level.

       MOVE: wa_structpernr TO ts1_pernrpernr,

             wa_struct1pernr TO ts1_pernrf_pernr,

             wa_structlevel TO ts1_pernrlevel.

       APPEND  ts1_pernr TO gt_pernr.

    ELSE.

       IF lv_index > 1.

         lv_index = sytabix 1.

         PERFORM get_heir USING  wa_struct

                         CHANGING lv_index

                                  gt_pernr .

       ELSE.

         MOVE: wa_structpernr TO ts1_pernrpernr,

               wa_struct1pernr TO ts1_pernrf_pernr,

               wa_structlevel TO ts1_pernrlevel.

         APPEND  ts1_pernr TO gt_pernr.

       ENDIF.

     ENDIF.

   ENDIF.

ENDFORM.        

To create the ALV Tree, we have to create a method, below code has been created for displaying the ALV Tree.

FORM display_alv_tree .

   LOOP AT gt_pernr ASSIGNING <fs_pernr>.

     READ TABLE it_struct INTO wa_struct

     WITH KEY pernr = <fs_pernr>pernr.

     IF <fs_pernr>f_pernr = .

       READ TABLE gt_pernr3 WITH KEY pernr = wa_structpernr.

       IF sysubrc IS INITIAL.

         MOVE gt_pernr3count TO lv_str.

         CONCATENATE wa_structptext ‘( count’ lv_str ‘)’INTO  l_node_text SEPARATED BY space.

       ELSE.

         l_node_text wa_structename.

       ENDIF.

       READ TABLE it_pernr WITH KEY pernr = wa_structpernr.

       IF sysubrc  IS INITIAL.

         MOVE it_pernrcount TO wa_structcount.

       ELSE.

         MOVE 1 TO wa_structcount.

       ENDIF.

       CLEAR l_node_key.

       CALL METHOD g_alv_tree->add_node

         EXPORTING

           i_relat_node_key = l_node_key

           i_relationship   = cl_gui_column_tree=>relat_last_child

           i_node_text      = l_node_text

           is_outtab_line   = wa_struct

         IMPORTING

           e_new_node_key   = l_node_key.

     ELSE.

       READ TABLE gt_pernr INTO w_pernr

       WITH KEY pernr = <fs_pernr>f_pernr.

       READ TABLE gt_pernr3 WITH KEY pernr = wa_structpernr.

       IF sysubrc IS INITIAL.

         MOVE gt_pernr3count TO lv_str.

         CONCATENATE wa_structptext ‘( count’ lv_str ‘)’INTO  l_node_text SEPARATED BY space.

       ELSE.

         l_node_text wa_structename.

       ENDIF.

       READ TABLE it_pernr WITH KEY pernr = wa_structpernr.

       IF sysubrc  IS INITIAL.

         MOVE it_pernrcount TO wa_structcount.

       ELSE.

         MOVE 1 TO wa_structcount.

       ENDIF.

       lv_key =   w_pernrkey.

       CALL METHOD g_alv_tree->add_node

         EXPORTING

           i_relat_node_key = lv_key

           i_relationship   = cl_gui_column_tree=>relat_last_child

           i_node_text      = l_node_text

           is_outtab_line   = wa_struct

         IMPORTING

           e_new_node_key   = l_node_key.

    ENDIF.

     <fs_pernr>key = l_node_key.

     lv_key = <fs_pernr>key.

  ENDLOOP.

ENDFORM.                    ” DISPLAY_ALV_

MODULE status_0100 OUTPUT.

   SET PF-STATUS ‘MAIN11.

   SET TITLEBAR ‘MAINTITLE1’.

   IF g_alv_tree IS INITIAL.

     PERFORM init_tree.

     CALL METHOD cl_gui_cfw=>flush

       EXCEPTIONS

         cntl_system_error = 1

         cntl_error        = 2.

     IF sysubrc NE 0.

       CALL FUNCTION ‘POPUP_TO_INFORM’

         EXPORTING

           titel = ‘Automation Queue failure’(801)

           txt1  = ‘Internal error:’(802)

           txt2  = ‘A method in the automation queue’(803)

           txt3  = ’caused a failure.’(804).

     ENDIF.

   ENDIF.

ENDMODULE.  



Now creating the container for holding the node containing the details


FORM init_tree .

   DATA: l_tree_container_name(30) TYPE c.

   l_tree_container_name = ‘CCONTAINER1’.

   CREATE OBJECT g_custom_container

     EXPORTING

       container_name              = l_tree_container_name

     EXCEPTIONS

       cntl_error                  = 1

       cntl_system_error           = 2

       create_error                = 3

       lifetime_error              = 4

       lifetime_dynpro_dynpro_link = 5.

   IF sysubrc <> 0.

     MESSAGE x208(00) WITH ‘ERROR’(100).

   ENDIF.

* create tree control

   CREATE OBJECT g_alv_tree

     EXPORTING

       parent                      = g_custom_container

       node_selection_mode         = cl_gui_column_tree=>node_sel_mode_single

       item_selection              = ‘X’

       no_html_header              = ‘X’

       no_toolbar                  =

     EXCEPTIONS

       cntl_error                  = 1

       cntl_system_error           = 2

       create_error                = 3

       lifetime_error              = 4

       illegal_node_selection_mode = 5

       failed                      = 6

       illegal_column_name         = 7.

   IF sysubrc <> 0.

     MESSAGE x208(00) WITH ‘ERROR.                          “#EC NOTEXT

   ENDIF.

   DATA l_hierarchy_header TYPE treev_hhdr.

   PERFORM build_hierarchy_header CHANGING l_hierarchy_header.

  CALL METHOD g_alv_tree->set_table_for_first_display

     EXPORTING

       i_structure_name    = ‘ZHR_EMP’

       is_hierarchy_header = l_hierarchy_header

     CHANGING

       it_outtab           = gt_pernr1. “table must be empty !

   PERFORM get_data.

   PERFORM preapare_final_table.

   PERFORM prepare_relationship.

   PERFORM display_alv_tree.

   CALL METHOD g_alv_tree->frontend_update.

ENDFORM.   


When you will execute the report , you will get a result like this


Capture1.PNG


On opening its successive nodes, you will get the various level of hierarchy.



PS.: Editing still is in Process.

Employee Hierarchy.PNG

In the above screenshot i have shown that how many peoples are there under each level, The Source Code can be optimised for any data related to this Hierarchy (Means you can add your needy data to show here.).

Regards

Sanjeev kumar.

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Flavio Furlan

    Hi Sanjeev,

    Very good initiative! That’s the spirity, if you didn’t find the solution, create one!

    I’m very happy you share your code with the community. It’s a excelent chance for you learn a little bit more about code sharing to community.

    Have you ever heard about Github? The best definition for that is: Social network for developers. If you have some time try to share your code there. So others developers can contribute.

    Again, very good initiative!

    Take care!

    Furlan

    (0) 
  2. Matthew Billingham

    Please edit your blog to give a simple description of the algorithm you’ve worked out. If you do this, then there will be no reason to reject your blog. While I applaud your desire to share the solution, blogs that are mainly ABAP code are on the edge of acceptability.

    thanks!

    (0) 
    1. Sanjeev Kumar Post author

      Hi Matthew Billingham,

      surely i will edit my blog to give it a good look by means of understanding, actually i was not seeing any initiative from anywhere to know about the algo, so i droped it. Thanks a lot for your suggestions. I will clarify my blog more generally soon.

      (0) 

Leave a Reply