Page 1 of 1

How to use recursion in ABAP?

Posted: Wed Mar 11, 2015 9:10 am
by omarb
Hi Gurus,

My abap report display an ALV with transactions and their folders , first you specify a role and lenguage into the selection screen,
Alv will display a list with : role name, role descriptio, folder name, transaction. description of transaction.
You can run my report using this standard role : SAP_EP_RW_FSCM_TRM_TM-FO.

My problem is when transactions are located under folders with several levels.

1 - I look for transactions without folders (append to LT_OUTPUT, my ALV)
2- I look for Folders
3- I look folders one by one if there is transactions (folder name-transaction)
4- I look if there is more folders in each folder and I look if there is transaction (Folder1>Folder1.2 - PA20 add to my ALV)

I want to make this dynamic using recursive level cheks

How to I can do it ?

Thanks a lot for you help.


Source code of my entire report + data declarations include (you should create the include).

Code: Select all

REPORT ZPRGN_PRINT_AGR_MENU3.
*&---------------------------------------------------------------------*
*& INCLUDES
*&---------------------------------------------------------------------*
INCLUDE ZPRGN_PRINT_AGR_DATA.
 
*** Program START ****
 
CLEAR: LS_OUTPUT,
i_agrhier.
 
 
SELECT agr_name from AGR_HIER into i_agrhier-agr_name where agr_name in p_agr.
 
append i_agrhier.
 
ENDSELECT.
 
DELETE ADJACENT DUPLICATES FROM i_agrhier COMPARING agr_name.
 
PERFORM f00_get_nodes.
  
data: lv_floo type flag.
 
*lt_MENU
*l_tcodes
*lt_NODES2
 
 
loop at lt_nodes2 into ls_nodes where folder ne 'X'.
 
if ls_nodes-reporttype = 'TR' and ls_nodes-parent_id = '00000001'.
ls_output-TRANSCODE = ls_nodes-report.
ls_output-SUBMENU = 'No menu assigned'.
 
read table l_tcodes into l_tcodes WITH KEY tcode = ls_nodes-report.
ls_output-TRANSTXT = l_tcodes-txt.
ls_output-role = ls_nodes-agr_name.
 
SELECT single text from agr_texts into ls_output-txtrole where agr_name eq ls_nodes-agr_name
and spras eq p_langu
and line eq '00000'.
Append ls_output to lt_output.
endif.

ENDLOOP.
 
clear ls_output.
 
LOOP at lt_nodes2 into ls_nodes.
*
** do 10 times.
* read table lt_MENU WITH KEY object_id = ls_nodes-parent_id into ls_menu.
*
* ls_output-TRANSCODE = ls_nodes-report.
* ls_output-SUBMENU = ls_menu-TEXT.
*
* read table l_tcodes into l_tcodes WITH KEY tcode = ls_nodes-report.
* ls_output-TRANSTXT = l_tcodes-txt.
*
*
* read table lt_nodes2 into ls_nodes WITH KEY folder = 'X' parent_id = ls_nodes-object_id.
ENDLOOP.
 
 
 
 
 
 
*** CALL THE ALV OUTPUT.
PERFORM F0002_PRINT_REPORT TABLES LT_OUTPUT.
 
 
 
 
 
*&---------------------------------------------------------------------*
*& S t a r t o f forms / routines
*&---------------------------------------------------------------------*
 
FORM F0002_PRINT_REPORT TABLES LT_OUTPUT.
 
TYPE-POOLS: SLIS, TRUXS, ICON.
DATA: S_LAYOUT TYPE SLIS_LAYOUT_ALV.
DATA S_CAT TYPE SLIS_FIELDCAT_ALV.
DATA T_CAT TYPE SLIS_T_FIELDCAT_ALV.
 
S_LAYOUT-NO_INPUT = 'X'.
S_LAYOUT-COLWIDTH_OPTIMIZE = 'X'.
S_LAYOUT-ZEBRA = 'X'.

REFRESH T_CAT.
CLEAR S_CAT.
S_CAT-FIELDNAME = 'ROLE'. " Nombre del role
S_CAT-SELTEXT_L = TEXT-T10.
S_CAT-DATATYPE = 'CHAR'.
S_CAT-OUTPUTLEN = '50'.
APPEND S_CAT TO T_CAT.
 
CLEAR S_CAT.
S_CAT-FIELDNAME = 'TXTROLE'. "Description del role
S_CAT-SELTEXT_L = TEXT-T20.
S_CAT-DATATYPE = 'CHAR'.
S_CAT-OUTPUTLEN = '50'.
APPEND S_CAT TO T_CAT.
 
 
CLEAR S_CAT.
S_CAT-FIELDNAME = 'SUBMENU'. "Nombre de la carpeta (ruta de la transaction)
S_CAT-SELTEXT_L = TEXT-T21.
S_CAT-DATATYPE = 'CHAR'.
S_CAT-OUTPUTLEN = '50'.
APPEND S_CAT TO T_CAT.
 
