点击此处---> 群内免费提供SAP练习系统(在群公告中)
加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)
* This program can be a model for any ABAP recursion. * This is often needed to navigate down hierarchical data. * One example is BOM. * Important point is to chack for stack overflow * and give RIGHT MESSAGE so that corrective action can be taken. *&---------------------------------------------------------------------* * Sample Program Showing Recursion in ABAP * Simple BOM Tree walking in ABAP * Takes Care of Diagnostics as well - detects Loops * Hence never experience Stack Overflow! *&---------------------------------------------------------------------* REPORT zjncrecursion. INCLUDE zjncinclude. " From www.erpgreat.com TABLES: makt. CONSTANTS: maxlevels TYPE i VALUE 10. TYPES: BEGIN OF ty_usage, parent TYPE makt-matnr, child TYPE makt-matnr, usage TYPE mseg-menge, END OF ty_usage. DATA: wa_usage TYPE ty_usage, it_usage TYPE STANDARD TABLE OF ty_usage. " USAGE data TYPES: BEGIN OF ty_stack, level TYPE h_level, matnr TYPE makt-matnr, menge TYPE mseg-menge, END OF ty_stack. DATA: istackpos TYPE i, wa_stack TYPE ty_stack, it_stack TYPE STANDARD TABLE OF ty_stack. "BOM Stack TYPES: BEGIN OF ty_reqd, matnr TYPE makt-matnr, menge TYPE mseg-menge, END OF ty_reqd. DATA: wa_reqd TYPE ty_reqd, it_reqd TYPE STANDARD TABLE OF ty_reqd. "NET Requirement of RAW Material PARAMETERS: p_build TYPE makt-matnr, "Target to Build p_menge TYPE mseg-menge. "Quantity to Build INITIALIZATION. PERFORM f_usage_data. START-OF-SELECTION. istackpos = 0. MOVE istackpos TO wa_stack-level. MOVE p_build TO wa_stack-matnr. MOVE p_menge TO wa_stack-menge. APPEND wa_stack TO it_stack. " 1st PUSH PERFORM f_explode USING p_build. SORT it_reqd BY matnr. PERFORM zjnc_dump_list USING 'IT_REQD' 'WA_REQD' 'Net RAW Requirement'. *&--------------------------------------------------------------------* *& Form f_Explode *&--------------------------------------------------------------------* FORM f_explode USING p_pmatnr. DATA: icount TYPE i, totalreq TYPE mseg-menge. istackpos = istackpos + 1. " PUSH IF istackpos GE maxlevels. PERFORM f_dumpstack. " terminate LEAVE PROGRAM. ENDIF. icount = 0. LOOP AT it_usage INTO wa_usage WHERE parent = p_pmatnr. icount = icount + 1. MOVE istackpos TO wa_stack-level. MOVE wa_usage-child TO wa_stack-matnr. MOVE wa_usage-usage TO wa_stack-menge. APPEND wa_stack TO it_stack. " PUSH PERFORM f_explode USING wa_usage-child. ENDLOOP. IF icount = 0. " then LEAF totalreq = '1.0'. LOOP AT it_stack INTO wa_stack. totalreq = totalreq * wa_stack-menge. ENDLOOP. MOVE p_pmatnr TO wa_reqd-matnr. MOVE totalreq TO wa_reqd-menge. COLLECT wa_reqd INTO it_reqd. ENDIF. DELETE it_stack INDEX istackpos. " POP istackpos = istackpos - 1. " POP ENDFORM. "f_Explode *&--------------------------------------------------------------------* *& Form f_dumpstack *&--------------------------------------------------------------------* FORM f_dumpstack. PERFORM zjnc_dump_list USING 'IT_STACK' 'WA_STACK' 'LOOP in BOM STACK'. ENDFORM. "f_dumpstack *&--------------------------------------------------------------------* *& Form f_usage_data for Hungry Bengali ABAPer in Kolkata *&--------------------------------------------------------------------* FORM f_usage_data. MOVE 'FISHCURRY' TO wa_usage-parent. MOVE 'SPICES' TO wa_usage-child. MOVE 10 TO wa_usage-usage. APPEND wa_usage TO it_usage. MOVE 'FISHCURRY' TO wa_usage-parent. MOVE 'MIRCHI' TO wa_usage-child. MOVE 5 TO wa_usage-usage. APPEND wa_usage TO it_usage. MOVE 'FISHCURRY' TO wa_usage-parent. MOVE 'ALOO' TO wa_usage-child. MOVE 8 TO wa_usage-usage. APPEND wa_usage TO it_usage. MOVE 'SPICES' TO wa_usage-parent. MOVE 'MIRCHI' TO wa_usage-child. MOVE 2 TO wa_usage-usage. APPEND wa_usage TO it_usage. MOVE 'SPICES' TO wa_usage-parent. MOVE 'JEERA' TO wa_usage-child. MOVE 3 TO wa_usage-usage. APPEND wa_usage TO it_usage. MOVE 'SPICES' TO wa_usage-parent. MOVE 'HALUD' TO wa_usage-child. MOVE 7 TO wa_usage-usage. APPEND wa_usage TO it_usage. ENDFORM. "f_usage_data
下边是这个 include 的代码
INCLUDE zjncinclude
*&---------------------------------------------------------------------* *& Include ZJNCINCLUDE * *&---------------------------------------------------------------------* *&---------------------------------------------------------------------* *& Reincarnations of REUSE_ALV_FIELDCATALOG_MERGE *&---------------------------------------------------------------------* *----------------------------------------------------------------------- * These FORMs are for people accustomed to * REUSE_ALV_FIELDCATALOG_MERGE (despite the 72 ch source line limit) * but not happy with LVC_FIELDCATALOG_MERGE * We do not want to crowd DDIC with too many structures! *----------------------------------------------------------------------- *&--------------------------------------------------------------------* *& Form ZJNC_DUMP_LIST Our Good Old ALV list - RECOMMENDED! *&--------------------------------------------------------------------* FORM zjnc_dump_list USING value(p_it_name) TYPE c value(p_wa_name) TYPE c value(p_heading) TYPE c. TYPE-POOLS: slis. DATA: stru_ref TYPE REF TO cl_abap_structdescr, comp_tab TYPE abap_compdescr_tab, one_comp TYPE abap_compdescr, one_name TYPE string, type_ref TYPE REF TO cl_abap_typedescr, is_ddic TYPE abap_bool, lt_ddic TYPE dd_x031l_table, wa_ddic TYPE x031l, lt_fcat TYPE slis_t_fieldcat_alv, wa_fcat TYPE slis_fieldcat_alv, ls_layo TYPE slis_layout_alv, l_alv TYPE REF TO cl_gui_alv_grid. FIELD-SYMBOLS: <fs_type> TYPE ANY, <fs_table> TYPE STANDARD TABLE, <fs_line> TYPE ANY. ASSIGN (p_it_name) TO <fs_table>. ASSIGN (p_wa_name) TO <fs_line>. ls_layo-colwidth_optimize = 'X'. ls_layo-zebra = 'X'. ls_layo-window_titlebar = p_heading. ls_layo-box_tabname = p_it_name. stru_ref ?= cl_abap_structdescr=>describe_by_data( <fs_line> ). comp_tab = stru_ref->components. LOOP AT comp_tab INTO one_comp. CLEAR wa_fcat. wa_fcat-tabname = p_it_name. wa_fcat-fieldname = one_comp-name. CONCATENATE p_wa_name '-' one_comp-name INTO one_name. ASSIGN (one_name) TO <fs_type>. type_ref ?= cl_abap_typedescr=>describe_by_data( <fs_type> ). is_ddic = type_ref->is_ddic_type( ). IF is_ddic = abap_true. lt_ddic = type_ref->get_ddic_object( ). LOOP AT lt_ddic INTO wa_ddic. CLEAR wa_ddic-tabname. SELECT SINGLE dd03l~tabname INTO wa_ddic-tabname FROM dd03l WHERE dd03l~fieldname = wa_ddic-fieldname AND dd03l~tabname NOT LIKE '/%'. " I live in normal namespace wa_fcat-ref_tabname = wa_ddic-tabname. wa_fcat-ref_fieldname = wa_ddic-fieldname. SELECT SINGLE dd04t~scrtext_s dd04t~scrtext_m dd04t~scrtext_l INTO (wa_fcat-seltext_s, wa_fcat-seltext_m, wa_fcat-seltext_l) FROM dd04t WHERE dd04t~rollname = wa_ddic-fieldname AND dd04t~ddlanguage = sy-langu. ENDLOOP. ELSE. MOVE one_comp-name TO: wa_fcat-seltext_s, wa_fcat-seltext_m, wa_fcat-seltext_l. ENDIF. APPEND wa_fcat TO lt_fcat. ENDLOOP. CALL FUNCTION 'REUSE_ALV_LIST_DISPLAY' EXPORTING is_layout = ls_layo it_fieldcat = lt_fcat TABLES t_outtab = <fs_table>. ENDFORM. "ZJNC_DUMP_LIST *&--------------------------------------------------------------------* *& Form ZJNC_DUMP_GRID Object Oriented *&--------------------------------------------------------------------* FORM zjnc_dump_grid USING value(p_it_name) TYPE c value(p_wa_name) TYPE c value(p_screen) TYPE n value(p_heading) TYPE c. DATA: stru_ref TYPE REF TO cl_abap_structdescr, comp_tab TYPE abap_compdescr_tab, one_comp TYPE abap_compdescr, one_name TYPE string, type_ref TYPE REF TO cl_abap_typedescr, is_ddic TYPE abap_bool, lt_ddic TYPE dd_x031l_table, wa_ddic TYPE x031l, lt_fcat TYPE lvc_t_fcat, wa_fcat TYPE lvc_s_fcat, ls_layo TYPE lvc_s_layo, l_alv TYPE REF TO cl_gui_alv_grid. FIELD-SYMBOLS: <fs_type> TYPE ANY, <fs_table> TYPE ANY TABLE, <fs_line> TYPE ANY. ASSIGN (p_it_name) TO <fs_table>. ASSIGN (p_wa_name) TO <fs_line>. ls_layo-cwidth_opt = 'X'. ls_layo-zebra = 'X'. ls_layo-grid_title = p_heading. ls_layo-box_fname = p_it_name. stru_ref ?= cl_abap_structdescr=>describe_by_data( <fs_line> ). comp_tab = stru_ref->components. LOOP AT comp_tab INTO one_comp. CLEAR wa_fcat. wa_fcat-tabname = p_it_name. wa_fcat-fieldname = one_comp-name. CONCATENATE p_wa_name '-' one_comp-name INTO one_name. ASSIGN (one_name) TO <fs_type>. type_ref ?= cl_abap_typedescr=>describe_by_data( <fs_type> ). is_ddic = type_ref->is_ddic_type( ). IF is_ddic = abap_true. lt_ddic = type_ref->get_ddic_object( ). LOOP AT lt_ddic INTO wa_ddic. CLEAR wa_ddic-tabname. SELECT SINGLE dd03l~tabname INTO wa_ddic-tabname FROM dd03l WHERE dd03l~fieldname = wa_ddic-fieldname AND dd03l~tabname NOT LIKE '/%'. " I live in normal namespace wa_fcat-ref_table = wa_ddic-tabname. wa_fcat-ref_field = wa_ddic-fieldname. SELECT SINGLE dd04t~scrtext_s dd04t~scrtext_m dd04t~scrtext_l INTO (wa_fcat-scrtext_s, wa_fcat-scrtext_m, wa_fcat-scrtext_l) FROM dd04t WHERE dd04t~rollname = wa_ddic-fieldname AND dd04t~ddlanguage = sy-langu. ENDLOOP. ELSE. MOVE one_comp-name TO: wa_fcat-scrtext_s, wa_fcat-scrtext_m, wa_fcat-scrtext_l. ENDIF. APPEND wa_fcat TO lt_fcat. ENDLOOP. CREATE OBJECT l_alv EXPORTING i_parent = cl_gui_container=>screen0. CALL METHOD l_alv->set_table_for_first_display EXPORTING is_layout = ls_layo CHANGING it_outtab = <fs_table> it_fieldcatalog = lt_fcat. CALL SELECTION-SCREEN p_screen. ENDFORM. "ZJNC_DUMP_GRID
These FORMs are for people accustomed to REUSE_ALV_FIELDCATALOG_MERGE (despite the 72 ch source line limit) but not happy with LVC_FIELDCATALOG_MERGE which has NO Internal table option We do not want to crowd DDIC with too many structures! The routines handle any internal table using field name as title if not a DDIC data element. Create a Include ZJNCINCLUDE with the 2 FORMs There are two FORMs: ZJNC_DUMP_LIST will be very useful as it is simple and needs no screen and can be called any number of times. Should be very useful also for debugging esp. where Excel is not available as you can dump any internal table anytime and inspect contents. I wrote these routine mainly for debugging and the problem created by half-line long comments in internal tables. With RTTI there is no source code dependency. ZJNC_DUMP_GRID is for OO-GRID loving people who can adapt that routine for one off reports. You can call this ONLY ONCE as it is best used using a dummy selection screen - tip from SDN ABAP FAQ. As FORMs use RTTI there is no special case for Structures!