diff --git a/zbackup4abap.abap b/zbackup4abap.abap index fc3d0e1..4c8bf2b 100644 --- a/zbackup4abap.abap +++ b/zbackup4abap.abap @@ -1,11 +1,7 @@ -*&---------------------------------------------------------------------* -*& Report zbackup4abap -*&---------------------------------------------------------------------* -*& -*&---------------------------------------------------------------------* REPORT zbackup4abap. -" 借用 DEMO_INDX_BLOB 记录一些增量信息 以加快运行速度 +" v3.00.00 +" 逻辑整理 *&---------------------------------------------------------------------- * Type-Pools @@ -19,98 +15,596 @@ TABLES: tadir, sscrfields. *&---------------------------------------------------------------------- * Types *&---------------------------------------------------------------------- -TYPES: BEGIN OF ty_folder, - tag TYPE char10, - folder TYPE char10, - END OF ty_folder. - -TYPES: BEGIN OF ty_function, - functionname LIKE tfdir-funcname, - functiongroup LIKE enlfdir-area, - includenumber LIKE tfdir-include, - functionmaininclude LIKE tfdir-funcname, - functiontitle LIKE tftit-stext, - progname LIKE tfdir-pname, - - reportname TYPE reposrc-progname, - END OF ty_function. - -TYPES: BEGIN OF ty_log_list, - main TYPE text30, - uname TYPE text12, - datum TYPE datum, - uzeit TYPE uzeit, - END OF ty_log_list. -TYPES: tt_log_list TYPE STANDARD TABLE OF ty_log_list WITH DEFAULT KEY. -TYPES: BEGIN OF ty_log_flow, - type TYPE text30, - info TYPE tt_log_list, - END OF ty_log_flow. - -TYPES: BEGIN OF ty_delt_log, - object TYPE trobjtype, " 对象类型 - ddate TYPE datum, " 增量日期 - dtime TYPE uzeit, " 增量时间 - END OF ty_delt_log. - -TYPES: BEGIN OF ty_tdevc_parentcl, - parentcl TYPE tdevc-parentcl, - END OF ty_tdevc_parentcl. -TYPES: tt_tdevc_parentcl TYPE TABLE OF ty_tdevc_parentcl. - -CLASS lcl_export_ddldict DEFINITION DEFERRED. -CLASS lcl_pretty_json DEFINITION DEFERRED. +INTERFACE lif_backup4abap_object DEFERRED. +CLASS lcl_backup4abap_filter_time DEFINITION DEFERRED. +CLASS lcl_backup4abap_filter_package DEFINITION DEFERRED. +CLASS lcl_backup4abap_screen_option DEFINITION DEFERRED. +CLASS lcl_backup4abap_folder DEFINITION DEFERRED. + +CLASS lcl_backup4abap_objects DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_prog DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_fugr DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_clas DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_text DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_msag DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_tabl DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_doma DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_dtel DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_ttyp DEFINITION DEFERRED. +CLASS lcl_backup4abap_object_ddls DEFINITION DEFERRED. + +CLASS lcl_backup4abap_export DEFINITION DEFERRED. + +" TOOLS CLASS lcl_progress_bar DEFINITION DEFERRED. +CLASS lcl_pretty_json DEFINITION DEFERRED. + +DEFINE _stop. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 DISPLAY LIKE 'E'. + STOP. + ENDIF. +END-OF-DEFINITION. *&---------------------------------------------------------------------- * Variables *&---------------------------------------------------------------------- -DATA: gr_zip TYPE REF TO cl_abap_zip, " abap 压缩类 - gr_cover_out TYPE REF TO cl_abap_conv_out_ce. " abap 编码转换类 +INTERFACE lif_backup4abap_object. + + TYPES: BEGIN OF ty_split_limit_normal, + name TYPE string, + END OF ty_split_limit_normal. + TYPES: BEGIN OF ty_files, + name TYPE string, + data TYPE xstring, + END OF ty_files. + DATA: parent_folder TYPE string, + files TYPE TABLE OF ty_files. + + " loadfiles + METHODS loadfiles. + + " split folder + METHODS split_folder IMPORTING i_limit TYPE data + RETURNING VALUE(rv_filename) TYPE string. + + " load to zip + METHODS load2zip IMPORTING io_zip TYPE REF TO cl_abap_zip. + +ENDINTERFACE. +CLASS lcl_backup4abap_filter_package DEFINITION. + PUBLIC SECTION. + + TYPES: BEGIN OF ty_tdevc_parentcl, + parentcl TYPE tdevc-parentcl, + END OF ty_tdevc_parentcl. + TYPES: tt_tdevc_parentcl TYPE TABLE OF ty_tdevc_parentcl. + CLASS-DATA: lt_range TYPE RANGE OF tadir-devclass. + + CLASS-METHODS set EXCEPTIONS e_no_filter. + CLASS-METHODS fix IMPORTING it_package TYPE tt_tdevc_parentcl. +ENDCLASS. +CLASS lcl_backup4abap_filter_time DEFINITION. + PUBLIC SECTION. + TYPES: BEGIN OF ty_delt_log, + object TYPE trobjtype, " 对象类型 + ddate TYPE datum, " 增量日期 + dtime TYPE uzeit, " 增量时间 + END OF ty_delt_log, + tt_delt_log TYPE STANDARD TABLE OF ty_delt_log WITH EMPTY KEY. + DATA: lt_delt_log TYPE tt_delt_log. + + CLASS-METHODS factory IMPORTING iv_limit TYPE sy-uname DEFAULT sy-uname + RETURNING VALUE(ro_objt) TYPE REF TO lcl_backup4abap_filter_time. + METHODS constructor IMPORTING iv_limit TYPE sy-uname. + + METHODS get IMPORTING iv_object TYPE trobjtype + RETURNING VALUE(rs_delt_log) TYPE ty_delt_log. + PROTECTED SECTION. + CLASS-DATA objt TYPE REF TO lcl_backup4abap_filter_time. + CONSTANTS c_delta_store_id_fix_part TYPE char18 VALUE 'DeltaDown'. +ENDCLASS. +CLASS lcl_backup4abap_screen_option DEFINITION. + PUBLIC SECTION. + TYPES: ty_option TYPE char30, + tt_options TYPE STANDARD TABLE OF ty_option WITH EMPTY KEY. + CLASS-DATA: options TYPE tt_options, + option_seted TYPE abap_bool. + + CLASS-METHODS set_option IMPORTING iv_option TYPE ty_option. + CLASS-METHODS selected_option RETURNING VALUE(rt_options) TYPE tt_options. + +ENDCLASS. +CLASS lcl_backup4abap_folder DEFINITION. + PUBLIC SECTION. + + TYPES: BEGIN OF ty_folder, + tag TYPE char10, + folder TYPE char10, + END OF ty_folder. + CLASS-DATA: folder TYPE TABLE OF ty_folder. + + CLASS-METHODS: class_constructor. + + " 由于需要在 TEXT 中调用,将原本分散的分割方法合并到此 + CLASS-METHODS: split_folder_prog IMPORTING name TYPE string subc TYPE reposrc-subc + RETURNING VALUE(rv_folder) TYPE string. + CLASS-METHODS: split_folder_clas IMPORTING name TYPE string + RETURNING VALUE(rv_folder) TYPE string. + CLASS-METHODS: split_folder_fugr IMPORTING name TYPE string + RETURNING VALUE(rv_folder) TYPE string. + CLASS-METHODS: split_folder_ddls IMPORTING name TYPE string + RETURNING VALUE(rv_folder) TYPE string. +ENDCLASS. +CLASS lcl_backup4abap_objects DEFINITION. + PUBLIC SECTION. + CONSTANTS c_extension_abap TYPE string VALUE 'abap'. + CONSTANTS c_extension_txt TYPE string VALUE 'txt'. + CONSTANTS c_extension_ddl TYPE string VALUE 'ddl'. + CONSTANTS c_extension_json TYPE string VALUE 'json'. + CONSTANTS c_newline TYPE abap_cr_lf VALUE cl_abap_char_utilities=>cr_lf. + CONSTANTS c_tab TYPE abap_char1 VALUE cl_abap_char_utilities=>horizontal_tab. + + " init + METHODS: constructor. + + " delta load file + METHODS: is_delta RETURNING VALUE(rv_bool) TYPE abap_bool. + + " set map file + + " set log file + + PROTECTED SECTION. + DATA: o_pb TYPE REF TO lcl_progress_bar, + o_conv_out TYPE REF TO cl_abap_conv_out_ce. + +ENDCLASS. +CLASS lcl_backup4abap_object_prog DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: BEGIN OF ty_split_limit, + name TYPE string, + subc TYPE reposrc-subc, + END OF ty_split_limit. +ENDCLASS. +CLASS lcl_backup4abap_object_fugr DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + TYPES: BEGIN OF ty_function, + functionname TYPE tfdir-funcname, + functiongroup TYPE enlfdir-area, + includenumber TYPE tfdir-include, + functionmaininclude TYPE tfdir-funcname, + functiontitle TYPE tftit-stext, + progname TYPE tfdir-pname, + + uname TYPE reposrc-unam, + udate TYPE reposrc-udat, + utime TYPE reposrc-utime, + + reportname TYPE reposrc-progname, + END OF ty_function, + tt_function TYPE STANDARD TABLE OF ty_function WITH EMPTY KEY. + TYPES: tt_range_area TYPE RANGE OF reposrc-progname. + + METHODS: constructor. + + METHODS: fix_more IMPORTING io_func TYPE REF TO data. + METHODS: get_more IMPORTING it_range_area TYPE tt_range_area. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: ty_split_limit TYPE string. +ENDCLASS. +CLASS lcl_backup4abap_object_clas DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + TYPES: BEGIN OF ty_type, + type TYPE seop_include_ext_app, + exline TYPE i, + END OF ty_type. + DATA: BEGIN OF ls_class_key, + classnamelength TYPE i, + publicclasskey TYPE string, + privateclasskey TYPE string, + protectedclasskey TYPE string, + textelementkey TYPE string, + typesclasskey TYPE string, + END OF ls_class_key. + DATA: lt_type TYPE TABLE OF ty_type. + + DATA: o_source TYPE REF TO object, + o_instance TYPE REF TO object. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: ty_split_limit TYPE string. +ENDCLASS. +CLASS lcl_backup4abap_object_text DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: BEGIN OF ty_split_limit, + object TYPE tadir-object, + progname TYPE string, + END OF ty_split_limit. +ENDCLASS. +CLASS lcl_backup4abap_object_msag DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + TYPES: BEGIN OF ty_arbgb, + arbgb TYPE t100u-arbgb, + datum TYPE t100u-datum, + END OF ty_arbgb. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: BEGIN OF ty_split_limit, + object TYPE tadir-object, + progname TYPE string, + END OF ty_split_limit. +ENDCLASS. +CLASS lcl_backup4abap_object_tabl DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + TYPES: BEGIN OF ty_dd02l, + tabname TYPE dd02l-tabname, + contflag TYPE dd02l-contflag, + authclass TYPE dd02l-authclass, + mainflag TYPE dd02l-mainflag, + exclass TYPE dd02l-exclass, + as4date TYPE dd02l-as4date, + as4time TYPE dd02l-as4time, + END OF ty_dd02l, + BEGIN OF ty_dd02t, + tabname TYPE dd02t-tabname, + ddlanguage TYPE dd02t-ddlanguage, + ddtext TYPE dd02t-ddtext, + END OF ty_dd02t, + BEGIN OF ty_dd03t, + tabname TYPE dd03t-tabname, + fieldname TYPE dd03t-fieldname, + ddlanguage TYPE dd03t-ddlanguage, + ddtext TYPE dd03t-ddtext, + END OF ty_dd03t. + TYPES: BEGIN OF ty_dd05q, + tabname TYPE dd05q-tabname, + fieldname TYPE dd05q-fieldname, + primpos TYPE dd05q-primpos, + fortable TYPE dd05q-fortable, + forkey TYPE dd05q-forkey, + checktable TYPE dd05q-checktable, + checkfield TYPE dd05q-checkfield, + END OF ty_dd05q, + BEGIN OF ty_dd08l, + tabname TYPE dd08l-tabname, + fieldname TYPE dd08l-fieldname, + checktable TYPE dd08l-checktable, + frkart TYPE dd08l-frkart, + cardleft TYPE dd08l-cardleft, + card TYPE dd08l-card, + ddlanguage TYPE dd08t-ddlanguage, + ddtext TYPE dd08t-ddtext, + END OF ty_dd08l. + DATA: tdd02l TYPE TABLE OF ty_dd02l, + tdd02t TYPE TABLE OF ty_dd02t, + tdd03l TYPE TABLE OF dd03l, + tdd03t TYPE TABLE OF ty_dd03t. + DATA: tdd05q TYPE TABLE OF ty_dd05q, + tdd08l TYPE TABLE OF ty_dd08l. + + DATA: ddldicts TYPE TABLE OF text1000. -DATA: gv_parent_folder TYPE string. -DATA: gt_folder TYPE TABLE OF ty_folder. + METHODS: constructor. -DATA: gc_extension_name TYPE string VALUE 'abap'. + METHODS: get_base IMPORTING iv_tabcls TYPE tabclass. + METHODS: get_transp_more. -DATA: gv_export_fullpath TYPE string. -DATA: gt_map_file TYPE TABLE OF string. + METHODS: fill_table. + METHODS: fill_struct. -DATA: gt_log_flow TYPE TABLE OF ty_log_flow. + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. -DATA: gt_range_devclass TYPE RANGE OF tadir-devclass. + TYPES: ty_split_limit TYPE string. -"CONSTANTS: gc_newline type ABAP_CHAR1 VALUE CL_ABAP_CHAR_UTILITIES=>NEWLINE. -CONSTANTS: gc_newline TYPE abap_cr_lf VALUE cl_abap_char_utilities=>cr_lf. -CONSTANTS: gc_tab TYPE abap_char1 VALUE cl_abap_char_utilities=>horizontal_tab. + TYPES: BEGIN OF ty_foreignkey_eq, + fortable TYPE fortable, + forkey TYPE forkey, + checkfield TYPE fieldname, + END OF ty_foreignkey_eq. + TYPES: tty_foreignkey_eq TYPE TABLE OF ty_foreignkey_eq WITH EMPTY KEY. + TYPES: BEGIN OF ty_foreignkey, + label TYPE string, + screencheck TYPE text6, + keytype TYPE frkart, + cardleft TYPE cardleft, + card TYPE card, + checktable TYPE string, + foreignkey_eq TYPE tty_foreignkey_eq, + END OF ty_foreignkey. + TYPES: BEGIN OF ty_field, + name TYPE string, + key TYPE char1, + nonull TYPE char1, + type TYPE string, + addtion TYPE string, " 补充 + adddesc TYPE string, + foreignkey TYPE ty_foreignkey, + END OF ty_field. + TYPES: tt_fields TYPE TABLE OF ty_field WITH EMPTY KEY. + + DATA: field_max TYPE i. + METHODS: preproc_fields IMPORTING tabname TYPE tabname + RETURNING VALUE(r_fields) TYPE tt_fields. + + METHODS: field_type IMPORTING iv_datatype TYPE dd03l-datatype + iv_leng TYPE dd03l-leng + iv_decimals TYPE dd03l-decimals + RETURNING VALUE(rv_type) TYPE string. + + METHODS: + set_label IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string, + set_encat IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string, + set_tabty IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string, + set_edits IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string, + set_deliv IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string, + set_actty IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string, + set_repla IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string, + set_define IMPORTING str TYPE data RETURNING VALUE(rv_str) TYPE string. + +ENDCLASS. +CLASS lcl_backup4abap_object_doma DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: ty_split_limit TYPE string. + + TYPES: BEGIN OF ty_domavalues, + valpos TYPE i, + ddtext TYPE string, + domvalue_l TYPE string, + domvalue_h TYPE string, + appval TYPE abap_bool, " 附加 + END OF ty_domavalues. + TYPES: BEGIN OF ty_doma, + domname TYPE dd01l-domname, + as4user TYPE dd01l-as4user, + as4date TYPE dd01l-as4date, + as4time TYPE dd01l-as4time, + values TYPE TABLE OF ty_domavalues WITH DEFAULT KEY, + END OF ty_doma. +ENDCLASS. +CLASS lcl_backup4abap_object_dtel DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: ty_split_limit TYPE string. + + TYPES: BEGIN OF ty_elem, + rollname TYPE dd04l-rollname, + domname TYPE dd04l-domname, + as4user TYPE dd04l-as4user, + as4date TYPE dd04l-as4date, + as4time TYPE dd04l-as4time, + datatype TYPE dd04l-datatype, + leng TYPE dd04l-leng, + decimals TYPE dd04l-decimals, + outputlen TYPE dd04l-outputlen, + lowercase TYPE dd04l-lowercase, + convexit TYPE dd04l-convexit, + entitytab TYPE dd04l-entitytab, + refkind TYPE dd04l-refkind, + ddtext TYPE dd04t-ddtext, + reptext TYPE dd04t-reptext, + scrtext_s TYPE dd04t-scrtext_s, + scrtext_m TYPE dd04t-scrtext_m, + scrtext_l TYPE dd04t-scrtext_l, + END OF ty_elem. +ENDCLASS. +CLASS lcl_backup4abap_object_ttyp DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: ty_split_limit TYPE string. + + TYPES: BEGIN OF ty_ttyp, + typename TYPE dd40l-typename, + rowtype TYPE dd40l-rowtype, + rowkind TYPE dd40l-rowkind, + datatype TYPE dd40l-datatype, + leng TYPE dd40l-leng, + decimals TYPE dd40l-decimals, + accessmode TYPE dd40l-accessmode, + keydef TYPE dd40l-keydef, + keykind TYPE dd40l-keykind, + keyfdcount TYPE dd40l-keyfdcount, + generic TYPE dd40l-generic, + typelen TYPE dd40l-typelen, + as4user TYPE dd40l-as4user, + as4date TYPE dd40l-as4date, + as4time TYPE dd40l-as4time, + ddtext TYPE dd40t-ddtext, + END OF ty_ttyp. +ENDCLASS. +CLASS lcl_backup4abap_object_ddls DEFINITION INHERITING FROM lcl_backup4abap_objects CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES lif_backup4abap_object. + + ALIASES loadfiles FOR lif_backup4abap_object~loadfiles. + ALIASES load2zip FOR lif_backup4abap_object~load2zip. + + METHODS: constructor. + + PROTECTED SECTION. + ALIASES split_folder FOR lif_backup4abap_object~split_folder. + ALIASES parent_folder FOR lif_backup4abap_object~parent_folder. + ALIASES files FOR lif_backup4abap_object~files. + + TYPES: ty_split_limit TYPE string. +ENDCLASS. + + + +CLASS lcl_backup4abap_export DEFINITION. + PUBLIC SECTION. + DATA: file_path TYPE string. + + CLASS-METHODS factory RETURNING VALUE(ro_objt) TYPE REF TO lcl_backup4abap_export. + + METHODS: constructor. + + METHODS: path EXCEPTIONS e_no_choese. + METHODS: download EXCEPTIONS e_no_file. + + METHODS: main EXCEPTIONS e_no_screen_choese. + + PROTECTED SECTION. + CLASS-DATA objt TYPE REF TO lcl_backup4abap_export. + DATA: o_zip TYPE REF TO cl_abap_zip. +ENDCLASS. -DATA: gt_range_append_class TYPE RANGE OF vseoclass-clsname. +CLASS lcl_progress_bar DEFINITION. + PUBLIC SECTION. + + DATA: count TYPE i, + base_desc TYPE string, + curr TYPE i. -DATA: gt_delt_log TYPE TABLE OF ty_delt_log. + METHODS constructor IMPORTING " i_count TYPE i OPTIONAL + i_base_desc TYPE string OPTIONAL. + + METHODS add IMPORTING i_add TYPE i DEFAULT 1 + i_desc TYPE data OPTIONAL. + PRIVATE SECTION. + DATA: percent TYPE p DECIMALS 0 LENGTH 5, + percent_old TYPE p DECIMALS 0 LENGTH 5. + METHODS display IMPORTING desc TYPE data. +ENDCLASS. -DATA: gt_range_objname TYPE RANGE OF tadir-obj_name. +CLASS lcl_pretty_json DEFINITION. + PUBLIC SECTION. -DATA: gv_delta_store_id TYPE char30. -CONSTANTS: gc_delta_store_id_fix_part TYPE char18 VALUE 'DeltaDownload'. + CLASS-METHODS: pretty IMPORTING json TYPE string + RETURNING VALUE(pretty_json) TYPE string. +ENDCLASS. *&---------------------------------------------------------------------- * Select Screen *&---------------------------------------------------------------------- SELECTION-SCREEN BEGIN OF BLOCK blck1 WITH FRAME. + SELECTION-SCREEN BEGIN OF LINE. + SELECTION-SCREEN COMMENT 5(23) t_pack FOR FIELD s_pack. + SELECT-OPTIONS: s_pack FOR tadir-devclass. + SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN END OF BLOCK blck1. + +SELECTION-SCREEN BEGIN OF BLOCK blck2 WITH FRAME. + SELECTION-SCREEN BEGIN OF LINE. + SELECTION-SCREEN COMMENT 5(23) t_delt FOR FIELD p_delt. + PARAMETERS: p_delt TYPE c AS CHECKBOX DEFAULT 'X'. + SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN END OF BLOCK blck2. + +SELECTION-SCREEN BEGIN OF BLOCK blck3 WITH FRAME. " 代码相关 " report SELECTION-SCREEN BEGIN OF LINE. SELECTION-SCREEN COMMENT 5(23) t_prog FOR FIELD p_prog. - PARAMETERS: p_prog AS CHECKBOX DEFAULT 'X'. + PARAMETERS: p_prog AS CHECKBOX DEFAULT ''."'X'. SELECTION-SCREEN END OF LINE. - " function + " function -> 基于函数组 SELECTION-SCREEN BEGIN OF LINE. - SELECTION-SCREEN COMMENT 5(23) t_func FOR FIELD p_func. - PARAMETERS: p_func AS CHECKBOX DEFAULT 'X'. + SELECTION-SCREEN COMMENT 5(23) t_fugr FOR FIELD p_fugr. + PARAMETERS: p_fugr AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. " Class @@ -131,9 +625,9 @@ SELECTION-SCREEN BEGIN OF BLOCK blck1 WITH FRAME. PARAMETERS: p_msag AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. -SELECTION-SCREEN END OF BLOCK blck1. +SELECTION-SCREEN END OF BLOCK blck3. -SELECTION-SCREEN BEGIN OF BLOCK blck2 WITH FRAME. +SELECTION-SCREEN BEGIN OF BLOCK blck4 WITH FRAME. " 表相关 " Table @@ -142,18 +636,10 @@ SELECTION-SCREEN BEGIN OF BLOCK blck2 WITH FRAME. PARAMETERS: p_tabl AS CHECKBOX DEFAULT 'X' USER-COMMAND tab. SELECTION-SCREEN END OF LINE. - SELECTION-SCREEN BEGIN OF LINE. - SELECTION-SCREEN COMMENT 15(10) t_txml MODIF ID gp1 FOR FIELD p_txml. - PARAMETERS: p_txml TYPE c RADIOBUTTON GROUP gp1 USER-COMMAND gp1 MODIF ID gp1. - SELECTION-SCREEN COMMENT 35(10) t_tddl MODIF ID gp1 FOR FIELD p_tddl. - PARAMETERS: p_tddl TYPE c RADIOBUTTON GROUP gp1 MODIF ID gp1 DEFAULT 'X'. - SELECTION-SCREEN END OF LINE. - SELECTION-SCREEN COMMENT 5(70) t_dddl MODIF ID gp1. - " DDL SELECTION-SCREEN BEGIN OF LINE. - SELECTION-SCREEN COMMENT 5(23) t_cdsv FOR FIELD p_cdsv. - PARAMETERS: p_cdsv AS CHECKBOX DEFAULT 'X'. + SELECTION-SCREEN COMMENT 5(23) t_ddls FOR FIELD p_ddls. + PARAMETERS: p_ddls AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. " Domain @@ -174,9 +660,9 @@ SELECTION-SCREEN BEGIN OF BLOCK blck2 WITH FRAME. PARAMETERS: p_ttyp AS CHECKBOX DEFAULT 'X'. SELECTION-SCREEN END OF LINE. -SELECTION-SCREEN END OF BLOCK blck2. +SELECTION-SCREEN END OF BLOCK blck4. -SELECTION-SCREEN BEGIN OF BLOCK blck3 WITH FRAME. +SELECTION-SCREEN BEGIN OF BLOCK blck5 WITH FRAME. " 其他 " Smw0 @@ -197,131 +683,68 @@ SELECTION-SCREEN BEGIN OF BLOCK blck3 WITH FRAME. PARAMETERS: p_xslt AS CHECKBOX DEFAULT ''. SELECTION-SCREEN END OF LINE. -SELECTION-SCREEN END OF BLOCK blck3. - -SELECTION-SCREEN BEGIN OF BLOCK blck4 WITH FRAME. - SELECTION-SCREEN BEGIN OF LINE. - SELECTION-SCREEN COMMENT 5(23) t_pack FOR FIELD s_pack. - SELECT-OPTIONS: s_pack FOR tadir-devclass. - SELECTION-SCREEN END OF LINE. -SELECTION-SCREEN END OF BLOCK blck4. - -SELECTION-SCREEN BEGIN OF BLOCK blck5 WITH FRAME. - SELECTION-SCREEN BEGIN OF LINE. - SELECTION-SCREEN COMMENT 5(23) t_delt FOR FIELD p_delt. - PARAMETERS: p_delt TYPE c AS CHECKBOX DEFAULT 'X'. - SELECTION-SCREEN END OF LINE. SELECTION-SCREEN END OF BLOCK blck5. -" 标识用于 接口获取内容 -SELECTION-SCREEN BEGIN OF BLOCK brun WITH FRAME. - " __ 借用 blob 表存储 xstring 数据,读取后删除 - " 同时为返回的文件名 - PARAMETERS: p_brun TYPE char30 NO-DISPLAY. -SELECTION-SCREEN END OF BLOCK brun. +SELECTION-SCREEN BEGIN OF BLOCK nodis WITH FRAME. + SELECT-OPTIONS: s_objnam FOR tadir-obj_name NO-DISPLAY. +SELECTION-SCREEN END OF BLOCK nodis. -SELECTION-SCREEN FUNCTION KEY 1. *&---------------------------------------------------------------------- * Initialization *&---------------------------------------------------------------------- INITIALIZATION. - PERFORM frm_init_text. + PERFORM frm_init_sets. *&---------------------------------------------------------------------- * At Selection-Screen Output *&---------------------------------------------------------------------- AT SELECTION-SCREEN OUTPUT. - LOOP AT SCREEN. - IF screen-group1 = 'GP1' AND p_tabl = ''. - screen-active = 0. - MODIFY SCREEN. - ENDIF. - " 功能未有,此处暂时不可显示 - IF screen-name = 'P_TXML'. - screen-input = 0. - MODIFY SCREEN. + LOOP AT SCREEN. + IF screen-group3 = 'PAR' + AND lcl_backup4abap_screen_option=>option_seted = abap_false + AND screen-name <> 'P_DELT'. + lcl_backup4abap_screen_option=>set_option( |{ screen-name }| ). ENDIF. ENDLOOP. + lcl_backup4abap_screen_option=>option_seted = abap_true. *&---------------------------------------------------------------------- -* Start-Of-Selection +* At Selection-Screen *&---------------------------------------------------------------------- AT SELECTION-SCREEN. - IF sy-ucomm = 'FC01'. - PERFORM frm_display_timestamp. - ENDIF. - - *&---------------------------------------------------------------------- -* At Selection-Screen +* Start-Of-Selection *&---------------------------------------------------------------------- START-OF-SELECTION. - IF s_pack[] IS NOT INITIAL. - PERFORM frm_fix_packages. - ENDIF. - - PERFORM frm_check. - - PERFORM frm_get_more. - - PERFORM frm_init_variables. - - IF p_brun IS INITIAL. - " 不获取文件路径 - PERFORM frm_get_path. - ENDIF. - - PERFORM frm_get_code. - PERFORM frm_get_ddic. - - PERFORM frm_get_others. - - PERFORM frm_export_zip. - - -*----------------------------------------------------------------------* -* CLASS lcl_progress_bar DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_progress_bar DEFINITION. - PUBLIC SECTION. + " 默认子开发包 + lcl_backup4abap_filter_package=>set( EXCEPTIONS e_no_filter = 1 ). + _stop. - DATA: count TYPE i, - base_desc TYPE string, - curr TYPE i. + " 获取文件路径 + lcl_backup4abap_export=>factory( )->path( ). - METHODS constructor IMPORTING i_count TYPE i OPTIONAL - i_base_desc TYPE string OPTIONAL. + " 处理逻辑 + lcl_backup4abap_export=>factory( )->main( EXCEPTIONS e_no_screen_choese = 1 ). + _stop. - METHODS add IMPORTING i_add TYPE i DEFAULT 1 - i_desc TYPE data OPTIONAL. - PRIVATE SECTION. - DATA: percent TYPE p DECIMALS 0 LENGTH 5, - percent_old TYPE p DECIMALS 0 LENGTH 5. - METHODS display IMPORTING desc TYPE data. -ENDCLASS. + lcl_backup4abap_export=>factory( )->download( EXCEPTIONS e_no_file = 1 ). + _stop. *&---------------------------------------------------------------------* -*& Form frm_init_text +*& Form FRM_INIT_SETS *&---------------------------------------------------------------------* -*& 文本初始化 +*& t 初始化设置 *&---------------------------------------------------------------------* -FORM frm_init_text . - " 类限制 - gt_range_devclass = VALUE #( ). - +FORM frm_init_sets . t_prog = '报表程序'. - t_func = '函数程序'. + t_fugr = '函数程序'. t_tabl = '表内容'. - t_txml = '导出 XML'. - t_tddl = '导出 DDL'. t_clas = '类程序'. - t_cdsv = 'CDS视图'. + t_ddls = 'CDS视图'. t_doma = '数据域'. t_dtel = '数据元素'. t_ttyp = '表类型'. @@ -334,2166 +757,1473 @@ FORM frm_init_text . t_pack = '开发类(包)'. t_delt = '增量获取(不跨client)'. - t_dddl = '导出DDL文件, 用于 SAP NetWeaver AS for ABAP 7.52 SP00 以上版本 ADT'. - " 按钮 sscrfields-functxt_01 = VALUE smp_dyntxt( quickinfo = '当前增量时戳' text = '增量信息' ). -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_check -*&---------------------------------------------------------------------* -*& 检查输入 -*&---------------------------------------------------------------------* -FORM frm_check . - " 指定包后 不在进行增量获取 - IF s_pack[] IS NOT INITIAL. - p_delt = ''. - ENDIF. - -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_init_variables -*&---------------------------------------------------------------------* -*& 初始化压缩相关类 -*&---------------------------------------------------------------------* -FORM frm_init_variables . - " 压缩对象 - CREATE OBJECT gr_zip. - - " 编码转换 - gr_cover_out = cl_abap_conv_out_ce=>create( encoding = 'UTF-8' ). - - " 文件目录 - gt_folder = VALUE #( ( tag = 'MM' ) ( tag = 'PP' ) - ( tag = 'SD' ) ( tag = 'FI' ) ( tag = 'FICO' folder = 'FI' ) - ( tag = 'HR' ) - ( tag = 'TEST' ) - ( tag = 'DEMO' ) - ( tag = 'HD' ) " 汉得包 - ( tag = 'TX' ) " 推送测试平台类 - ( tag = 'API' ) " 接口处理 - ( tag = 'JOB' ) " job 处理 - ( tag = 'JO' folder = 'JOB' ) - ( tag = 'FILE' ) " 文件处理 - ). - SORT gt_folder BY tag. - - " 文件名 - gt_range_objname = VALUE #( sign = 'I' option = 'CP' ( low = 'Z*' ) - ( low = 'Y*' ) ). - - " 增量数据获取 - gv_delta_store_id = gc_delta_store_id_fix_part && sy-uname. - - IF p_delt = 'X'. - " DeltaDownload && SY-UNAME - IMPORT gt_delt_log FROM DATABASE demo_indx_blob(zd) ID gv_delta_store_id. - SORT gt_delt_log BY object. - " 时间减3s - LOOP AT gt_delt_log ASSIGNING FIELD-SYMBOL(). - -dtime = -dtime - 3. - ENDLOOP. - ENDIF. ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_folder_name -*&---------------------------------------------------------------------* -*& 获取文件名 -*&---------------------------------------------------------------------* -FORM frm_get_folder_name USING p_type TYPE char2 - p_name - p_folder. - - " 由于 PCRE 在 755 后才引入,针对之前版本需要调整正则逻辑 - DATA: lv_name TYPE string, - lv_regex TYPE string. - DATA: l_off TYPE i, - l_len TYPE i. +CLASS lcl_backup4abap_filter_package IMPLEMENTATION. + METHOD set. - lv_name = p_name. + MOVE-CORRESPONDING s_pack[] TO lt_range. - CLEAR p_folder. + IF lt_range IS INITIAL. + " lt_range = VALUE #( sign = 'I' option = 'CP' ( low = 'Z*' ) ( low = 'Y*' ) ). + s_objnam[] = VALUE #( sign = 'I' option = 'CP' ( low = 'Z*' ) ( low = 'Y*' ) ). + ELSE. + SELECT + devclass + FROM tdevc + WHERE devclass IN @lt_range[] + INTO TABLE @DATA(lt_tdev). + + IF lt_tdev IS INITIAL. + MESSAGE '请填写正确的包名' TYPE 'E' RAISING e_no_filter. + ENDIF. - DATA: lv_folder TYPE ty_folder-tag. + lt_range = VALUE #( BASE lt_range FOR item IN lt_tdev + sign = 'I' option = 'EQ' ( low = item-devclass ) ). - CASE p_type+0(1). - WHEN 'R'. " report - " 1. 清除 _ 后的所有内容 - " 2. 正则匹配(为兼容不能使用PCRE 贪婪模式) - " - MG/[RBM] 结尾内容(不含MM) - " - B/E +数字 +拷贝标识 结尾 - " - M/R/F +数字 +拷贝标识 结尾 - " - 特殊(直接截取) + fix( lt_tdev ). - " 通过 REPLACE 替换内容 - REPLACE REGEX `_.*$` IN lv_name WITH ''. + ENDIF. - " 匹配内容 - FIND REGEX `MG$` IN lv_name - MATCH OFFSET l_off - MATCH LENGTH l_len. - IF sy-subrc = 0. - l_off = l_off - 1. " 匹配到内容减去 `Z` - lv_folder = lv_name+1(l_off). - ELSE. - " - FIND REGEX `([B]|[^M]M|[^H]R)$` IN lv_name - MATCH OFFSET l_off - MATCH LENGTH l_len. - IF sy-subrc = 0. - l_off = COND #( WHEN l_len = 1 THEN l_off - 1 " 匹配到内容减去 `Z` - ELSE l_off ). " 匹配到内容 -1 + 1 - lv_folder = lv_name+1(l_off). - ELSE. - FIND REGEX `[BE]\d+[A-Z]?$` IN lv_name - MATCH OFFSET l_off - MATCH LENGTH l_len. - IF sy-subrc = 0. - lv_folder = lv_name+0(l_off). - REPLACE REGEX `^[YZ]` IN lv_folder WITH ''. - ELSE. - FIND REGEX `([^M]M|[^H]R|[^F]I)\d+[A-Z]?$` IN lv_name - MATCH OFFSET l_off - MATCH LENGTH l_len. - IF sy-subrc = 0. - l_off = l_off + 1. - lv_folder = lv_name+0(l_off). - REPLACE REGEX `^[YZ]` IN lv_folder WITH ''. - ELSE. - IF strlen( lv_name ) >= 3. - lv_folder = lv_name+1(2). - ENDIF. - ENDIF. - ENDIF. + MOVE-CORRESPONDING lt_range TO s_pack[]. - ENDIF. + ENDMETHOD. - ENDIF. + METHOD fix. - WHEN 'F'. - " 1. 清除 ^ZFM_?|^Z - " 2. 清除 _ 后的所有内容 + CHECK it_package IS NOT INITIAL. - REPLACE REGEX `^[YZ]FM_?|^[YZ]` IN lv_name WITH ''. - REPLACE REGEX `_.*$` IN lv_name WITH ''. + SELECT + devclass + FROM tdevc + FOR ALL ENTRIES IN @it_package + WHERE parentcl = @it_package-parentcl + INTO TABLE @DATA(lt_tdev). + IF sy-subrc = 0. - lv_folder = lv_name. + lt_range = VALUE #( BASE lt_range FOR item IN lt_tdev + sign = 'I' option = 'EQ' ( low = item-devclass ) ). - WHEN 'C'. - " 类 特殊判定,不走配置逻辑 + fix( lt_tdev ). - IF lv_name+1(2) = 'HD'. - lv_folder = 'HD'. - ENDIF. - IF lv_name+4(2) = 'SI'. - lv_folder = 'IF/'. - ENDIF. - IF lv_name+1(2) = 'BP'. - lv_folder = 'BP'. - ENDIF. + ENDIF. - p_folder = lv_folder. - RETURN. + ENDMETHOD. +ENDCLASS. - WHEN 'T'. - " 1. 清除 `^ZT` - " 2. 清除 `T[\d_]*$` +CLASS lcl_backup4abap_filter_time IMPLEMENTATION. + METHOD factory. + IF objt IS INITIAL. + objt = NEW #( iv_limit ). + ENDIF. - REPLACE REGEX `^[YZ]T|^[YZ]` IN lv_name WITH ''. - REPLACE REGEX `T[\d_]*$` IN lv_name WITH ''. + ro_objt = objt. + ENDMETHOD. - lv_folder = lv_name. + METHOD constructor. + DATA lv_delta_store_id TYPE char30. - WHEN 'D'. " ddl 视图 - " 1. 清除 `^ZV` - " 2. 清除 `_.*$` + lv_delta_store_id = c_delta_store_id_fix_part && iv_limit. - REPLACE REGEX `^[YZ]V|^[YZ]` IN lv_name WITH ''. - REPLACE REGEX `_.*$` IN lv_name WITH ''. + " DeltaDownload && SY-UNAME + IMPORT delta = me->lt_delt_log FROM DATABASE demo_indx_blob(zd) ID lv_delta_store_id. + SORT me->lt_delt_log BY object. - lv_folder = lv_name. + " 时间减3s + LOOP AT me->lt_delt_log ASSIGNING FIELD-SYMBOL(). + -dtime = -dtime - 3. + ENDLOOP. + ENDMETHOD. - WHEN OTHERS. - ENDCASE. + METHOD get. - READ TABLE gt_folder INTO DATA(ls_folder) WITH KEY tag = lv_folder BINARY SEARCH. - IF sy-subrc = 0. + GET TIME. - IF ls_folder-folder IS INITIAL. - p_folder = ls_folder-tag. + READ TABLE lt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = iv_object. + IF sy-subrc <> 0. + APPEND VALUE #( object = iv_object ddate = sy-datum dtime = sy-uzeit ) TO lt_delt_log. ELSE. - p_folder = ls_folder-folder. + rs_delt_log = . + -ddate = sy-datum. + -dtime = sy-uzeit. ENDIF. + ENDMETHOD. +ENDCLASS. - ENDIF. - -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_code -*&---------------------------------------------------------------------* -*& 获取代码数据 -*&---------------------------------------------------------------------* -FORM frm_get_code . +CLASS lcl_backup4abap_screen_option IMPLEMENTATION. + METHOD set_option. + APPEND iv_option TO options. + ENDMETHOD. - IF p_prog = abap_true. - PERFORM frm_set_parent_folder USING `SE38/`. - PERFORM frm_get_report. - ENDIF. + METHOD selected_option. + LOOP AT options INTO DATA(l_option). + ASSIGN (l_option) TO FIELD-SYMBOL(). + IF sy-subrc = 0. + IF = 'X'. + APPEND l_option+2 TO rt_options. + ENDIF. + ENDIF. + ENDLOOP. + ENDMETHOD. +ENDCLASS. - IF p_func = abap_true. - PERFORM frm_set_parent_folder USING `SE37/`. - PERFORM frm_get_function. - ENDIF. +CLASS lcl_backup4abap_folder IMPLEMENTATION. + METHOD class_constructor. + folder = VALUE #( ( tag = 'MM' ) ( tag = 'PP' ) + ( tag = 'SD' ) ( tag = 'FI' ) ( tag = 'FICO' folder = 'FI' ) + ( tag = 'HR' ) + ( tag = 'CO' ) + ( tag = 'RAF' ) " RAF 框架 + ( tag = 'AKIT' ) " AKIT 工具集 + ( tag = 'TEST' ) + ( tag = 'DEMO' ) + ( tag = 'ABAP' ) + ( tag = 'API' ) " 接口处理 + ( tag = 'JOB' ) " job 处理 + ( tag = 'FILE' ) " 文件处理 + ). + SORT folder BY tag. + ENDMETHOD. + METHOD split_folder_prog. + DATA: lv_strlen TYPE i, + lv_filename TYPE string, + lv_folder TYPE ty_folder-tag. - IF p_clas = abap_true. - PERFORM frm_set_parent_folder USING `SE24/`. - PERFORM frm_get_class. - ENDIF. + " 1. 清除 _|\d 后的所有内容 + " 2. 正则匹配(为兼容不能使用PCRE 贪婪模式) - IF p_text = abap_true. - PERFORM frm_set_parent_folder USING `TEXT/`. - PERFORM frm_get_text. - ENDIF. + " 标准程序不做分目录 + IF name(1) = 'Y' OR name(1) = 'Z'. - IF p_msag = abap_true. - PERFORM frm_set_parent_folder USING `SE91/`. - PERFORM frm_get_msag. - ENDIF. + lv_filename = name+1. + REPLACE REGEX `[_\d].*$` IN lv_filename WITH ''. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_DDIC -*&---------------------------------------------------------------------* -*& 获取表相关内容 -*&---------------------------------------------------------------------* -FORM frm_get_ddic . + lv_strlen = strlen( lv_filename ). - IF p_tabl = abap_true. - "PERFORM frm_set_parent_folder USING `SE11/`. - IF p_txml = abap_true. - " no realization - ELSE. - PERFORM frm_get_tables_ddl USING gr_zip gr_cover_out `SE11/DDL/TABLE/`. - PERFORM frm_get_structs_ddl USING gr_zip gr_cover_out `SE11/DDL/STRUCT/`. - ENDIF. + IF lv_strlen <= 1. + " 无父目录 PASS + ELSEIF lv_strlen = 2. + " 无特殊标识 + lv_folder = lv_filename. - ENDIF. + READ TABLE folder INTO DATA(ls_folder) WITH KEY tag = lv_folder BINARY SEARCH. + IF sy-subrc = 0. + rv_folder = COND #( WHEN ls_folder-folder IS INITIAL + THEN ls_folder-tag + ELSE ls_folder-folder ) && '/'. + ENDIF. + ELSE. - IF p_cdsv = abap_true. - PERFORM frm_set_parent_folder USING `DDL/`. - PERFORM frm_get_ddl. - ENDIF. + " 分页反查 + LOOP AT folder INTO ls_folder. + FIND REGEX |^{ ls_folder-tag }| IN lv_filename. + IF sy-subrc = 0. + rv_folder = COND #( WHEN ls_folder-folder IS INITIAL + THEN ls_folder-tag + ELSE ls_folder-folder ) && '/'. + EXIT. + ENDIF. + ENDLOOP. - IF p_doma = abap_true. - PERFORM frm_set_parent_folder USING `SE11/field/Domain/`. - PERFORM frm_get_domain. - ENDIF. + ENDIF. - IF p_dtel = abap_true. - PERFORM frm_set_parent_folder USING `SE11/field/Element/`. - PERFORM frm_get_element. - ENDIF. + ENDIF. - IF p_ttyp = abap_true. - PERFORM frm_set_parent_folder USING `SE11/TABLETYPE/`. - PERFORM frm_get_tabletypes. - ENDIF. + IF subc = 'I'. + IF name+1(1) = 'X'. " 特殊 + rv_folder = `CMOD/` && rv_folder. + ELSE. + rv_folder = rv_folder && 'INCLUDE/'. + ENDIF. + ELSEIF subc = 'M'. + rv_folder = 'MODULEPOOLS/' && rv_folder. + ELSEIF subc = 'T'. + rv_folder = 'TYPEPOOLS/' && rv_folder. + ENDIF. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_report -*&---------------------------------------------------------------------* -*& 获取报表数据 -*&---------------------------------------------------------------------* -FORM frm_get_report . - - " D010SINF REPOSRC 视图(INF 部分) => REPOSRC 程序含代码 - " D010TINF REPOTEXT 视图(INF 部分)=> REPOTEXT 程序文本 - " trdirt 标题文本 - - DATA: lv_filename TYPE string. - DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - DATA: lv_c_flag TYPE char2. - - DATA: lv_folder TYPE char10, - lv_max TYPE i. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - " 读取 报表 - SELECT - rep~progname, - rep~r3state, - rep~subc, - rep~unam, " 修改人 - rep~udat, - rep~utime, - des~text - FROM reposrc AS rep - INNER JOIN tadir AS tad ON tad~obj_name = rep~progname AND tad~object = 'PROG' - LEFT JOIN trdirt AS des ON des~name = rep~progname AND des~sprsl = @sy-langu - WHERE ( - ( rep~subc = '1' ) - OR ( rep~subc = 'I' AND rep~rload = '1' ) - OR ( rep~subc = 'M' ) - OR ( rep~subc = 'T' ) ) - AND rep~r3state = 'A' - AND tad~obj_name IN @gt_range_objname - AND tad~devclass IN @gt_range_devclass - INTO TABLE @DATA(lt_list). - SORT lt_list BY progname. - - lr_pb->count = lines( lt_list ). - lr_pb->base_desc = 'Process Report & '. - - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'PROG' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'PROG' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + ENDMETHOD. + METHOD split_folder_clas. + " 类 特殊判定,不走配置逻辑 + DATA: lv_filename TYPE string, + lv_strlen TYPE i. - LOOP AT lt_list INTO DATA(ls_list). - lr_pb->add( i_desc = ls_list-progname ). + DATA: l_off TYPE i, + l_len TYPE i. - " 忽略当前程序 - IF ls_list-progname = sy-cprog. - CONTINUE. + IF strlen( name ) > 5 AND name+4(2) = 'SI'. + rv_folder = 'IF/'. + RETURN. + ELSEIF name+1(2) = 'BP'. + rv_folder = 'BP/'. + RETURN. ENDIF. - " 文件夹匹配 -> 文件名 - lv_c_flag = |R{ ls_list-subc }|. - PERFORM frm_get_folder_name USING lv_c_flag ls_list-progname lv_folder. - - IF ls_list-subc = 'I'. - IF ls_list-progname+1(1) = 'X'. - " 特殊 - lv_filename = |CMOD/{ ls_list-progname }.{ gc_extension_name }|. - ELSE. - lv_filename = COND #( WHEN lv_folder IS NOT INITIAL - THEN |{ lv_folder }/| ). - lv_filename = lv_filename && |INCLUDE/{ ls_list-progname }.{ gc_extension_name }|. - ENDIF. - ELSEIF ls_list-subc = '1'. - lv_filename = COND #( WHEN lv_folder IS NOT INITIAL - THEN |{ lv_folder }/| ). - lv_filename = lv_filename && |{ ls_list-progname }.{ gc_extension_name }|. - ELSEIF ls_list-subc = 'M'. - lv_filename = 'MODULEPOOLS/' && COND #( WHEN lv_folder IS NOT INITIAL - THEN |{ lv_folder }/| ). - lv_filename = lv_filename && |{ ls_list-progname }.{ gc_extension_name }|. - ELSEIF ls_list-subc = 'T'. - lv_filename = 'TYPEPOOLS/' && COND #( WHEN lv_folder IS NOT INITIAL - THEN |{ lv_folder }/| ). - lv_filename = lv_filename && |{ ls_list-progname }.{ gc_extension_name }|. - ENDIF. + lv_filename = name. - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_list-text. + REPLACE REGEX `[_\d].*$` IN lv_filename WITH ``. - lv_filename = gv_parent_folder && lv_filename. + lv_strlen = strlen( lv_filename ). - " 日志 生成 - PERFORM frm_set_log_flow USING 'PROG' ls_list-progname ls_list-unam ls_list-udat ls_list-utime. + IF lv_strlen = 3. + rv_folder = name. + rv_folder = rv_folder+4. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_list-udat - OR ( ls_delt_log-ddate = ls_list-udat AND ls_delt_log-dtime > ls_list-utime ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. + REPLACE REGEX `_.*$` IN rv_folder WITH ``. + ELSE. + rv_folder = name. + rv_folder = rv_folder+1. - CONTINUE. - ENDIF. + REPLACE REGEX `[(:?CL)|(:?CO)|(:?CX)|(:?IF)]$` IN rv_folder WITH ``. ENDIF. - " 读取激活状态的代码 - READ REPORT ls_list-progname INTO lt_source STATE 'A' MAXIMUM WIDTH INTO lv_max. - IF sy-subrc = 0. - " 内表转换为长字符串 - CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY gc_newline. - - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). + IF rv_folder IS NOT INITIAL. + rv_folder = rv_folder && '/'. ENDIF. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + ENDMETHOD. + METHOD split_folder_fugr. + DATA: lv_filename TYPE string, + lv_folder TYPE ty_folder-tag. - " 清除缓存 - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. - ENDLOOP. + " 1. 清除 ^ZFM_?|^Z + " 2. 清除 _ 后的所有内容 - " --> TODO: get screen - " 程序 LWBSCREENF50 子例程 dynpro_download - " 数据源 RS_SCREEN_IMPORT => `IMPORT DYNPRO h f e m ID dynp_id` - " 相关表 D020S DYNPSOURCE D020T DYNPLOAD DWWASYNC DWINACTIV D347T - " <-- + " 标准程序不做分目录 + CHECK name(1) = 'Y' OR name(1) = 'Z'. - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + lv_filename = name. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_function -*&---------------------------------------------------------------------* -*& 获取函数 -*&---------------------------------------------------------------------* -FORM frm_get_function . - - " V_FDIR 查找功能模块的视图(函数名 函数组名) - " TFDIR 功能模块 (实际程序名) - " ENLFDIR 功能模块的附加属性(函数的函数组) - " TFTIT 功能模块描述信息 - " TLIBV 负责功能组(函数组 函数组负责人) - " TADIR 资源对象库(不仅函数部分数据)(包 关联函数) - - DATA: lt_func TYPE TABLE OF ty_function. - - DATA: lv_filename TYPE string. - DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - DATA: lv_report_name TYPE char50. - - DATA: lv_folder TYPE char10, - lv_max TYPE i. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - " 此处获取所有的 Z* 函数组数据 - SELECT - fu~funcname AS functionname, - gr~area AS functiongroup, - fu~pname AS progname, - fu~include AS includenumber - FROM enlfdir AS gr - INNER JOIN tfdir AS fu ON fu~funcname = gr~funcname - LEFT JOIN tadir AS tad ON tad~obj_name = gr~area AND tad~object = 'FUGR' - WHERE gr~area IN @gt_range_objname " 限制函数组(部分标准程序也会有Z开头的函数) - AND gr~funcname IN @gt_range_objname - AND tad~devclass IN @gt_range_devclass - INTO CORRESPONDING FIELDS OF TABLE @lt_func. - IF lt_func IS NOT INITIAL. - SELECT - funcname, - stext - FROM tftit - FOR ALL ENTRIES IN @lt_func - WHERE spras = @sy-langu - AND funcname = @lt_func-functionname - INTO TABLE @DATA(lt_tftit). - SORT lt_tftit BY funcname. - ENDIF. - SORT lt_func BY functionname. + REPLACE REGEX `^[YZ]FM_?|^[YZ]` IN lv_filename WITH ''. + REPLACE REGEX `_.*$` IN lv_filename WITH ''. - lr_pb->count = lines( lt_func ). - lr_pb->base_desc = 'Process Function & '. + lv_folder = lv_filename. - LOOP AT lt_func ASSIGNING FIELD-SYMBOL(). - READ TABLE lt_tftit INTO DATA(ls_tftit) WITH KEY funcname = -functionname BINARY SEARCH. + READ TABLE folder INTO DATA(ls_folder) WITH KEY tag = lv_folder BINARY SEARCH. IF sy-subrc = 0. - -functiontitle = ls_tftit-stext. + rv_folder = COND #( WHEN ls_folder-folder IS INITIAL + THEN ls_folder-tag + ELSE ls_folder-folder ) && '/'. ENDIF. + ENDMETHOD. - " 函数对应的实体 - CONCATENATE 'L' -functiongroup 'U' -includenumber INTO -reportname. - ENDLOOP. + METHOD split_folder_ddls. + " 1. 清除 `^ZV` + " 2. 清除 `_.*$` - " 更新人获取 - IF lt_func IS NOT INITIAL. - SELECT - progname, - unam, - udat, - utime - FROM reposrc - FOR ALL ENTRIES IN @lt_func - WHERE progname = @lt_func-reportname - AND appl = 'S' - INTO TABLE @DATA(lt_rep). - SORT lt_rep BY progname. - ENDIF. + rv_folder = name. - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'FUNC' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'FUNC' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + REPLACE REGEX `^[YZ]V|^[YZ]` IN rv_folder WITH ''. + REPLACE REGEX `_.*$` IN rv_folder WITH ''. + + IF rv_folder IS NOT INITIAL. + rv_folder = rv_folder && '/'. + ENDIF. + + ENDMETHOD. +ENDCLASS. - LOOP AT lt_func INTO DATA(ls_func). - lr_pb->add( i_desc = ls_func-functionname ). +CLASS lcl_backup4abap_objects IMPLEMENTATION. - PERFORM frm_get_folder_name USING 'F' ls_func-functionname lv_folder. + METHOD constructor. + me->o_conv_out = cl_abap_conv_out_ce=>create( encoding = 'UTF-8' ). + ENDMETHOD. - IF lv_folder IS NOT INITIAL. - lv_filename = |{ lv_folder }/{ ls_func-functionname }.abap|. + METHOD is_delta. + + IF p_delt = 'X' AND s_pack[] IS INITIAL. + rv_bool = abap_true. ELSE. - CONCATENATE ls_func-functionname '.abap' INTO lv_filename. + rv_bool = abap_false. ENDIF. - CONCATENATE 'L' ls_func-functiongroup 'U' ls_func-includenumber INTO lv_report_name. + ENDMETHOD. - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_func-functiontitle. +ENDCLASS. - lv_filename = gv_parent_folder && lv_filename. +CLASS lcl_backup4abap_object_prog IMPLEMENTATION. + METHOD constructor. + super->constructor( ). - " 日志 生成 - READ TABLE lt_rep INTO DATA(ls_rep) WITH KEY progname = lv_report_name BINARY SEARCH. - PERFORM frm_set_log_flow USING 'FUNC' ls_func-functionname ls_rep-unam ls_rep-udat ls_rep-utime. + me->o_pb = NEW #( `Process Report & ` ). + me->parent_folder = 'SE38' && '/'. + ENDMETHOD. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_rep-udat - OR ( ls_delt_log-ddate = ls_rep-udat AND ls_delt_log-dtime > ls_rep-utime ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring, lv_report_name. + METHOD loadfiles. + DATA: lv_filename TYPE string. + DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, + lv_source TYPE string. - CONTINUE. + " 读取报表数据 + SELECT + rep~progname, + rep~r3state, + rep~subc, + rep~unam, " 修改人 + rep~udat, + rep~utime, + des~text + FROM reposrc AS rep + INNER JOIN tadir AS tad ON tad~obj_name = rep~progname AND tad~object = 'PROG' + LEFT JOIN trdirt AS des ON des~name = rep~progname AND des~sprsl = @sy-langu + WHERE ( ( rep~subc = '1' ) + OR ( rep~subc = 'I' AND rep~rload = '1' ) + OR ( rep~subc = 'M' ) + OR ( rep~subc = 'T' ) ) + AND rep~r3state = 'A' + AND tad~obj_name IN @s_objnam + AND tad~devclass IN @s_pack + INTO TABLE @DATA(lt_list). + SORT lt_list BY progname. + + me->o_pb->count = lines( lt_list ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'PROG' ). + + LOOP AT lt_list INTO DATA(ls_list). + me->o_pb->add( i_desc = ls_list-progname ). + + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_list-udat + OR ( ls_delt_log-ddate = ls_list-udat AND ls_delt_log-dtime > ls_list-utime ). + + CONTINUE. + ENDIF. ENDIF. - ENDIF. - - CLEAR ls_rep. - " 读取激活状态的代码 - READ REPORT lv_report_name INTO lt_source STATE 'A' MAXIMUM WIDTH INTO lv_max. - IF sy-subrc = 0. - " 内表转换为长字符串 - CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY gc_newline. - - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). - ENDIF. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + -name = split_folder( VALUE ty_split_limit( name = ls_list-progname + subc = ls_list-subc ) ) + && ls_list-progname && '.' && c_extension_abap. - " 清除缓存 - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring, lv_report_name. - ENDLOOP. + -name = me->parent_folder && -name. - " --> more - CHECK lt_func IS NOT INITIAL. + " 读取激活状态的代码 + READ REPORT ls_list-progname INTO lt_source STATE 'A'." MAXIMUM WIDTH INTO lv_max. + IF sy-subrc = 0. + " 内表转换为长字符串 + CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY c_newline. + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). + ENDIF. - DATA: lt_area TYPE RANGE OF reposrc-progname. - LOOP AT lt_func INTO DATA(ls_area). - APPEND VALUE #( sign = 'I' option = 'CP' low = |L{ ls_area-functiongroup }*| ) TO lt_area. - ENDLOOP. - SORT lt_area BY low. - DELETE ADJACENT DUPLICATES FROM lt_area COMPARING low. - - REFRESH lt_func. - - " 读取 函数组其他信息 - SELECT - rep~progname, - rep~r3state, - rep~subc, - rep~unam, " 修改人 - rep~udat, - rep~utime - FROM reposrc AS rep - WHERE ( " ( rep~progname LIKE 'LZ%' AND rep~subc = 'I' AND rep~appl = '' ) " 索引页 - ( rep~rstat = 'S' ) " 索引页 + RFC - OR ( rep~subc = 'I' AND rep~appl = 'S' AND rep~dbapl = '' ) " O/I/F - OR ( rep~subc = 'I' AND rep~appl = 'S' ) ) " TOP - AND rep~progname IN @lt_area - AND rep~r3state = 'A' - INTO TABLE @DATA(lt_list). - SORT lt_list BY progname. - - lr_pb->count = lines( lt_list ). - lr_pb->base_desc = 'Process Function More & '. - lr_pb->curr = 0. - - DATA: lv_str_len TYPE i. - - READ TABLE gt_delt_log ASSIGNING WITH KEY object = 'FINC' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'FINC' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + REFRESH lt_source. + CLEAR lv_source. + ENDLOOP. - LOOP AT lt_list INTO DATA(ls_list). - lr_pb->add( i_desc = ls_list-progname ). - - " 文件名 - lv_filename = |{ ls_list-progname }.{ gc_extension_name }|. - - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ''. - - lv_str_len = strlen( ls_list-progname ) - 3. - CASE ls_list-progname+lv_str_len(1). - WHEN 'V'. - lv_filename = gv_parent_folder && `Rfc/` && lv_filename. - WHEN '$'. - lv_filename = gv_parent_folder && `Rfc/Unit/` && lv_filename. - WHEN 'U'. - " 和上面的取值重复 - CLEAR: lv_filename, lv_str_len. - CONTINUE. - WHEN OTHERS. - lv_filename = gv_parent_folder && `More/` && lv_filename. - ENDCASE. + ENDMETHOD. - " 日志 生成 - PERFORM frm_set_log_flow USING 'FINC' ls_list-progname ls_list-unam ls_list-udat ls_list-utime. + METHOD split_folder. + DATA: ls_limit TYPE ty_split_limit. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_list-udat - OR ( ls_delt_log-ddate = ls_list-udat AND ls_delt_log-dtime > ls_list-utime ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. + ls_limit = i_limit. - CONTINUE. - ENDIF. - ENDIF. + rv_filename = lcl_backup4abap_folder=>split_folder_prog( name = ls_limit-name + subc = ls_limit-subc ). - " 读取激活状态的代码 - READ REPORT ls_list-progname INTO lt_source STATE 'A' MAXIMUM WIDTH INTO lv_max. - IF sy-subrc = 0. - " 内表转换为长字符串 - CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY gc_newline. + ENDMETHOD. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). - ENDIF. + METHOD load2zip. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + CHECK io_zip IS BOUND. - " 清除缓存 - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. - ENDLOOP. - " <-- + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + ENDMETHOD. +ENDCLASS. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_export_zip -*&---------------------------------------------------------------------* -*& 导出压缩文件 -*&---------------------------------------------------------------------* -FORM frm_export_zip . - DATA: lv_zip_xstr TYPE xstring. +CLASS lcl_backup4abap_object_fugr IMPLEMENTATION. + METHOD constructor. + super->constructor( ). - TYPES: ty_hex TYPE x LENGTH 200. + me->o_pb = NEW #( `Process Function & ` ). + me->parent_folder = 'SE37' && '/'. + ENDMETHOD. - DATA: lt_xdata TYPE STANDARD TABLE OF ty_hex WITH DEFAULT KEY, - lv_xlen TYPE i. + METHOD loadfiles. + " V_FDIR 查找功能模块的视图(函数名 函数组名) + " TFDIR 功能模块 (实际程序名) + " ENLFDIR 功能模块的附加属性(函数的函数组) + " TFTIT 功能模块描述信息 + " TLIBV 负责功能组(函数组 函数组负责人) + " TADIR 资源对象库(不仅函数部分数据)(包 关联函数) - " 压缩文件保存 - lv_zip_xstr = gr_zip->save( ). + DATA: lt_func TYPE tt_function. - lv_xlen = xstrlen( lv_zip_xstr ). + DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, + lv_source TYPE string. - " __接口获取时导入 blob表 + " 此处获取函数组 + SELECT + fu~funcname AS functionname, + gr~area AS functiongroup, + fu~pname AS progname, + fu~include AS includenumber + FROM enlfdir AS gr + INNER JOIN tfdir AS fu ON fu~funcname = gr~funcname + LEFT JOIN tadir AS tad ON tad~obj_name = gr~area AND tad~object = 'FUGR' + WHERE gr~area IN @s_objnam " 限制函数组(部分标准程序也会有Z开头的函数) + AND gr~funcname IN @s_objnam + AND tad~devclass IN @s_pack + INTO CORRESPONDING FIELDS OF TABLE @lt_func. + SORT lt_func BY functionname. + + me->o_pb->count = lines( lt_func ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'FUGR' ). + + " 补充更多信息 + fix_more( REF #( lt_func ) ). + + LOOP AT lt_func INTO DATA(ls_func). + me->o_pb->add( i_desc = ls_func-functionname ). + + " 检查增量 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_func-udate + OR ( ls_delt_log-ddate = ls_func-udate AND ls_delt_log-dtime > ls_func-utime ). + + CONTINUE. + ENDIF. + ENDIF. - IF p_brun IS INITIAL. - CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' - EXPORTING - buffer = lv_zip_xstr - IMPORTING - output_length = lv_xlen - TABLES - binary_tab = lt_xdata. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - CALL FUNCTION 'GUI_DOWNLOAD' - EXPORTING - bin_filesize = lv_xlen - filename = gv_export_fullpath - filetype = 'BIN' - TABLES - data_tab = lt_xdata. - ELSE. - EXPORT xlen = lv_xlen - zip = lv_zip_xstr TO DATABASE demo_indx_blob(zb) ID p_brun. - ENDIF. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_path -*&---------------------------------------------------------------------* -*& 获取存储路径 -*&---------------------------------------------------------------------* -FORM frm_get_path . - - DATA: lv_path TYPE string, - lv_fullpath TYPE string, - lv_filename TYPE string. - - CALL METHOD cl_gui_frontend_services=>file_save_dialog - EXPORTING - window_title = 'download zip' - default_extension = 'zip' - default_file_name = |{ sy-datum }{ sy-uzeit }| - file_filter = '(*.zip)|*.zip|' - CHANGING - filename = lv_filename - path = lv_path - fullpath = lv_fullpath - EXCEPTIONS - cntl_error = 1 - error_no_gui = 2 - not_supported_by_gui = 3 - OTHERS = 4. - IF sy-subrc <> 0 OR lv_fullpath IS INITIAL. - MESSAGE '用户取消' TYPE 'S' DISPLAY LIKE 'E'. - STOP. - ENDIF. + -name = split_folder( ls_func-functionname ) + && ls_func-functionname && '.' && c_extension_abap. - gv_export_fullpath = lv_fullpath. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_set_map_file -*&---------------------------------------------------------------------* -*& 设置 map 文件内容 -*&---------------------------------------------------------------------* -FORM frm_set_map_file USING VALUE(p_file_path) - VALUE(p_file_desc). + -name = me->parent_folder && -name. - APPEND |{ p_file_desc }| TO gt_map_file. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_add_map_file -*&---------------------------------------------------------------------* -*& 添加 map 文件到 zip -*&---------------------------------------------------------------------* -FORM frm_add_map_file USING VALUE(p_folder). - DATA: lv_source TYPE string, - lv_xstring TYPE xstring. - - CONCATENATE LINES OF gt_map_file INTO lv_source SEPARATED BY gc_newline. - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). - gr_zip->add( name = |{ gv_parent_folder }map.html| - content = lv_xstring ). - - REFRESH gt_map_file. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form FRM_GET_CLASS -*&---------------------------------------------------------------------* -*& 获取类代码 -*&---------------------------------------------------------------------* -FORM frm_get_class . - DATA: BEGIN OF ls_class_key, - classnamelength TYPE i, - publicclasskey TYPE string, - privateclasskey TYPE string, - protectedclasskey TYPE string, - textelementkey TYPE string, - typesclasskey TYPE string, - END OF ls_class_key. - DATA: ls_include TYPE progstruc. - DATA: lt_str TYPE rswsourcet, - lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - DATA: lv_folder TYPE char10. - - DATA: lv_filename TYPE string, - lv_more TYPE string. - - TYPES: BEGIN OF ty_type, - type TYPE seop_include_ext_app, - exline TYPE i, - END OF ty_type. - - DATA: lt_type TYPE TABLE OF ty_type, - lv_max TYPE i. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - lt_type = VALUE #( ( type = seop_ext_class_locals_def exline = 4 ) - ( type = seop_ext_class_locals_imp exline = 4 ) - ( type = seop_ext_class_macros exline = 3 ) - ( type = seop_ext_class_testclasses exline = 1 ) ). - - SELECT - clsname, - langu, - descript, - "msg_id, - - exposure, - state, - "clsfinal, - "r3release, - changedby, - changedon, - CAST( '000000' AS TIMS ) AS changetm - FROM vseoclass AS ss - INNER JOIN tadir AS ta ON ta~obj_name = ss~clsname AND ta~object = 'CLAS' - WHERE ta~obj_name IN @gt_range_objname - AND version = '1' " 激活 - AND ( state = '0' OR state = '1' ) - AND ta~devclass IN @gt_range_devclass - INTO TABLE @DATA(lt_class). - " 排序去重 - SORT lt_class BY clsname langu. - DELETE ADJACENT DUPLICATES FROM lt_class COMPARING clsname. - - IF gt_range_append_class IS NOT INITIAL. - SELECT - clsname, - langu, - descript, - "msg_id, - - exposure, - state, - "clsfinal, - "r3release, - changedby, - changedon - FROM vseoclass - WHERE clsname IN @gt_range_append_class - AND version = '1' " 激活 - AND ( state = '0' OR state = '1' ) - APPENDING TABLE @lt_class. - ENDIF. + " 读取激活状态的代码 + READ REPORT ls_func-reportname INTO lt_source STATE 'A'." MAXIMUM WIDTH INTO lv_max. + IF sy-subrc = 0. + " 内表转换为长字符串 + CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY c_newline. + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). + ENDIF. - SELECT - clsname, - langu, - descript, - "msg_id, - - exposure, - state, - "clsfinal, - "r3release, - changedby, - changedon, - CAST( '000000' AS TIMS ) AS changetm - FROM vseoclif AS ss - INNER JOIN tadir AS ta ON ta~obj_name = ss~clsname AND ta~object = 'INTF' - WHERE ta~obj_name IN @gt_range_objname - AND version = '1' " 激活 - AND state = '1' - AND ta~devclass IN @gt_range_devclass - APPENDING TABLE @lt_class. - - " 多语言去重 - SORT lt_class BY clsname langu. - DELETE ADJACENT DUPLICATES FROM lt_class COMPARING clsname. - - " --> 获取真实修改时间(类下的子节点) - " 参考 LSEODF1X 948 行 - DATA: lt_range_name TYPE RANGE OF progdir-name. - lt_range_name = VALUE #( FOR itm IN lt_class - " WHERE ( changedon IS INITIAL ) - ( sign = 'I' option = 'CP' low = |{ itm-clsname }*| ) ). - IF lt_range_name IS NOT INITIAL. - SELECT - progname AS name, - unam, - udat, - utime - FROM reposrc - WHERE progname IN @lt_range_name - INTO TABLE @DATA(lt_progdir). - - LOOP AT lt_progdir ASSIGNING FIELD-SYMBOL(). - " __ 当名称足够长时 无标识 `=` 正则无效 - " -name = replace( val = -name pcre = `=+.*$` with = `` occ = -1 ). - -name = replace( val = -name regex = `=*(?:CCAU|CCDEF|CCIMP|CCMAC|CI|CM\d{3}|CO|CP|CS|CT|CU|IP|IT|IU)$` with = `` occ = -1 ). + REFRESH lt_source. + CLEAR lv_source. ENDLOOP. - SORT lt_progdir BY name udat DESCENDING utime DESCENDING. - ENDIF. - " <-- - - " 读取类 - DATA: lo_source TYPE REF TO object, - lo_instance TYPE REF TO object. - DATA: lr_source TYPE REF TO cl_oo_source, - ls_clskey TYPE seoclskey. - CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') - RECEIVING - result = lo_instance. + " --> get more(rfc\incloud\) + DATA: lt_area TYPE tt_range_area. - lr_pb->count = lines( lt_class ). - lr_pb->base_desc = 'Process Class & '. + lt_area = VALUE #( FOR _ IN lt_func sign = 'I' option = 'CP' ( low = |L{ _-functiongroup }*| ) ). + SORT lt_area BY low. + DELETE ADJACENT DUPLICATES FROM lt_area COMPARING low. - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'CLSS' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'CLSS' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + REFRESH lt_func. - LOOP AT lt_class INTO DATA(ls_class). - lr_pb->add( i_desc = ls_class-clsname ). + get_more( lt_area ). + " <-- - lv_filename = ls_class-clsname && '.abap'. + ENDMETHOD. - " >> 特殊指定 -> 文件夹 - PERFORM frm_get_folder_name USING 'C' lv_filename lv_folder. - IF lv_folder IS NOT INITIAL. - lv_filename = lv_folder && '/' && lv_filename. + METHOD fix_more. + FIELD-SYMBOLS: TYPE tt_function. + + ASSIGN io_func->* TO . + + IF IS NOT INITIAL. " 描述 + SELECT + funcname, + stext + FROM tftit + FOR ALL ENTRIES IN @ + WHERE spras = @sy-langu + AND funcname = @-functionname + INTO TABLE @DATA(lt_tftit). + SORT lt_tftit BY funcname. ENDIF. - "ls_class_key-classnamelength = strlen( ls_class-clsname ). - " - "ls_class_key-publicclasskey = cl_oo_classname_service=>get_pubsec_name( clsname = ls_class-clsname ). - "ls_class_key-privateclasskey = cl_oo_classname_service=>get_prisec_name( clsname = ls_class-clsname ). - "ls_class_key-protectedclasskey = cl_oo_classname_service=>get_prosec_name( clsname = ls_class-clsname ). - " - "ls_class_key-textelementkey = ls_class-clsname. - "DO 30 - ls_class_key-classnamelength TIMES. - " CONCATENATE ls_class_key-textelementkey '=' INTO ls_class_key-textelementkey. - "ENDDO. - "CONCATENATE ls_class_key-textelementkey 'CP' INTO ls_class_key-textelementkey. - " - "ls_class_key-typesclasskey = ls_class-clsname. - "DO 30 - ls_class_key-classnamelength TIMES. - " CONCATENATE ls_class_key-typesclasskey '=' INTO ls_class_key-typesclasskey. - "ENDDO. - "CONCATENATE ls_class_key-typesclasskey 'CT' INTO ls_class_key-typesclasskey. - - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_class-descript. - - lv_filename = gv_parent_folder && lv_filename. - - " 真实修改时间 - READ TABLE lt_progdir INTO DATA(ls_prodir_udat) WITH KEY name = ls_class-clsname BINARY SEARCH. - IF sy-subrc = 0. - IF ls_class-changedon IS INITIAL OR ls_prodir_udat-udat > ls_class-changedon. - ls_class-changedon = ls_prodir_udat-udat. + LOOP AT ASSIGNING FIELD-SYMBOL(). + READ TABLE lt_tftit INTO DATA(ls_tftit) WITH KEY funcname = -functionname BINARY SEARCH. + IF sy-subrc = 0. + -functiontitle = ls_tftit-stext. ENDIF. - ls_class-changedby = ls_prodir_udat-unam. - ls_class-changetm = ls_prodir_udat-utime. - ENDIF. + " 函数对应的实体 + CONCATENATE 'L' -functiongroup 'U' -includenumber INTO -reportname. + ENDLOOP. - " 日志 生成 - PERFORM frm_set_log_flow USING 'CLASS' ls_class-clsname ls_class-changedby ls_class-changedon ls_class-changetm. + IF IS NOT INITIAL. + SELECT + progname, + unam, + udat, + utime + FROM reposrc + FOR ALL ENTRIES IN @ + WHERE progname = @-reportname + AND appl = 'S' + INTO TABLE @DATA(lt_rep). + SORT lt_rep BY progname. + + LOOP AT ASSIGNING . + READ TABLE lt_rep INTO DATA(ls_rep) WITH KEY progname = -reportname BINARY SEARCH. + IF sy-subrc = 0. + -uname = ls_rep-unam. + -udate = ls_rep-udat. + -utime = ls_rep-utime. + ENDIF. + ENDLOOP. + ENDIF. + ENDMETHOD. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_class-changedon - OR ( ls_delt_log-ddate = ls_class-changedon AND ls_delt_log-dtime > ls_class-changetm ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. + METHOD get_more. + DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, + lv_source TYPE string. - CONTINUE. - ENDIF. - ENDIF. + DATA: lv_str_len TYPE i. - " > 读取源码 - CALL METHOD lo_instance->('CREATE_CLIF_SOURCE') - EXPORTING - clif_name = ls_class-clsname - version = 'A' - RECEIVING - result = lo_source. + " 读取 函数组其他信息 + SELECT + rep~progname, + rep~r3state, + rep~subc, + rep~unam, " 修改人 + rep~udat, + rep~utime + FROM reposrc AS rep + WHERE ( " ( rep~progname LIKE 'LZ%' AND rep~subc = 'I' AND rep~appl = '' ) " 索引页 + ( rep~rstat = 'S' ) " 索引页 + RFC + OR ( rep~subc = 'I' AND rep~appl = 'S' AND rep~dbapl = '' ) " O/I/F + OR ( rep~subc = 'I' AND rep~appl = 'S' ) ) " TOP + AND rep~progname IN @it_range_area + AND rep~r3state = 'A' + INTO TABLE @DATA(lt_list). + SORT lt_list BY progname. + + me->o_pb->count = lines( lt_list ). + me->o_pb->base_desc = 'Process Function More & '. + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'FINC' ). + + LOOP AT lt_list INTO DATA(ls_list). + me->o_pb->add( i_desc = ls_list-progname ). + + " 检查增量 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_list-udat + OR ( ls_delt_log-ddate = ls_list-udat AND ls_delt_log-dtime > ls_list-utime ). + + CONTINUE. + ENDIF. + ENDIF. - CALL METHOD lo_source->('GET_SOURCE') - IMPORTING - source = lt_str. + lv_str_len = strlen( ls_list-progname ) - 3. - " 内表转换为长字符串 - CONCATENATE LINES OF lt_str INTO lv_source SEPARATED BY gc_newline. + CHECK NOT ls_list-progname+lv_str_len(1) = 'U'. " 取值重复 - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + " 文件名 + -name = |{ ls_list-progname }.{ c_extension_abap }|. - " --> add 更多信息 + CASE ls_list-progname+lv_str_len(1). + WHEN 'V'. + -name = me->parent_folder && `Rfc/` && -name. + WHEN '$'. + -name = me->parent_folder && `Rfc/Unit/` && -name. + WHEN OTHERS. + -name = me->parent_folder && `More/` && -name. + ENDCASE. - LOOP AT lt_type INTO DATA(ls_type). - ls_include-rootname = ls_class-clsname. - TRANSLATE ls_include-rootname USING ' ='. - ls_include-categorya = ls_type-type(1). - ls_include-codea = ls_type-type+1(4). + " 读取激活状态的代码 + READ REPORT ls_list-progname INTO lt_source STATE 'A'." MAXIMUM WIDTH INTO lv_max. + IF sy-subrc = 0. + " 内表转换为长字符串 + CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY c_newline. + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). + ENDIF. - READ REPORT ls_include INTO lt_source STATE 'A' MAXIMUM WIDTH INTO lv_max. - IF sy-subrc = 0 AND lines( lt_source ) > ls_type-exline. - lv_more = lv_filename. - REPLACE FIRST OCCURRENCE OF |{ ls_class-clsname }.abap| - IN lv_more WITH |More/{ ls_class-clsname }-{ ls_type-type }.abap|. + REFRESH lt_source. + CLEAR: lv_str_len, lv_source. + ENDLOOP. - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_type-type. + ENDMETHOD. - " 内表转换为长字符串 - CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY gc_newline. + METHOD split_folder. + DATA: lv_limit TYPE ty_split_limit. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). + lv_limit = i_limit. - " 添加到压缩包 - gr_zip->add( name = lv_more - content = lv_xstring ). - ENDIF. - CLEAR ls_include. - ENDLOOP. - " <-- + rv_filename = lcl_backup4abap_folder=>split_folder_fugr( name = lv_limit ). - REFRESH lt_str. - CLEAR: lv_filename, lv_xstring. - ENDLOOP. + ENDMETHOD. - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + METHOD load2zip. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_text -*&---------------------------------------------------------------------* -*& 程序文本 -*&---------------------------------------------------------------------* -FORM frm_get_text . + CHECK io_zip IS BOUND. - " 程序文本 - " 由于无法直接关联 TADIR 间接通过程序名进行处理分为三个模块 - " SE38 \ SE37 \ SE24 + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - DATA: lt_textpool TYPE TABLE OF textpool, - lv_textpool TYPE string, - lv_xstring TYPE xstring. - DATA: ls_include TYPE progstruc. - DATA: lv_folder TYPE char10. + ENDMETHOD. +ENDCLASS. +CLASS lcl_backup4abap_object_clas IMPLEMENTATION. - DATA: ls_delt_log LIKE LINE OF gt_delt_log. + METHOD constructor. + super->constructor( ). - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'TEXT' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'TEXT' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + me->o_pb = NEW #( `Process Class & ` ). + me->parent_folder = 'SE24' && '/'. - SELECT - ta~obj_name, - ta~object - FROM tadir AS ta - WHERE ta~pgmid = 'R3TR' - AND ta~object IN ('PROG','FUGR','CLAS') - AND ta~obj_name IN @gt_range_objname - AND ta~devclass IN @gt_range_devclass - INTO TABLE @DATA(lt_tadir). + me->lt_type = VALUE #( ( type = seop_ext_class_locals_def exline = 4 ) + ( type = seop_ext_class_locals_imp exline = 4 ) + ( type = seop_ext_class_macros exline = 3 ) + ( type = seop_ext_class_testclasses exline = 1 ) ). + ENDMETHOD. - CHECK lt_tadir IS NOT INITIAL. + METHOD loadfiles. + DATA: lt_source TYPE rswsourcet, + lv_source TYPE string. + DATA: ls_include TYPE progstruc, + lv_filename TYPE string. - LOOP AT lt_tadir ASSIGNING FIELD-SYMBOL() WHERE object = 'FUGR' OR object = 'CLAS'. + SELECT + ss~clsname, " SEOCLASS + ss~langu, + ss~descript, + ss~exposure, + ss~state, + ss~changedby, + ss~changedon, + CAST( '000000' AS TIMS ) AS changetm + FROM vseoclass AS ss + INNER JOIN tadir AS ta ON ta~obj_name = ss~clsname AND ta~object = 'CLAS' + WHERE ta~obj_name IN @s_objnam + AND version = '1' " 激活 + AND ( state = '0' OR state = '1' ) + AND ta~devclass IN @s_pack + INTO TABLE @DATA(lt_class). + " 排序去重 + SORT lt_class BY clsname langu. + DELETE ADJACENT DUPLICATES FROM lt_class COMPARING clsname. - " CLAS - IF -object = 'CLAS'. - ls_include = VALUE #( rootname = -obj_name categorya = 'C' codea = 'P' ). - TRANSLATE ls_include-rootname USING ' ='. + SELECT + ss~clsname, + ss~langu, + ss~descript, + ss~exposure, + ss~state, + ss~changedby, + ss~changedon, + CAST( '000000' AS TIMS ) AS changetm + FROM vseoclif AS ss + INNER JOIN tadir AS ta ON ta~obj_name = ss~clsname AND ta~object = 'INTF' + WHERE ta~obj_name IN @s_objnam + AND version = '1' " 激活 + AND state = '1' + AND ta~devclass IN @s_pack + APPENDING TABLE @lt_class. - -obj_name = ls_include. + " 多语言去重 + SORT lt_class BY clsname langu. + DELETE ADJACENT DUPLICATES FROM lt_class COMPARING clsname. + + " --> 获取真实修改时间(类下的子节点) + " 参考 LSEODF1X 948 行 + DATA: lt_range_name TYPE RANGE OF progdir-name. + lt_range_name = VALUE #( FOR itm IN lt_class + " WHERE ( changedon IS INITIAL ) + ( sign = 'I' option = 'CP' low = |{ itm-clsname }*| ) ). + IF lt_range_name IS NOT INITIAL. + SELECT + progname AS name, + unam, + udat, + utime + FROM reposrc + WHERE progname IN @lt_range_name + INTO TABLE @DATA(lt_progdir). + + LOOP AT lt_progdir ASSIGNING FIELD-SYMBOL(). + " __ 当名称足够长时 无标识 `=` 正则无效 + " -name = replace( val = -name pcre = `=+.*$` with = `` occ = -1 ). + -name = replace( val = -name regex = `=*(?:CCAU|CCDEF|CCIMP|CCMAC|CI|CM\d{3}|CO|CP|CS|CT|CU|IP|IT|IU)$` with = `` occ = -1 ). + ENDLOOP. + SORT lt_progdir BY name udat DESCENDING utime DESCENDING. + DELETE ADJACENT DUPLICATES FROM lt_progdir COMPARING name. ENDIF. + " <-- - " FUGR - IF -object = 'FUGR'. - -obj_name = 'SAPL' && -obj_name. - ENDIF. - ENDLOOP. - SORT lt_tadir BY obj_name object. + CALL METHOD ('CL_OO_FACTORY')=>('CREATE_INSTANCE') + RECEIVING + result = me->o_instance. - SELECT - progname, - r3state, - language, - unam, - udat, - utime - FROM repotext - FOR ALL ENTRIES IN @lt_tadir - WHERE progname = @lt_tadir-obj_name - AND r3state = 'A' - INTO TABLE @DATA(lt_repot). + DATA: lr_source TYPE REF TO cl_oo_source, + ls_clskey TYPE seoclskey. - CHECK lt_repot IS NOT INITIAL. + me->o_pb->count = lines( lt_class ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'CLAS' ). - SELECT spras, laiso FROM t002 INTO TABLE @DATA(lt_t002). - SORT lt_t002 BY spras. + LOOP AT lt_class INTO DATA(ls_class). + me->o_pb->add( i_desc = ls_class-clsname ). - DATA: lv_filename TYPE string, - lv_language TYPE string. - DATA: lr_pb TYPE REF TO lcl_progress_bar. + " 真实修改时间 + READ TABLE lt_progdir INTO DATA(ls_prodir_udat) WITH KEY name = ls_class-clsname BINARY SEARCH. + IF sy-subrc = 0. + IF ls_class-changedon IS INITIAL OR ls_prodir_udat-udat > ls_class-changedon. + ls_class-changedon = ls_prodir_udat-udat. + ENDIF. + ls_class-changedby = ls_prodir_udat-unam. + ls_class-changetm = ls_prodir_udat-utime. + ENDIF. - CREATE OBJECT lr_pb. + " 检查增量 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_class-changedon + OR ( ls_delt_log-ddate = ls_class-changedon AND ls_delt_log-dtime > ls_class-changetm ). - lr_pb->count = lines( lt_repot ). - lr_pb->base_desc = 'Process Text & '. + CONTINUE. + ENDIF. + ENDIF. - LOOP AT lt_repot INTO DATA(ls_repot). - lr_pb->add( i_desc = ls_repot-progname ). + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - " 忽略当前程序 - IF ls_repot-progname = sy-cprog. - CONTINUE. - ENDIF. + -name = split_folder( ls_class-clsname ) + && ls_class-clsname && '.' && c_extension_abap. - READ TABLE lt_tadir INTO DATA(ls_tadir) WITH KEY obj_name = ls_repot-progname BINARY SEARCH. - IF sy-subrc = 0. " 还原名称 - CASE ls_tadir-object. - WHEN 'CLAS'. - lv_filename = ls_repot-progname. - REPLACE REGEX '=*CP$' IN lv_filename WITH ''. + -name = me->parent_folder && -name. - PERFORM frm_get_folder_name USING 'C' lv_filename lv_folder. - IF lv_folder IS NOT INITIAL. - lv_filename = lv_folder && '/' && lv_filename. - ENDIF. + " > 读取源码 + CALL METHOD me->o_instance->('CREATE_CLIF_SOURCE') + EXPORTING + clif_name = ls_class-clsname + version = 'A' + RECEIVING + result = me->o_source. - lv_filename = 'SE24/' && lv_filename. - WHEN 'FUGR'. - lv_filename = ls_repot-progname. - REPLACE REGEX '^SAPL' IN lv_filename WITH ''. + CALL METHOD me->o_source->('GET_SOURCE') + IMPORTING + source = lt_source. - PERFORM frm_get_folder_name USING 'F' lv_filename lv_folder. - IF lv_folder IS NOT INITIAL. - lv_filename = lv_folder && '/' && lv_filename. - ENDIF. + " 内表转换为长字符串 + CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY c_newline. - lv_filename = 'SE37/' && lv_filename. - WHEN OTHERS. - lv_filename = ls_repot-progname. + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). - PERFORM frm_get_folder_name USING 'R' ls_repot-progname lv_folder. - IF lv_folder IS NOT INITIAL. - lv_filename = lv_folder && '/' && lv_filename. - ENDIF. + REFRESH lt_source. + CLEAR lv_source. - lv_filename = 'SE38/' && lv_filename. - ENDCASE. + " --> add 更多信息 + LOOP AT me->lt_type INTO DATA(ls_type). + ls_include-rootname = ls_class-clsname. + TRANSLATE ls_include-rootname USING ' ='. + ls_include-categorya = ls_type-type(1). + ls_include-codea = ls_type-type+1(4). - lv_filename = lv_filename && '.txt'. - ELSE. - lv_filename = ls_repot-progname && '.txt'. - ENDIF. + READ REPORT ls_include INTO lt_source STATE 'A'." MAXIMUM WIDTH INTO lv_max. + IF sy-subrc = 0 AND lines( lt_source ) > ls_type-exline. - " 文件夹匹配 -> 文件名 - READ TABLE lt_t002 INTO DATA(ls_t002) WITH KEY spras = ls_repot-language BINARY SEARCH. - IF sy-subrc = 0. - lv_filename = gv_parent_folder && |{ ls_t002-laiso }/| && lv_filename. - ELSE. - lv_filename = gv_parent_folder && lv_filename. - ENDIF. + APPEND INITIAL LINE TO me->files ASSIGNING . - " 日志 生成 - PERFORM frm_set_log_flow USING 'TEXT' ls_repot-progname ls_repot-unam ls_repot-udat ls_repot-utime. + -name = 'More/' + && split_folder( ls_class-clsname ) + && ls_class-clsname && |-{ ls_type-type }.| && c_extension_abap. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_repot-udat - OR ( ls_delt_log-ddate = ls_repot-udat AND ls_delt_log-dtime > ls_repot-utime ). - REFRESH lt_textpool. - CLEAR: lv_textpool, lv_filename, lv_xstring. + -name = me->parent_folder && -name. - CONTINUE. - ENDIF. - ENDIF. + " 内表转换为长字符串 + CONCATENATE LINES OF lt_source INTO lv_source SEPARATED BY c_newline. - READ TEXTPOOL ls_repot-progname LANGUAGE ls_repot-language STATE 'A' INTO lt_textpool. - IF sy-subrc = 0. - " 标题 - CONCATENATE 'ID' gc_tab 'KEY_____' gc_tab 'ENTRY' gc_newline INTO lv_textpool. - - " 内表转换为长字符串 - LOOP AT lt_textpool INTO DATA(ls_textpool). - " ID - lv_textpool = lv_textpool && ls_textpool-id && gc_tab. + " string -> xstring + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). - " key => 为方便好看补齐8位 - lv_textpool = lv_textpool && |{ ls_textpool-key WIDTH = 8 }| && gc_tab. - - " value - lv_textpool = lv_textpool && ls_textpool-entry. + ENDIF. - " newline - lv_textpool = lv_textpool && gc_newline. + REFRESH lt_source. + CLEAR: ls_include, lv_source. ENDLOOP. + " <-- - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_textpool - IMPORTING buffer = lv_xstring ). - ENDIF. + ENDLOOP. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + ENDMETHOD. - " 清除缓存 - REFRESH lt_textpool. - CLEAR: lv_textpool, lv_filename, lv_xstring. - ENDLOOP. + METHOD split_folder. + DATA: lv_limit TYPE ty_split_limit. - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + lv_limit = i_limit. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form FRM_GET_MSAG -*&---------------------------------------------------------------------* -*& 获取消息类 -*&---------------------------------------------------------------------* -FORM frm_get_msag . - - " T100 T100U - TYPES: BEGIN OF ty_arbgb, - arbgb TYPE t100u-arbgb, - datum TYPE t100u-datum, - END OF ty_arbgb. - DATA: lt_arbgb TYPE TABLE OF ty_arbgb. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - DATA: lv_tabix TYPE sytabix, - lv_spras TYPE t002-spras, - lv_spras_last TYPE t002-spras. - DATA: lv_string TYPE string, - lv_xstring TYPE xstring, - lv_filename TYPE string. - - SELECT - tu~arbgb, - tu~msgnr, - tu~name, - tu~datum, - tu~selfdef - FROM tadir AS ta - LEFT JOIN t100u AS tu ON tu~arbgb = ta~obj_name - WHERE ta~pgmid = 'R3TR' - AND ta~object = 'MSAG' - AND ta~obj_name IN @gt_range_objname - AND ta~devclass IN @gt_range_devclass - INTO TABLE @DATA(lt_t100u). - SORT lt_t100u BY arbgb msgnr. - - CHECK lt_t100u IS NOT INITIAL. - - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'MSAG' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'MSAG' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + rv_filename = lcl_backup4abap_folder=>split_folder_clas( name = lv_limit ). - " 去重 + 时间限制 - MOVE-CORRESPONDING lt_t100u TO lt_arbgb. - SORT lt_arbgb BY arbgb datum DESCENDING. - DELETE ADJACENT DUPLICATES FROM lt_arbgb COMPARING arbgb. + ENDMETHOD. - IF p_delt = 'X'. - DELETE lt_arbgb WHERE datum < ls_delt_log-ddate. - ENDIF. + METHOD load2zip. - SELECT - arbgb, - msgnr, - sprsl, - text - FROM t100 - FOR ALL ENTRIES IN @lt_t100u - WHERE arbgb = @lt_t100u-arbgb - AND msgnr = @lt_t100u-msgnr - INTO TABLE @DATA(lt_t100). - SORT lt_t100 BY arbgb sprsl msgnr. - - SELECT spras, laiso FROM t002 INTO TABLE @DATA(lt_t002). - SORT lt_t002 BY spras. - DATA: ls_t002 LIKE LINE OF lt_t002. - - CREATE OBJECT lr_pb. - - lr_pb->count = lines( lt_arbgb ). - lr_pb->base_desc = 'Process Message Class & '. - - DEFINE mc_process. - " 文件名 - READ TABLE lt_t002 INTO ls_t002 WITH KEY spras = lv_spras_last BINARY SEARCH. - IF sy-subrc = 0. - lv_filename = ls_t002-laiso && '/' && ls_arbgb-arbgb && '.txt'. - ELSE. - lv_filename = ls_arbgb-arbgb && '.txt'. - ENDIF. + CHECK io_zip IS BOUND. - lv_filename = gv_parent_folder && lv_filename. + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - " 内容标题 - CONCATENATE 'KEY' gc_tab 'CHANGER_____' gc_tab 'CDATUM__' gc_tab 'T' gc_tab 'TEXT' gc_newline lv_string INTO lv_string. + ENDMETHOD. +ENDCLASS. +CLASS lcl_backup4abap_object_text IMPLEMENTATION. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_string - IMPORTING buffer = lv_xstring ). + METHOD constructor. + super->constructor( ). - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + me->o_pb = NEW #( `Process Text & ` ). + me->parent_folder = 'TEXT' && '/'. + ENDMETHOD. - CLEAR: lv_string, lv_xstring, lv_filename. - END-OF-DEFINITION. + METHOD loadfiles. + DATA: ls_include TYPE progstruc. + DATA: lt_textpool TYPE TABLE OF textpool, + lv_textpool TYPE string. - LOOP AT lt_arbgb INTO DATA(ls_arbgb). - lr_pb->add( i_desc = ls_arbgb-arbgb ). + " 获取文本程序名 + SELECT + ta~obj_name, + ta~object + FROM tadir AS ta + WHERE ta~pgmid = 'R3TR' + AND ta~object IN ('PROG','FUGR','CLAS') + AND ta~obj_name IN @s_objnam + AND ta~devclass IN @s_pack + INTO TABLE @DATA(lt_tadir). - READ TABLE lt_t100 TRANSPORTING NO FIELDS WITH KEY arbgb = ls_arbgb-arbgb BINARY SEARCH. - IF sy-subrc = 0. - lv_tabix = sy-tabix. + CHECK lt_tadir IS NOT INITIAL. - LOOP AT lt_t100 INTO DATA(ls_t100) FROM lv_tabix. - IF ls_t100-arbgb <> ls_arbgb-arbgb. - EXIT. - ENDIF. + LOOP AT lt_tadir ASSIGNING FIELD-SYMBOL() WHERE object = 'FUGR' OR object = 'CLAS'. - IF lv_spras IS INITIAL. - lv_spras = ls_t100-sprsl. - ENDIF. + " CLAS + IF -object = 'CLAS'. + ls_include = VALUE #( rootname = -obj_name categorya = 'C' codea = 'P' ). + TRANSLATE ls_include-rootname USING ' ='. - " 多个语言 - IF lv_spras IS NOT INITIAL AND lv_spras <> ls_t100-sprsl. - lv_spras_last = lv_spras. - lv_spras = ls_t100-sprsl. + -obj_name = ls_include. + ENDIF. - mc_process. - ENDIF. + " FUGR + IF -object = 'FUGR'. + -obj_name = 'SAPL' && -obj_name. + ENDIF. + ENDLOOP. + SORT lt_tadir BY obj_name object. - " 消息编号 - lv_string = lv_string && ls_t100-msgnr && gc_tab. + SELECT + progname, + r3state, + language, + unam, + udat, + utime + FROM repotext + FOR ALL ENTRIES IN @lt_tadir + WHERE progname = @lt_tadir-obj_name + AND r3state = 'A' + INTO TABLE @DATA(lt_repot). - READ TABLE lt_t100u INTO DATA(ls_t100u) WITH KEY arbgb = ls_t100-arbgb msgnr = ls_t100-msgnr BINARY SEARCH. - " 修改人 - lv_string = lv_string && |{ ls_t100u-name WIDTH = 12 }| && gc_tab. + CHECK lt_repot IS NOT INITIAL. - " 修改时间 - lv_string = lv_string && ls_t100u-datum && gc_tab. + SELECT spras, laiso FROM t002 INTO TABLE @DATA(lt_t002). + SORT lt_t002 BY spras. - " 类型 - lv_string = lv_string && ls_t100u-selfdef && gc_tab. + me->o_pb->count = lines( lt_repot ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'TEXT' ). - " 内容 - lv_string = lv_string && ls_t100-text && gc_newline. + LOOP AT lt_repot INTO DATA(ls_repot). + me->o_pb->add( i_desc = ls_repot-progname ). - ENDLOOP. + " 检查增量 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_repot-udat + OR ( ls_delt_log-ddate = ls_repot-udat AND ls_delt_log-dtime > ls_repot-utime ). - " 多个语言 最后一个 - IF lv_spras_last <> lv_spras. - lv_spras_last = lv_spras. - mc_process. + CONTINUE. + ENDIF. ENDIF. - ENDIF. - - CLEAR: lv_spras, lv_spras_last, lv_tabix. - ENDLOOP. - - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_logs -*&---------------------------------------------------------------------* -*& 日志记录 -*&---------------------------------------------------------------------* -FORM frm_get_logs . - - DATA: lv_xstring TYPE xstring. - DATA: lv_filename TYPE string. + READ TABLE lt_tadir INTO DATA(ls_tadir) WITH KEY obj_name = ls_repot-progname BINARY SEARCH. - " json - lv_filename = `logs/log_flow_` && sy-datum && `.json`. + -name = split_folder( VALUE ty_split_limit( object = ls_tadir-object + progname = ls_repot-progname ) ) + && '.' && c_extension_txt. - GET REFERENCE OF gt_log_flow INTO DATA(lr_log_flow). - DATA: lv_req_json TYPE string. - lv_req_json = /ui2/cl_json=>serialize( data = lr_log_flow - pretty_name = /ui2/cl_json=>pretty_mode-low_case ). + CLEAR ls_tadir. - gr_cover_out->convert( - EXPORTING data = lv_req_json - IMPORTING buffer = lv_xstring ). + " 文件夹匹配 -> 文件名 + READ TABLE lt_t002 INTO DATA(ls_t002) WITH KEY spras = ls_repot-language BINARY SEARCH. + IF sy-subrc = 0. + -name = me->parent_folder && |{ ls_t002-laiso }/| && -name. + ELSE. + -name = me->parent_folder && -name. + ENDIF. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + READ TEXTPOOL ls_repot-progname LANGUAGE ls_repot-language STATE 'A' INTO lt_textpool. + IF sy-subrc = 0. + " 标题 + CONCATENATE 'ID' c_tab 'KEY_____' c_tab 'ENTRY' c_newline INTO lv_textpool. + " 内表转换为长字符串 + LOOP AT lt_textpool INTO DATA(ls_textpool). + " ID + lv_textpool = lv_textpool && ls_textpool-id && c_tab. + " key => 为方便好看补齐8位 + lv_textpool = lv_textpool && |{ ls_textpool-key WIDTH = 8 }| && c_tab. + " value + lv_textpool = lv_textpool && ls_textpool-entry. + " newline + lv_textpool = lv_textpool && c_newline. + ENDLOOP. + + me->o_conv_out->convert( EXPORTING data = lv_textpool + IMPORTING buffer = -data ). + ENDIF. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_set_log_flow -*&---------------------------------------------------------------------* -*& 获取流日志 -*&---------------------------------------------------------------------* -FORM frm_set_log_flow USING VALUE(p_type) TYPE text30 - VALUE(p_progname) - VALUE(p_unam) - VALUE(p_udat) - VALUE(p_utime). + REFRESH lt_textpool. + CLEAR: lv_textpool. + ENDLOOP. - DATA: lv_uname TYPE text12. + ENDMETHOD. - lv_uname = p_unam. + METHOD split_folder. + DATA: ls_limit TYPE ty_split_limit, + lv_filename TYPE string. + ls_limit = i_limit. + + CASE ls_limit-object. + WHEN ''. + " pass + rv_filename = ls_limit-progname. + WHEN 'CLAS'. + lv_filename = ls_limit-progname. + REPLACE REGEX '=*CP$' IN lv_filename WITH ''. + + rv_filename = 'SE24/' + && lcl_backup4abap_folder=>split_folder_clas( name = lv_filename ) && lv_filename. + WHEN 'FUGR'. + lv_filename = ls_limit-progname. + REPLACE REGEX '^SAPL' IN lv_filename WITH ''. + + rv_filename = 'SE37/' + && lcl_backup4abap_folder=>split_folder_fugr( name = lv_filename ) && lv_filename. + WHEN OTHERS. + lv_filename = ls_limit-progname. - IF p_unam IS INITIAL. - lv_uname = `Other`. - ENDIF. + rv_filename = 'SE38/' + && lcl_backup4abap_folder=>split_folder_prog( name = lv_filename subc = '1' ) && lv_filename. + ENDCASE. - READ TABLE gt_log_flow ASSIGNING FIELD-SYMBOL() WITH KEY type = p_type. - IF sy-subrc <> 0. - APPEND INITIAL LINE TO gt_log_flow ASSIGNING . - -type = p_type. - ENDIF. + ENDMETHOD. - APPEND VALUE #( main = |{ p_progname }| - uname = lv_uname - datum = |{ p_udat }| - uzeit = |{ p_utime }| ) TO -info. + METHOD load2zip. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_ddl -*&---------------------------------------------------------------------* -*& 获取 DDL -*&---------------------------------------------------------------------* -FORM frm_get_ddl . - - DATA: lv_filename TYPE string. - DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - - DATA: lv_folder TYPE char2, - lv_max TYPE i. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - " 读取 DDL - SELECT - rc~ddlname, - rc~as4user, - rc~as4date, - rc~as4time, - rc~source, - ct~ddtext - FROM ddddlsrc AS rc - INNER JOIN tadir AS ta ON ta~obj_name = rc~ddlname AND object = 'DDLS' " 存在 STOB 结构化对象 - LEFT JOIN ddddlsrct AS ct ON ct~ddlname = rc~ddlname - AND ct~ddlanguage = '1' - AND ct~as4local = rc~as4local - WHERE ta~obj_name IN @gt_range_objname "rc~ddlname - AND rc~as4local = 'A' - AND ta~devclass IN @gt_range_devclass - INTO TABLE @DATA(lt_ddlsrc). - - SORT lt_ddlsrc BY ddlname. - - lr_pb->count = lines( lt_ddlsrc ). - lr_pb->base_desc = 'Process CDS & '. - - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'DDLS' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'DDLS' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + CHECK io_zip IS BOUND. - LOOP AT lt_ddlsrc INTO DATA(ls_ddl). - lr_pb->add( i_desc = ls_ddl-ddlname ). - " 文件夹匹配 -> 文件名 + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - PERFORM frm_get_folder_name USING 'D' ls_ddl-ddlname lv_folder. + ENDMETHOD. +ENDCLASS. +CLASS lcl_backup4abap_object_msag IMPLEMENTATION. - IF lv_folder IS NOT INITIAL. - lv_filename = |{ lv_folder }/{ ls_ddl-ddlname }.ddl|. - ELSE. - CONCATENATE ls_ddl-ddlname '.ddl' INTO lv_filename. - ENDIF. + METHOD constructor. + super->constructor( ). - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_ddl-ddtext. + me->o_pb = NEW #( `Process MSAG & ` ). + me->parent_folder = 'SE91' && '/'. + ENDMETHOD. - lv_filename = gv_parent_folder && lv_filename. + METHOD loadfiles. - " 日志 生成 - PERFORM frm_set_log_flow USING 'DDLS' ls_ddl-ddlname ls_ddl-as4user ls_ddl-as4date ls_ddl-as4time. + " T100 T100U - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_ddl-as4date - OR ( ls_delt_log-ddate = ls_ddl-as4date AND ls_delt_log-dtime > ls_ddl-as4time ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. + DATA: lt_arbgb TYPE TABLE OF ty_arbgb. + DATA: lv_spras TYPE t002-spras, + lv_spras_last TYPE t002-spras, + lv_string TYPE string. + FIELD-SYMBOLS: LIKE LINE OF me->files. - CONTINUE. - ENDIF. + SELECT + tu~arbgb, + tu~msgnr, + tu~name, + tu~datum, + tu~selfdef + FROM tadir AS ta + LEFT JOIN t100u AS tu ON tu~arbgb = ta~obj_name + WHERE ta~pgmid = 'R3TR' + AND ta~object = 'MSAG' + AND ta~obj_name IN @s_objnam + AND ta~devclass IN @s_pack + INTO TABLE @DATA(lt_t100u). + SORT lt_t100u BY arbgb msgnr. + + CHECK lt_t100u IS NOT INITIAL. + + me->o_pb->count = lines( lt_t100u ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'MSAG' ). + + MOVE-CORRESPONDING lt_t100u TO lt_arbgb. + SORT lt_arbgb BY arbgb datum DESCENDING. + DELETE ADJACENT DUPLICATES FROM lt_arbgb COMPARING arbgb. + + IF is_delta( ) = 'X'. + DELETE lt_arbgb WHERE datum < ls_delt_log-ddate. ENDIF. - " --> Begin 清除末尾注释 - REPLACE FIRST OCCURRENCE OF REGEX `\/\*\+\[internal\].*\*\/` IN ls_ddl-source WITH ``. - " <-- + SELECT + arbgb, + msgnr, + sprsl, + text + FROM t100 + FOR ALL ENTRIES IN @lt_t100u + WHERE arbgb = @lt_t100u-arbgb + AND msgnr = @lt_t100u-msgnr + INTO TABLE @DATA(lt_t100). + SORT lt_t100 BY arbgb sprsl msgnr. + + SELECT spras, laiso FROM t002 INTO TABLE @DATA(lt_t002). + SORT lt_t002 BY spras. + DATA: ls_t002 LIKE LINE OF lt_t002. + + DEFINE mc_process. + APPEND INITIAL LINE TO me->files ASSIGNING . + + " 文件名 + READ TABLE lt_t002 INTO ls_t002 WITH KEY spras = lv_spras_last BINARY SEARCH. + IF sy-subrc = 0. + -name = ls_t002-laiso && '/' && ls_arbgb-arbgb && '.' && c_extension_txt. + ELSE. + -name = ls_arbgb-arbgb && '.' && c_extension_txt. + ENDIF. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = ls_ddl-source - IMPORTING buffer = lv_xstring ). + -name = me->parent_folder && -name. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + " 内容标题 + CONCATENATE 'KEY' c_tab 'CHANGER_____' c_tab 'CDATUM__' c_tab 'T' c_tab 'TEXT' c_newline lv_string INTO lv_string. - " 清除缓存 - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. - ENDLOOP. + " string -> xstring + me->o_conv_out->convert( EXPORTING data = lv_string + IMPORTING buffer = -data ). - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + CLEAR: lv_string. + END-OF-DEFINITION. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_more -*&---------------------------------------------------------------------* -*& 获取更多数据 -*&---------------------------------------------------------------------* -FORM frm_get_more . - - IF s_pack[] IS INITIAL. - " 更多 类 + LOOP AT lt_arbgb INTO DATA(ls_arbgb). + me->o_pb->add( i_desc = ls_arbgb-arbgb ). - ENDIF. -ENDFORM. + READ TABLE lt_t100 TRANSPORTING NO FIELDS WITH KEY arbgb = ls_arbgb-arbgb BINARY SEARCH. + IF sy-subrc = 0. + LOOP AT lt_t100 INTO DATA(ls_t100) FROM sy-tabix. + IF ls_t100-arbgb <> ls_arbgb-arbgb. + EXIT. + ENDIF. -CLASS lcl_export_ddldict DEFINITION FINAL. - PUBLIC SECTION. - TYPES: ty_type TYPE string. - CONSTANTS: BEGIN OF types, - label TYPE ty_type VALUE 'label', - encat TYPE ty_type VALUE 'encat', - tabty TYPE ty_type VALUE 'tabty', - edits TYPE ty_type VALUE 'edits', - deliv TYPE ty_type VALUE 'deliv', - actty TYPE ty_type VALUE 'actty', - repla TYPE ty_type VALUE 'repla', - define TYPE ty_type VALUE 'define', - END OF types. - TYPES: BEGIN OF ty_foreignkey_eq, - fortable TYPE fortable, - forkey TYPE forkey, - checkfield TYPE fieldname, - END OF ty_foreignkey_eq. - TYPES: tty_foreignkey_eq TYPE TABLE OF ty_foreignkey_eq WITH EMPTY KEY. - TYPES: BEGIN OF ty_foreignkey, - label TYPE string, - screencheck TYPE text6, - keytype TYPE frkart, - cardleft TYPE cardleft, - card TYPE card, - checktable TYPE string, - foreignkey_eq TYPE tty_foreignkey_eq, - END OF ty_foreignkey. - TYPES: BEGIN OF ty_field, - name TYPE string, - key TYPE char1, - nonull TYPE char1, - type TYPE string, - addtion TYPE string, " 补充 - adddesc TYPE string, - foreignkey TYPE ty_foreignkey, - END OF ty_field. - TYPES: tty_fields TYPE TABLE OF ty_field WITH EMPTY KEY. + IF lv_spras IS INITIAL. + lv_spras = ls_t100-sprsl. + ENDIF. - TYPES: BEGIN OF ty_table, - name TYPE string, " 表名 - desc TYPE string, " 表描述 - fields TYPE tty_fields, - field_max TYPE i, + " 多个语言 + IF lv_spras IS NOT INITIAL AND lv_spras <> ls_t100-sprsl. + lv_spras_last = lv_spras. + lv_spras = ls_t100-sprsl. - deliv TYPE string, " 提交类 - actty TYPE string, " 激活类型 - edits TYPE string, " 表维护 - encat TYPE string, " 增强类别 - END OF ty_table. + mc_process. + ENDIF. - TYPES: BEGIN OF ty_string, - table TYPE string, - string TYPE string, - END OF ty_string. + " 消息编号 + lv_string = lv_string && ls_t100-msgnr && c_tab. + + READ TABLE lt_t100u INTO DATA(ls_t100u) WITH KEY arbgb = ls_t100-arbgb msgnr = ls_t100-msgnr BINARY SEARCH. + " 修改人 + lv_string = lv_string && |{ ls_t100u-name WIDTH = 12 }| && c_tab. + " 修改时间 + lv_string = lv_string && ls_t100u-datum && c_tab. + " 类型 + lv_string = lv_string && ls_t100u-selfdef && c_tab. + " 内容 + lv_string = lv_string && ls_t100-text && c_newline. + CLEAR ls_t100u. + ENDLOOP. + + " 多个语言 最后一个 + IF lv_spras_last <> lv_spras. + lv_spras_last = lv_spras. + mc_process. + ENDIF. - DATA: gt_tables TYPE TABLE OF ty_table, - gt_string TYPE TABLE OF ty_string. + ENDIF. - METHODS: table_maintain. - METHODS: struct_maintain. + CLEAR: lv_spras, lv_spras_last. + ENDLOOP. - PRIVATE SECTION. - DATA: ddldicts TYPE TABLE OF text1000. + ENDMETHOD. - METHODS: add_line IMPORTING str TYPE string OPTIONAL type TYPE ty_type. + METHOD split_folder. + " pass + ENDMETHOD. -ENDCLASS. + METHOD load2zip. + CHECK io_zip IS BOUND. -CLASS lcl_pretty_json DEFINITION. - PUBLIC SECTION. + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - CLASS-METHODS: pretty IMPORTING json TYPE string - RETURNING VALUE(pretty_json) TYPE string. + ENDMETHOD. ENDCLASS. +CLASS lcl_backup4abap_object_tabl IMPLEMENTATION. -CLASS lcl_export_ddldict IMPLEMENTATION. - - METHOD: table_maintain. - DATA: lv_string TYPE string, - lv_xstring TYPE xstring. - - LOOP AT gt_tables INTO DATA(ls_table). - " 描述 - add_line( str = ls_table-desc type = me->types-label ). - " 增强类别 - add_line( str = ls_table-encat type = me->types-encat ). - " 表类别 - add_line( str = '' type = me->types-tabty ). - " 交付类 - add_line( str = ls_table-deliv type = me->types-deliv ). - " 维护方式 - add_line( str = ls_table-edits type = me->types-edits ). - " ?? - "add_line( str = ls_table-actty type = me->types-actty ). - " 表名称 - add_line( str = |{ ls_table-name CASE = LOWER }| type = me->types-define ). - - LOOP AT ls_table-fields INTO DATA(ls_field). - IF ls_field-foreignkey-label IS NOT INITIAL. - APPEND | @AbapCatalog.foreignKey.label : '{ ls_field-foreignkey-label }'| TO me->ddldicts. - ENDIF. - IF ls_field-foreignkey-keytype IS NOT INITIAL. - CASE ls_field-foreignkey-keytype. - WHEN 'KEY'. - APPEND | @AbapCatalog.foreignKey.keyType : #{ 'KEY' }| TO me->ddldicts. - WHEN 'REF'. - APPEND | @AbapCatalog.foreignKey.keyType : #{ 'NON_KEY' }| TO me->ddldicts. - WHEN 'TEXT'. - APPEND | @AbapCatalog.foreignKey.keyType : #{ 'TEXT_KEY' }| TO me->ddldicts. - WHEN OTHERS. - ENDCASE. - ENDIF. - IF ls_field-foreignkey-screencheck IS NOT INITIAL. - APPEND | @AbapCatalog.foreignKey.screenCheck : { ls_field-foreignkey-screencheck }| TO me->ddldicts. - ENDIF. - - lv_string = COND #( WHEN ls_field-key = 'X' THEN `key ` ELSE `` ) && ls_field-name. - - IF ls_field-adddesc IS NOT INITIAL. - APPEND | @EndUserText.label : '{ ls_field-adddesc }'| TO me->ddldicts. - ENDIF. - - IF ls_field-addtion IS NOT INITIAL. - APPEND ls_field-addtion TO me->ddldicts. - ENDIF. - - IF ls_field-foreignkey-checktable IS INITIAL. - IF ls_field-name IS INITIAL. - APPEND | { ls_field-type }{ COND #( WHEN ls_field-nonull = 'X' THEN | not null| ) };| TO me->ddldicts. - ELSE. - APPEND | { lv_string WIDTH = ls_table-field_max + 1 }: { ls_field-type }{ COND #( WHEN ls_field-nonull = 'X' THEN | not null| ) };| TO me->ddldicts. - ENDIF. - ELSE. - IF ls_field-name IS INITIAL. - APPEND | { ls_field-type }{ COND #( WHEN ls_field-nonull = 'X' THEN | not null| ) }| TO me->ddldicts. - ELSE. - APPEND | { lv_string WIDTH = ls_table-field_max + 1 }: { ls_field-type }{ COND #( WHEN ls_field-nonull = 'X' THEN | not null| ) }| TO me->ddldicts. - ENDIF. + METHOD constructor. + super->constructor( ). - IF ls_field-foreignkey-card = '' AND ls_field-foreignkey-cardleft = ''. - APPEND | with foreign key { ls_field-foreignkey-checktable }| TO me->ddldicts. - ELSE. - APPEND | with foreign key [{ COND string( WHEN ls_field-foreignkey-card = '1' THEN '1' - WHEN ls_field-foreignkey-card = 'C' THEN '0..1' - ELSE '0..*' ) },{ COND string( WHEN ls_field-foreignkey-cardleft = '1' THEN '1' ELSE '0..1' ) }] { ls_field-foreignkey-checktable }| TO me->ddldicts. - ENDIF. - LOOP AT ls_field-foreignkey-foreignkey_eq ASSIGNING FIELD-SYMBOL(). - AT FIRST. - APPEND | where { -checkfield } = { COND string( WHEN -forkey IS INITIAL THEN -fortable - ELSE |{ -fortable CASE = LOWER }.{ -forkey }| ) }| TO me->ddldicts. - CONTINUE. - ENDAT. + me->o_pb = NEW #( `Process TABL & `). + me->parent_folder = 'SE11' && '/'. + ENDMETHOD. - APPEND | and { -checkfield } = { COND string( WHEN -forkey IS INITIAL THEN -fortable - ELSE |{ -fortable CASE = LOWER }.{ -forkey }| ) }| TO me->ddldicts. - ENDLOOP. - IF sy-subrc = 0. - me->ddldicts[ lines( me->ddldicts ) ] = me->ddldicts[ lines( me->ddldicts ) ] && ';'. - ENDIF. - ENDIF. - ENDLOOP. + METHOD get_base. - " 结束 - add_line( str = '' type = '' ). - add_line( str = '}' type = '' ). + " 查询基础数据 + SELECT + dd~tabname, + dd~contflag, + dd~authclass, + dd~mainflag, + dd~exclass, + dd~as4date, + dd~as4time + FROM dd02l AS dd + INNER JOIN tadir AS ta ON dd~tabname = ta~obj_name + WHERE ta~obj_name IN @s_objnam + AND dd~tabclass = @iv_tabcls + AND dd~as4local = 'A' + AND ta~pgmid = 'R3TR' + AND ta~object = 'TABL' + AND ta~devclass IN @s_pack + INTO TABLE @me->tdd02l. + + CHECK me->tdd02l IS NOT INITIAL. - APPEND INITIAL LINE TO me->gt_string ASSIGNING FIELD-SYMBOL(). - -table = ls_table-name. + SELECT + tabname, + ddlanguage, + ddtext + FROM dd02t + FOR ALL ENTRIES IN @me->tdd02l + WHERE tabname = @me->tdd02l-tabname + AND ddlanguage IN ('1','E') + INTO TABLE @me->tdd02t. + SORT me->tdd02t BY tabname ddlanguage. + DELETE ADJACENT DUPLICATES FROM me->tdd02t COMPARING tabname. + + " 字段 与 字段描述 + SELECT + * + FROM dd03l AS 3l + FOR ALL ENTRIES IN @me->tdd02l + WHERE tabname = @me->tdd02l-tabname + AND adminfield = '0' " 仅处理第一级别的字段/结构 => 在函数里有效 直接查表需要下方的逻辑 + AND depth = '00' " adminfield 针对结构有效 depth 针对结构套结构有效 + AND as4local = 'A' + INTO TABLE @me->tdd03l. + SORT me->tdd03l BY tabname position. - CONCATENATE LINES OF me->ddldicts INTO -string SEPARATED BY cl_abap_char_utilities=>cr_lf. - REFRESH me->ddldicts. - ENDLOOP. + SELECT + tabname, + fieldname, + ddlanguage, + ddtext + FROM dd03t AS 3t + FOR ALL ENTRIES IN @me->tdd02l + WHERE tabname = @me->tdd02l-tabname + AND as4local = 'A' + AND ddlanguage IN ('1','E') + INTO TABLE @me->tdd03t. + SORT me->tdd03t BY tabname fieldname ddlanguage. + DELETE ADJACENT DUPLICATES FROM me->tdd03t COMPARING tabname fieldname. ENDMETHOD. - METHOD struct_maintain. - DATA: lv_string TYPE string. + METHOD get_transp_more. - LOOP AT gt_tables INTO DATA(ls_table). - " 描述 - add_line( str = ls_table-desc type = me->types-label ). - " 增强类别 - add_line( str = ls_table-encat type = me->types-encat ). + CHECK me->tdd02l IS NOT INITIAL. - " 表名称 - add_line( str = |define structure { ls_table-name CASE = LOWER } \{| type = '' ). + " --> TRANSP 外键逻辑 + SELECT + tabname, + fieldname, + primpos, + fortable, + forkey, + checktable, + checkfield + FROM dd05q + FOR ALL ENTRIES IN @me->tdd02l + WHERE tabname = @me->tdd02l-tabname + INTO TABLE @me->tdd05q. + SORT me->tdd05q BY tabname fieldname primpos. - LOOP AT ls_table-fields INTO DATA(ls_field). - IF ls_field-adddesc IS NOT INITIAL. - APPEND | @EndUserText.label : '{ ls_field-adddesc }'| TO me->ddldicts. - ENDIF. + SELECT + 8l~tabname, + 8l~fieldname, + 8l~checktable, + 8l~frkart, + 8l~cardleft, + 8l~card, + 8t~ddlanguage, + 8t~ddtext + FROM dd08l AS 8l + LEFT JOIN dd08t AS 8t ON 8t~tabname = 8l~tabname + AND 8t~fieldname = 8l~fieldname + AND 8t~as4local = 8l~as4local + AND 8t~as4vers = 8l~as4vers + AND 8t~ddlanguage IN ('1','E') + FOR ALL ENTRIES IN @me->tdd02l + WHERE 8l~tabname = @me->tdd02l-tabname + INTO TABLE @me->tdd08l. + SORT me->tdd08l BY tabname fieldname ddlanguage. + DELETE ADJACENT DUPLICATES FROM me->tdd08l COMPARING tabname fieldname. - IF ls_field-addtion IS NOT INITIAL. - APPEND ls_field-addtion TO me->ddldicts. - ENDIF. + " <-- - IF ls_field-name IS INITIAL. - APPEND | { ls_field-type }{ COND #( WHEN ls_field-nonull = 'X' THEN | not null| ) };| TO me->ddldicts. - ELSE. - APPEND | { ls_field-name WIDTH = ls_table-field_max + 1 }: { ls_field-type }{ COND #( WHEN ls_field-nonull = 'X' THEN | not null| ) };| TO me->ddldicts. - ENDIF. - ENDLOOP. + ENDMETHOD. - " 结束 - add_line( str = '' type = '' ). - add_line( str = '}' type = '' ). + METHOD fill_table. + DATA: lv_string TYPE string, + lv_source TYPE string, + lt_ddldicts TYPE TABLE OF text1000. - APPEND INITIAL LINE TO me->gt_string ASSIGNING FIELD-SYMBOL(). - -table = ls_table-name. + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'TABT' ). " 特殊增量 TABL - CONCATENATE LINES OF me->ddldicts INTO -string SEPARATED BY cl_abap_char_utilities=>cr_lf. - REFRESH me->ddldicts. - ENDLOOP. + me->o_pb->base_desc = `Process TABL Table & `. + me->o_pb->count = lines( me->tdd02l ). - ENDMETHOD. + LOOP AT me->tdd02l INTO DATA(ls_dd02l). + me->o_pb->add( i_desc = ls_dd02l-tabname ). - METHOD: add_line. - CASE type. - WHEN me->types-label. - " 描述 - APPEND |@EndUserText.label : '{ str }'| TO me->ddldicts. - WHEN me->types-encat. - " 增强类别 - - " #NOT_CLASSIFIED - 未分类 - " #NOT_EXTENSIBLE - 无法增强(扩展) - " #EXTENSIBLE_CHARACTER - 可以增强(扩展)并且类似于角色 - " #EXTENSIBLE_CHARACTER_NUMERIC - 可以增强(扩展),并且是类似字符或数字的 - " #EXTENSIBLE_ANY - 可以以任何方式增强(扩展) - CASE str. - WHEN '0'. - APPEND |@AbapCatalog.enhancementCategory : #{ 'NOT_CLASSIFIED' }| TO me->ddldicts. - WHEN '1'. - APPEND |@AbapCatalog.enhancementCategory : #{ 'NOT_EXTENSIBLE' }| TO me->ddldicts. - WHEN '2'. - APPEND |@AbapCatalog.enhancementCategory : #{ 'EXTENSIBLE_CHARACTER' }| TO me->ddldicts. - WHEN '3'. - APPEND |@AbapCatalog.enhancementCategory : #{ 'EXTENSIBLE_CHARACTER_NUMERIC' }| TO me->ddldicts. - WHEN '4'. - APPEND |@AbapCatalog.enhancementCategory : #{ 'EXTENSIBLE_ANY' }| TO me->ddldicts. - WHEN OTHERS. - ENDCASE. - WHEN me->types-tabty. - " 表类别 - - " #TRANSPARENT - 透明表 - " #GLOBAL_TEMPORARY - 全局临时表 (GTT) - APPEND |@AbapCatalog.tableCategory : { COND #( WHEN str IS INITIAL THEN '#TRANSPARENT' ELSE str ) }| TO me->ddldicts. - WHEN me->types-edits. - " 维护方式 - - " RESTRICTED - 补充 - " #NOT_ALLOWED - 无显示/编辑 - " #LIMITED - 有限的显示/编辑 - " #ALLOWED - 允许显示/编辑 - CASE str. - WHEN ''. - APPEND |@AbapCatalog.dataMaintenance : #{ 'RESTRICTED' }| TO me->ddldicts. - WHEN 'D'. - APPEND |@AbapCatalog.dataMaintenance : #{ 'LIMITED' }| TO me->ddldicts. - WHEN 'N'. - APPEND |@AbapCatalog.dataMaintenance : #{ 'NOT_ALLOWED' }| TO me->ddldicts. - WHEN 'X'. - APPEND |@AbapCatalog.dataMaintenance : #{ 'ALLOWED' }| TO me->ddldicts. - WHEN OTHERS. - ENDCASE. - WHEN me->types-deliv. - " 交付类 - - " #A - delivery class A - " #C - delivery class C - " #L - delivery class L - " #G - delivery class G - " #E - delivery class E - " #S - delivery class S - " #W - delivery class W - APPEND |@AbapCatalog.deliveryClass : #{ COND #( WHEN str IS INITIAL THEN 'A' ELSE str ) }| TO me->ddldicts. - WHEN me->types-actty. - " 激活类型 - - " #NOT_CLASSIFIED - 激活类型 00 - " #NAMETAB_GENERATION_OFFLINE - 激活类型 01 - " #ADAPT_C_STRUCTURES - 激活类型 02 - " #INITIAL_TABLE_REQUIRED - 激活类型 10 - CASE str. - WHEN '00'. - APPEND |@AbapCatalog.activationType : #{ 'NOT_CLASSIFIED' }| TO me->ddldicts. - WHEN '01'. - APPEND |@AbapCatalog.activationType : #{ 'NAMETAB_GENERATION_OFFLINE' }| TO me->ddldicts. - WHEN '02'. - APPEND |@AbapCatalog.activationType : #{ 'ADAPT_C_STRUCTURES' }| TO me->ddldicts. - WHEN '10'. - APPEND |@AbapCatalog.activationType : #{ 'INITIAL_TABLE_REQUIRED' }| TO me->ddldicts. - WHEN OTHERS. - ENDCASE. - WHEN me->types-repla. - " 替换对象 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_dd02l-as4date + OR ( ls_delt_log-ddate = ls_dd02l-as4date AND ls_delt_log-dtime > ls_dd02l-as4time ). + CONTINUE. + ENDIF. + ENDIF. - APPEND |@AbapCatalog.replacementObject : { str }| TO me->ddldicts. - WHEN me->types-define. - " 表名 - APPEND |define table { str } \{| TO me->ddldicts. - WHEN OTHERS. - APPEND str TO me->ddldicts. - ENDCASE. - ENDMETHOD. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). -ENDCLASS. + -name = split_folder( ls_dd02l-tabname ) + && ls_dd02l-tabname && '.' && c_extension_ddl. -CLASS lcl_pretty_json IMPLEMENTATION. - METHOD pretty. + -name = me->parent_folder && 'Table/' && -name. - "cloud - " DATA(json_xstring) = cl_abap_conv_codepage=>create_out( )->convert( json ). - "on_premise - DATA(json_xstring) = cl_abap_codepage=>convert_to( json ). + " 表描述 + READ TABLE me->tdd02t INTO DATA(ls_dd02t) WITH KEY tabname = ls_dd02l-tabname BINARY SEARCH. - "Check and pretty print JSON + APPEND set_label( ls_dd02t-ddtext ) TO lt_ddldicts. " 描述 + APPEND set_encat( ls_dd02l-exclass ) TO lt_ddldicts. " 增强类别 + APPEND set_encat( '' ) TO lt_ddldicts. " 表类别 + APPEND set_encat( ls_dd02l-contflag ) TO lt_ddldicts. " 交付类\提交类 + APPEND set_encat( ls_dd02l-mainflag ) TO lt_ddldicts. " 维护方式\表维护 + APPEND set_actty( ls_dd02l-authclass ) TO lt_ddldicts. " 激活类型 + APPEND set_define( |{ ls_dd02l-tabname CASE = LOWER }| ) TO lt_ddldicts. " 表名 - DATA(reader) = cl_sxml_string_reader=>create( json_xstring ). - DATA(writer) = CAST if_sxml_writer( - cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ). - writer->set_option( option = if_sxml_writer=>co_opt_linebreaks ). - writer->set_option( option = if_sxml_writer=>co_opt_indent ). - reader->next_node( ). - reader->skip_node( writer ). - - "cloud - " DATA(json_formatted_string) = cl_abap_conv_codepage=>create_in( )->convert( CAST cl_sxml_string_writer( writer )->get_output( ) ). - "on premise - DATA(json_formatted_string) = cl_abap_codepage=>convert_from( CAST cl_sxml_string_writer( writer )->get_output( ) ). - - pretty_json = escape( val = json_formatted_string format = cl_abap_format=>e_xml_text ). + DATA(fields) = preproc_fields( ls_dd02l-tabname ). - ENDMETHOD. -ENDCLASS. + LOOP AT fields INTO DATA(field). + IF field-foreignkey-label IS NOT INITIAL. + APPEND | @AbapCatalog.foreignKey.label : '{ field-foreignkey-label }'| TO lt_ddldicts. + ENDIF. -FORM frm_get_tables_ddl USING pr_zip TYPE REF TO cl_abap_zip - pr_cover_out TYPE REF TO cl_abap_conv_out_ce - p_filename TYPE string. - CHECK pr_zip IS NOT INITIAL - AND pr_cover_out IS NOT INITIAL. + CASE field-foreignkey-keytype. + WHEN 'KEY'. + APPEND | @AbapCatalog.foreignKey.keyType : #{ 'KEY' }| TO lt_ddldicts. + WHEN 'REF'. + APPEND | @AbapCatalog.foreignKey.keyType : #{ 'NON_KEY' }| TO lt_ddldicts. + WHEN 'TEXT'. + APPEND | @AbapCatalog.foreignKey.keyType : #{ 'TEXT_KEY' }| TO lt_ddldicts. + WHEN OTHERS. + ENDCASE. - PERFORM frm_set_parent_folder USING p_filename. + IF field-foreignkey-screencheck IS NOT INITIAL. + APPEND | @AbapCatalog.foreignKey.screenCheck : { field-foreignkey-screencheck }| TO lt_ddldicts. + ENDIF. - DATA: lr_ddl TYPE REF TO lcl_export_ddldict. + lv_string = COND #( WHEN field-key = 'X' THEN `key ` ELSE `` ) && field-name. - lr_ddl = NEW lcl_export_ddldict( ). + IF field-adddesc IS NOT INITIAL. + APPEND | @EndUserText.label : '{ field-adddesc }'| TO lt_ddldicts. + ENDIF. - PERFORM frm_get_xx_ddl USING 'TRANSP' lr_ddl. + IF field-addtion IS NOT INITIAL. + APPEND field-addtion TO lt_ddldicts. + ENDIF. - lr_ddl->table_maintain( ). - DATA: lv_filename TYPE string, - lv_xstring TYPE xstring. - LOOP AT lr_ddl->gt_string INTO DATA(ls_string). + IF field-foreignkey-checktable IS INITIAL. + IF field-name IS INITIAL. + APPEND | { field-type }{ COND #( WHEN field-nonull = 'X' THEN | not null| ) };| TO lt_ddldicts. + ELSE. + APPEND | { lv_string WIDTH = me->field_max + 1 }: { + field-type }{ + COND #( WHEN field-nonull = 'X' THEN | not null| ) };| TO lt_ddldicts. + ENDIF. + ELSE. + IF field-name IS INITIAL. + APPEND | { field-type }{ COND #( WHEN field-nonull = 'X' THEN | not null| ) }| TO lt_ddldicts. + ELSE. + APPEND | { lv_string WIDTH = me->field_max + 1 }: { + field-type }{ + COND #( WHEN field-nonull = 'X' THEN | not null| ) }| TO lt_ddldicts. + ENDIF. - lv_filename = p_filename && ls_string-table && `.ddl`. + IF field-foreignkey-card = '' AND field-foreignkey-cardleft = ''. + APPEND | with foreign key { field-foreignkey-checktable }| TO lt_ddldicts. + ELSE. + APPEND | with foreign key [{ + COND string( WHEN field-foreignkey-card = '1' THEN '1' + WHEN field-foreignkey-card = 'C' THEN '0..1' + ELSE '0..*' ) },{ + COND string( WHEN field-foreignkey-cardleft = '1' THEN '1' + ELSE '0..1' ) }] { + field-foreignkey-checktable }| TO lt_ddldicts. + ENDIF. + LOOP AT field-foreignkey-foreignkey_eq ASSIGNING FIELD-SYMBOL(). + AT FIRST. + APPEND | where { -checkfield } = { + COND string( WHEN -forkey IS INITIAL THEN -fortable + ELSE |{ -fortable CASE = LOWER }.{ + -forkey }| ) }| TO lt_ddldicts. + CONTINUE. + ENDAT. - pr_cover_out->convert( - EXPORTING data = ls_string-string - IMPORTING buffer = lv_xstring ). + APPEND | and { -checkfield } = { + COND string( WHEN -forkey IS INITIAL THEN -fortable + ELSE |{ -fortable CASE = LOWER }.{ + -forkey }| ) }| TO lt_ddldicts. + ENDLOOP. + IF sy-subrc = 0. + lt_ddldicts[ lines( lt_ddldicts ) ] = lt_ddldicts[ lines( lt_ddldicts ) ] && ';'. + ENDIF. + ENDIF. - " 添加到压缩包 - pr_zip->add( name = lv_filename - content = lv_xstring ). - ENDLOOP. + ENDLOOP. -ENDFORM. + APPEND INITIAL LINE TO lt_ddldicts. + APPEND `}` TO lt_ddldicts. -FORM frm_get_structs_ddl USING pr_zip TYPE REF TO cl_abap_zip - pr_cover_out TYPE REF TO cl_abap_conv_out_ce - p_filename TYPE string. - CHECK pr_zip IS NOT INITIAL - AND pr_cover_out IS NOT INITIAL. + " 内表转换为长字符串 + CONCATENATE LINES OF lt_ddldicts INTO lv_source SEPARATED BY c_newline. - DATA: lr_ddl TYPE REF TO lcl_export_ddldict. + " string -> xstring + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). - lr_ddl = NEW lcl_export_ddldict( ). + CLEAR: ls_dd02t, lv_string, lv_source. + REFRESH fields. + ENDLOOP. - PERFORM frm_get_xx_ddl USING 'INTTAB' lr_ddl. + ENDMETHOD. - lr_ddl->struct_maintain( ). - DATA: lv_filename TYPE string, - lv_xstring TYPE xstring. + METHOD fill_struct. + DATA: lv_source TYPE string, + lt_ddldicts TYPE TABLE OF text1000. - LOOP AT lr_ddl->gt_string INTO DATA(ls_string). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'TABS' ). " 特殊增量 TABL + me->o_pb->base_desc = `Process TABL Struct & `. + me->o_pb->count = lines( me->tdd02l ). - lv_filename = p_filename && ls_string-table && `.ddl`. + LOOP AT me->tdd02l INTO DATA(ls_dd02l). + me->o_pb->add( i_desc = ls_dd02l-tabname ). - pr_cover_out->convert( - EXPORTING data = ls_string-string - IMPORTING buffer = lv_xstring ). + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_dd02l-as4date + OR ( ls_delt_log-ddate = ls_dd02l-as4date AND ls_delt_log-dtime > ls_dd02l-as4time ). + CONTINUE. + ENDIF. + ENDIF. - " 添加到压缩包 - pr_zip->add( name = lv_filename - content = lv_xstring ). - ENDLOOP. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). -ENDFORM. + -name = split_folder( ls_dd02l-tabname ) + && ls_dd02l-tabname && '.' && c_extension_ddl. + -name = me->parent_folder && 'Struct/' && -name. -FORM frm_get_xx_ddl USING p_type TYPE tabclass pr_ddl TYPE REF TO lcl_export_ddldict. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - " 查询基础数据 - SELECT - dd~tabname, - dd~contflag, - dd~authclass, - dd~mainflag, - dd~exclass, - dd~as4date, - dd~as4time - FROM dd02l AS dd - INNER JOIN tadir AS ta ON dd~tabname = ta~obj_name - WHERE ta~obj_name IN @gt_range_objname "dd~tabname - AND dd~tabclass = @p_type - AND dd~as4local = 'A' - AND ta~pgmid = 'R3TR' - AND ta~object = 'TABL' - AND ta~devclass IN @gt_range_devclass - INTO TABLE @DATA(lt_dd02l). - - CHECK lt_dd02l IS NOT INITIAL. - - SELECT - tabname, - ddlanguage, - ddtext - FROM dd02t - FOR ALL ENTRIES IN @lt_dd02l - WHERE tabname = @lt_dd02l-tabname - AND ddlanguage IN ('1','E') - INTO TABLE @DATA(lt_dd02t). - SORT lt_dd02t BY tabname ddlanguage. - DELETE ADJACENT DUPLICATES FROM lt_dd02t COMPARING tabname. - - " 字段 与 字段描述 - SELECT - * - FROM dd03l AS 3l - FOR ALL ENTRIES IN @lt_dd02l - WHERE tabname = @lt_dd02l-tabname - AND adminfield = '0' " 仅处理第一级别的字段/结构 => 在函数里有效 直接查表需要下方的逻辑 - AND depth = '00' " adminfield 针对结构有效 depth 针对结构套结构有效 - AND as4local = 'A' - INTO TABLE @DATA(lt_dd03l). - SORT lt_dd03l BY tabname position. - - SELECT - tabname, - fieldname, - ddlanguage, - ddtext - FROM dd03t AS 3t - FOR ALL ENTRIES IN @lt_dd02l - WHERE tabname = @lt_dd02l-tabname - AND as4local = 'A' - AND ddlanguage IN ('1','E') - INTO TABLE @DATA(lt_dd03t). - SORT lt_dd03t BY tabname fieldname ddlanguage. - DELETE ADJACENT DUPLICATES FROM lt_dd03t COMPARING tabname fieldname. - - - " --> 补充 外键逻辑 - IF p_type = 'TRANSP'. - SELECT - tabname, - fieldname, - primpos, - fortable, - forkey, - checktable, - checkfield - FROM dd05q - FOR ALL ENTRIES IN @lt_dd02l - WHERE tabname = @lt_dd02l-tabname - INTO TABLE @DATA(lt_dd05q). - SORT lt_dd05q BY tabname fieldname primpos. + " 表描述 + READ TABLE me->tdd02t INTO DATA(ls_dd02t) WITH KEY tabname = ls_dd02l-tabname BINARY SEARCH. - SELECT - 8l~tabname, - 8l~fieldname, - 8l~checktable, - 8l~frkart, - 8l~cardleft, - 8l~card, - 8t~ddlanguage, - 8t~ddtext - FROM dd08l AS 8l - LEFT JOIN dd08t AS 8t ON 8t~tabname = 8l~tabname - AND 8t~fieldname = 8l~fieldname - AND 8t~as4local = 8l~as4local - AND 8t~as4vers = 8l~as4vers - AND 8t~ddlanguage IN ('1','E') - FOR ALL ENTRIES IN @lt_dd02l - WHERE 8l~tabname = @lt_dd02l-tabname - INTO TABLE @DATA(lt_dd08l). - SORT lt_dd08l BY tabname fieldname ddlanguage. - DELETE ADJACENT DUPLICATES FROM lt_dd08l COMPARING tabname fieldname. - ENDIF. - " <-- + APPEND set_label( ls_dd02t-ddtext ) TO lt_ddldicts. " 描述 + APPEND set_encat( ls_dd02l-exclass ) TO lt_ddldicts. " 增强类别 - DATA: lv_gotstate TYPE dcobjif-gotstate. - DATA: lt_dd03p TYPE TABLE OF dd03p, - ls_dd02v TYPE dd02v. + APPEND |define structure { ls_dd02l-tabname CASE = LOWER } \{| TO lt_ddldicts. " 表名 - DATA: lv_tabix TYPE sytabix. + DATA(fields) = preproc_fields( ls_dd02l-tabname ). + LOOP AT fields INTO DATA(field). + IF field-adddesc IS NOT INITIAL. + APPEND | @EndUserText.label : '{ field-adddesc }'| TO lt_ddldicts. + ENDIF. - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = p_type+0(4) BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = p_type+0(4) ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + IF field-addtion IS NOT INITIAL. + APPEND field-addtion TO lt_ddldicts. + ENDIF. - lr_pb->count = lines( lt_dd02l ). - lr_pb->base_desc = 'Process ' && p_type && ' & '. + IF field-name IS INITIAL. + APPEND | { field-type }{ COND #( WHEN field-nonull = 'X' THEN | not null| ) };| TO lt_ddldicts. + ELSE. + APPEND | { field-name WIDTH = me->field_max + 1 }: { + field-type }{ + COND #( WHEN field-nonull = 'X' THEN | not null| ) };| TO lt_ddldicts. + ENDIF. + ENDLOOP. - LOOP AT lt_dd02l INTO DATA(ls_dd02l). - lr_pb->add( i_desc = ls_dd02l-tabname ). + APPEND INITIAL LINE TO lt_ddldicts. + APPEND `}` TO lt_ddldicts. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_dd02l-as4date - OR ( ls_delt_log-ddate = ls_dd02l-as4date AND ls_delt_log-dtime > ls_dd02l-as4time ). - CONTINUE. - ENDIF. - ENDIF. + " 内表转换为长字符串 + CONCATENATE LINES OF lt_ddldicts INTO lv_source SEPARATED BY c_newline. - APPEND INITIAL LINE TO pr_ddl->gt_tables ASSIGNING FIELD-SYMBOL(). + " string -> xstring + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). - " 表名 - -name = ls_dd02l-tabname. + CLEAR: ls_dd02t, lv_source. + REFRESH fields. + ENDLOOP. - " 表描述 - READ TABLE lt_dd02t INTO DATA(ls_dd02t) WITH KEY tabname = ls_dd02l-tabname BINARY SEARCH. - IF sy-subrc = 0. - -desc = ls_dd02t-ddtext. - ENDIF. + ENDMETHOD. - " 额外数据 - -deliv = ls_dd02l-contflag. " 提交类 - -actty = ls_dd02l-authclass. " 激活类型 - -edits = ls_dd02l-mainflag. " 表维护 - -encat = ls_dd02l-exclass. " 增强类别 + METHOD preproc_fields. - READ TABLE lt_dd03l TRANSPORTING NO FIELDS WITH KEY tabname = ls_dd02l-tabname BINARY SEARCH. + READ TABLE me->tdd03l TRANSPORTING NO FIELDS WITH KEY tabname = tabname BINARY SEARCH. IF sy-subrc = 0. - lv_tabix = sy-tabix. - - LOOP AT lt_dd03l INTO DATA(ls_dd03l) FROM lv_tabix. - IF ls_dd03l-tabname <> ls_dd02l-tabname. + LOOP AT me->tdd03l INTO DATA(ls_dd03l) FROM sy-tabix. + IF tabname <> ls_dd03l-tabname. EXIT. ENDIF. - APPEND INITIAL LINE TO -fields ASSIGNING FIELD-SYMBOL(). + APPEND INITIAL LINE TO r_fields ASSIGNING FIELD-SYMBOL(). " 字段名 -name = |{ ls_dd03l-fieldname CASE = LOWER }|. IF ls_dd03l-fieldname = '.INCLUDE' OR ls_dd03l-fieldname = '.INCLU--AP'. + " include | append 使用参考字段 CLEAR -name. IF ls_dd03l-reffield IS NOT INITIAL. @@ -2507,37 +2237,25 @@ FORM frm_get_xx_ddl USING p_type TYPE tabclass pr_ddl TYPE REF TO lcl_export_ddl lv_fieldlen = lv_fieldlen + 3 + 1. ENDIF. - IF -field_max < lv_fieldlen. - -field_max = lv_fieldlen. + IF me->field_max < lv_fieldlen. + me->field_max = lv_fieldlen. ENDIF. -key = ls_dd03l-keyflag. -nonull = ls_dd03l-notnull. + " 数据元素是否为空 + IF ls_dd03l-rollname IS INITIAL AND NOT ( ls_dd03l-fieldname = '.INCLUDE' " 切换为表取值后 include 的 rollname 为空 OR ls_dd03l-fieldname = '.INCLU--AP' ). " append 特殊类型 " 数据元素为空 - CASE ls_dd03l-datatype. - WHEN 'DATS' OR 'TIMS'. - -type = |abap.{ ls_dd03l-datatype CASE = LOWER }|. - WHEN 'CHAR' OR 'NUMC'. - -type = |abap.{ ls_dd03l-datatype CASE = LOWER }({ CONV i( ls_dd03l-leng ) })|. - WHEN 'CURR'. - -type = |abap.{ ls_dd03l-datatype CASE = LOWER }({ CONV i( ls_dd03l-leng ) },{ CONV i( ls_dd03l-decimals ) })|. - WHEN 'DEC'. - -type = |abap.{ ls_dd03l-datatype CASE = LOWER }({ CONV i( ls_dd03l-leng ) },{ CONV i( ls_dd03l-decimals ) })|. - WHEN 'QUAN'. - -type = |abap.{ ls_dd03l-datatype CASE = LOWER }({ CONV i( ls_dd03l-leng ) },{ CONV i( ls_dd03l-decimals ) })|. - WHEN 'STRG'. - -type = |abap.string({ CONV i( ls_dd03l-leng ) })|. - WHEN 'INT4' OR 'INT1' OR 'INT2' OR 'INT8'. - -type = |abap.{ ls_dd03l-datatype CASE = LOWER }|. - WHEN OTHERS. - -type = ls_dd03l-datatype && '-' && ls_dd03l-leng. - ENDCASE. + -type = field_type( iv_datatype = ls_dd03l-datatype + iv_leng = ls_dd03l-leng + iv_decimals = ls_dd03l-decimals ). + " 补充描述 - READ TABLE lt_dd03t INTO DATA(ls_dd03t) WITH KEY tabname = ls_dd03l-tabname fieldname = ls_dd03l-fieldname BINARY SEARCH. + READ TABLE me->tdd03t INTO DATA(ls_dd03t) WITH KEY tabname = ls_dd03l-tabname fieldname = ls_dd03l-fieldname BINARY SEARCH. IF sy-subrc = 0. -adddesc = ls_dd03t-ddtext. ENDIF. @@ -2558,15 +2276,19 @@ FORM frm_get_xx_ddl USING p_type TYPE tabclass pr_ddl TYPE REF TO lcl_export_ddl CASE ls_dd03l-datatype. WHEN 'CURR'. - -addtion = | @Semantics.amount.currencyCode : '{ |{ ls_dd03l-reftable CASE = LOWER }| }.{ ls_dd03l-reffield CASE = LOWER }'|. + -addtion = | @Semantics.amount.currencyCode : '{ + |{ ls_dd03l-reftable CASE = LOWER }| }.{ + ls_dd03l-reffield CASE = LOWER }'|. WHEN 'QUAN'. - -addtion = | @Semantics.quantity.unitOfMeasure : '{ |{ ls_dd03l-reftable CASE = LOWER }| }.{ ls_dd03l-reffield CASE = LOWER }'|. + -addtion = | @Semantics.quantity.unitOfMeasure : '{ + |{ ls_dd03l-reftable CASE = LOWER }| }.{ + ls_dd03l-reffield CASE = LOWER }'|. WHEN 'LANG'. -addtion = | @AbapCatalog.textLanguage|. WHEN OTHERS. ENDCASE. - READ TABLE lt_dd08l INTO DATA(ls_dd08l) WITH KEY tabname = ls_dd03l-tabname fieldname = ls_dd03l-fieldname BINARY SEARCH. + READ TABLE me->tdd08l INTO DATA(ls_dd08l) WITH KEY tabname = ls_dd03l-tabname fieldname = ls_dd03l-fieldname BINARY SEARCH. IF sy-subrc = 0. -foreignkey-label = ls_dd08l-ddtext. -foreignkey-screencheck = COND #( WHEN ls_dd08l-frkart IS INITIAL THEN 'false' ELSE 'true' ). @@ -2581,11 +2303,9 @@ FORM frm_get_xx_ddl USING p_type TYPE tabclass pr_ddl TYPE REF TO lcl_export_ddl -foreignkey-checktable = |{ ls_dd08l-checktable CASE = LOWER }|. ENDIF. - READ TABLE lt_dd05q TRANSPORTING NO FIELDS WITH KEY tabname = ls_dd03l-tabname fieldname = ls_dd03l-fieldname BINARY SEARCH. + READ TABLE me->tdd05q TRANSPORTING NO FIELDS WITH KEY tabname = ls_dd03l-tabname fieldname = ls_dd03l-fieldname BINARY SEARCH. IF sy-subrc = 0. - lv_tabix = sy-tabix. - - LOOP AT lt_dd05q INTO DATA(ls_dd05q) FROM lv_tabix. + LOOP AT me->tdd05q INTO DATA(ls_dd05q) FROM sy-tabix. IF ls_dd05q-tabname <> ls_dd03l-tabname OR ls_dd05q-fieldname <> ls_dd03l-fieldname. EXIT. @@ -2601,796 +2321,704 @@ FORM frm_get_xx_ddl USING p_type TYPE tabclass pr_ddl TYPE REF TO lcl_export_ddl ENDLOOP. ENDIF. - ENDLOOP. + ENDMETHOD. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_domain -*&---------------------------------------------------------------------* -*& 获取数据域 -*&---------------------------------------------------------------------* -FORM frm_get_domain . - - " 数据元素和数据域对应关系 DD04L - " 数据域值 DD07L - " 数据域文本 DD01T - " 数据域 DD01L - - " 数据域 - " 目的便于查看与还原 - TYPES: BEGIN OF ty_domavalues, - valpos TYPE i, - ddtext TYPE string, - domvalue_l TYPE string, - domvalue_h TYPE string, - appval TYPE abap_bool, " 附加 - END OF ty_domavalues. - TYPES: BEGIN OF ty_doma, - domname TYPE dd01l-domname, - as4user TYPE dd01l-as4user, - as4date TYPE dd01l-as4date, - as4time TYPE dd01l-as4time, - values TYPE TABLE OF ty_domavalues WITH DEFAULT KEY, - END OF ty_doma. - - DATA: lv_filename TYPE string. - - DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - DATA: ls_doma TYPE ty_doma, - lv_tabix TYPE sytabix. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - " 数据获取 - SELECT - dd~domname, - dd~as4user, - dd~as4date, - dd~as4time, - dt~ddtext - FROM dd01l AS dd - INNER JOIN tadir AS ta ON dd~domname = ta~obj_name - LEFT JOIN dd01t AS dt ON dt~domname = dd~domname AND dt~ddlanguage = @sy-langu - AND dt~as4local = dd~as4local AND dt~as4vers = dd~as4vers - WHERE ta~pgmid = 'R3TR' - AND ta~object = 'DOMA' - AND ta~devclass IN @gt_range_devclass - AND dd~as4local = 'A' - AND ta~obj_name IN @gt_range_objname " dd~domname - AND dd~as4user <> 'SAP' - INTO TABLE @DATA(lt_dd01l). - - lr_pb->count = lines( lt_dd01l ). - lr_pb->base_desc = 'Process Domain & '. - - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'DOMA' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'DOMA' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + METHOD field_type. + CASE iv_datatype. + WHEN 'DATS' OR 'TIMS'. + rv_type = |abap.{ iv_datatype CASE = LOWER }|. + WHEN 'CHAR' OR 'NUMC'. + rv_type = |abap.{ iv_datatype CASE = LOWER }({ CONV i( iv_leng ) })|. + WHEN 'CURR'. + rv_type = |abap.{ iv_datatype CASE = LOWER }({ CONV i( iv_leng ) },{ CONV i( iv_decimals ) })|. + WHEN 'DEC'. + rv_type = |abap.{ iv_datatype CASE = LOWER }({ CONV i( iv_leng ) },{ CONV i( iv_decimals ) })|. + WHEN 'QUAN'. + rv_type = |abap.{ iv_datatype CASE = LOWER }({ CONV i( iv_leng ) },{ CONV i( iv_decimals ) })|. + WHEN 'STRG'. + rv_type = |abap.string({ CONV i( iv_leng ) })|. + WHEN 'INT4' OR 'INT1' OR 'INT2' OR 'INT8'. + rv_type = |abap.{ iv_datatype CASE = LOWER }|. + WHEN OTHERS. + rv_type = iv_datatype && '-' && iv_leng. + ENDCASE. + ENDMETHOD. - " 获取域值 - IF lt_dd01l IS NOT INITIAL. - SELECT - dl~domname, - dl~valpos, - dt~ddtext, - dl~domvalue_l, - dl~domvalue_h, - dl~appval " 附加 - FROM dd07l AS dl - LEFT JOIN dd07t AS dt ON dt~domname = dl~domname - AND dt~valpos = dl~valpos - AND dt~as4vers = dl~as4vers - AND dt~ddlanguage = @sy-langu - FOR ALL ENTRIES IN @lt_dd01l - WHERE dl~domname = @lt_dd01l-domname - INTO TABLE @DATA(lt_dd07). - SORT lt_dd07 BY domname valpos. - ENDIF. + METHOD set_label. + " 描述 + rv_str = |@EndUserText.label : '{ str }'|. + ENDMETHOD. + METHOD set_encat. + " 增强类别 + + " #NOT_CLASSIFIED - 未分类 + " #NOT_EXTENSIBLE - 无法增强(扩展) + " #EXTENSIBLE_CHARACTER - 可以增强(扩展)并且类似于角色 + " #EXTENSIBLE_CHARACTER_NUMERIC - 可以增强(扩展),并且是类似字符或数字的 + " #EXTENSIBLE_ANY - 可以以任何方式增强(扩展) + CASE str. + WHEN '0'. + rv_str = |@AbapCatalog.enhancementCategory : #{ 'NOT_CLASSIFIED' }|. + WHEN '1'. + rv_str = |@AbapCatalog.enhancementCategory : #{ 'NOT_EXTENSIBLE' }|. + WHEN '2'. + rv_str = |@AbapCatalog.enhancementCategory : #{ 'EXTENSIBLE_CHARACTER' }|. + WHEN '3'. + rv_str = |@AbapCatalog.enhancementCategory : #{ 'EXTENSIBLE_CHARACTER_NUMERIC' }|. + WHEN '4'. + rv_str = |@AbapCatalog.enhancementCategory : #{ 'EXTENSIBLE_ANY' }|. + WHEN OTHERS. + ENDCASE. + ENDMETHOD. + METHOD set_tabty. + " 表类别 - LOOP AT lt_dd01l INTO DATA(ls_dd01). - lr_pb->add( i_desc = ls_dd01-domname ). + " #TRANSPARENT - 透明表 + " #GLOBAL_TEMPORARY - 全局临时表 (GTT) + rv_str = |@AbapCatalog.tableCategory : { '#TRANSPARENT' }|. + ENDMETHOD. + METHOD set_edits. + " 维护方式 + + " RESTRICTED - 补充 + " #NOT_ALLOWED - 无显示/编辑 + " #LIMITED - 有限的显示/编辑 + " #ALLOWED - 允许显示/编辑 + CASE str. + WHEN ''. + rv_str = |@AbapCatalog.dataMaintenance : #{ 'RESTRICTED' }|. + WHEN 'D'. + rv_str = |@AbapCatalog.dataMaintenance : #{ 'LIMITED' }|. + WHEN 'N'. + rv_str = |@AbapCatalog.dataMaintenance : #{ 'NOT_ALLOWED' }|. + WHEN 'X'. + rv_str = |@AbapCatalog.dataMaintenance : #{ 'ALLOWED' }|. + WHEN OTHERS. + ENDCASE. + ENDMETHOD. + METHOD set_deliv. + " 交付类 + + " #A - delivery class A + " #C - delivery class C + " #L - delivery class L + " #G - delivery class G + " #E - delivery class E + " #S - delivery class S + " #W - delivery class W + rv_str = |@AbapCatalog.deliveryClass : #{ COND #( WHEN str IS INITIAL THEN 'A' ELSE str ) }|. + ENDMETHOD. + METHOD set_actty. + " 激活类型 + + " #NOT_CLASSIFIED - 激活类型 00 + " #NAMETAB_GENERATION_OFFLINE - 激活类型 01 + " #ADAPT_C_STRUCTURES - 激活类型 02 + " #INITIAL_TABLE_REQUIRED - 激活类型 10 + CASE str. + WHEN '00'. + rv_str = |@AbapCatalog.activationType : #{ 'NOT_CLASSIFIED' }|. + WHEN '01'. + rv_str = |@AbapCatalog.activationType : #{ 'NAMETAB_GENERATION_OFFLINE' }|. + WHEN '02'. + rv_str = |@AbapCatalog.activationType : #{ 'ADAPT_C_STRUCTURES' }|. + WHEN '10'. + rv_str = |@AbapCatalog.activationType : #{ 'INITIAL_TABLE_REQUIRED' }|. + WHEN OTHERS. + ENDCASE. + ENDMETHOD. + METHOD set_repla. + " 替换对象 + rv_str = |@AbapCatalog.replacementObject : { str }|. + ENDMETHOD. + METHOD set_define. + " 表名 + rv_str = |define table { str } \{|. + ENDMETHOD. - lv_filename = ls_dd01-domname && '.json'. + METHOD loadfiles. + DATA: lt_tabcls TYPE TABLE OF tabclass. - lv_filename = gv_parent_folder && lv_filename. + " table & struct + lt_tabcls = VALUE #( ( 'TRANSP' ) ( 'INTTAB' ) ). - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_dd01-ddtext. + LOOP AT lt_tabcls INTO DATA(lv_tabcls). - " 日志 生成 - PERFORM frm_set_log_flow USING 'DOMA' ls_dd01-domname ls_dd01-as4user ls_dd01-as4date ls_dd01-as4time. + get_base( lv_tabcls ). - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_dd01-as4date - OR ( ls_delt_log-ddate = ls_dd01-as4date AND ls_delt_log-dtime > ls_dd01-as4time ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. + CHECK me->tdd02l IS NOT INITIAL. - CONTINUE. + IF lv_tabcls = 'TRANSP'. + get_transp_more( ). ENDIF. - ENDIF. - " 生成 json 文件 - ls_doma-domname = ls_dd01-domname. - ls_doma-as4user = ls_dd01-as4user. - ls_doma-as4date = ls_dd01-as4date. - ls_doma-as4time = ls_dd01-as4time. + " FILL FILE + IF lv_tabcls = 'TRANSP'. + fill_table( ). + ELSEIF lv_tabcls = 'INTTAB'. + fill_struct( ). + ENDIF. - READ TABLE lt_dd07 TRANSPORTING NO FIELDS WITH KEY domname = ls_dd01-domname BINARY SEARCH. - IF sy-subrc = 0. - lv_tabix = sy-tabix. + REFRESH: me->tdd02l, me->tdd02t, me->tdd03l, + me->tdd03t, me->tdd05q, me->tdd08l. + ENDLOOP. - LOOP AT lt_dd07 INTO DATA(ls_dd07) FROM lv_tabix. - IF ls_dd07-domname <> ls_dd01-domname. - EXIT. - ENDIF. + ENDMETHOD. - APPEND CORRESPONDING #( ls_dd07 ) TO ls_doma-values. - ENDLOOP. - ENDIF. + METHOD split_folder. + DATA: l_limit TYPE ty_split_limit. - GET REFERENCE OF ls_doma INTO DATA(lo_doma). + l_limit = i_limit. - lv_source = /ui2/cl_json=>serialize( data = lo_doma - pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). - CLEAR ls_doma. + " rv_filename = . + ENDMETHOD. - lv_source = lcl_pretty_json=>pretty( lv_source ). + METHOD load2zip. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). + CHECK io_zip IS BOUND. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - " 清除缓存 - CLEAR: lv_filename, lv_xstring, lv_source. - ENDLOOP. + ENDMETHOD. +ENDCLASS. +CLASS lcl_backup4abap_object_doma IMPLEMENTATION. - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + METHOD constructor. + super->constructor( ). -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_element -*&---------------------------------------------------------------------* -*& 获取数据元素 -*&---------------------------------------------------------------------* -FORM frm_get_element . - - " 数据元素和数据域对应关系 DD04L - - " 数据元素 - " 目的便于查看与还原 - TYPES: BEGIN OF ty_elem, - rollname TYPE dd04l-rollname, - domname TYPE dd04l-domname, - as4user TYPE dd04l-as4user, - as4date TYPE dd04l-as4date, - as4time TYPE dd04l-as4time, - datatype TYPE dd04l-datatype, - leng TYPE dd04l-leng, - decimals TYPE dd04l-decimals, - outputlen TYPE dd04l-outputlen, - lowercase TYPE dd04l-lowercase, - convexit TYPE dd04l-convexit, - entitytab TYPE dd04l-entitytab, - refkind TYPE dd04l-refkind, - ddtext TYPE dd04t-ddtext, - reptext TYPE dd04t-reptext, - scrtext_s TYPE dd04t-scrtext_s, - scrtext_m TYPE dd04t-scrtext_m, - scrtext_l TYPE dd04t-scrtext_l, - END OF ty_elem. - - DATA: lv_filename TYPE string. - - DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - DATA: ls_elem TYPE ty_elem, - lv_tabix TYPE sytabix. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - " 数据获取 - SELECT - dd~rollname, - dd~domname, - dd~as4user, - dd~as4date, - dd~as4time, - dd~datatype, - dd~leng, - dd~decimals, - dd~outputlen, - dd~lowercase, - dd~convexit, - dd~entitytab, - dd~refkind, - dt~ddtext, - dt~reptext, - dt~scrtext_s, - dt~scrtext_m, - dt~scrtext_l - FROM dd04l AS dd - INNER JOIN tadir AS ta ON dd~rollname = ta~obj_name - LEFT JOIN dd04t AS dt ON dt~rollname = dd~rollname AND dt~ddlanguage = dd~dtelmaster - AND dt~as4local = dd~as4local AND dt~as4vers = dd~as4vers - WHERE ta~pgmid = 'R3TR' - AND ta~object = 'DTEL' - AND ta~devclass IN @gt_range_devclass - AND dd~as4local = 'A' - AND ta~obj_name IN @gt_range_objname " dd~rollname - AND dd~as4user <> 'SAP' - INTO TABLE @DATA(lt_dd04l). - - lr_pb->count = lines( lt_dd04l ). - lr_pb->base_desc = 'Process Element & '. - - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'DTEL' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'DTEL' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + me->o_pb = NEW #( `Process Domain & ` ). + me->parent_folder = 'SE11/Domain' && '/'. + ENDMETHOD. - LOOP AT lt_dd04l INTO DATA(ls_dd04). - lr_pb->add( i_desc = ls_dd04-rollname ). + METHOD loadfiles. + " 数据元素和数据域对应关系 DD04L + " 数据域值 DD07L + " 数据域文本 DD01T + " 数据域 DD01L - lv_filename = ls_dd04-rollname && '.json'. + " 数据域 + " 目的便于查看与还原 + DATA: ls_doma TYPE ty_doma, + lv_source TYPE string. - lv_filename = gv_parent_folder && lv_filename. + " 数据获取 + SELECT + dd~domname, + dd~as4user, + dd~as4date, + dd~as4time, + dt~ddtext + FROM dd01l AS dd + INNER JOIN tadir AS ta ON dd~domname = ta~obj_name + LEFT JOIN dd01t AS dt ON dt~domname = dd~domname AND dt~ddlanguage = @sy-langu + AND dt~as4local = dd~as4local AND dt~as4vers = dd~as4vers + WHERE ta~pgmid = 'R3TR' + AND ta~object = 'DOMA' + AND ta~devclass IN @s_pack + AND dd~as4local = 'A' + AND ta~obj_name IN @s_objnam " dd~domname + INTO TABLE @DATA(lt_dd01l). + + " 获取域值 + IF lt_dd01l IS NOT INITIAL. + SELECT + dl~domname, + dl~valpos, + dt~ddtext, + dl~domvalue_l, + dl~domvalue_h, + dl~appval " 附加 + FROM dd07l AS dl + LEFT JOIN dd07t AS dt ON dt~domname = dl~domname + AND dt~valpos = dl~valpos + AND dt~as4vers = dl~as4vers + AND dt~ddlanguage = @sy-langu + FOR ALL ENTRIES IN @lt_dd01l + WHERE dl~domname = @lt_dd01l-domname + INTO TABLE @DATA(lt_dd07). + SORT lt_dd07 BY domname valpos. + ENDIF. - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_dd04-ddtext. + me->o_pb->count = lines( lt_dd01l ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'DOMA' ). - " 日志 生成 - PERFORM frm_set_log_flow USING 'DTEL' ls_dd04-domname ls_dd04-as4user ls_dd04-as4date ls_dd04-as4time. + LOOP AT lt_dd01l INTO DATA(ls_dd01). + me->o_pb->add( i_desc = ls_dd01-domname ). - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_dd04-as4date - OR ( ls_delt_log-ddate = ls_dd04-as4date AND ls_delt_log-dtime > ls_dd04-as4time ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_dd01-as4date + OR ( ls_delt_log-ddate = ls_dd01-as4date AND ls_delt_log-dtime > ls_dd01-as4time ). - CONTINUE. + CONTINUE. + ENDIF. ENDIF. - ENDIF. - " 生成 json 文件 - MOVE-CORRESPONDING ls_dd04 TO ls_elem. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - GET REFERENCE OF ls_elem INTO DATA(lo_elem). + -name = split_folder( ls_dd01-domname ) + && ls_dd01-domname && '.' && c_extension_json. - lv_source = /ui2/cl_json=>serialize( data = lo_elem - pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). - CLEAR ls_elem. + -name = me->parent_folder && -name. - lv_source = lcl_pretty_json=>pretty( lv_source ). + " 生成 json 文件 + ls_doma-domname = ls_dd01-domname. + ls_doma-as4user = ls_dd01-as4user. + ls_doma-as4date = ls_dd01-as4date. + ls_doma-as4time = ls_dd01-as4time. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). + READ TABLE lt_dd07 TRANSPORTING NO FIELDS WITH KEY domname = ls_dd01-domname BINARY SEARCH. + IF sy-subrc = 0. + LOOP AT lt_dd07 INTO DATA(ls_dd07) FROM sy-tabix. + IF ls_dd07-domname <> ls_dd01-domname. + EXIT. + ENDIF. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + APPEND CORRESPONDING #( ls_dd07 ) TO ls_doma-values. + ENDLOOP. + ENDIF. - " 清除缓存 - CLEAR: lv_filename, lv_xstring, lv_source. - ENDLOOP. + GET REFERENCE OF ls_doma INTO DATA(lo_doma). - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + lv_source = /ui2/cl_json=>serialize( data = lo_doma + pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). + CLEAR ls_doma. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form FRM_GET_TABLETYPES_DDL -*&---------------------------------------------------------------------* -*& 获取表类型 -*&---------------------------------------------------------------------* -FORM frm_get_tabletypes. - " 表类型 DD40L - " 表类型文本 DD40T - - " 目的便于查看 - TYPES: BEGIN OF ty_ttyp, - typename TYPE dd40l-typename, - rowtype TYPE dd40l-rowtype, - rowkind TYPE dd40l-rowkind, - datatype TYPE dd40l-datatype, - leng TYPE dd40l-leng, - decimals TYPE dd40l-decimals, - accessmode TYPE dd40l-accessmode, - keydef TYPE dd40l-keydef, - keykind TYPE dd40l-keykind, - keyfdcount TYPE dd40l-keyfdcount, - generic TYPE dd40l-generic, - typelen TYPE dd40l-typelen, - as4user TYPE dd40l-as4user, - as4date TYPE dd40l-as4date, - as4time TYPE dd40l-as4time, - ddtext TYPE dd40t-ddtext, - END OF ty_ttyp. - - " rowkind => 'E' 基本类型\'S' 结构类型\'L' 表格类型\' ' 直接类型条目\'R' 参考类型\'D' 域 - - DATA: lv_filename TYPE string. - - DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - DATA: ls_ttyp TYPE ty_ttyp, - lv_tabix TYPE sytabix. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - " 数据获取 - SELECT - dd~typename, - dd~rowtype, - dd~rowkind, - dd~datatype, - dd~leng, - dd~decimals, - dd~accessmode, - dd~keydef, - dd~keykind, - dd~keyfdcount, - dd~generic, - dd~typelen, - dd~as4user, - dd~as4date, - dd~as4time, - dt~ddtext - FROM dd40l AS dd - INNER JOIN tadir AS ta ON dd~typename = ta~obj_name - LEFT JOIN dd40t AS dt ON dt~typename = dd~typename AND dt~ddlanguage = @sy-langu - WHERE ta~pgmid = 'R3TR' - AND ta~object = 'TTYP' - AND ta~devclass IN @gt_range_devclass - AND dd~as4local = 'A' - AND ta~obj_name IN @gt_range_objname "dd~typename - INTO TABLE @DATA(lt_dd40l). - - lr_pb->count = lines( lt_dd40l ). - lr_pb->base_desc = 'Process TableType & '. - - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'TTYP' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'TTYP' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + lv_source = lcl_pretty_json=>pretty( lv_source ). - LOOP AT lt_dd40l INTO DATA(ls_dd40). - lr_pb->add( i_desc = ls_dd40-typename ). + " string -> xstring + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). - lv_filename = ls_dd40-typename && '.json'. + CLEAR: ls_doma, lv_source. + ENDLOOP. - lv_filename = gv_parent_folder && lv_filename. + ENDMETHOD. - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_dd40-ddtext. + METHOD split_folder. + DATA: l_limit TYPE ty_split_limit. - " 日志 生成 - PERFORM frm_set_log_flow USING 'DTEL' ls_dd40-typename ls_dd40-as4user ls_dd40-as4date ls_dd40-as4time. + l_limit = i_limit. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_dd40-as4date - OR ( ls_delt_log-ddate = ls_dd40-as4date AND ls_delt_log-dtime > ls_dd40-as4time ). - REFRESH lt_source. - CLEAR: lv_filename, lv_xstring. + " rv_filename = . + ENDMETHOD. - CONTINUE. - ENDIF. - ENDIF. + METHOD load2zip. - " 生成 json 文件 - MOVE-CORRESPONDING ls_dd40 TO ls_ttyp. + CHECK io_zip IS BOUND. - GET REFERENCE OF ls_ttyp INTO DATA(lo_ttyp). + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data + compress_level = 9 ). + ENDLOOP. - lv_source = /ui2/cl_json=>serialize( data = lo_ttyp - pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). - CLEAR ls_ttyp. + ENDMETHOD. +ENDCLASS. +CLASS lcl_backup4abap_object_dtel IMPLEMENTATION. - lv_source = lcl_pretty_json=>pretty( lv_source ). + METHOD constructor. + super->constructor( ). - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). + me->o_pb = NEW #( `Process DTEL & ` ). + me->parent_folder = 'SE11/Element' && '/'. + ENDMETHOD. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + METHOD loadfiles. - " 清除缓存 - CLEAR: lv_filename, lv_xstring, lv_source. - ENDLOOP. + " 数据元素和数据域对应关系 DD04L - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + " 数据元素 + " 目的便于查看与还原 + DATA: ls_elem TYPE ty_elem. + DATA: lv_source TYPE string. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_others -*&---------------------------------------------------------------------* -*& 保存其他 -*&---------------------------------------------------------------------* -FORM frm_get_others . + " 数据获取 + SELECT + dd~rollname, + dd~domname, + dd~as4user, + dd~as4date, + dd~as4time, + dd~datatype, + dd~leng, + dd~decimals, + dd~outputlen, + dd~lowercase, + dd~convexit, + dd~entitytab, + dd~refkind, + dt~ddtext, + dt~reptext, + dt~scrtext_s, + dt~scrtext_m, + dt~scrtext_l + FROM dd04l AS dd + INNER JOIN tadir AS ta ON dd~rollname = ta~obj_name + LEFT JOIN dd04t AS dt ON dt~rollname = dd~rollname AND dt~ddlanguage = dd~dtelmaster + AND dt~as4local = dd~as4local AND dt~as4vers = dd~as4vers + WHERE ta~pgmid = 'R3TR' + AND ta~object = 'DTEL' + AND ta~devclass IN @s_pack + AND dd~as4local = 'A' + AND ta~obj_name IN @s_objnam " dd~rollname + INTO TABLE @DATA(lt_dd04l). + + CHECK lt_dd04l IS NOT INITIAL. + + me->o_pb->count = lines( lt_dd04l ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'DTEL' ). + + LOOP AT lt_dd04l INTO DATA(ls_dd04). + me->o_pb->add( i_desc = ls_dd04-rollname ). + + " 检查增量 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_dd04-as4date + OR ( ls_delt_log-ddate = ls_dd04-as4date AND ls_delt_log-dtime > ls_dd04-as4time ). + + CONTINUE. + ENDIF. + ENDIF. - IF p_smw0 = abap_true. - PERFORM frm_set_parent_folder USING `SMW0/`. - " 由于文件名包含中文,设置编码格式为 UTF-8 - gr_zip->support_unicode_names = abap_true. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - PERFORM frm_get_smw0. + -name = split_folder( ls_dd04-rollname ) + && ls_dd04-rollname && '.' && c_extension_json. - " 还原设置 - gr_zip->support_unicode_names = abap_false. - ENDIF. + -name = me->parent_folder && -name. - IF p_tran = abap_true. - PERFORM frm_set_parent_folder USING `TCODE/`. + " 生成 json 文件 + MOVE-CORRESPONDING ls_dd04 TO ls_elem. - PERFORM frm_get_tcode. - ENDIF. + GET REFERENCE OF ls_elem INTO DATA(lo_elem). - IF p_xslt = abap_true. - PERFORM frm_set_parent_folder USING `STRANS/`. + lv_source = /ui2/cl_json=>serialize( data = lo_elem + pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). - PERFORM frm_get_strans. - ENDIF. + lv_source = lcl_pretty_json=>pretty( lv_source ). - PERFORM frm_get_ench IN PROGRAM zsltest18 IF FOUND USING gr_zip gr_cover_out `ENCH/`. + " string -> xstring + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). + CLEAR: ls_elem, lv_source. + ENDLOOP. - " 结果存储 - gv_parent_folder = `logs/flow/`. - PERFORM frm_get_logs. + ENDMETHOD. - DATA: ls_blob TYPE demo_indx_blob. + METHOD split_folder. + DATA: l_limit TYPE ty_split_limit. - IF p_delt = 'X'. - ls_blob-userid = sy-uname. - GET TIME STAMP FIELD ls_blob-timestamp. - " gv_delta_store_id && SY-UNAME - EXPORT gt_delt_log TO DATABASE demo_indx_blob(zd) FROM ls_blob ID gv_delta_store_id. - ENDIF. + l_limit = i_limit. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_smw0 -*&---------------------------------------------------------------------* -*& 获取 SMW0 -*&---------------------------------------------------------------------* -FORM frm_get_smw0 . - DATA: lv_filename TYPE string. - DATA: lt_mime TYPE TABLE OF w3mime. - DATA: lv_xstring TYPE xstring, - lv_size TYPE i. - - DATA: lr_pb TYPE REF TO lcl_progress_bar. - - CREATE OBJECT lr_pb. - - SELECT - relid, - objid, - chname, - tdate, - ttime, - text - FROM wwwdata - WHERE srtf2 = 0 - AND relid = 'MI' - AND ( objid LIKE 'Z%' - OR objid LIKE 'Y%' ) - INTO TABLE @DATA(lt_smw0). - IF sy-subrc <> 0. - " 未找到数据不进行下载 - RETURN. - ENDIF. + " rv_filename = . + ENDMETHOD. - " 获取文件参数 - SELECT - objid, - name, - value - FROM wwwparams - WHERE relid = 'MI' - AND ( objid LIKE 'Z%' - OR objid LIKE 'Y%' ) - INTO TABLE @DATA(lt_param). - - SORT lt_smw0 BY objid. - SORT lt_param BY objid name. - - lr_pb->count = lines( lt_smw0 ). - lr_pb->base_desc = 'Process SMW0 & '. - - DATA: ls_delt_log LIKE LINE OF gt_delt_log. - READ TABLE gt_delt_log ASSIGNING FIELD-SYMBOL() WITH KEY object = 'SMW0' BINARY SEARCH. - IF sy-subrc <> 0. - APPEND VALUE #( object = 'SMW0' ddate = sy-datum dtime = sy-uzeit ) TO gt_delt_log. - ELSE. - ls_delt_log = . - -ddate = sy-datum. - -dtime = sy-uzeit. - ENDIF. + METHOD load2zip. - LOOP AT lt_smw0 INTO DATA(ls_smw0). - lr_pb->add( i_desc = ls_smw0-objid ). + CHECK io_zip IS BOUND. - lv_filename = ls_smw0-objid && `_` && ls_smw0-text. + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - " 后缀名 - READ TABLE lt_param INTO DATA(ls_param_ext) WITH KEY objid = ls_smw0-objid name = 'fileextension' BINARY SEARCH. - IF sy-subrc = 0. - lv_filename = lv_filename && ls_param_ext-value. - ENDIF. + ENDMETHOD. +ENDCLASS. +CLASS lcl_backup4abap_object_ttyp IMPLEMENTATION. + + METHOD constructor. + super->constructor( ). - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename ls_smw0-text. + me->o_pb = NEW #( `Process TTYP & ` ). + me->parent_folder = 'SE11/TABLETYPE' && '/'. + ENDMETHOD. - lv_filename = gv_parent_folder && lv_filename. + METHOD loadfiles. + " 表类型 DD40L + " 表类型文本 DD40T - " 日志 生成 - PERFORM frm_set_log_flow USING 'SMW0' ls_smw0-objid ls_smw0-chname ls_smw0-tdate ls_smw0-ttime. + " 目的便于查看 + DATA: ls_ttyp TYPE ty_ttyp, + lv_source TYPE string. - " 检查增量 - IF p_delt = 'X'. - IF ls_delt_log-ddate > ls_smw0-tdate - OR ( ls_delt_log-ddate = ls_smw0-tdate AND ls_delt_log-dtime > ls_smw0-ttime ). - REFRESH lt_mime. - CLEAR: lv_filename, lv_xstring, lv_size. + " rowkind => 'E' 基本类型\'S' 结构类型\'L' 表格类型\' ' 直接类型条目\'R' 参考类型\'D' 域 - CONTINUE. + " 数据获取 + SELECT + dd~typename, + dd~rowtype, + dd~rowkind, + dd~datatype, + dd~leng, + dd~decimals, + dd~accessmode, + dd~keydef, + dd~keykind, + dd~keyfdcount, + dd~generic, + dd~typelen, + dd~as4user, + dd~as4date, + dd~as4time, + dt~ddtext + FROM dd40l AS dd + INNER JOIN tadir AS ta ON dd~typename = ta~obj_name + LEFT JOIN dd40t AS dt ON dt~typename = dd~typename AND dt~ddlanguage = @sy-langu + WHERE ta~pgmid = 'R3TR' + AND ta~object = 'TTYP' + AND ta~devclass IN @s_pack + AND dd~as4local = 'A' + AND ta~obj_name IN @s_objnam "dd~typename + INTO TABLE @DATA(lt_dd40l). + + CHECK lt_dd40l IS NOT INITIAL. + + me->o_pb->count = lines( lt_dd40l ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'TTYP' ). + + LOOP AT lt_dd40l INTO DATA(ls_dd40). + me->o_pb->add( i_desc = ls_dd40-typename ). + + " 检查增量 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_dd40-as4date + OR ( ls_delt_log-ddate = ls_dd40-as4date AND ls_delt_log-dtime > ls_dd40-as4time ). + + CONTINUE. + ENDIF. ENDIF. - ENDIF. - " 文件长度 - READ TABLE lt_param INTO DATA(ls_param_size) WITH KEY objid = ls_smw0-objid name = 'filesize' BINARY SEARCH. - IF sy-subrc = 0. - lv_size = ls_param_size-value. - ENDIF. + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - IMPORT mime = lt_mime FROM DATABASE wwwdata(mi) ID ls_smw0-objid . - IF sy-subrc = 0. - CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' - EXPORTING - input_length = lv_size - IMPORTING - buffer = lv_xstring - TABLES - binary_tab = lt_mime - EXCEPTIONS - failed = 1 - OTHERS = 2. - ENDIF. + -name = split_folder( ls_dd40-typename ) + && ls_dd40-typename && '.' && c_extension_json. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + -name = me->parent_folder && -name. - " 清除缓存 - REFRESH lt_mime. - CLEAR: lv_filename, lv_xstring, lv_size. - ENDLOOP. + " 生成 json 文件 + MOVE-CORRESPONDING ls_dd40 TO ls_ttyp. - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + GET REFERENCE OF ls_ttyp INTO DATA(lo_ttyp). -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_tcode -*&---------------------------------------------------------------------* -*& 事务码 -*&---------------------------------------------------------------------* -FORM frm_get_tcode . - - " 事务码 tstc - - " 事务码 - " 目的便于查看与还原 - TYPES: BEGIN OF ty_tran, - tcode TYPE tstc-tcode, - pgmna TYPE tstc-pgmna, - dypno TYPE tstc-dypno, - menue TYPE tstc-menue, - cinfo TYPE tstc-cinfo, - arbgb TYPE tstc-arbgb, - ttext TYPE tstct-ttext, - param TYPE tstcp-param, - END OF ty_tran. - - DATA: lv_filename TYPE string. - - DATA: lt_source TYPE TABLE OF text1000 WITH EMPTY KEY, - lv_source TYPE string, - lv_xstring TYPE xstring. - DATA: ls_tran TYPE ty_tran, - lt_tran TYPE TABLE OF ty_tran, - lv_tabix TYPE sytabix. - - " 数据获取 - SELECT - tc~tcode, - tc~pgmna, - tc~dypno, - tc~menue, - tc~cinfo, - tc~arbgb, - tt~ttext, - tp~param - FROM tstc AS tc - INNER JOIN tadir AS ta ON tc~tcode = ta~obj_name - LEFT JOIN tstcp AS tp ON tp~tcode = tc~tcode - LEFT JOIN tstct AS tt ON tt~tcode = tc~tcode AND tt~sprsl = @sy-langu - WHERE ta~pgmid = 'R3TR' - AND ta~object = 'TRAN' - AND ta~devclass IN @gt_range_devclass - AND ta~obj_name IN @gt_range_objname " tc~tcode - INTO TABLE @DATA(lt_tstc). - - LOOP AT lt_tstc INTO DATA(ls_tstc). - " 生成 json 文件 - MOVE-CORRESPONDING ls_tstc TO ls_tran. - - APPEND ls_tran TO lt_tran. - CLEAR ls_tran. - ENDLOOP. + lv_source = /ui2/cl_json=>serialize( data = lo_ttyp + pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). + + lv_source = lcl_pretty_json=>pretty( lv_source ). + + " string -> xstring + me->o_conv_out->convert( EXPORTING data = lv_source + IMPORTING buffer = -data ). + CLEAR: ls_ttyp, lv_source. + ENDLOOP. - lv_filename = `TCode` && '.json'. + ENDMETHOD. - lv_filename = gv_parent_folder && lv_filename. + METHOD split_folder. + DATA: l_limit TYPE ty_split_limit. - " map 文件路径 - PERFORM frm_set_map_file USING lv_filename '事务码目录'. + l_limit = i_limit. - GET REFERENCE OF lt_tran INTO DATA(lo_tran). + " rv_filename = . + ENDMETHOD. - lv_source = /ui2/cl_json=>serialize( data = lo_tran - pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). + METHOD load2zip. - lv_source = lcl_pretty_json=>pretty( lv_source ). + CHECK io_zip IS BOUND. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + ENDMETHOD. +ENDCLASS. - " 清除缓存 - CLEAR: lv_filename, lv_xstring, lv_source. +CLASS lcl_backup4abap_object_ddls IMPLEMENTATION. - " map 文件 - PERFORM frm_add_map_file USING gv_parent_folder. + METHOD constructor. + super->constructor( ). -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_get_STRANS -*&---------------------------------------------------------------------* -*& 获取转换 -*&---------------------------------------------------------------------* -FORM frm_get_strans . + me->o_pb = NEW #( `Process DDLS & ` ). + me->parent_folder = 'DDL' && '/'. + ENDMETHOD. + + METHOD loadfiles. + + " 读取 DDL + SELECT + rc~ddlname, + rc~as4user, + rc~as4date, + rc~as4time, + rc~source, + ct~ddtext + FROM ddddlsrc AS rc + INNER JOIN tadir AS ta ON ta~obj_name = rc~ddlname AND object = 'DDLS' " 存在 STOB 结构化对象 + LEFT JOIN ddddlsrct AS ct ON ct~ddlname = rc~ddlname + AND ct~ddlanguage = '1' + AND ct~as4local = rc~as4local + WHERE ta~obj_name IN @s_objnam "rc~ddlname + AND rc~as4local = 'A' + AND ta~devclass IN @s_pack + INTO TABLE @DATA(lt_ddlsrc). + SORT lt_ddlsrc BY ddlname. + + CHECK lt_ddlsrc IS NOT INITIAL. + + me->o_pb->count = lines( lt_ddlsrc ). + DATA(ls_delt_log) = lcl_backup4abap_filter_time=>factory( )->get( 'DDLS' ). + + LOOP AT lt_ddlsrc INTO DATA(ls_ddl). + me->o_pb->add( i_desc = ls_ddl-ddlname ). + + " 检查增量 + IF is_delta( ) = 'X'. + IF ls_delt_log-ddate > ls_ddl-as4date + OR ( ls_delt_log-ddate = ls_ddl-as4date AND ls_delt_log-dtime > ls_ddl-as4time ). + + CONTINUE. + ENDIF. + ENDIF. - " 内容表 O2XSLTDESC - " 描述 O2XSLTTEXT + APPEND INITIAL LINE TO me->files ASSIGNING FIELD-SYMBOL(). - DATA: lv_xstr_xslt TYPE xstring. - DATA: lt_tline TYPE TABLE OF abaptxt255. + -name = split_folder( ls_ddl-ddlname ) + && ls_ddl-ddlname && '.' && c_extension_ddl. - DATA: lv_source TYPE string, - lv_xstring TYPE xstring. + -name = me->parent_folder && -name. - DATA: lv_filename TYPE string. + " --> Begin 清除末尾注释 + REPLACE FIRST OCCURRENCE OF REGEX `\/\*\+\[internal\].*\*\/` IN ls_ddl-source WITH ``. + " <-- - SELECT - o2~xsltdesc, - o2~srtf2, - o2~clustr, - o2~clustd - FROM tadir AS ta - INNER JOIN o2xsltdesc AS o2 ON ta~obj_name = o2~xsltdesc - WHERE ta~pgmid = 'R3TR' - AND ta~object = 'XSLT' - AND ta~obj_name IN @gt_range_objname - AND ta~devclass IN @gt_range_devclass - AND o2~state = 'A' - AND o2~relid = 'TR' - INTO TABLE @DATA(lt_xslt). + " string -> xstring + me->o_conv_out->convert( EXPORTING data = ls_ddl-source + IMPORTING buffer = -data ). - CHECK lt_xslt IS NOT INITIAL. + ENDLOOP. - SORT lt_xslt BY xsltdesc srtf2. + ENDMETHOD. - LOOP AT lt_xslt ASSIGNING FIELD-SYMBOL(). - lv_xstr_xslt = lv_xstr_xslt && -clustd. + METHOD split_folder. + DATA: l_limit TYPE ty_split_limit. - AT END OF xsltdesc. + l_limit = i_limit. - IMPORT xsltdesc = lt_tline FROM DATA BUFFER lv_xstr_xslt. + rv_filename = lcl_backup4abap_folder=>split_folder_ddls( l_limit ). + ENDMETHOD. - IF lt_tline IS NOT INITIAL. + METHOD load2zip. - CONCATENATE LINES OF lt_tline INTO lv_source SEPARATED BY gc_newline. + CHECK io_zip IS BOUND. - lv_filename = -xsltdesc && '.xsd'. + LOOP AT me->files INTO DATA(file). + io_zip->add( name = file-name + content = file-data ). + ENDLOOP. - lv_filename = gv_parent_folder && lv_filename. + ENDMETHOD. +ENDCLASS. - " string -> xstring - gr_cover_out->convert( - EXPORTING data = lv_source - IMPORTING buffer = lv_xstring ). +CLASS lcl_backup4abap_export IMPLEMENTATION. - " 添加到压缩包 - gr_zip->add( name = lv_filename - content = lv_xstring ). + METHOD constructor. + me->o_zip = NEW #( ). + ENDMETHOD. - " 清除缓存 - CLEAR: lv_filename, lv_xstring, lv_source. - ENDIF. + METHOD factory. + IF objt IS INITIAL. + objt = NEW #( ). + ENDIF. - CLEAR: lt_tline[], lv_xstr_xslt. - ENDAT. + ro_objt = objt. + ENDMETHOD. - ENDLOOP. + METHOD path. + DATA: lv_path TYPE string, + lv_fullpath TYPE string, + lv_filename TYPE string. -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_set_parent_folder -*&---------------------------------------------------------------------* -*& 设置父层目录 -*&---------------------------------------------------------------------* -FORM frm_set_parent_folder USING p_folder. + CALL METHOD cl_gui_frontend_services=>file_save_dialog + EXPORTING + window_title = 'download zip' + default_extension = 'zip' + default_file_name = |{ sy-datum }{ sy-uzeit }| + file_filter = '(*.zip)|*.zip|' + CHANGING + filename = lv_filename + path = lv_path + fullpath = lv_fullpath + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4. + IF sy-subrc <> 0 OR lv_fullpath IS INITIAL. + MESSAGE '用户取消' TYPE 'E' RAISING e_no_choese. + ENDIF. - gv_parent_folder = p_folder. + me->file_path = lv_fullpath. + ENDMETHOD. -ENDFORM. + METHOD download. + TYPES: ty_hex TYPE x LENGTH 200. + DATA: lt_xdata TYPE STANDARD TABLE OF ty_hex WITH DEFAULT KEY, + lv_xlen TYPE i. + + IF lines( o_zip->files ) = 0. + MESSAGE '未找到增量文件,取消导出' TYPE 'E' RAISING e_no_file. + ENDIF. + + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = o_zip->save( ) + IMPORTING + output_length = lv_xlen + TABLES + binary_tab = lt_xdata. + + CALL FUNCTION 'GUI_DOWNLOAD' + EXPORTING + bin_filesize = lv_xlen + filename = me->file_path + filetype = 'BIN' + TABLES + data_tab = lt_xdata. + + ENDMETHOD. + + METHOD main. + DATA: lv_class TYPE seoclsname. + DATA: li_object TYPE REF TO lif_backup4abap_object. + + " 获取选中的数据 + DATA(lt_option) = lcl_backup4abap_screen_option=>selected_option( ). + + LOOP AT lt_option INTO DATA(lv_option). + lv_class = 'LCL_BACKUP4ABAP_OBJECT_' && lv_option. + + TRY. + CREATE OBJECT li_object TYPE (lv_class). + CATCH cx_sy_create_object_error. + " PASS + CONTINUE. + ENDTRY. + + li_object->loadfiles( ). + li_object->load2zip( me->o_zip ). + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. -*----------------------------------------------------------------------* -* CLASS lcl_progress_bar IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* CLASS lcl_progress_bar IMPLEMENTATION. METHOD constructor. - me->count = i_count. + " me->count = i_count. me->base_desc = i_base_desc. ENDMETHOD. @@ -3420,76 +3048,32 @@ CLASS lcl_progress_bar IMPLEMENTATION. percentage = me->percent text = lv_text. ENDMETHOD. -ENDCLASS. -*&---------------------------------------------------------------------* -*& Form FRM_FIX_PACKAGES -*&---------------------------------------------------------------------* -*& 补全子包 -*&---------------------------------------------------------------------* -FORM frm_fix_packages . - - SELECT - devclass - FROM tdevc - WHERE devclass IN @s_pack[] - INTO TABLE @DATA(lt_tdev). - - IF lt_tdev IS INITIAL. - MESSAGE '请填写正确的包名' TYPE 'S' DISPLAY LIKE 'E'. - STOP. - ENDIF. - - gt_range_devclass = VALUE #( BASE gt_range_devclass FOR item IN lt_tdev - sign = 'I' option = 'EQ' ( low = item-devclass ) ). - - PERFORM frm_fix_package USING lt_tdev. - -ENDFORM. -*&---------------------------------------------------------------------* -*& Form FRM_FIX_PACKAGE -*&---------------------------------------------------------------------* -*& 补全子包=>递归 -*&---------------------------------------------------------------------* -FORM frm_fix_package USING t_devclass TYPE tt_tdevc_parentcl. - - CHECK t_devclass IS NOT INITIAL. - - SELECT - devclass - FROM tdevc - FOR ALL ENTRIES IN @t_devclass - WHERE parentcl = @t_devclass-parentcl - INTO TABLE @DATA(lt_tdev). - IF sy-subrc = 0. - - gt_range_devclass = VALUE #( BASE gt_range_devclass FOR item IN lt_tdev - sign = 'I' option = 'EQ' ( low = item-devclass ) ). - PERFORM frm_fix_package USING lt_tdev. - - ENDIF. - -ENDFORM. -*&---------------------------------------------------------------------* -*& Form frm_display_timestamp -*&---------------------------------------------------------------------* -*& 展示当前系统中增量时戳 -*&---------------------------------------------------------------------* -FORM frm_display_timestamp . - DATA: lv_timestamp TYPE timestamp. +ENDCLASS. +CLASS lcl_pretty_json IMPLEMENTATION. + METHOD pretty. - " 增量数据获取 - gv_delta_store_id = gc_delta_store_id_fix_part && sy-uname. + "cloud + " DATA(json_xstring) = cl_abap_conv_codepage=>create_out( )->convert( json ). + "on_premise + DATA(json_xstring) = cl_abap_codepage=>convert_to( json ). - " DeltaDownload && SY-UNAME - IMPORT gt_delt_log FROM DATABASE demo_indx_blob(zd) ID gv_delta_store_id. - SORT gt_delt_log BY object. + "Check and pretty print JSON - cl_demo_output=>write( gt_delt_log ). + DATA(reader) = cl_sxml_string_reader=>create( json_xstring ). + DATA(writer) = CAST if_sxml_writer( + cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ). + writer->set_option( option = if_sxml_writer=>co_opt_linebreaks ). + writer->set_option( option = if_sxml_writer=>co_opt_indent ). + reader->next_node( ). + reader->skip_node( writer ). - GET TIME STAMP FIELD lv_timestamp. - cl_demo_output=>write( lv_timestamp ). + "cloud + " DATA(json_formatted_string) = cl_abap_conv_codepage=>create_in( )->convert( CAST cl_sxml_string_writer( writer )->get_output( ) ). + "on premise + DATA(json_formatted_string) = cl_abap_codepage=>convert_from( CAST cl_sxml_string_writer( writer )->get_output( ) ). - cl_demo_output=>display( ). + pretty_json = escape( val = json_formatted_string format = cl_abap_format=>e_xml_text ). -ENDFORM. \ No newline at end of file + ENDMETHOD. +ENDCLASS. \ No newline at end of file