*&---------------------------------------------------------------------* *& Report Z_ERPFORGE_02_EXPORT *&---------------------------------------------------------------------* *& ERPForgeAI - Step 2: Repository Metadata Export *& Run this AFTER Z_ERPFORGE_01_STECKBRIEF to extract repository data. *& *& Compatible: SAP_BASIS 7.40 SP02+ *& No external type dependencies - all types are primitive or *& direct table-field references from core BASIS tables only. *& *& MEMORY-SAFE: Uses PACKAGE SIZE for large tables (DD03L, TSTC, *& TADIR, TFDIR, D010TAB) to prevent TSV_TNEW_PAGE_ALLOC_FAILED. *& Rows are counted first via SELECT COUNT(*), then streamed in *& chunks into gt_output with p_max enforcement. *& *& What it exports (tab-delimited TXT): *& 1. TABLES - DD02L (transparent/pool/cluster) *& 2. STRUCTURES - DD02L (INTTAB) *& 3. FIELDS - DD03L + DD04T (descriptions) *& 4. FUNC_MODULES - TFDIR + TFTIT *& 5. BAPIS - TFDIR (funcname starts BAPI) *& 6. CLASSES - TADIR (object=CLAS) *& 7. TRANSACTIONS - TSTC + TSTCT *& 8. PACKAGES - TDEVC *& 9. WHERE_USED - D010TAB (only with s_tab filter!) *& *& Workflow: *& 1) Run Z_ERPFORGE_01_STECKBRIEF -> understand the system *& 2) Feed output into ERPForgeAI -> configure AI model *& 3) Run Z_ERPFORGE_02_EXPORT -> extract repository data *& 4) Feed export into ERPForgeAI -> generate ABAP code *&---------------------------------------------------------------------* REPORT z_erpforge_02_export. *----------------------------------------------------------------------* * Constants *----------------------------------------------------------------------* CONSTANTS: gc_pkg_size TYPE i VALUE 5000. "PACKAGE SIZE for chunking *----------------------------------------------------------------------* * TYPES *----------------------------------------------------------------------* TYPES: " Tables and Structures BEGIN OF ty_table, tabname TYPE dd02l-tabname, tabclass TYPE dd02l-tabclass, ddtext TYPE c LENGTH 80, devclass TYPE tadir-devclass, END OF ty_table, " Fields BEGIN OF ty_field, tabname TYPE dd03l-tabname, fieldname TYPE dd03l-fieldname, position TYPE dd03l-position, datatype TYPE dd03l-datatype, leng TYPE dd03l-leng, decimals TYPE dd03l-decimals, rollname TYPE dd03l-rollname, keyflag TYPE dd03l-keyflag, ddtext TYPE c LENGTH 80, END OF ty_field, " Function Modules BEGIN OF ty_func, funcname TYPE tfdir-funcname, fmode TYPE tfdir-fmode, pname TYPE tfdir-pname, devclass TYPE tadir-devclass, stext TYPE c LENGTH 60, END OF ty_func, " Classes BEGIN OF ty_class, clsname TYPE c LENGTH 30, devclass TYPE tadir-devclass, END OF ty_class, " Transactions BEGIN OF ty_tcode, tcode TYPE tstc-tcode, pgmna TYPE tstc-pgmna, ttext TYPE c LENGTH 60, devclass TYPE tadir-devclass, END OF ty_tcode, " Packages BEGIN OF ty_package, devclass TYPE tdevc-devclass, ctext TYPE tdevc-ctext, parentcl TYPE tdevc-parentcl, END OF ty_package, " Where-Used BEGIN OF ty_whereused, tabname TYPE d010tab-tabname, master TYPE d010tab-master, END OF ty_whereused. *----------------------------------------------------------------------* * DATA *----------------------------------------------------------------------* DATA: gt_output TYPE TABLE OF string, gv_line TYPE string, gv_cntstr TYPE c LENGTH 20, gv_tab TYPE c LENGTH 1 VALUE cl_abap_char_utilities=>horizontal_tab, " Typed anchor fields for SELECT-OPTIONS gv_tabref TYPE dd02l-tabname, gv_funcref TYPE tfdir-funcname, gv_packref TYPE tdevc-devclass. *----------------------------------------------------------------------* * SELECTION SCREEN *----------------------------------------------------------------------* SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE gt_b1. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_tab. PARAMETERS p_tables AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_str. PARAMETERS p_struct AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_fld. PARAMETERS p_fields AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_fnc. PARAMETERS p_funcs AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_bpi. PARAMETERS p_bapis AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_cls. PARAMETERS p_class AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_tcd. PARAMETERS p_tcode AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_pkg. PARAMETERS p_pack AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(30) lbl_wu. PARAMETERS p_wused AS CHECKBOX DEFAULT ' '. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN END OF BLOCK b1. SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE gt_b2. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(25) lbl_stab. SELECT-OPTIONS s_tab FOR gv_tabref NO INTERVALS. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(25) lbl_sfc. SELECT-OPTIONS s_func FOR gv_funcref NO INTERVALS. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(25) lbl_spk. SELECT-OPTIONS s_pack FOR gv_packref NO INTERVALS. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(25) lbl_lng. PARAMETERS p_lang TYPE spras DEFAULT sy-langu. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(25) lbl_max. PARAMETERS p_max TYPE i DEFAULT 50000. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN END OF BLOCK b2. *----------------------------------------------------------------------* * INITIALIZATION *----------------------------------------------------------------------* INITIALIZATION. IF sy-langu = 'E' OR sy-langu = 'e'. gt_b1 = 'Export Sections'. gt_b2 = 'Filters'. lbl_tab = 'Tables'. lbl_str = 'Structures'. lbl_fld = 'Fields'. lbl_fnc = 'Function Modules'. lbl_bpi = 'BAPIs'. lbl_cls = 'Classes / Interfaces'. lbl_tcd = 'Transactions'. lbl_pkg = 'Packages'. lbl_wu = 'Where-Used (S_TAB)'. lbl_stab = 'Table Filter'. lbl_sfc = 'Func.Module Filter'. lbl_spk = 'Package Filter'. lbl_lng = 'Language'. lbl_max = 'Max. Rows'. ELSE. gt_b1 = 'Export-Bereiche'. gt_b2 = 'Filter'. lbl_tab = 'Tabellen'. lbl_str = 'Strukturen'. lbl_fld = 'Felder'. lbl_fnc = 'Funktionsbausteine'. lbl_bpi = 'BAPIs'. lbl_cls = 'Klassen / Interfaces'. lbl_tcd = 'Transaktionen'. lbl_pkg = 'Pakete'. lbl_wu = 'Where-Used (S_TAB)'. lbl_stab = 'Tabellen-Filter'. lbl_sfc = 'Funktionsbst.-Filter'. lbl_spk = 'Paket-Filter'. lbl_lng = 'Sprache'. lbl_max = 'Max. Zeilen'. ENDIF. *----------------------------------------------------------------------* * START OF SELECTION *----------------------------------------------------------------------* START-OF-SELECTION. PERFORM write_header. IF p_tables = 'X'. PERFORM collect_tables. ENDIF. IF p_struct = 'X'. PERFORM collect_structures. ENDIF. IF p_fields = 'X'. PERFORM collect_fields. ENDIF. IF p_funcs = 'X' OR p_bapis = 'X'. PERFORM collect_funcs. ENDIF. IF p_class = 'X'. PERFORM collect_classes. ENDIF. IF p_tcode = 'X'. PERFORM collect_tcodes. ENDIF. IF p_pack = 'X'. PERFORM collect_packages. ENDIF. IF p_wused = 'X'. PERFORM collect_whereused. ENDIF. PERFORM export_file. *----------------------------------------------------------------------* * FORM: write_section (writes ## header line to output) *----------------------------------------------------------------------* FORM write_section USING pv_name TYPE string pv_count TYPE i. WRITE pv_count TO gv_cntstr LEFT-JUSTIFIED. CONDENSE gv_cntstr. CONCATENATE '## ' pv_name ': ' gv_cntstr ' rows' INTO gv_line. APPEND gv_line TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: write_header *----------------------------------------------------------------------* FORM write_header. DATA: lv_date TYPE c LENGTH 10, lv_sys TYPE c LENGTH 10. WRITE sy-datum TO lv_date. lv_sys = sy-sysid. APPEND '##ERPForgeAI Repository Export' TO gt_output. CONCATENATE '##System:' lv_sys INTO gv_line SEPARATED BY gv_tab. APPEND gv_line TO gt_output. CONCATENATE '##Date:' lv_date INTO gv_line SEPARATED BY gv_tab. APPEND gv_line TO gt_output. CONCATENATE '##Lang:' p_lang INTO gv_line SEPARATED BY gv_tab. APPEND gv_line TO gt_output. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_tables * DD02L filtered by tabclass + s_tab → manageable row count. * Use UP TO p_max ROWS as safety cap. *----------------------------------------------------------------------* FORM collect_tables. DATA: lt_raw TYPE TABLE OF dd02l, ls_d TYPE dd02l, lv_text TYPE c LENGTH 80, lv_pkg TYPE tadir-devclass. SELECT tabname tabclass FROM dd02l INTO TABLE lt_raw WHERE as4local = 'A' AND ( tabclass = 'TRANSP' OR tabclass = 'POOL' OR tabclass = 'CLUSTER' ) AND tabname IN s_tab. DATA lv_cnt TYPE i. DESCRIBE TABLE lt_raw LINES lv_cnt. IF lv_cnt > p_max. DELETE lt_raw FROM p_max + 1. DESCRIBE TABLE lt_raw LINES lv_cnt. ENDIF. PERFORM write_section USING 'TABLES' lv_cnt. CONCATENATE 'TABNAME' gv_tab 'TABCLASS' gv_tab 'DESCRIPTION' gv_tab 'DEVCLASS' INTO gv_line. APPEND gv_line TO gt_output. LOOP AT lt_raw INTO ls_d. CLEAR: lv_text, lv_pkg. SELECT SINGLE ddtext FROM dd02t INTO lv_text WHERE tabname = ls_d-tabname AND ddlanguage = p_lang AND as4local = 'A'. SELECT SINGLE devclass FROM tadir INTO lv_pkg WHERE obj_name = ls_d-tabname AND object = 'TABL'. CONCATENATE ls_d-tabname gv_tab ls_d-tabclass gv_tab lv_text gv_tab lv_pkg INTO gv_line. APPEND gv_line TO gt_output. ENDLOOP. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_structures *----------------------------------------------------------------------* FORM collect_structures. DATA: lt_raw TYPE TABLE OF dd02l, ls_d TYPE dd02l, lv_text TYPE c LENGTH 80, lv_pkg TYPE tadir-devclass. SELECT tabname tabclass FROM dd02l INTO TABLE lt_raw WHERE as4local = 'A' AND tabclass = 'INTTAB' AND tabname IN s_tab. DATA lv_cnt TYPE i. DESCRIBE TABLE lt_raw LINES lv_cnt. IF lv_cnt > p_max. DELETE lt_raw FROM p_max + 1. DESCRIBE TABLE lt_raw LINES lv_cnt. ENDIF. PERFORM write_section USING 'STRUCTURES' lv_cnt. CONCATENATE 'TABNAME' gv_tab 'TABCLASS' gv_tab 'DESCRIPTION' gv_tab 'DEVCLASS' INTO gv_line. APPEND gv_line TO gt_output. LOOP AT lt_raw INTO ls_d. CLEAR: lv_text, lv_pkg. SELECT SINGLE ddtext FROM dd02t INTO lv_text WHERE tabname = ls_d-tabname AND ddlanguage = p_lang AND as4local = 'A'. SELECT SINGLE devclass FROM tadir INTO lv_pkg WHERE obj_name = ls_d-tabname AND object = 'TABL'. CONCATENATE ls_d-tabname gv_tab ls_d-tabclass gv_tab lv_text gv_tab lv_pkg INTO gv_line. APPEND gv_line TO gt_output. ENDLOOP. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_fields * DD03L is the BIGGEST table — this caused the OOM crash with * 17 million rows. Fix: COUNT first, then PACKAGE SIZE streaming. *----------------------------------------------------------------------* FORM collect_fields. DATA: lt_chunk TYPE TABLE OF dd03l, ls_f TYPE dd03l, lv_text TYPE c LENGTH 80, lv_pos TYPE c LENGTH 10, lv_len TYPE c LENGTH 10, lv_dec TYPE c LENGTH 10, lv_total TYPE i, lv_written TYPE i. " Count first (cheap — no data transfer) SELECT COUNT(*) FROM dd03l INTO lv_total WHERE tabname IN s_tab AND as4local = 'A' AND fieldname NOT LIKE '.%'. " Cap at p_max for the header IF lv_total > p_max. lv_total = p_max. ENDIF. PERFORM write_section USING 'FIELDS' lv_total. CONCATENATE 'TABNAME' gv_tab 'FIELDNAME' gv_tab 'POS' gv_tab 'TYPE' gv_tab 'LEN' gv_tab 'DEC' gv_tab 'ROLLNAME' gv_tab 'KEY' gv_tab 'DESCRIPTION' INTO gv_line. APPEND gv_line TO gt_output. " Stream in chunks of gc_pkg_size — never loads all rows at once lv_written = 0. SELECT tabname fieldname position datatype leng decimals rollname keyflag FROM dd03l INTO CORRESPONDING FIELDS OF TABLE lt_chunk PACKAGE SIZE gc_pkg_size WHERE tabname IN s_tab AND as4local = 'A' AND fieldname NOT LIKE '.%'. LOOP AT lt_chunk INTO ls_f. IF lv_written >= p_max. EXIT. ENDIF. CLEAR lv_text. IF ls_f-rollname IS NOT INITIAL. SELECT SINGLE ddtext FROM dd04t INTO lv_text WHERE rollname = ls_f-rollname AND ddlanguage = p_lang AND as4local = 'A'. ENDIF. WRITE ls_f-position TO lv_pos LEFT-JUSTIFIED. WRITE ls_f-leng TO lv_len LEFT-JUSTIFIED. WRITE ls_f-decimals TO lv_dec LEFT-JUSTIFIED. CONDENSE lv_pos. CONDENSE lv_len. CONDENSE lv_dec. CONCATENATE ls_f-tabname gv_tab ls_f-fieldname gv_tab lv_pos gv_tab ls_f-datatype gv_tab lv_len gv_tab lv_dec gv_tab ls_f-rollname gv_tab ls_f-keyflag gv_tab lv_text INTO gv_line. APPEND gv_line TO gt_output. lv_written = lv_written + 1. ENDLOOP. IF lv_written >= p_max. EXIT. ENDIF. ENDSELECT. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_funcs * TFDIR can be large. Use PACKAGE SIZE + p_max cap. *----------------------------------------------------------------------* FORM collect_funcs. DATA: lt_chunk TYPE TABLE OF tfdir, ls_tf TYPE tfdir, ls_out TYPE ty_func, lt_fms TYPE TABLE OF ty_func, lt_bapis TYPE TABLE OF ty_func, lv_stext TYPE c LENGTH 60, lv_pkg TYPE tadir-devclass, lv_written TYPE i. lv_written = 0. SELECT funcname fmode pname FROM tfdir INTO CORRESPONDING FIELDS OF TABLE lt_chunk PACKAGE SIZE gc_pkg_size WHERE funcname IN s_func. LOOP AT lt_chunk INTO ls_tf. IF lv_written >= p_max. EXIT. ENDIF. CLEAR: lv_stext, lv_pkg. SELECT SINGLE stext FROM tftit INTO lv_stext WHERE funcname = ls_tf-funcname AND spras = p_lang. SELECT SINGLE devclass FROM tadir INTO lv_pkg WHERE obj_name = ls_tf-funcname AND object = 'FUNC'. ls_out-funcname = ls_tf-funcname. ls_out-fmode = ls_tf-fmode. ls_out-pname = ls_tf-pname. ls_out-devclass = lv_pkg. ls_out-stext = lv_stext. IF ls_tf-funcname CP 'BAPI*'. APPEND ls_out TO lt_bapis. ELSE. APPEND ls_out TO lt_fms. ENDIF. lv_written = lv_written + 1. ENDLOOP. IF lv_written >= p_max. EXIT. ENDIF. ENDSELECT. IF p_funcs = 'X'. DATA lv_cnt TYPE i. DESCRIBE TABLE lt_fms LINES lv_cnt. PERFORM write_section USING 'FUNCTION_MODULES' lv_cnt. CONCATENATE 'FUNCNAME' gv_tab 'FMODE' gv_tab 'FUNCGROUP' gv_tab 'DEVCLASS' gv_tab 'DESCRIPTION' INTO gv_line. APPEND gv_line TO gt_output. LOOP AT lt_fms INTO ls_out. CONCATENATE ls_out-funcname gv_tab ls_out-fmode gv_tab ls_out-pname gv_tab ls_out-devclass gv_tab ls_out-stext INTO gv_line. APPEND gv_line TO gt_output. ENDLOOP. APPEND '' TO gt_output. ENDIF. IF p_bapis = 'X'. DESCRIBE TABLE lt_bapis LINES lv_cnt. PERFORM write_section USING 'BAPIS' lv_cnt. CONCATENATE 'FUNCNAME' gv_tab 'FMODE' gv_tab 'FUNCGROUP' gv_tab 'DEVCLASS' gv_tab 'DESCRIPTION' INTO gv_line. APPEND gv_line TO gt_output. LOOP AT lt_bapis INTO ls_out. CONCATENATE ls_out-funcname gv_tab ls_out-fmode gv_tab ls_out-pname gv_tab ls_out-devclass gv_tab ls_out-stext INTO gv_line. APPEND gv_line TO gt_output. ENDLOOP. APPEND '' TO gt_output. ENDIF. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_classes * TADIR with object=CLAS can return 100k+ rows. * Use PACKAGE SIZE + p_max cap. *----------------------------------------------------------------------* FORM collect_classes. DATA: lt_chunk TYPE TABLE OF tadir, ls_ta TYPE tadir, ls_out TYPE ty_class, lv_total TYPE i, lv_written TYPE i. " Count first SELECT COUNT(*) FROM tadir INTO lv_total WHERE object = 'CLAS' AND devclass IN s_pack. IF lv_total > p_max. lv_total = p_max. ENDIF. PERFORM write_section USING 'CLASSES' lv_total. CONCATENATE 'CLSNAME' gv_tab 'DEVCLASS' INTO gv_line. APPEND gv_line TO gt_output. lv_written = 0. SELECT obj_name devclass FROM tadir INTO CORRESPONDING FIELDS OF TABLE lt_chunk PACKAGE SIZE gc_pkg_size WHERE object = 'CLAS' AND devclass IN s_pack. LOOP AT lt_chunk INTO ls_ta. IF lv_written >= p_max. EXIT. ENDIF. ls_out-clsname = ls_ta-obj_name. ls_out-devclass = ls_ta-devclass. CONCATENATE ls_out-clsname gv_tab ls_out-devclass INTO gv_line. APPEND gv_line TO gt_output. lv_written = lv_written + 1. ENDLOOP. IF lv_written >= p_max. EXIT. ENDIF. ENDSELECT. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_tcodes * TSTC has NO filter → selects ALL transactions in the system. * Use PACKAGE SIZE + p_max cap. *----------------------------------------------------------------------* FORM collect_tcodes. DATA: lt_chunk TYPE TABLE OF tstc, ls_t TYPE tstc, lv_text TYPE c LENGTH 60, lv_pkg TYPE tadir-devclass, lv_total TYPE i, lv_written TYPE i. " Count first SELECT COUNT(*) FROM tstc INTO lv_total. IF lv_total > p_max. lv_total = p_max. ENDIF. PERFORM write_section USING 'TRANSACTIONS' lv_total. CONCATENATE 'TCODE' gv_tab 'PROGRAM' gv_tab 'DESCRIPTION' gv_tab 'DEVCLASS' INTO gv_line. APPEND gv_line TO gt_output. lv_written = 0. SELECT tcode pgmna FROM tstc INTO CORRESPONDING FIELDS OF TABLE lt_chunk PACKAGE SIZE gc_pkg_size. LOOP AT lt_chunk INTO ls_t. IF lv_written >= p_max. EXIT. ENDIF. CLEAR: lv_text, lv_pkg. SELECT SINGLE ttext FROM tstct INTO lv_text WHERE tcode = ls_t-tcode AND sprsl = p_lang. SELECT SINGLE devclass FROM tadir INTO lv_pkg WHERE obj_name = ls_t-tcode AND object = 'TRAN'. CONCATENATE ls_t-tcode gv_tab ls_t-pgmna gv_tab lv_text gv_tab lv_pkg INTO gv_line. APPEND gv_line TO gt_output. lv_written = lv_written + 1. ENDLOOP. IF lv_written >= p_max. EXIT. ENDIF. ENDSELECT. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_packages * TDEVC is usually small (<10k). UP TO for safety. *----------------------------------------------------------------------* FORM collect_packages. DATA: lt_raw TYPE TABLE OF tdevc, ls_p TYPE tdevc. SELECT devclass ctext parentcl FROM tdevc INTO CORRESPONDING FIELDS OF TABLE lt_raw WHERE devclass IN s_pack. DATA lv_cnt TYPE i. DESCRIBE TABLE lt_raw LINES lv_cnt. IF lv_cnt > p_max. DELETE lt_raw FROM p_max + 1. DESCRIBE TABLE lt_raw LINES lv_cnt. ENDIF. PERFORM write_section USING 'PACKAGES' lv_cnt. CONCATENATE 'DEVCLASS' gv_tab 'DESCRIPTION' gv_tab 'PARENT' INTO gv_line. APPEND gv_line TO gt_output. LOOP AT lt_raw INTO ls_p. CONCATENATE ls_p-devclass gv_tab ls_p-ctext gv_tab ls_p-parentcl INTO gv_line. APPEND gv_line TO gt_output. ENDLOOP. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: collect_whereused * D010TAB can be large. Use PACKAGE SIZE + p_max cap. *----------------------------------------------------------------------* FORM collect_whereused. DATA: lt_chunk TYPE TABLE OF ty_whereused, ls_wu TYPE ty_whereused, lv_total TYPE i, lv_written TYPE i. IF s_tab[] IS INITIAL. APPEND '## WHERE_USED: Skipped - set table filter s_tab first' TO gt_output. APPEND '' TO gt_output. RETURN. ENDIF. " Count first SELECT COUNT(*) FROM d010tab INTO lv_total WHERE tabname IN s_tab. IF lv_total > p_max. lv_total = p_max. ENDIF. PERFORM write_section USING 'WHERE_USED' lv_total. CONCATENATE 'TABNAME' gv_tab 'PROGRAM' INTO gv_line. APPEND gv_line TO gt_output. lv_written = 0. SELECT tabname master FROM d010tab INTO CORRESPONDING FIELDS OF TABLE lt_chunk PACKAGE SIZE gc_pkg_size WHERE tabname IN s_tab. LOOP AT lt_chunk INTO ls_wu. IF lv_written >= p_max. EXIT. ENDIF. CONCATENATE ls_wu-tabname gv_tab ls_wu-master INTO gv_line. APPEND gv_line TO gt_output. lv_written = lv_written + 1. ENDLOOP. IF lv_written >= p_max. EXIT. ENDIF. ENDSELECT. APPEND '' TO gt_output. ENDFORM. *----------------------------------------------------------------------* * FORM: export_file *----------------------------------------------------------------------* FORM export_file. DATA: lv_fn TYPE string, lv_path TYPE string, lv_fp TYPE string, lv_action TYPE i, lv_rows TYPE c LENGTH 20. CONCATENATE 'ERPForge_RepoExport_' sy-sysid '_' sy-datum INTO lv_fn. cl_gui_frontend_services=>file_save_dialog( EXPORTING default_file_name = lv_fn default_extension = 'txt' file_filter = 'Text (*.txt)|*.txt|All|*.*' CHANGING filename = lv_fn path = lv_path fullpath = lv_fp user_action = lv_action EXCEPTIONS OTHERS = 4 ). IF sy-subrc <> 0 OR lv_action <> 0. MESSAGE 'Export cancelled.' TYPE 'I'. RETURN. ENDIF. cl_gui_frontend_services=>gui_download( EXPORTING filename = lv_fp filetype = 'ASC' trunc_trailing_blanks = 'X' codepage = '4110' CHANGING data_tab = gt_output EXCEPTIONS OTHERS = 22 ). IF sy-subrc = 0. DATA lv_cnt TYPE i. DESCRIBE TABLE gt_output LINES lv_cnt. WRITE lv_cnt TO lv_rows LEFT-JUSTIFIED. CONDENSE lv_rows. CONCATENATE 'Export OK:' lv_rows 'lines ->' lv_fp INTO gv_line SEPARATED BY ' '. MESSAGE gv_line TYPE 'S'. ELSE. MESSAGE 'Export failed - check path and permissions.' TYPE 'E'. ENDIF. ENDFORM.