CLEAR S_CAT.
S_CAT-FIELDNAME = 'TRANSCODE'. "Transaction
S_CAT-SELTEXT_L = TEXT-T22.
S_CAT-DATATYPE = 'CHAR'.
S_CAT-OUTPUTLEN = '50'.
APPEND S_CAT TO T_CAT.
 
CLEAR S_CAT.
S_CAT-FIELDNAME = 'TRANSTXT'. "Descripcion de la transaccion.
S_CAT-SELTEXT_L = TEXT-T23.
S_CAT-DATATYPE = 'CHAR'.
S_CAT-OUTPUTLEN = '50'.
APPEND S_CAT TO T_CAT.
 
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
I_CALLBACK_PROGRAM = SY-REPID
IS_LAYOUT = S_LAYOUT
IT_FIELDCAT = T_CAT
I_CALLBACK_TOP_OF_PAGE = 'TOP_OF_PAGE'
I_BACKGROUND_ID = 'ALV_BACKGROUND'
TABLES
T_OUTTAB = LT_OUTPUT
EXCEPTIONS
PROGRAM_ERROR = 1
OTHERS = 2.
IF SY-SUBRC NE 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
 
ENDFORM. " F0002_PRINT_REPORT
 
 
*** ALV HEADER ****
FORM TOP_OF_PAGE.
 
* Table affichage ALV - entête
DATA: LT_LINE TYPE SLIS_T_LISTHEADER.
DATA: LS_LINE TYPE SLIS_LISTHEADER.
 
DATA : L_TEXT1(70).
DATA : L_TEXT2(70).
DATA : L_TEXT3(70).
DATA : L_DATE(10).
 
DATA : W_TOT(10) TYPE C.
 
*************************
* Titre d'entête
*************************
* Date d'éxécution
WRITE SY-DATUM TO L_DATE DD/MM/YYYY.
CLEAR L_TEXT1.
CONCATENATE TEXT-X01 L_DATE INTO L_TEXT1 SEPARATED BY SPACE.
LS_LINE-INFO = L_TEXT1.

*- Titre d'entête
CLEAR LS_LINE.
LS_LINE-TYP = 'H'.
LS_LINE-INFO = SY-TITLE.
APPEND LS_LINE TO LT_LINE.
 
*- Date d'éxécution
CLEAR LS_LINE.
LS_LINE-TYP = 'S'.
LS_LINE-INFO = L_TEXT1.
APPEND LS_LINE TO LT_LINE.
 
* Nombre total d'enregistrements
CLEAR L_TEXT2.
DESCRIBE TABLE LT_OUTPUT LINES W_TOT.
CONCATENATE TEXT-X02 W_TOT INTO L_TEXT2 SEPARATED BY SPACE.
LS_LINE-INFO = L_TEXT2.
APPEND LS_LINE TO LT_LINE.
 
* chargement d'entête
CALL FUNCTION 'REUSE_ALV_COMMENTARY_WRITE'
EXPORTING
i_logo = 'ENJOYSAP_LOGO'
IT_LIST_COMMENTARY = LT_LINE.
 
 
ENDFORM. "top_of_page

*&---------------------------------------------------------------------*
*& Form F00_GET_NODES
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM F00_GET_NODES .
 
DATA: l_transco type TSTCT.
 
DATA: i_smenurls LIKE agr_buffi OCCURS 100 WITH HEADER LINE,
i_smendtls LIKE agr_shier_bor OCCURS 0 WITH HEADER LINE.
 
LOOP AT i_agrhier. " specified roles into selection screen
 
* Reading nodes, texts and transactions.
CALL FUNCTION 'MENU_AGR_TREE_READ_HIERARCHY'
EXPORTING
ACTIVITY_GROUP = i_agrhier-agr_name
TABLES
NODES = lt_NODES
TEXTS = lt_TEXTS
URLS = i_smenurls
add_details = i_smendtls
TCODES = lt_TCODES.
* Sorting nodes
CALL FUNCTION 'MENU_AGR_TREE_SORT_NODES'
TABLES
INPUT_TABLE_UNSORTED = lt_NODES
OUTPUT_TABLE_SORTED = lt_NODES2.
 
