*&---------------------------------------------------------------------* *& Report Z_ERPFORGE_03_FORMS_INVENTORY *&---------------------------------------------------------------------* *& ERPForgeAI - Step 3: Forms Inventory Export *& *& -- GOVERNANCE (read in under a minute) ------------------------------ *& READS : Form INVENTORY - SAPscript/SmartForms/Adobe/NACE object *& names, types, package and element counts (TADIR + form *& dictionaries). No form business content is read. *& DOES NOT : No UPDATE/INSERT/MODIFY/DELETE on DB tables (read-only). *& No RFC, no DESTINATION, no network/internet. No server-side *& file write. No business data / table rows / PII is read. *& Output is SAP METADATA only (structure, not contents) - *& nothing leaves your system unless YOU export it. *& FOOTPRINT: Transient analysis report - delete after extraction. *& SOURCE : MIT-licensed; public source + SHA-256 checksum at *& https://erpforgeai.de/sap-tools.html *& --------------------------------------------------------------------- *& *& VERSION: v0.3 *& v0.1 -> v0.2: *& - Fixed STXH field names: TDDATUM/TDTIME -> TDLDATE/TDLTIME *& - Wired TDLUSER as last_changed_by *& - Wired s_devc devclass filter (SAPscript only) *& - Resolved FOR-ALL-ENTRIES escaping & type-mismatch errors *& v0.2 -> v0.3 (after reading the Steckbrief for system ): *& - Added IS_SAP_STANDARD heuristic per row (shipped vs customer-touched). *& SAPscript: TDLDATE=TDFDATE && TDLTIME=TDFTIME, OR TDLUSER='DDIC'/'SAP*'. *& SF/Adobe: TADIR-AUTHOR='DDIC' OR matches 'SAP*'. *& - NACE split by KAPPL: EB (utility billing print), V3 (FI-CA *& correspondence), OTHER. System has IS-UT 618 + FI-CA 618 + *& IDEXDE 618 SP40 -> EB and V3 are the high-value segments. *& - Adobe Forms split into FPLY (layout) and FPCT (context/interface). *& IDEXDE-based MaBiS/GPKE output relies on layout+interface pairs. *& - NACE description now picks first non-empty of TDFORM (SAPscript) -> *& SFORM (SmartForm) -> PDFFORM (Adobe). *& *& Compatible: SAP_BASIS 7.40 SP02+ (target system : SAP_BASIS 750 SP34) *& *& Output schema (each row tab-delimited): *& FORM_TYPE | FORM_NAME | LANGUAGE | LAST_CHANGED_AT | LAST_CHANGED_BY | *& ELEMENT_COUNT | DEVCLASS | DESCRIPTION | COMPLEXITY_PROXY | *& IS_SAP_STANDARD *&---------------------------------------------------------------------* REPORT z_erpforge_03_forms_inventory. *----------------------------------------------------------------------* * Constants *----------------------------------------------------------------------* CONSTANTS: gc_pkg_size TYPE i VALUE 5000. CONSTANTS: gc_tab TYPE c VALUE cl_abap_char_utilities=>horizontal_tab. CONSTANTS: gc_lf TYPE c VALUE cl_abap_char_utilities=>newline. *----------------------------------------------------------------------* * TYPES *----------------------------------------------------------------------* TYPES: BEGIN OF ty_form_row, form_type TYPE c LENGTH 16, " SAPSCRIPT / SMARTFORMS / ADOBE_LAYOUT / ADOBE_INTERFACE / NACE_EB / NACE_V3 / NACE_OTHER form_name TYPE c LENGTH 40, " widened from 30 for TADIR obj_name language TYPE c LENGTH 2, last_changed_at TYPE c LENGTH 14, " YYYYMMDDhhmmss (where available) last_changed_by TYPE c LENGTH 12, element_count TYPE i, devclass TYPE tadir-devclass, description TYPE c LENGTH 60, complexity_proxy TYPE i, is_sap_standard TYPE abap_bool, " v0.3: 'X' = shipped/untouched, ' ' = custom-touched END OF ty_form_row, tt_form_row TYPE TABLE OF ty_form_row. DATA: gt_output TYPE tt_form_row. " Selection-screen labels (tb1, tb2, l_*) are auto-declared by the " SELECTION-SCREEN BEGIN OF BLOCK ... TITLE / COMMENT statements below. " Do NOT declare them with DATA — that triggers "already declared". " Their values are assigned in the INITIALIZATION event block. *----------------------------------------------------------------------* * SELECTION SCREEN *----------------------------------------------------------------------* SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE tb1. SELECTION-SCREEN BEGIN OF LINE. PARAMETERS: p_sapscr AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN COMMENT 4(60) l_sapscr. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. PARAMETERS: p_smartf AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN COMMENT 4(60) l_smartf. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. PARAMETERS: p_adobe AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN COMMENT 4(60) l_adobe. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. PARAMETERS: p_nace AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN COMMENT 4(60) l_nace. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN SKIP 1. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(33) l_devc. SELECT-OPTIONS: s_devc FOR sy-mandt MATCHCODE OBJECT zh_devclass NO INTERVALS. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(33) l_max. PARAMETERS: p_max TYPE i DEFAULT 5000. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN END OF BLOCK b1. SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE tb2. SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 1(33) l_file. PARAMETERS: p_file TYPE string LOWER CASE DEFAULT 'C:\Temp\Z_ERPFORGE_03_FORMS_INVENTORY.txt'. SELECTION-SCREEN END OF LINE. SELECTION-SCREEN END OF BLOCK b2. *----------------------------------------------------------------------* * SAPscript extraction *----------------------------------------------------------------------* FORM extract_sapscript USING ut_devclass TYPE STANDARD TABLE CHANGING ct_output TYPE tt_form_row. DATA: ls_row TYPE ty_form_row. DATA: lt_stxh TYPE TABLE OF stxh. " lt_names row must match stxh-tdname (CHAR 70) for FOR ALL ENTRIES DATA: BEGIN OF ls_name, tdname TYPE stxh-tdname, END OF ls_name. DATA: lt_names LIKE TABLE OF ls_name. IF ut_devclass IS NOT INITIAL. SELECT obj_name FROM tadir INTO TABLE lt_names WHERE pgmid = 'R3TR' AND object = 'FORM' AND devclass IN ut_devclass. IF lt_names IS NOT INITIAL. SELECT * FROM stxh INTO TABLE lt_stxh UP TO p_max ROWS FOR ALL ENTRIES IN lt_names WHERE tdobject = 'FORM' AND tdname = lt_names-tdname. ENDIF. ELSE. SELECT * FROM stxh INTO TABLE lt_stxh UP TO p_max ROWS WHERE tdobject = 'FORM'. ENDIF. LOOP AT lt_stxh ASSIGNING FIELD-SYMBOL(). CLEAR ls_row. ls_row-form_type = 'SAPSCRIPT'. ls_row-form_name = -tdname. ls_row-language = -tdspras. CONCATENATE -tdldate -tdltime INTO ls_row-last_changed_at. ls_row-last_changed_by = -tdluser. " is_sap_standard heuristic: " shipped/untouched if last-changed equals first-created " OR last-changed-by is DDIC / starts with 'SAP' IF ( -tdldate = -tdfdate AND -tdltime = -tdftime ) OR -tdluser = 'DDIC' OR -tdluser CP 'SAP*'. ls_row-is_sap_standard = abap_true. ELSE. ls_row-is_sap_standard = abap_false. ENDIF. " Element count proxy from STXL ITF lines SELECT COUNT(*) FROM stxl INTO ls_row-element_count WHERE tdobject = 'FORM' AND tdname = -tdname AND tdspras = -tdspras. ls_row-complexity_proxy = ls_row-element_count. SELECT SINGLE devclass FROM tadir INTO ls_row-devclass WHERE pgmid = 'R3TR' AND object = 'FORM' AND obj_name = -tdname. ls_row-description = -tdtitle. APPEND ls_row TO ct_output. ENDLOOP. ENDFORM. *----------------------------------------------------------------------* * SmartForms extraction *----------------------------------------------------------------------* FORM extract_smartforms CHANGING ct_output TYPE tt_form_row. DATA: ls_row TYPE ty_form_row. DATA: lt_admin TYPE TABLE OF stxfadm. SELECT * FROM stxfadm INTO TABLE lt_admin UP TO p_max ROWS. LOOP AT lt_admin ASSIGNING FIELD-SYMBOL(). CLEAR ls_row. ls_row-form_type = 'SMARTFORMS'. ls_row-form_name = -formname. ls_row-language = -masterlang. " STXFADM change-tracking field names vary by SP; v0.3 leaves " last_changed_at blank, populates last_changed_by from TADIR-AUTHOR " (which is creator, not last-changer — refine in v0.4 once we have " real output from system to calibrate against). ls_row-last_changed_at = ''. SELECT SINGLE author devclass FROM tadir INTO (ls_row-last_changed_by, ls_row-devclass) WHERE pgmid = 'R3TR' AND object = 'SSFO' AND obj_name = -formname. ls_row-element_count = 0. ls_row-complexity_proxy = 0. " is_sap_standard heuristic for SmartForms: TADIR author is SAP/DDIC IF ls_row-last_changed_by = 'DDIC' OR ls_row-last_changed_by CP 'SAP*'. ls_row-is_sap_standard = abap_true. ELSE. ls_row-is_sap_standard = abap_false. ENDIF. APPEND ls_row TO ct_output. ENDLOOP. ENDFORM. *----------------------------------------------------------------------* * Adobe Forms extraction (v0.3: split FPLY layout / FPCT interface) *----------------------------------------------------------------------* FORM extract_adobe_forms CHANGING ct_output TYPE tt_form_row. DATA: ls_row TYPE ty_form_row. DATA: lt_tadir TYPE TABLE OF tadir. " On IDEXDE/IS-U Versorger systems, Adobe is heavily used for regulatory " output (MaBiS, GPKE). Layout (FPLY) and Interface (FPCT) come as a pair; " we read both so the migration audit can match them up downstream. SELECT * FROM tadir INTO TABLE lt_tadir UP TO p_max ROWS WHERE pgmid = 'R3TR' AND ( object = 'FPLY' OR object = 'FPCT' ). LOOP AT lt_tadir ASSIGNING FIELD-SYMBOL(). CLEAR ls_row. IF -object = 'FPLY'. ls_row-form_type = 'ADOBE_LAYOUT'. ELSE. ls_row-form_type = 'ADOBE_INTERFACE'. ENDIF. ls_row-form_name = -obj_name. ls_row-language = ''. ls_row-last_changed_at = ''. ls_row-last_changed_by = -author. ls_row-element_count = 0. ls_row-complexity_proxy = 2. " refine after operator feedback ls_row-devclass = -devclass. IF -author = 'DDIC' OR -author CP 'SAP*'. ls_row-is_sap_standard = abap_true. ELSE. ls_row-is_sap_standard = abap_false. ENDIF. APPEND ls_row TO ct_output. ENDLOOP. ENDFORM. *----------------------------------------------------------------------* * NACE output-determination cross-reference (v0.3: split by KAPPL) *----------------------------------------------------------------------* FORM extract_nace CHANGING ct_output TYPE tt_form_row. DATA: ls_row TYPE ty_form_row. DATA: lt_tnapr TYPE TABLE OF tnapr. " TNAPR maps output-type -> ABAP-Programm + Form-routine + form-name. " On a Versorger (IS-UT + FI-CA + IDEXDE) the high-value KAPPLs are: " EB = utility billing print " V3 = FI-CA correspondence " Everything else (V1 = SD, EF = MM, etc.) is OTHER. SELECT * FROM tnapr INTO TABLE lt_tnapr UP TO p_max ROWS. LOOP AT lt_tnapr ASSIGNING FIELD-SYMBOL(). CLEAR ls_row. CASE -kappl. WHEN 'EB'. ls_row-form_type = 'NACE_EB'. WHEN 'V3'. ls_row-form_type = 'NACE_V3'. WHEN OTHERS. ls_row-form_type = 'NACE_OTHER'. ENDCASE. CONCATENATE -kappl -kschl INTO ls_row-form_name SEPARATED BY '/'. " Description = the actual referenced form name. " v0.3 only uses SFORM (SmartForm name) since the compiler confirmed " it exists on SAP_BASIS 750. TNAPR field names for SAPscript and " Adobe references vary across releases — to be added in v0.4 once " their actual field names on system are known. IF -sform IS NOT INITIAL. ls_row-description = -sform. ENDIF. ls_row-complexity_proxy = 1. ls_row-is_sap_standard = abap_false. " NACE config rows are tenant-specific by definition APPEND ls_row TO ct_output. ENDLOOP. ENDFORM. *----------------------------------------------------------------------* * Output writer *----------------------------------------------------------------------* FORM write_output_to_file USING uv_filename TYPE string ut_output TYPE tt_form_row. DATA: lv_line TYPE string. DATA: lt_lines TYPE TABLE OF string. " Header row — using explicit { gc_tab } to avoid any \t-escape ambiguity lv_line = |FORM_TYPE{ gc_tab }FORM_NAME{ gc_tab }LANGUAGE{ gc_tab }| && |LAST_CHANGED_AT{ gc_tab }LAST_CHANGED_BY{ gc_tab }| && |ELEMENT_COUNT{ gc_tab }DEVCLASS{ gc_tab }DESCRIPTION{ gc_tab }| && |COMPLEXITY_PROXY{ gc_tab }IS_SAP_STANDARD|. APPEND lv_line TO lt_lines. LOOP AT ut_output ASSIGNING FIELD-SYMBOL(). lv_line = |{ -form_type }{ gc_tab }{ -form_name }{ gc_tab }| && |{ -language }{ gc_tab }{ -last_changed_at }{ gc_tab }| && |{ -last_changed_by }{ gc_tab }{ -element_count }{ gc_tab }| && |{ -devclass }{ gc_tab }{ -description }{ gc_tab }| && |{ -complexity_proxy }{ gc_tab }{ -is_sap_standard }|. APPEND lv_line TO lt_lines. ENDLOOP. cl_gui_frontend_services=>gui_download( EXPORTING filename = uv_filename filetype = 'ASC' write_field_separator = ' ' trunc_trailing_blanks = abap_true CHANGING data_tab = lt_lines EXCEPTIONS OTHERS = 1 ). IF sy-subrc <> 0. WRITE: / 'gui_download failed:', sy-subrc. ELSE. WRITE: / 'Forms inventory written to:', uv_filename. WRITE: / |Total rows: { lines( ut_output ) }|. ENDIF. ENDFORM. *----------------------------------------------------------------------* * Selection-screen labels (set once before screen is displayed) *----------------------------------------------------------------------* INITIALIZATION. tb1 = 'Forms Inventory - Extraction Options'. tb2 = 'Output File'. l_sapscr = 'Extract SAPscript Forms (STXH headers + STXL lines)'. l_smartf = 'Extract SmartForms (STXFADM admin table)'. l_adobe = 'Extract Adobe Forms (TADIR FPLY layouts + FPCT ifaces)'. l_nace = 'Extract NACE Output-Determination (TNAPR cross-ref)'. l_devc = 'Filter by Devclass (optional)'. l_max = 'Max rows per source (cap)'. l_file = 'Output file path'. *----------------------------------------------------------------------* * Main *----------------------------------------------------------------------* START-OF-SELECTION. WRITE: / 'Z_ERPFORGE_03_FORMS_INVENTORY v0.3'. WRITE: / '====================================='. WRITE: /. IF p_sapscr = 'X'. PERFORM extract_sapscript USING s_devc[] CHANGING gt_output. WRITE: / | SAPscript: { lines( gt_output ) } rows so far|. ENDIF. IF p_smartf = 'X'. PERFORM extract_smartforms CHANGING gt_output. WRITE: / | SmartForms: { lines( gt_output ) } rows so far|. ENDIF. IF p_adobe = 'X'. PERFORM extract_adobe_forms CHANGING gt_output. WRITE: / | Adobe Forms: { lines( gt_output ) } rows so far|. ENDIF. IF p_nace = 'X'. PERFORM extract_nace CHANGING gt_output. WRITE: / | NACE x-ref: { lines( gt_output ) } rows so far|. ENDIF. WRITE: /. PERFORM write_output_to_file USING p_file gt_output. WRITE: /. WRITE: / 'Done. Send the TXT to ERPforgeAI for parsing + analysis.'. WRITE: / 'NOTE (v0.3): IS_SAP_STANDARD = X means the form was either never'. WRITE: / 'modified after creation, or its last-toucher was'. WRITE: / 'DDIC or a SAP* user. Filter on IS_SAP_STANDARD = blank'. WRITE: / 'to focus the migration audit on customer-touched forms.'.