if sy-subrc ne 0.
message s422(s#) with i_agrhier-agr_name raising action_cancelled.
else.
 
if lt_NODES[] is initial.
* Role doesn't have a menu.
message s363(s#) with i_agrhier-agr_name raising menu_does_not_exist.
endif.
 
endif.

loop at lt_NODES2 into ls_nodes where folder eq 'X'.
 
LOOP AT LT_TEXTS into ls_TEXTS where spras eq p_langu and object_id eq ls_nodes-object_id .
 
Append LS_TEXTS to LT_MENU.
 
ENDLOOP.
endloop.
 
ENDLOOP.
 
LOOP AT lt_tcodes into ls_tcodes.
SELECT * from TSTCT into l_transco where SPRSL eq p_langu and tcode eq ls_tcodes-tcode.
l_tcodes-tcode = l_transco-tcode.
l_tcodes-txt = l_transco-ttext.
append l_tcodes.
ENDSELECT.
 
ENDLOOP.
 
 
ENDFORM. " F00_GET_NODES

Code: Select all

*&---------------------------------------------------------------------*
*& Include ZPRGN_PRINT_AGR_DATA
*&---------------------------------------------------------------------*
 
TABLES: AGR_DEFINE.
TYPES: begin of lt_menuroles,
ROLE like AGR_HIER-AGR_NAME,
TXTROLE like AGR_HIERT-TEXT,
SUBMENU like AGR_HIERT-TEXT,
TRANSCODE like AGR_TCODES-TCODE,
TRANSTXT like TSTCT-TTEXT,
END OF lt_menuroles.
 
 
DATA: LT_OUTPUT TYPE TABLE OF lt_menuroles WITH HEADER LINE,
LS_OUTPUT type lt_menuroles.
 
 
DATA: i_agrhier type AGR_HIER OCCURS 0 WITH HEADER LINE,
lt_hiertcd type AGR_HIER OCCURS 0 WITH HEADER LINE,
i_agrhiert type AGR_HIERT OCCURS 0 WITH HEADER LINE,
i_agrtxt type AGR_TEXTS OCCURS 0 WITH HEADER LINE.

DATA: lv_sortord type agr_hier-sort_order ,
lv_parentid type agr_hier-parent_id,
lv_objectid type agr_hier-object_id.
 
 
Types: BEGIN OF lt_folders,
objid like agr_hier-object_id,
parentid like agr_hier-parent_id,
menutxt like agr_hiert-text,
end of lt_folders.
 
Types: BEGIN OF l_tcodes,
tcode like agr_hier-report,
txt like agr_hiert-text,
end of l_tcodes.
 
DATA : LT_folders TYPE TABLE OF lt_folders WITH HEADER LINE.
DATA : l_tcodes TYPE TABLE OF l_tcodes WITH HEADER LINE.
 
 
DATA: lv_numfold type agr_hier-object_id,
lv_lastF type agr_hier-object_id.
 
 
 
DATA:
lt_NODES type AGR_HIER OCCURS 0,
lt_TEXTS type AGR_HIERT OCCURS 0,
lt_MENU type AGR_HIERT OCCURS 0,
lt_TCODES type AGR_TCODES OCCURS 0,
lt_NODES2 type AGR_HIER OCCURS 0.
 
DATA: ls_TEXTS like LINE OF lt_TEXTS,
ls_TCODES like line of lt_TCODES,
ls_NODES like line of lt_NODES,
ls_NODES2 like line of lt_NODES,
ls_MENU like line of lt_MENU .
 
 
*&---------------------------------------------------------------------*
*& S e l e c t i o n s c r e e n
*&---------------------------------------------------------------------*
 
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-sel.
SELECT-OPTIONS: p_agr for agr_define-agr_name.
PARAMETERS: p_langu LIKE t002-spras DEFAULT sy-langu.
SELECTION-SCREEN END OF BLOCK b1.

Re: How to use recursion in ABAP?

Posted: Wed Mar 11, 2015 9:57 am
by Gothmog
You can have a FORM call itself - have a routine add the current folder's transactions to your table, and call itself for each child folder.

Re: How to use recursion in ABAP?

Posted: Wed Mar 11, 2015 11:39 am
by omarb
Thanks Gothmog,
I'm very junior programing in ABAP, how do I can write it ?

Thank you very much.

Omar

Re: How to use recursion in ABAP?

Posted: Mon Mar 16, 2015 8:37 am
by Rich
Just don't use the curse of global variables......

Re: How to use recursion in ABAP?

Posted: Tue Mar 17, 2015 6:53 am
by omarb
I'm still stuck with this issue, :-(
Someone can help with the code ?

Thank you.

Re: How to use recursion in ABAP?

Posted: Tue Mar 17, 2015 8:32 am
by Gothmog
Create a routine with parent node as a parameter (and the node text if you want)
In this routine, for each child node
- if it's a transaction, add it
- if it's a folder, call the same routine with this folder as the parent node

Re: How to use recursion in ABAP?

Posted: Wed Mar 18, 2015 1:02 pm
by Rich

Code: Select all

Start-Of-Selection.

Data: w_Start Type i,
      w_Total Type i.

w_Start = 6.
w_Total = 1.
Perform Factorial Using w_Start Changing w_Total.

Write :/ w_Start, w_Total.


Form Factorial Using pu_Start Type i
            Changing pu_Total Type i.

     Data w_New_Start Type i.
*
     pu_Total = pu_Start * pu_Total.
     If pu_Start > 1.
        w_New_Start = pu_Start - 1.
        Perform Factorial Using w_New_Start
                       Changing pu_Total.
     EndIf.
EndForm.