通过ABAP代码实现批导创建SAP表/结构/数据元素/域(SE11/BAPI)

前段时间在群里看到一个问题,问有没有人知道SE11的BAPI,确实之前没有找过相关的BAPI,但是在项目上,避免不了手动创建各种自建表,特别是对日项目,字段比较多的时候,创建这些表,结构,数据元素,域就会花费很多时间,最近事情不是特别多,就抽出闲暇时间,写了一个批导程序,主要包括以下功能:

1.批量创建表

2.批量创建结构

3.批量创建数据元素

4.批量创建域

5.使用OLE生成上传模板,无需SMW0先上传模板

6.程序自动按照屏幕选项读取对应页签的数据,无需上传前再次切换页签保存

7.可以创建时指定请求

8.可以覆盖创建

为了方便直接将代码复制粘贴后就能执行,我在代码中将屏幕元素的文本描述用代码直接指定了,只维护了中文描述。

程序执行界面:

 补充说明几个主要功能实现时碰到的问题:

1.OLE下载模板时碰到的问题:

问题点1:需要在调用SaveAs方法之前先执行语句GET PROPERTY OF myexcel 'ActiveWorkbook' = myworkbook.

否则会无法保存。

问题点2:在测试时最开始并没有指定第二个参数,导致我直接指定文件后缀为*.xlsx时,保存出来的文件一直无法正常打开,会提示内容与文件类型不符,后来经过查询资料才发现,这个参数需要指定为51,该参数的含义可以在EXCEL中查看:

可以看到该方法第二个参数为FileFormat,右键WorkBook,点击“帮助”即可跳转到官方的API说明界面,就可以查看该参数可以赋什么值,都代表什么含义。

可以看到 XlFileFormat 参数是一个枚举类型, xlsx对应的值为51,所以在代码中指定该参数就可以避免无法正常将Excel文件保存为后缀为*.xlsx格式的问题。

2.上传EXCEL的问题

由于我想写一个比较通用的程序,ABAP2XLSX应该可以很好的解决这个问题,但是并不是所有系统里都部署了这个工具类,普通的上传函数又无法实现一次性将所有TAB页内容上传的需求,而且普通的上传函数上传前,需要将Excel切换到你要上传的页签才行,我不想每次上传前还要再手动切换一下页签再保存一次,麻烦,最后在SAP社区找到了一份帖子,提供了一个方法可以实现我想要的效果,那就是使用类 CL_FDT_XL_SPREADSHEET 配合 GUI_UPLOAD。

原贴连接如下:

Excel Upload and Download Program with multiple tabs from Fiori Launch Pad(Web GUI)

不过需要注意的是,该方法有官方note指定,不推荐使用,非要用也可以当做一种变通的方案,只不过SAP不支持,不过我在实际使用过程中,也没有发现有什么问题,包括设置粗体,合并单元格,设置颜色等都可以正常工作,应对常规需求应该没有问题,系统中如果实装了ABAP2XLSX类,那还是遵循SAP建议,不要用这个类吧。

功能测试截图:

1.创建table,需要添加MANDT字段,并没有在代码中默认

2022/12/30日更新:新增支持外键表字段,源码已更新

 SE11确认结果:

 2.创建structure

报错是为了查看有错误的时候日志输出情况,代码改为正确的增强类别后,创建成功

 3.创建DataElements

 

 

 4.创建Domain

 

 

 

以下是完整代码,直接复制粘贴即可运行。

*&---------------------------------------------------------------------*
*& Report ZSE11
*&---------------------------------------------------------------------*
*& 功能:
*& 批量创建Table
*& 批量创建Structure
*& 批量创建Data Elements
*& 批量创建Domain
*&---------------------------------------------------------------------*
*& 创建者:HAND13065  创建日期:2022/12/06
*&---------------------------------------------------------------------*
REPORT zse11 NO STANDARD PAGE HEADING.
TABLES:sscrfields.

*命名前缀
CONSTANTS:
  gc_prefix_table TYPE char10 VALUE 'ZT*',
  gc_prefix_struc TYPE char10 VALUE 'ZS*',
  gc_prefix_dtel  TYPE char10 VALUE 'ZE*',
  gc_prefix_doma  TYPE char10 VALUE 'ZD*'.

TYPES:
* 表格类型
  BEGIN OF ty_table,
    fieldname  TYPE coms_gox_fieldinfo-fieldname,  "字段名称
    keyflag    TYPE coms_gox_fieldinfo-keyflag,    "是否主键
    rollname   TYPE coms_gox_fieldinfo-rollname,   "数据元素
    datatype   TYPE coms_gox_fieldinfo-datatype,   "数据类型
    leng       TYPE coms_gox_fieldinfo-leng,       "长度
    decimals   TYPE coms_gox_fieldinfo-decimals,   "小数位
    ddtext     TYPE coms_gox_fieldinfo-ddtext,     "简短描述
    reftable   TYPE coms_gox_fieldinfo-reftable,   "参照表
    reffield   TYPE coms_gox_fieldinfo-reffield,   "参照字段
    checktable TYPE coms_gox_fieldinfo-checktable, "检查表
    checkfield TYPE coms_gox_fieldinfo-checktable, "检查字段
  END OF ty_table,
  ty_tab_table TYPE STANDARD TABLE OF ty_table,

* 结构类型
  BEGIN OF ty_struc,
    fieldname TYPE coms_gox_fieldinfo-fieldname,  "字段名称
    rollname  TYPE coms_gox_fieldinfo-rollname,   "数据元素
    datatype  TYPE coms_gox_fieldinfo-datatype,   "数据类型
    leng      TYPE coms_gox_fieldinfo-leng,       "长度
    decimals  TYPE coms_gox_fieldinfo-decimals,   "小数位
    ddtext    TYPE coms_gox_fieldinfo-ddtext,     "简短描述
    reftable  TYPE coms_gox_fieldinfo-reftable,   "参照表
    reffield  TYPE coms_gox_fieldinfo-reffield,   "参照字段
  END OF ty_struc,
  ty_tab_struc TYPE STANDARD TABLE OF ty_struc,

* 数据元素
  BEGIN OF ty_dtel,
    rollname  TYPE dd04v-rollname,                "数据元素
    ddtext    TYPE dd04v-ddtext,                  "描述
    domname   TYPE dd04v-domname,                 "域
    datatype  TYPE dd04v-datatype,                "数据类型
    leng      TYPE dd04v-leng,                    "长度
    decimals  TYPE dd04v-decimals,                "小数位
    scrtext_s TYPE dd04v-scrtext_s,               "短描述
    scrtext_m TYPE dd04v-scrtext_m,               "中描述
    scrtext_l TYPE dd04v-scrtext_l,               "长描述
    reptext   TYPE dd04v-reptext,                 "标题
  END OF ty_dtel,
  ty_tab_dtel TYPE STANDARD TABLE OF ty_dtel,

* 域
  BEGIN OF ty_doma,
    domname    TYPE dd04v-domname,                "域
    ddtext     TYPE dd04v-ddtext,                 "描述
    datatype   TYPE dd04v-datatype,               "数据类型
    leng       TYPE dd04v-leng,                   "长度
    decimals   TYPE dd04v-decimals,               "小数位
    signflag   TYPE dd04v-signflag,               "是否支持符号
    lowercase  TYPE dd04v-lowercase,              "是否支持大小写
    convexit   TYPE dd04v-convexit,               "转换例程
    domvalue_l TYPE dd07v-domvalue_l,             "固定值
    ddtext_fix TYPE dd07v-ddtext,                 "固定值描述
  END OF ty_doma,
  ty_tab_doma TYPE STANDARD TABLE OF ty_doma,

* 字段名
  BEGIN OF ty_objname,
    objname TYPE char30,                          "字段名
  END OF ty_objname,
  ty_tab_objname TYPE STANDARD TABLE OF ty_objname,

* 建议的外键
  BEGIN OF ty_sug_foreign,
    tabname   TYPE dd03l-tabname,                 "外键表名
    fieldname TYPE coms_gox_fieldinfo-fieldname,  "外键字段名
    primpos   TYPE dd05m-primpos,                 "外键字段位置
  END OF ty_sug_foreign,
  ty_tab_sug_foreign TYPE SORTED TABLE OF ty_sug_foreign
    WITH UNIQUE KEY tabname fieldname primpos,

* 外键表名
  BEGIN OF ty_key_table,
    tabname TYPE dd03l-tabname,                   "外键表名
  END OF ty_key_table,
  ty_tab_key_table TYPE SORTED TABLE OF ty_key_table
    WITH UNIQUE KEY tabname,

* 执行结果
  BEGIN OF ty_result,
    objtype   TYPE char14,                        "对象类型
    objname   TYPE char30,                        "对象名称
    result    TYPE icon_d,                        "结果
    objnumber TYPE char4,                         "总条目数
    objnum_s  TYPE char4,                         "成功条目数
    objnum_e  TYPE char4,                         "失败条目数
  END OF ty_result,

  BEGIN OF ty_err_info,
    objtype TYPE char14,                          "对象类型
    objname TYPE char30,                          "对象名称
    msgid   TYPE sy-msgid,                        "消息类
    msgno   TYPE sy-msgno,                        "消息号
    msgty   TYPE sy-msgty,                        "消息类型
    message TYPE bapi_msg,                        "消息内容
  END OF ty_err_info,
  ty_tab_err_info TYPE STANDARD TABLE OF ty_err_info.

*OLE使用相关参数定义
DATA:
  myexcel     TYPE ole2_object,
  mysheet     TYPE ole2_object,
  mysheetname TYPE ole2_object,
  mycell      TYPE ole2_object,
  myworkbook  TYPE ole2_object,
  myrange     TYPE ole2_object.

DATA:
  gt_err_info TYPE ty_tab_err_info,
  gs_result   TYPE ty_result.

**********************************************************************
*   选择屏幕定义
**********************************************************************
*定义按钮
SELECTION-SCREEN FUNCTION KEY 1.
*文件路径
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE gv_text1.
  PARAMETERS:
    p_file TYPE rlgrap-filename MEMORY ID file.
SELECTION-SCREEN END OF BLOCK b1.
*创建对象
SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE gv_text2.
  PARAMETERS:
    p_table TYPE button RADIOBUTTON GROUP g1 DEFAULT 'X' USER-COMMAND ta,
    p_struc TYPE button RADIOBUTTON GROUP g1,
    p_dtel  TYPE button RADIOBUTTON GROUP g1,
    p_doma  TYPE button RADIOBUTTON GROUP g1.
SELECTION-SCREEN END OF BLOCK b2.
*包&请求
SELECTION-SCREEN BEGIN OF BLOCK b3 WITH FRAME TITLE gv_text3.
  PARAMETERS:
    p_devcl  TYPE devclass  MATCHCODE OBJECT devclass,
    p_transp TYPE tr_trkorr MATCHCODE OBJECT seef_mig_trkorr.

SELECTION-SCREEN END OF BLOCK b3.
*必输项
SELECTION-SCREEN BEGIN OF BLOCK b4 WITH FRAME TITLE gv_text4.
  PARAMETERS:
    p_tabnam TYPE tabname16 MODIF ID tab,
    p_tabtxt TYPE ddtext    MODIF ID tab.
  PARAMETERS:
    p_strnam TYPE tabname16 MODIF ID str,
    p_strtxt TYPE ddtext    MODIF ID str.

SELECTION-SCREEN END OF BLOCK b4.
*附加选项
SELECTION-SCREEN BEGIN OF BLOCK b5 WITH FRAME TITLE gv_text5.
  PARAMETERS:
    p_tabart TYPE tabart    MODIF ID tab,
    p_tabkat TYPE tabkat    MODIF ID tab,
    p_comcl  TYPE contflag  MODIF ID tab,
    p_maint  TYPE maintflag MODIF ID tab AS CHECKBOX.

SELECTION-SCREEN END OF BLOCK b5.
*检查规则
SELECTION-SCREEN BEGIN OF BLOCK b6 WITH FRAME TITLE gv_text6.
  PARAMETERS:
    p_prefix TYPE char10,
    p_check  TYPE boolean AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b6.

**********************************************************************
*   初始化事件
**********************************************************************
INITIALIZATION.
  PERFORM frm_init_screen_desc.

**********************************************************************
*   屏幕显示前事件
**********************************************************************
AT SELECTION-SCREEN OUTPUT.
* 动态更新选择画面
  PERFORM frm_update_screen.

**********************************************************************
*   选择屏幕事件
**********************************************************************
AT SELECTION-SCREEN.
* 选择屏幕事件
  PERFORM frm_on_screen.

**********************************************************************
*   F4搜索帮助
**********************************************************************
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  PERFORM frm_path_f4.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_tabart.
  PERFORM frm_tabart_f4.

**********************************************************************
*   选择事件开始
**********************************************************************
START-OF-SELECTION.
* 上传EXCEL并处理数据
  PERFORM frm_upload_and_process.

**********************************************************************
*   选择事件结束
**********************************************************************
END-OF-SELECTION.
* 执行结果显示
  PERFORM frm_log_display.
*&---------------------------------------------------------------------*
*& Form FRM_INIT_SCREEN_DESC
*&---------------------------------------------------------------------*
*& 初始化屏幕描述
*&---------------------------------------------------------------------*
FORM frm_init_screen_desc .
  DATA:
    ls_functxt     TYPE smp_dyntxt.

  ls_functxt-icon_id   = icon_export.
  ls_functxt-quickinfo = '下载上传模板'.
  ls_functxt-icon_text = '下载上传模板'.
  sscrfields-functxt_01 = ls_functxt.

  gv_text1 = '文件路径'.
  gv_text2 = '创建对象'.
  gv_text3 = '包与请求'.
  gv_text4 = '必输项'.
  gv_text5 = '附加选项'.
  gv_text6 = '检查规则'.

  p_tabart = 'APPL0'.
  p_tabkat = '0'.
  p_comcl  = 'A'.

  PERFORM frm_change_scr_desc USING 'P_FILE'    '文件路径'.
  PERFORM frm_change_scr_desc USING 'P_TABLE'   '数据库表'.
  PERFORM frm_change_scr_desc USING 'P_STRUC'   '结构'.
  PERFORM frm_change_scr_desc USING 'P_DTEL'    '数据元素'.
  PERFORM frm_change_scr_desc USING 'P_DOMA'    '域'.

  PERFORM frm_change_scr_desc USING 'P_DEVCL'   '包'.
  PERFORM frm_change_scr_desc USING 'P_TRANSP'  '请求号'.

  PERFORM frm_change_scr_desc USING 'P_TABNAM'  '表名'.
  PERFORM frm_change_scr_desc USING 'P_TABTXT'  '表格描述'.
  PERFORM frm_change_scr_desc USING 'P_STRNAM'  '结构名'.
  PERFORM frm_change_scr_desc USING 'P_STRTXT'  '结构描述'.

  PERFORM frm_change_scr_desc USING 'P_TABART'  '数据类'.
  PERFORM frm_change_scr_desc USING 'P_TABKAT'  '大小范畴'.
  PERFORM frm_change_scr_desc USING 'P_COMCL'   '提交类'.
  PERFORM frm_change_scr_desc USING 'P_MAINT'   '是否允许维护'.

  PERFORM frm_change_scr_desc USING 'P_PREFIX' '命名前缀'.
  PERFORM frm_change_scr_desc USING 'P_CHECK'  '是否检查'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_CHANGE_SCR_DESC
*&---------------------------------------------------------------------*
*& 更改选择屏幕字段描述
*&---------------------------------------------------------------------*
*&      --> UV_FILED  字段名
*&      --> UV_DESC   字段描述
*&---------------------------------------------------------------------*
FORM frm_change_scr_desc  USING    VALUE(uv_filed)
                                   VALUE(uv_desc).
  DATA(lv_fname) = |%_{ uv_filed }_%_APP_%-TEXT|.
  ASSIGN (lv_fname) TO FIELD-SYMBOL(<fs_desc>).
  IF <fs_desc> IS ASSIGNED.
    <fs_desc> = uv_desc.
  ENDIF.
  UNASSIGN <fs_desc>.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_UPDATE_SCREEN
*&---------------------------------------------------------------------*
*& 动态更新选择画面
*&---------------------------------------------------------------------*
FORM frm_update_screen .
  LOOP AT SCREEN.
*   动态隐藏字段
    CASE abap_on.
*     表
      WHEN p_table.
        IF screen-group1 = 'STR'.
          screen-active = 0.
        ENDIF.
        p_prefix = gc_prefix_table.
*     结构
      WHEN p_struc.
        IF screen-group1 = 'TAB'.
          screen-active = 0.
        ENDIF.
        p_prefix = gc_prefix_struc.
*     数据元素
      WHEN p_dtel.
        IF screen-group1 IS NOT INITIAL.
          screen-active = 0.
        ENDIF.
        p_prefix = gc_prefix_dtel.
*     域
      WHEN p_doma.
        IF screen-group1 IS NOT INITIAL.
          screen-active = 0.
        ENDIF.
        p_prefix = gc_prefix_doma.
      WHEN OTHERS.
    ENDCASE.

*   必输字段设置
    IF screen-name = 'P_FILE'   OR                "文件路径
       screen-name = 'P_TABNAM' OR                "表名
       screen-name = 'P_TABTXT' OR                "表格描述
       screen-name = 'P_STRNAM' OR                "结构名
       screen-name = 'P_STRTXT' OR                "结构描述
       screen-name = 'P_DEVCL'.                   "包

      screen-required = 2.
    ENDIF.

*   禁止输入
    IF screen-name = 'P_PREFIX'.                  "命名前缀
      screen-input = 0.
    ENDIF.

    MODIFY SCREEN.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_path_f4
*&---------------------------------------------------------------------*
*& 文件路径选择
*&---------------------------------------------------------------------*
FORM frm_path_f4 .
  CALL FUNCTION 'F4_FILENAME'
    IMPORTING
      file_name = p_file.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_tabart_f4
*&---------------------------------------------------------------------*
*& 数据类搜索帮助
*&---------------------------------------------------------------------*
FORM frm_tabart_f4 .
* 数据类获取
  SELECT a~tabart,
         b~darttext
    INTO TABLE @DATA(lt_tabart)
    FROM ddart AS a
   INNER JOIN dartt AS b
      ON a~tabart = b~tabart
     AND b~ddlangu = @sy-langu
   WHERE a~ddclass IN ('STD','USR').

  SORT lt_tabart BY tabart ASCENDING.

* 搜索帮助结果显示
  CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      retfield        = 'TABART'
      dynpprog        = sy-repid
      dynpnr          = sy-dynnr
      dynprofield     = 'P_TABART'
      value_org       = 'S'
    TABLES
      value_tab       = lt_tabart
    EXCEPTIONS
      parameter_error = 1
      no_values_found = 2
      OTHERS          = 3.

  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_download_temp
*&---------------------------------------------------------------------*
*& 下载上传模板
*&---------------------------------------------------------------------*
FORM frm_download_temp .
  DATA:
    lv_path     TYPE string.

* 获取模板保存路径
  PERFORM frm_get_savepath CHANGING lv_path.

* 使用ole创建excel模板
  PERFORM frm_crt_excel USING lv_path.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_savepath
*&---------------------------------------------------------------------*
*& 获取保存路径
*&---------------------------------------------------------------------*
*&      <-- cv_path
*&---------------------------------------------------------------------*
FORM frm_get_savepath  CHANGING cv_path TYPE string.
* 获取保存路径
  CALL METHOD cl_gui_frontend_services=>directory_browse
    CHANGING
      selected_folder      = cv_path
    EXCEPTIONS
      cntl_error           = 1
      error_no_gui         = 2
      not_supported_by_gui = 3
      OTHERS               = 4.

  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.

* 路径为空则退出
  IF cv_path IS INITIAL.
*   已取消下载!
    MESSAGE '已取消下载!' TYPE 'S'.
    LEAVE LIST-PROCESSING.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_crt_excel
*&---------------------------------------------------------------------*
*& 使用ole创建excel模板
*&---------------------------------------------------------------------*
*&      --> LV_PATH
*&---------------------------------------------------------------------*
FORM frm_crt_excel  USING  uv_path TYPE string.
  DATA:
    lt_value TYPE STANDARD TABLE OF char2000,
    ls_value LIKE LINE OF lt_value.

  uv_path = |{ uv_path }\\SE11批量创建模板.xlsx|.

* 创建excel对象
  CREATE OBJECT myexcel 'excel.application'.

* 设置后台执行  0后台 1前台
  SET PROPERTY OF myexcel 'visible' = 0.

* 创建工作簿对象
  CALL METHOD OF myexcel 'Workbooks' = myworkbook.

* 添加空白工作簿
  CALL METHOD OF myworkbook 'Add'.

**********************************************************************
* 创建Table Sheet
  CALL METHOD OF myexcel 'Worksheets' = mysheet
    EXPORTING #1 = 1.

* 激活当前Sheet
  CALL METHOD OF mysheet 'Activate'.

* 重命名Sheet页
  SET PROPERTY OF mysheet 'Name' = 'Table'.

* 内容填充
  PERFORM frm_crt_value USING '字段名'         CHANGING ls_value.
  PERFORM frm_crt_value USING '主键'           CHANGING ls_value.
  PERFORM frm_crt_value USING '数据元素'       CHANGING ls_value.
  PERFORM frm_crt_value USING '数据类型'       CHANGING ls_value.
  PERFORM frm_crt_value USING '长度'           CHANGING ls_value.
  PERFORM frm_crt_value USING '小数位'         CHANGING ls_value.
  PERFORM frm_crt_value USING '简短描述'       CHANGING ls_value.
  PERFORM frm_crt_value USING '参照表'         CHANGING ls_value.
  PERFORM frm_crt_value USING '参照字段'       CHANGING ls_value.
  PERFORM frm_crt_value USING '检查表'         CHANGING ls_value.
  PERFORM frm_crt_value USING '检查字段'       CHANGING ls_value.
  APPEND ls_value TO lt_value.

* 单元格填充
  PERFORM frm_fill_cell USING 1 1 lt_value.

  CLEAR:
    ls_value,
    lt_value.
**********************************************************************
* 创建Structure Sheet
  CALL METHOD OF myexcel 'Worksheets' = mysheet
    EXPORTING #1 = 2.

* 激活当前Sheet
  CALL METHOD OF mysheet 'Activate'.

* 重命名Sheet页
  SET PROPERTY OF mysheet 'Name' = 'Structure'.

* 内容填充
  PERFORM frm_crt_value USING '字段名'   CHANGING ls_value.
  PERFORM frm_crt_value USING '数据元素' CHANGING ls_value.
  PERFORM frm_crt_value USING '数据类型' CHANGING ls_value.
  PERFORM frm_crt_value USING '长度'     CHANGING ls_value.
  PERFORM frm_crt_value USING '小数位'   CHANGING ls_value.
  PERFORM frm_crt_value USING '简短描述' CHANGING ls_value.
  PERFORM frm_crt_value USING '参照表'   CHANGING ls_value.
  PERFORM frm_crt_value USING '参照字段' CHANGING ls_value.

  APPEND ls_value TO lt_value.

* 单元格填充
  PERFORM frm_fill_cell USING 1 1 lt_value.

  CLEAR:
    ls_value,
    lt_value.
**********************************************************************
* 创建DataElements Sheet
  CALL METHOD OF myexcel 'Worksheets' = mysheet
    EXPORTING #1 = 3.

* 激活当前Sheet
  CALL METHOD OF mysheet 'Activate'.

* 重命名Sheet页
  SET PROPERTY OF mysheet 'Name' = 'DataElements'.

* 内容填充
  PERFORM frm_crt_value USING '数据元素' CHANGING ls_value.
  PERFORM frm_crt_value USING '描述'     CHANGING ls_value.
  PERFORM frm_crt_value USING '域'       CHANGING ls_value.
  PERFORM frm_crt_value USING '数据类型' CHANGING ls_value.
  PERFORM frm_crt_value USING '长度'     CHANGING ls_value.
  PERFORM frm_crt_value USING '小数位'   CHANGING ls_value.
  PERFORM frm_crt_value USING '短描述'   CHANGING ls_value.
  PERFORM frm_crt_value USING '中描述'   CHANGING ls_value.
  PERFORM frm_crt_value USING '长描述'   CHANGING ls_value.
  PERFORM frm_crt_value USING '标题'     CHANGING ls_value.

  APPEND ls_value TO lt_value.

* 单元格填充
  PERFORM frm_fill_cell USING 1 1 lt_value.

  CLEAR:
    ls_value,
    lt_value.
**********************************************************************
* 创建Domain Sheet
  CALL METHOD OF myexcel 'Worksheets' = mysheet
    EXPORTING #1 = 4.

* 激活当前Sheet
  CALL METHOD OF mysheet 'Activate'.

* 重命名Sheet页
  SET PROPERTY OF mysheet 'Name' = 'Domain'.

* 内容填充
  PERFORM frm_crt_value USING '域'         CHANGING ls_value.
  PERFORM frm_crt_value USING '描述'       CHANGING ls_value.
  PERFORM frm_crt_value USING '数据类型'   CHANGING ls_value.
  PERFORM frm_crt_value USING '长度'       CHANGING ls_value.
  PERFORM frm_crt_value USING '小数位'     CHANGING ls_value.
  PERFORM frm_crt_value USING '符号'       CHANGING ls_value.
  PERFORM frm_crt_value USING '区分大小写' CHANGING ls_value.
  PERFORM frm_crt_value USING '转换例程'   CHANGING ls_value.
  PERFORM frm_crt_value USING '固定值'     CHANGING ls_value.
  PERFORM frm_crt_value USING '固定值描述' CHANGING ls_value.

  APPEND ls_value TO lt_value.

* 单元格填充
  PERFORM frm_fill_cell USING 1 1 lt_value.

  CLEAR:
    ls_value,
    lt_value.
**********************************************************************
* 切换至Table Sheet
  CALL METHOD OF myexcel 'Worksheets' = mysheet
    EXPORTING #1 = 1.

* 激活当前Sheet
  CALL METHOD OF mysheet 'Activate'.

* 获取活动的工作簿
  GET PROPERTY OF myexcel 'ActiveWorkbook' = myworkbook.

* 另存为
  CALL METHOD OF myworkbook 'SaveAs'
    EXPORTING
      #1 = uv_path                                "保存路径
      #2 = 51.                                    "XlFileFormat:默认为*.xls  51为*.xlsx

* 保存并关闭
  CALL METHOD OF myworkbook 'Close'
    EXPORTING
      #1 = 'YES'.

* 退出EXCEL
  CALL METHOD OF myexcel 'Quit'.

* 释放对象
  FREE OBJECT:
    mycell,
    mysheet,
    myworkbook,
    myexcel.

  MESSAGE |下载成功:{ uv_path }| TYPE 'S'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_FILL_CELL
*&---------------------------------------------------------------------*
*& 内容填充
*&---------------------------------------------------------------------*
*&      --> UC_ROW
*&      --> UV_COL
*&      --> UT_VALUE
*&---------------------------------------------------------------------*
FORM frm_fill_cell  USING    VALUE(uc_row)
                             VALUE(uv_col)
                             VALUE(ut_value).
  DATA lv_rc TYPE i.

* 将内容复制进粘贴板
  CALL METHOD cl_gui_frontend_services=>clipboard_export
    IMPORTING
      data                 = ut_value
    CHANGING
      rc                   = lv_rc
    EXCEPTIONS
      cntl_error           = 1
      error_no_gui         = 2
      not_supported_by_gui = 3
      OTHERS               = 4.

* 选中单元格
  CALL METHOD OF mysheet 'Cells' = mycell
    EXPORTING
      #1 = uc_row
      #2 = uv_col.

* 内容粘贴
  CALL METHOD OF mycell 'PasteSpecial'.

  CALL METHOD OF mysheet 'Cells' = mycell
    EXPORTING
      #1 = 2
      #2 = 1.

* 激活当前Sheet
  CALL METHOD OF mycell 'Activate'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_crt_value
*&---------------------------------------------------------------------*
*& 内容拼接
*&---------------------------------------------------------------------*
*&      --> UV_FIELD
*&      <-- CS_VALUE
*&---------------------------------------------------------------------*
FORM frm_crt_value  USING    VALUE(uv_field)
                    CHANGING cs_value TYPE char2000.
* TAB键分隔拼接
  cs_value = cs_value && uv_field && cl_abap_char_utilities=>horizontal_tab.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_CONDITION_CHECK
*&---------------------------------------------------------------------*
*& 选择屏幕输入检查
*&---------------------------------------------------------------------*
FORM frm_condition_check .
* 文件路径检查
  IF p_file IS INITIAL.
*   上传文件路径必填
    PERFORM frm_required_err USING 'P_FILE'.
  ENDIF.

* 包与请求检查
  IF p_devcl IS INITIAL.
*   包名必填
    PERFORM frm_required_err USING 'P_DEVCL'.
  ELSE.
*   非本地对象时,必须指定请求号
    IF p_devcl <> '$TMP' AND p_transp IS INITIAL.
*     请求号必填
      PERFORM frm_required_err USING 'P_TRANSP'.
    ENDIF.
  ENDIF.

* 必输字段检查
  CASE abap_on.
*   创建表格时
    WHEN p_table.
      IF p_tabnam IS INITIAL.
        PERFORM frm_required_err USING 'P_TABNAM'.
      ENDIF.

      IF p_tabtxt IS INITIAL.
        PERFORM frm_required_err USING 'P_TABTXT'.
      ENDIF.
*   创建结构时
    WHEN p_struc.
      IF p_strnam IS INITIAL.
        PERFORM frm_required_err USING 'P_STRNAM'.
      ENDIF.

      IF p_strtxt IS INITIAL.
        PERFORM frm_required_err USING 'P_STRTXT'.
      ENDIF.
    WHEN OTHERS.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_upload_and_process
*&---------------------------------------------------------------------*
*& 上传EXCEL并处理数据
*&---------------------------------------------------------------------*
FORM frm_upload_and_process .
  DATA :
    lv_filename      TYPE string,
    lt_records       TYPE solix_tab,
    lv_headerxstring TYPE xstring,
    lv_filelength    TYPE i.

  DATA:
    lo_excel_ref TYPE REF TO cl_fdt_xl_spreadsheet.

  FIELD-SYMBOLS:
    <fs_t_table> TYPE STANDARD TABLE,
    <fs_t_struc> TYPE STANDARD TABLE,
    <fs_t_dtel>  TYPE STANDARD TABLE,
    <fs_t_doma>  TYPE STANDARD TABLE.

  lv_filename = p_file.

* 二进制上传文件内容
  CALL FUNCTION 'GUI_UPLOAD'
    EXPORTING
      filename                = lv_filename
      filetype                = 'BIN'
    IMPORTING
      filelength              = lv_filelength
      header                  = lv_headerxstring
    TABLES
      data_tab                = lt_records
    EXCEPTIONS
      file_open_error         = 1
      file_read_error         = 2
      no_batch                = 3
      gui_refuse_filetransfer = 4
      invalid_type            = 5
      no_authority            = 6
      unknown_error           = 7
      bad_data_format         = 8
      header_not_allowed      = 9
      separator_not_allowed   = 10
      header_too_long         = 11
      unknown_dp_error        = 12
      access_denied           = 13
      dp_out_of_memory        = 14
      disk_full               = 15
      dp_timeout              = 16
      OTHERS                  = 17.

  IF sy-subrc IS NOT INITIAL.
    MESSAGE '请关闭Excel文件后再次尝试!' TYPE 'S' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.

* 二进制转换为XString
  CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
    EXPORTING
      input_length = lv_filelength
    IMPORTING
      buffer       = lv_headerxstring
    TABLES
      binary_tab   = lt_records
    EXCEPTIONS
      failed       = 1
      OTHERS       = 2.

  IF sy-subrc IS NOT INITIAL.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
       WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

**********************************************************************
*   补充说明:
*   类 CL_FDT_XL_SPREADSHEET 是专门为BRFplus工作台中的决策表而设计,官
*   方不建议在其他场景使用,该类仅算作一种变通的处理方式用于处理多页签
*   EXCEL,详细说明可以查看note:2468709/3242515。
*
*   本程序为了方便上传时根据选择界面动态读取对应页签数据,所以采用此方
*   法,减少用户上传前需要先将页签切换正确的操作,只需将所有需要创建的
*   对象正确维护进EXCEL中即可。
**********************************************************************

  TRY .
*     操作多tab页对象创建
      lo_excel_ref = NEW cl_fdt_xl_spreadsheet( document_name = lv_filename
                                                xdocument     = lv_headerxstring ) .
    CATCH cx_fdt_excel_core.
  ENDTRY .

  IF lo_excel_ref IS BOUND.
*   获取页签列表
    lo_excel_ref->if_fdt_doc_spreadsheet~get_worksheet_names(
      IMPORTING
        worksheet_names = DATA(lt_worksheets) ).

    IF NOT lt_worksheets IS INITIAL.
      CASE abap_on.
*       获取Table页签数据
        WHEN p_table.
          READ TABLE lt_worksheets INTO DATA(lv_woksheetname) INDEX 1.
          DATA(lo_data_ref) = lo_excel_ref->if_fdt_doc_spreadsheet~get_itab_from_worksheet( lv_woksheetname ).
          ASSIGN lo_data_ref->* TO <fs_t_table>.

*         创建表格
          PERFORM frm_create_table USING <fs_t_table>.
*       获取Structure页签数据
        WHEN p_struc.
          READ TABLE lt_worksheets INTO lv_woksheetname INDEX 2.
          lo_data_ref = lo_excel_ref->if_fdt_doc_spreadsheet~get_itab_from_worksheet( lv_woksheetname ).
          ASSIGN lo_data_ref->* TO <fs_t_struc>.

*         创建结构
          PERFORM frm_create_struc USING <fs_t_struc>.
*       获取DataElements页签数据
        WHEN p_dtel.
          READ TABLE lt_worksheets INTO lv_woksheetname INDEX 3.
          lo_data_ref = lo_excel_ref->if_fdt_doc_spreadsheet~get_itab_from_worksheet( lv_woksheetname ).
          ASSIGN lo_data_ref->* TO <fs_t_dtel>.

*         创建数据元素
          PERFORM frm_create_dtel USING <fs_t_dtel>.
*       获取Domain页签数据
        WHEN p_doma.
          READ TABLE lt_worksheets INTO lv_woksheetname INDEX 4.
          lo_data_ref = lo_excel_ref->if_fdt_doc_spreadsheet~get_itab_from_worksheet( lv_woksheetname ).
          ASSIGN lo_data_ref->* TO <fs_t_doma>.

*         创建域
          PERFORM frm_create_doma USING <fs_t_doma>.
        WHEN OTHERS.
      ENDCASE.
    ENDIF.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_LOG_DISPLAY
*&---------------------------------------------------------------------*
*& 执行结果显示
*&---------------------------------------------------------------------*
FORM frm_log_display .
  FORMAT COLOR = 3.
  WRITE:'执行结果:' INTENSIFIED OFF.
  FORMAT COLOR = 0.
  NEW-LINE.
  DO 132 TIMES.
    WRITE:'=' NO-GAP.
  ENDDO.
  NEW-LINE.
  WRITE:
    AT 1(14)   '对象类型',
    AT 15(30)  '对象名称',
    AT 46(4)   '结果',
    AT 51(10)  '总条目数',
    AT 62(10)  '成功条目数',
    AT 73(10)  '失败条目数'.
  NEW-LINE.
  DO 132 TIMES.
    WRITE:'=' NO-GAP.
  ENDDO.
  NEW-LINE.
  WRITE:
    AT 1(14)   gs_result-objtype,
    AT 15(30)  gs_result-objname,
    AT 46(4)   gs_result-result    AS ICON,
    AT 51(10)  gs_result-objnumber NO-ZERO NO-GAP LEFT-JUSTIFIED,
    AT 62(10)  gs_result-objnum_s  NO-ZERO NO-GAP LEFT-JUSTIFIED,
    AT 73(10)  gs_result-objnum_e  NO-ZERO NO-GAP LEFT-JUSTIFIED.

  IF gt_err_info IS NOT INITIAL.
    SORT gt_err_info BY objtype ASCENDING
                        objname ASCENDING
                        msgid   ASCENDING
                        msgno   ASCENDING
                        msgty   ASCENDING.
    DELETE ADJACENT DUPLICATES FROM gt_err_info
      COMPARING objtype objname msgid msgno msgty.

    NEW-LINE.
    FORMAT COLOR = 6.
    WRITE:/,/,'错误信息:' INTENSIFIED OFF.
    FORMAT COLOR = 0.
    NEW-LINE.
    DO 132 TIMES.
      WRITE:'=' NO-GAP.
    ENDDO.
    NEW-LINE.
    WRITE:
      AT 1(14)   '对象类型',
      AT 15(30)  '对象名称',
      AT 46(20)  '消息类',
      AT 67(6)   '消息号',
      AT 73(8)   '消息类型',
      AT 82(150) '消息内容'.
    NEW-LINE.
    DO 132 TIMES.
      WRITE:'=' NO-GAP.
    ENDDO.
    NEW-LINE.

    LOOP AT gt_err_info INTO DATA(ls_err_info).
      NEW-LINE.
      WRITE:
        AT 1(14)   ls_err_info-objtype,
        AT 15(30)  ls_err_info-objname,
        AT 46(20)  ls_err_info-msgid,
        AT 67(6)   ls_err_info-msgno,
        AT 73(8)   ls_err_info-msgty,
        AT 82(150) ls_err_info-message.
    ENDLOOP.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_required_err
*&---------------------------------------------------------------------*
*& 必输校验未通过
*&---------------------------------------------------------------------*
*&      --> UV_SCREEN_FIELD
*&---------------------------------------------------------------------*
FORM frm_required_err  USING    VALUE(uv_screen_field).
  SET CURSOR FIELD uv_screen_field.
  MESSAGE '请输入必输字段!' TYPE 'E'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_ON_SCREEN
*&---------------------------------------------------------------------*
*& 选择屏幕事件
*&---------------------------------------------------------------------*
FORM frm_on_screen .
  CASE sscrfields-ucomm.
*   下载按钮
    WHEN 'FC01'.
*     下载上传模板
      PERFORM frm_download_temp.
*   执行按钮
    WHEN 'ONLI'.
*     选择屏幕输入检查
      PERFORM frm_condition_check.
    WHEN OTHERS.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_table
*&---------------------------------------------------------------------*
*& 创建自建表
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&---------------------------------------------------------------------*
FORM frm_create_table  USING ut_table TYPE STANDARD TABLE.
  DATA:
    lt_table TYPE ty_tab_table.

* 内表转换
  PERFORM frm_data_conv USING ut_table
                     CHANGING lt_table.
* 检查前缀
  PERFORM frm_check_prefix USING lt_table.

* 检查对象是否存在
  PERFORM frm_check_exist USING lt_table.

* 执行创建
  PERFORM frm_create_table_begin USING lt_table.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_struc
*&---------------------------------------------------------------------*
*& 创建结构
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&---------------------------------------------------------------------*
FORM frm_create_struc  USING ut_table TYPE STANDARD TABLE.
  DATA:
    lt_struc TYPE ty_tab_struc.

* 内表转换
  PERFORM frm_data_conv USING ut_table
                     CHANGING lt_struc.
* 检查前缀
  PERFORM frm_check_prefix USING lt_struc.

* 检查对象是否存在
  PERFORM frm_check_exist USING lt_struc.

* 执行创建
  PERFORM frm_create_struc_begin USING lt_struc.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_dtel
*&---------------------------------------------------------------------*
*& 创建数据元素
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&---------------------------------------------------------------------*
FORM frm_create_dtel  USING ut_table TYPE STANDARD TABLE.
  DATA:
    lt_dtel TYPE ty_tab_dtel.

* 内表转换
  PERFORM frm_data_conv USING ut_table
                     CHANGING lt_dtel.
* 检查前缀
  PERFORM frm_check_prefix USING lt_dtel.

* 检查对象是否存在
  PERFORM frm_check_exist USING lt_dtel.

* 执行创建
  PERFORM frm_create_dtel_begin USING lt_dtel.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_doma
*&---------------------------------------------------------------------*
*& 创建域
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&---------------------------------------------------------------------*
FORM frm_create_doma  USING ut_table TYPE STANDARD TABLE.
  DATA:
    lt_doma TYPE ty_tab_doma.

* 内表转换
  PERFORM frm_data_conv USING ut_table
                     CHANGING lt_doma.
* 检查前缀
  PERFORM frm_check_prefix USING lt_doma.

* 检查对象是否存在
  PERFORM frm_check_exist USING lt_doma.

* 执行创建
  PERFORM frm_create_doma_begin USING lt_doma.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_data_conv
*&---------------------------------------------------------------------*
*& 内表转换
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&      <-- CT_TABLE
*&---------------------------------------------------------------------*
FORM frm_data_conv  USING    ut_table TYPE STANDARD TABLE
                    CHANGING ct_table TYPE STANDARD TABLE.
  DATA:
    lo_line  TYPE REF TO data,
    lv_index TYPE i.

* 动态获取目标结构类型
  DATA(lo_line_type) = CAST cl_abap_tabledescr(
                         cl_abap_tabledescr=>describe_by_data( ct_table )
                       )->get_table_line_type( ).
* 创建结构引用
  CREATE DATA lo_line TYPE HANDLE lo_line_type.

* 分配指针
  ASSIGN lo_line->* TO FIELD-SYMBOL(<fs_line>).

* 字段映射转换
  LOOP AT ut_table ASSIGNING FIELD-SYMBOL(<fs_table>) FROM 2.
    DO.
      ADD 1 TO lv_index.
      ASSIGN COMPONENT lv_index OF STRUCTURE <fs_table> TO FIELD-SYMBOL(<fs_data>).
      ASSIGN COMPONENT lv_index OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_cs_table>).
      IF <fs_data> IS ASSIGNED.
        IF <fs_data> IS NOT INITIAL.
          <fs_cs_table> = <fs_data>.
        ENDIF.
      ELSE.
        EXIT.
      ENDIF.
      UNASSIGN:
        <fs_data>,
        <fs_cs_table>.
    ENDDO.
    APPEND <fs_line> TO ct_table.
    CLEAR:
      <fs_line>,
      lv_index.
  ENDLOOP.

  IF ct_table IS INITIAL.
    MESSAGE '无数据' TYPE 'S' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_check_prefix
*&---------------------------------------------------------------------*
*& 检查前缀
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&---------------------------------------------------------------------*
FORM frm_check_prefix  USING ut_table TYPE STANDARD TABLE.

* 检查是否启用前缀检查
  CHECK p_check = 'X'.

  DATA:
    lv_error_flag TYPE boolean.

  CASE abap_on.
    WHEN p_table.
      IF p_tabnam+0(2) <> p_prefix+0(2).
        lv_error_flag = 'X'.
      ENDIF.
    WHEN p_struc.
      IF p_strnam+0(2) <> p_prefix+0(2).
        lv_error_flag = 'X'.
      ENDIF.
    WHEN p_dtel OR p_doma.
      LOOP AT ut_table ASSIGNING FIELD-SYMBOL(<fs_table>).
        ASSIGN COMPONENT 1 OF STRUCTURE <fs_table> TO FIELD-SYMBOL(<fs_fname>).
        IF <fs_fname> IS ASSIGNED.
          IF <fs_fname>+0(2) <> p_prefix+0(2).
            lv_error_flag = 'X'.
            EXIT.
          ENDIF.
        ENDIF.
      ENDLOOP.
    WHEN OTHERS.
  ENDCASE.

  IF lv_error_flag = 'X'.
    MESSAGE '命名前缀不符合规范,请检查数据!' TYPE 'S' DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_check_exist
*&---------------------------------------------------------------------*
*& 检查对象是否存在
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&---------------------------------------------------------------------*
FORM frm_check_exist  USING ut_table TYPE STANDARD TABLE.
  DATA:
    lv_exist_flag TYPE boolean.

  DATA:
    lt_objname  TYPE ty_tab_objname,
    ls_objname  TYPE ty_objname,
    lv_question TYPE string,
    lv_answer   TYPE char1.

  CASE abap_on.
    WHEN p_table.
*     获取表信息
      SELECT SINGLE
             tabname,
             as4local
        INTO @DATA(ls_dd02l_t)
        FROM dd02l
       WHERE tabname = @p_tabnam
         AND tabclass = 'TRANSP'.

      IF ls_dd02l_t IS NOT INITIAL.
        lv_exist_flag = 'X'.
      ENDIF.
    WHEN p_struc.
*     获取结构信息
      SELECT SINGLE
             tabname,
             as4local
        INTO @DATA(ls_dd02l_s)
        FROM dd02l
       WHERE tabname = @p_strnam
         AND tabclass = 'INTTAB'.

      IF ls_dd02l_s IS NOT INITIAL.
        lv_exist_flag = 'X'.
      ENDIF.
    WHEN p_dtel.
      LOOP AT ut_table ASSIGNING FIELD-SYMBOL(<fs_table>).
        ASSIGN COMPONENT 1 OF STRUCTURE <fs_table> TO FIELD-SYMBOL(<fs_fname>).
        IF <fs_fname> IS ASSIGNED.
          ls_objname-objname = <fs_fname>.
          APPEND ls_objname TO lt_objname.
        ENDIF.
        UNASSIGN <fs_fname>.
      ENDLOOP.

      IF lt_objname IS NOT INITIAL.
*       获取数据元素信息
        SELECT rollname,
               as4local,
               as4vers
          INTO TABLE @DATA(lt_dd04l)
          FROM dd04l
           FOR ALL ENTRIES IN @lt_objname
         WHERE rollname = @lt_objname-objname.

        IF lt_dd04l IS NOT INITIAL.
          lv_exist_flag = 'X'.
        ENDIF.
      ENDIF.
    WHEN p_doma.
      LOOP AT ut_table ASSIGNING <fs_table>.
        ASSIGN COMPONENT 1 OF STRUCTURE <fs_table> TO <fs_fname>.
        IF <fs_fname> IS ASSIGNED.
          ls_objname-objname = <fs_fname>.
          APPEND ls_objname TO lt_objname.
        ENDIF.
        UNASSIGN <fs_fname>.
      ENDLOOP.

      IF lt_objname IS NOT INITIAL.
*       获取域信息
        SELECT domname,
               as4local,
               as4vers
          INTO TABLE @DATA(lt_dd01l)
          FROM dd01l
           FOR ALL ENTRIES IN @lt_objname
         WHERE domname = @lt_objname-objname.

        IF lt_dd01l IS NOT INITIAL.
          lv_exist_flag = 'X'.
        ENDIF.
      ENDIF.
    WHEN OTHERS.
  ENDCASE.

  IF lv_exist_flag = 'X'.
    lv_question = |包含已存在对象,继续执行将覆盖更新,是否继续?|.

*   弹窗确认
    CALL FUNCTION 'POPUP_TO_CONFIRM'
      EXPORTING
        titlebar              = '确认'
        text_question         = lv_question
        text_button_1         = '是'
        text_button_2         = '否'
        display_cancel_button = ''
      IMPORTING
        answer                = lv_answer
      EXCEPTIONS
        text_not_found        = 1
        OTHERS                = 2.

    IF sy-subrc <> 0.
*     Implement suitable error handling here
    ELSE.
      IF lv_answer <> '1'.
        MESSAGE '已取消创建!' TYPE 'S'.
        LEAVE LIST-PROCESSING.
      ENDIF.
    ENDIF.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_table_BEGIN
*&---------------------------------------------------------------------*
*& 执行创建
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&---------------------------------------------------------------------*
FORM frm_create_table_begin  USING ut_table TYPE ty_tab_table.
* BAPI变量
  DATA:
    lv_object_name            TYPE char32,
    lt_object_new             TYPE comt_gox_def_header,
    ls_object_new             TYPE coms_gox_def_header,
    ls_object_new_details     TYPE coms_gox_table_entry_fields,
    ls_object_foreign         TYPE coms_gox_def_header,
    ls_object_foreign_details TYPE coms_gox_table_entry_fields,
    ls_object_new_text        TYPE coms_gox_def_text,
    lt_object_old             TYPE comt_gox_def_header,
    ls_object_old             TYPE coms_gox_def_header,
    lv_devclass               TYPE devclass,
    lv_request_wb             TYPE trkorr,
    lt_bapireturn             TYPE bapirettab,
    lt_transport              TYPE comt_gox_trans_object,
    lv_ddobjname              TYPE ddobjname,
    ls_dd02v                  TYPE dd02v.

* 其他变量
  DATA:
    lv_uuid        TYPE sysuuid-c,
    lv_parent_uuid TYPE sysuuid-c,
    lv_position    TYPE i,
    ls_err_info    TYPE ty_err_info,
    lt_sug_foreign TYPE ty_tab_sug_foreign.

* 进度条显示
  PERFORM frm_progress_show USING 'Table'.

* 获取建议外键字段列表
  PERFORM frm_get_sug_foreign USING ut_table
                           CHANGING lt_sug_foreign.

**********************************************************************
* 表格信息
**********************************************************************

* 获取UUID
  PERFORM frm_get_uuid_32 CHANGING lv_uuid.

* 表名
  ls_object_new-object_name = p_tabnam.
  ls_object_new-key_guid = lv_uuid.

* 表格描述
  ls_object_new_text-language = sy-langu.
  ls_object_new_text-description = p_tabtxt.
  APPEND ls_object_new_text TO ls_object_new-object_text.

  lv_parent_uuid = ls_object_new-key_guid.

* 表类型-透明表格
  ls_object_new_details-fieldname = 'TABCLASS'.
  ls_object_new_details-fieldvalue = 'TRANSP'.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

* 大小范畴
  ls_object_new_details-fieldname = 'TABKAT'.
  ls_object_new_details-fieldvalue = p_tabkat.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

* 数据类
  ls_object_new_details-fieldname = 'TABART'.
  ls_object_new_details-fieldvalue = p_tabart.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

* 缓冲类型
  ls_object_new_details-fieldname = 'PUFFERUNG'.
  ls_object_new_details-fieldvalue = ''.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

* 提交类
  ls_object_new_details-fieldname = 'CONTFLAG'.
  ls_object_new_details-fieldvalue = p_comcl.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

* 是否允许缓冲
  ls_object_new_details-fieldname = 'BUFFALLOW'.
  ls_object_new_details-fieldvalue = 'N'.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

* 普通缓冲区的关键区域号
  ls_object_new_details-fieldname = 'SCHFELDANZ'.
  ls_object_new_details-fieldvalue = '0'.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

  APPEND ls_object_new TO lt_object_new.
  CLEAR ls_object_new.

**********************************************************************
* 表格字段
**********************************************************************
  LOOP AT ut_table INTO DATA(ls_table).
    ADD 1 TO lv_position.

*   获取UUID
    PERFORM frm_get_uuid_32 CHANGING lv_uuid.

    ls_object_new-object_type = 'TABLE_FIELD'.
    ls_object_new-object_name = ls_table-fieldname.
    ls_object_new-key_guid    = lv_uuid.
    ls_object_new-parent_key  = lv_parent_uuid.

*   位置
    ls_object_new_details-fieldname = 'POSITION'.
    ls_object_new_details-fieldvalue = lv_position.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   是否为主键
    ls_object_new_details-fieldname = 'KEYFLAG'.
    ls_object_new_details-fieldvalue = ls_table-keyflag.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

    IF ls_table-keyflag = 'X'.
*     是否具有初始值
      ls_object_new_details-fieldname = 'NOTNULL'.
      ls_object_new_details-fieldvalue = 'X'.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ENDIF.

    IF ls_table-rollname IS NOT INITIAL.
*     数据元素
      ls_object_new_details-fieldname = 'ROLLNAME'.
      ls_object_new_details-fieldvalue = ls_table-rollname.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ELSE.
*     内置类型
      ls_object_new_details-fieldname = 'DATATYPE'.
      ls_object_new_details-fieldvalue = ls_table-datatype.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     长度
      ls_object_new_details-fieldname = 'LENG'.
      ls_object_new_details-fieldvalue = ls_table-leng.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     小数位
      ls_object_new_details-fieldname = 'DECIMALS'.
      ls_object_new_details-fieldvalue = ls_table-decimals.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     简短描述
      ls_object_new_details-fieldname = 'DDTEXT'.
      ls_object_new_details-fieldvalue = ls_table-ddtext.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     *语言 【对于内置类型,必须传值,否则无法更新描述】
      ls_object_new_details-fieldname = 'LANGUAGE'.
      ls_object_new_details-fieldvalue = sy-langu.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ENDIF.

    IF ls_table-reftable IS NOT INITIAL AND
       ls_table-reffield IS NOT INITIAL.

*     参考表
      ls_object_new_details-fieldname = 'REFTABLE'.
      ls_object_new_details-fieldvalue = ls_table-reftable.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     参考字段
      ls_object_new_details-fieldname = 'REFFIELD'.
      ls_object_new_details-fieldvalue = ls_table-reffield.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ENDIF.

    IF ls_table-checktable IS NOT INITIAL AND
       ls_table-checkfield IS NOT INITIAL.

*     检查表
      ls_object_new_details-fieldname = 'CHECKTABLE'.
      ls_object_new_details-fieldvalue = ls_table-checktable.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     要求屏幕检查
      ls_object_new_details-fieldname = 'CHECKFLAG'.
      ls_object_new_details-fieldvalue = ''.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     构建建议的外键信息
      PERFORM frm_make_foreign USING ut_table
                                     ls_table
                                     lt_sug_foreign
                                     ls_object_new-key_guid
                            CHANGING lt_object_new
                                     lt_object_old.
    ENDIF.

    APPEND ls_object_new TO lt_object_new.
    CLEAR ls_object_new.
  ENDLOOP.

  lv_devclass    = p_devcl.                       "包
  lv_request_wb  = p_transp.                      "请求
  lv_object_name = p_tabnam.                      "表格名称

* 创建/更新 Tabel
  CALL FUNCTION 'GOX_GEN_TABLE_STD'
    EXPORTING
      iv_object_name = lv_object_name
      it_object_new  = lt_object_new
      it_object_old  = lt_object_old
      iv_devclass    = lv_devclass
      iv_request_wb  = lv_request_wb
    IMPORTING
      et_bapireturn  = lt_bapireturn
      et_transport   = lt_transport.

  LOOP AT lt_bapireturn INTO DATA(ls_bapireturn) WHERE type CA 'EAX'.
    ls_err_info-objtype = 'Table'.
    ls_err_info-objname = p_tabnam.
    ls_err_info-msgid   = ls_bapireturn-id.
    ls_err_info-msgno   = ls_bapireturn-number.
    ls_err_info-msgty   = ls_bapireturn-type.

*   生成消息内容
    PERFORM frm_rebuild_msg USING ls_bapireturn
                         CHANGING ls_err_info-message.
    APPEND ls_err_info TO gt_err_info.
    CLEAR ls_err_info.
  ENDLOOP.

  IF p_maint = 'X'.
    lv_ddobjname = p_tabnam.

*   获取表格信息
    CALL FUNCTION 'DDIF_TABL_GET'
      EXPORTING
        name          = lv_ddobjname
        state         = 'A'
        langu         = sy-langu
      IMPORTING
        dd02v_wa      = ls_dd02v
      EXCEPTIONS
        illegal_input = 1
        OTHERS        = 2.

*   允许维护
    ls_dd02v-mainflag = 'X'.

*   更新表格
    CALL FUNCTION 'DDIF_TABL_PUT'
      EXPORTING
        name              = lv_ddobjname
        dd02v_wa          = ls_dd02v
      EXCEPTIONS
        tabl_not_found    = 1
        name_inconsistent = 2
        tabl_inconsistent = 3
        put_failure       = 4
        put_refused       = 5
        OTHERS            = 6.

*   激活表格
    CALL FUNCTION 'DDIF_TABL_ACTIVATE'
      EXPORTING
        name        = lv_ddobjname
        auth_chk    = ''
      EXCEPTIONS
        not_found   = 1
        put_failure = 2
        OTHERS      = 3.
  ENDIF.

  gs_result-objtype   = 'Table'.
  gs_result-objname   = p_tabnam.
  gs_result-objnumber = '1'.

  IF gt_err_info IS NOT INITIAL.
    gs_result-objnum_e = '1'.
    gs_result-result   = icon_led_red.
  ELSE.
    gs_result-objnum_s = '1'.
    gs_result-result   = icon_led_green.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_struc_begin
*&---------------------------------------------------------------------*
*& 执行创建
*&---------------------------------------------------------------------*
*&      --> UT_STRUC
*&---------------------------------------------------------------------*
FORM frm_create_struc_begin  USING ut_struc TYPE ty_tab_struc.
* BAPI变量
  DATA:
    lv_object_name        TYPE char32,
    lt_object_new         TYPE comt_gox_def_header,
    ls_object_new         TYPE coms_gox_def_header,
    ls_object_new_details TYPE coms_gox_table_entry_fields,
    ls_object_new_text    TYPE coms_gox_def_text,
    lt_object_old         TYPE comt_gox_def_header,
    ls_object_old         TYPE coms_gox_def_header,
    lv_devclass           TYPE devclass,
    lv_request_wb         TYPE trkorr,
    lt_bapireturn         TYPE bapirettab,
    lt_transport          TYPE comt_gox_trans_object,
    lv_ddobjname          TYPE ddobjname,
    ls_dd02v              TYPE dd02v.

* 其他变量
  DATA:
    lv_uuid        TYPE sysuuid-c,
    lv_parent_uuid TYPE sysuuid-c,
    lv_position    TYPE i,
    ls_err_info    TYPE ty_err_info.

* 进度条显示
  PERFORM frm_progress_show USING 'Structure'.

**********************************************************************
* 结构信息
**********************************************************************

* 获取UUID
  PERFORM frm_get_uuid_32 CHANGING lv_uuid.

* 结构名称
  ls_object_new-object_name = p_strnam.
  ls_object_new-key_guid = lv_uuid.

* 结构描述
  ls_object_new_text-language = sy-langu.
  ls_object_new_text-description = p_strtxt.
  APPEND ls_object_new_text TO ls_object_new-object_text.

  lv_parent_uuid = ls_object_new-key_guid.

* 表类型-结构
  ls_object_new_details-fieldname = 'TABCLASS'.
  ls_object_new_details-fieldvalue = 'INTTAB'.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

* 增强类别
  ls_object_new_details-fieldname = 'EXCLASS'.
  ls_object_new_details-fieldvalue = '3'.
  APPEND ls_object_new_details TO ls_object_new-details.
  CLEAR ls_object_new_details.

  APPEND ls_object_new TO lt_object_new.
  CLEAR ls_object_new.

**********************************************************************
* 结构字段
**********************************************************************
  LOOP AT ut_struc INTO DATA(ls_struc).
    ADD 1 TO lv_position.

*   获取UUID
    PERFORM frm_get_uuid_32 CHANGING lv_uuid.

    ls_object_new-object_name = ls_struc-fieldname.
    ls_object_new-key_guid    = lv_uuid.
    ls_object_new-parent_key  = lv_parent_uuid.

*   位置
    ls_object_new_details-fieldname = 'POSITION'.
    ls_object_new_details-fieldvalue = lv_position.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

    IF ls_struc-rollname IS NOT INITIAL.
*     数据元素
      ls_object_new_details-fieldname = 'ROLLNAME'.
      ls_object_new_details-fieldvalue = ls_struc-rollname.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ELSE.
*     内置类型
      ls_object_new_details-fieldname = 'DATATYPE'.
      ls_object_new_details-fieldvalue = ls_struc-datatype.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     长度
      ls_object_new_details-fieldname = 'LENG'.
      ls_object_new_details-fieldvalue = ls_struc-leng.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     小数位
      ls_object_new_details-fieldname = 'DECIMALS'.
      ls_object_new_details-fieldvalue = ls_struc-decimals.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     简短描述
      ls_object_new_details-fieldname = 'DDTEXT'.
      ls_object_new_details-fieldvalue = ls_struc-ddtext.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     *语言 【对于内置类型,必须传值,否则无法更新描述】
      ls_object_new_details-fieldname = 'LANGUAGE'.
      ls_object_new_details-fieldvalue = sy-langu.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ENDIF.

    IF ls_struc-reftable IS NOT INITIAL AND
       ls_struc-reffield IS NOT INITIAL.

*     参考表
      ls_object_new_details-fieldname = 'REFTABLE'.
      ls_object_new_details-fieldvalue = ls_struc-reftable.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     参考字段
      ls_object_new_details-fieldname = 'REFFIELD'.
      ls_object_new_details-fieldvalue = ls_struc-reffield.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ENDIF.

*   增强类别
    ls_object_new_details-fieldname = 'EXCLASS'.
    ls_object_new_details-fieldvalue = '3'.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

    APPEND ls_object_new TO lt_object_new.
    CLEAR ls_object_new.
  ENDLOOP.

  lv_devclass    = p_devcl.                       "包
  lv_request_wb  = p_transp.                      "请求
  lv_object_name = p_strnam.                      "结构名称

* 创建/更新 Structure
  CALL FUNCTION 'GOX_GEN_TABLE_STD'
    EXPORTING
      iv_object_name = lv_object_name
      it_object_new  = lt_object_new
      it_object_old  = lt_object_old
      iv_devclass    = lv_devclass
      iv_request_wb  = lv_request_wb
    IMPORTING
      et_bapireturn  = lt_bapireturn
      et_transport   = lt_transport.

  LOOP AT lt_bapireturn INTO DATA(ls_bapireturn) WHERE type CA 'EAX'.
    ls_err_info-objtype = 'Structure'.
    ls_err_info-objname = p_strnam.
    ls_err_info-msgid   = ls_bapireturn-id.
    ls_err_info-msgno   = ls_bapireturn-number.
    ls_err_info-msgty   = ls_bapireturn-type.

*   重构消息
    PERFORM frm_rebuild_msg USING ls_bapireturn
                         CHANGING ls_err_info-message.
    APPEND ls_err_info TO gt_err_info.
    CLEAR ls_err_info.
  ENDLOOP.

  gs_result-objtype   = 'Structure'.
  gs_result-objname   = p_strnam.
  gs_result-objnumber = '1'.

  IF gt_err_info IS NOT INITIAL.
    gs_result-objnum_e = '1'.
    gs_result-result   = icon_led_red.
  ELSE.
    gs_result-objnum_s = '1'.
    gs_result-result   = icon_led_green.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_dtel_begin
*&---------------------------------------------------------------------*
*& 执行创建
*&---------------------------------------------------------------------*
*&      --> UT_DTEL
*&---------------------------------------------------------------------*
FORM frm_create_dtel_begin  USING ut_dtel TYPE ty_tab_dtel.
* BAPI变量
  DATA:
    lv_object_name        TYPE char32,
    lt_object_new         TYPE comt_gox_def_header,
    ls_object_new         TYPE coms_gox_def_header,
    ls_object_new_details TYPE coms_gox_table_entry_fields,
    ls_object_new_text    TYPE coms_gox_def_text,
    lt_object_old         TYPE comt_gox_def_header,
    ls_object_old         TYPE coms_gox_def_header,
    lv_devclass           TYPE devclass,
    lv_request_wb         TYPE trkorr,
    lt_bapireturn         TYPE bapirettab,
    lt_transport          TYPE comt_gox_trans_object,
    lv_ddobjname          TYPE ddobjname,
    ls_dd02v              TYPE dd02v.

* 其他变量
  DATA:
    lv_uuid        TYPE sysuuid-c,
    lv_parent_uuid TYPE sysuuid-c,
    lv_position    TYPE i,
    ls_err_info    TYPE ty_err_info.

* 进度条显示
  PERFORM frm_progress_show USING 'DataElements'.

  LOOP AT ut_dtel INTO DATA(ls_dtel).
*   获取UUID
    PERFORM frm_get_uuid_32 CHANGING lv_uuid.

*   数据元素名称
    ls_object_new-object_name = ls_dtel-rollname.

*   描述
    ls_object_new_text-language = sy-langu.
    ls_object_new_text-description = ls_dtel-ddtext.
    APPEND ls_object_new_text TO ls_object_new-object_text.

    IF ls_dtel-domname IS NOT INITIAL.
      ls_object_new_details-fieldname = 'DOMNAME'.
      ls_object_new_details-fieldvalue = ls_dtel-domname.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ELSE.
*     内置类型
      ls_object_new_details-fieldname = 'DATATYPE'.
      ls_object_new_details-fieldvalue = ls_dtel-datatype.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     长度
      ls_object_new_details-fieldname = 'LENG'.
      ls_object_new_details-fieldvalue = ls_dtel-leng.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.

*     小数位
      ls_object_new_details-fieldname = 'DECIMALS'.
      ls_object_new_details-fieldvalue = ls_dtel-decimals.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR ls_object_new_details.
    ENDIF.

*   标题
    ls_object_new_details-fieldname = 'REPTEXT'.
    ls_object_new_details-fieldvalue = ls_dtel-reptext.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   标题最大长度
    ls_object_new_details-fieldname = 'HEADLEN'.
    ls_object_new_details-fieldvalue = '55'.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   短描述
    ls_object_new_details-fieldname = 'SCRTEXT_S'.
    ls_object_new_details-fieldvalue = ls_dtel-scrtext_s.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   短描述最大长度
    ls_object_new_details-fieldname = 'SCRLEN1'.
    ls_object_new_details-fieldvalue = '10'.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   中描述
    ls_object_new_details-fieldname = 'SCRTEXT_M'.
    ls_object_new_details-fieldvalue = ls_dtel-scrtext_m.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   中描述最大长度
    ls_object_new_details-fieldname = 'SCRLEN2'.
    ls_object_new_details-fieldvalue = '20'.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   长描述
    ls_object_new_details-fieldname = 'SCRTEXT_L'.
    ls_object_new_details-fieldvalue = ls_dtel-scrtext_l.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   长描述最大长度
    ls_object_new_details-fieldname = 'SCRLEN3'.
    ls_object_new_details-fieldvalue = '40'.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   语言
    ls_object_new_details-fieldname = 'DDLANGUAGE'.
    ls_object_new_details-fieldvalue = sy-langu.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

    APPEND ls_object_new TO lt_object_new.
    CLEAR ls_object_new.

    lv_devclass    = p_devcl.                     "包
    lv_request_wb  = p_transp.                    "请求
    lv_object_name = ls_dtel-rollname.            "数据元素

*   创建/更新 DataElements
    CALL FUNCTION 'GOX_GEN_DTEL_STD'
      EXPORTING
        iv_object_name = lv_object_name
        it_object_new  = lt_object_new
        it_object_old  = lt_object_old
        iv_devclass    = lv_devclass
        iv_request_wb  = lv_request_wb
      IMPORTING
        et_bapireturn  = lt_bapireturn
        et_transport   = lt_transport.

    LOOP AT lt_bapireturn INTO DATA(ls_bapireturn) WHERE type CA 'EAX'.
      ls_err_info-objtype = 'DataElements'.
      ls_err_info-objname = lv_object_name.
      ls_err_info-msgid   = ls_bapireturn-id.
      ls_err_info-msgno   = ls_bapireturn-number.
      ls_err_info-msgty   = ls_bapireturn-type.

*     重构消息
      PERFORM frm_rebuild_msg USING ls_bapireturn
                           CHANGING ls_err_info-message.
      APPEND ls_err_info TO gt_err_info.
      CLEAR ls_err_info.
    ENDLOOP.

    gs_result-objtype   = 'DataElements'.
    gs_result-objname   = lv_object_name.
    ADD 1 TO gs_result-objnumber.

    IF gt_err_info IS NOT INITIAL.
      ADD 1 TO gs_result-objnum_e.
    ELSE.
      ADD 1 TO gs_result-objnum_s.
    ENDIF.

    CLEAR:
      lv_object_name,
      lt_object_new,
      lt_object_old,
      lv_devclass,
      lv_request_wb,
      lt_bapireturn,
      lt_transport.
  ENDLOOP.

  IF gs_result-objnum_e > 0.
    gs_result-result   = icon_led_red.
  ELSE.
    gs_result-result   = icon_led_green.
  ENDIF.

  CONDENSE gs_result-objnum_e NO-GAPS.
  CONDENSE gs_result-objnum_s NO-GAPS.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_create_doma_begin
*&---------------------------------------------------------------------*
*& 执行创建
*&---------------------------------------------------------------------*
*&      --> UT_DOMA
*&---------------------------------------------------------------------*
FORM frm_create_doma_begin  USING ut_doma TYPE ty_tab_doma.
* BAPI变量
  DATA:
    lv_object_name        TYPE char32,
    lt_object_new         TYPE comt_gox_def_header,
    ls_object_new         TYPE coms_gox_def_header,
    ls_object_new_details TYPE coms_gox_table_entry_fields,
    ls_object_new_text    TYPE coms_gox_def_text,
    lt_object_fixvalues   TYPE comt_gox_table_entry_fields,
    ls_object_fixvalues   TYPE coms_gox_table_entry_fields,
    lt_object_old         TYPE comt_gox_def_header,
    ls_object_old         TYPE coms_gox_def_header,
    lv_devclass           TYPE devclass,
    lv_request_wb         TYPE trkorr,
    lt_bapireturn         TYPE bapirettab,
    lt_transport          TYPE comt_gox_trans_object,
    lv_ddobjname          TYPE ddobjname,
    ls_dd02v              TYPE dd02v.

* 其他变量
  DATA:
    lv_uuid        TYPE sysuuid-c,
    lv_parent_uuid TYPE sysuuid-c,
    lv_position    TYPE i,
    ls_err_info    TYPE ty_err_info,
    lv_valpos      TYPE dd07v-valpos,
    lv_has_fix     TYPE boolean.

* 进度条显示
  PERFORM frm_progress_show USING 'Domain'.

  LOOP AT ut_doma INTO DATA(ls_doma)
    GROUP BY ( domname = ls_doma-domname )
    ASCENDING REFERENCE INTO DATA(lo_doma).

*   获取UUID
    PERFORM frm_get_uuid_32 CHANGING lv_uuid.

    lv_parent_uuid = lv_uuid.

*   固定值集
    LOOP AT GROUP lo_doma ASSIGNING FIELD-SYMBOL(<fs_doma>).
      IF <fs_doma>-ddtext_fix IS NOT INITIAL.
        ADD 1 TO lv_valpos.

*       拥有固定值
        lv_has_fix = 'X'.

        ls_object_fixvalues-fieldname  = 'VALPOS'.
        ls_object_fixvalues-fieldvalue = lv_valpos.
        APPEND ls_object_fixvalues TO lt_object_fixvalues.
        CLEAR ls_object_fixvalues.

        ls_object_fixvalues-fieldname  = 'DOMVALUE_L'.
        ls_object_fixvalues-fieldvalue = <fs_doma>-domvalue_l.
        APPEND ls_object_fixvalues TO lt_object_fixvalues.
        CLEAR ls_object_fixvalues.

        ls_object_fixvalues-fieldname  = 'DDTEXT'.
        ls_object_fixvalues-fieldvalue = <fs_doma>-ddtext_fix.
        APPEND ls_object_fixvalues TO lt_object_fixvalues.
        CLEAR ls_object_fixvalues.

        APPEND LINES OF lt_object_fixvalues TO ls_object_new-details.
        CLEAR lt_object_fixvalues.

*       获取UUID
        PERFORM frm_get_uuid_32 CHANGING lv_uuid.

*       Key
        ls_object_new-key_guid = lv_uuid.

*       与域对象绑定父子关系
        ls_object_new-parent_key = lv_parent_uuid.
        APPEND ls_object_new TO lt_object_new.
        CLEAR ls_object_new.
      ENDIF.
    ENDLOOP.

    IF lv_has_fix = 'X'.
*     固定值存在
      ls_object_new_details-fieldname = 'VALEXI'.
      ls_object_new_details-fieldvalue = 'X'.
      APPEND ls_object_new_details TO ls_object_new-details.
      CLEAR:
        ls_object_new_details,
        lv_has_fix.
    ENDIF.

*   Key
    ls_object_new-key_guid = lv_parent_uuid.

*   域名称
    ls_object_new-object_name = <fs_doma>-domname.

*   描述
    ls_object_new_text-language = sy-langu.
    ls_object_new_text-description = <fs_doma>-ddtext.
    APPEND ls_object_new_text TO ls_object_new-object_text.

*   数据类型
    ls_object_new_details-fieldname = 'DATATYPE'.
    ls_object_new_details-fieldvalue = <fs_doma>-datatype.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   长度
    ls_object_new_details-fieldname = 'LENG'.
    ls_object_new_details-fieldvalue = <fs_doma>-leng.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   小数位
    ls_object_new_details-fieldname = 'DECIMALS'.
    ls_object_new_details-fieldvalue = <fs_doma>-decimals.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   是否支持符号
    ls_object_new_details-fieldname = 'SIGNFLAG'.
    ls_object_new_details-fieldvalue = <fs_doma>-signflag.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   是否支持大小写
    ls_object_new_details-fieldname = 'LOWERCASE'.
    ls_object_new_details-fieldvalue = <fs_doma>-lowercase.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   转换例程
    ls_object_new_details-fieldname = 'CONVEXIT'.
    ls_object_new_details-fieldvalue = <fs_doma>-convexit.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

*   语言
    ls_object_new_details-fieldname = 'DDLANGUAGE'.
    ls_object_new_details-fieldvalue = sy-langu.
    APPEND ls_object_new_details TO ls_object_new-details.
    CLEAR ls_object_new_details.

    APPEND ls_object_new TO lt_object_new.
    CLEAR ls_object_new.

    lv_devclass    = p_devcl.                     "包
    lv_request_wb  = p_transp.                    "请求
    lv_object_name = <fs_doma>-domname.           "域

*   创建/更新 Domain
    CALL FUNCTION 'GOX_GEN_DOMA_STD'
      EXPORTING
        iv_object_name = lv_object_name
        it_object_new  = lt_object_new
        it_object_old  = lt_object_old
        iv_devclass    = lv_devclass
        iv_request_wb  = lv_request_wb
      IMPORTING
        et_bapireturn  = lt_bapireturn
        et_transport   = lt_transport.

    LOOP AT lt_bapireturn INTO DATA(ls_bapireturn) WHERE type CA 'EAX'.
      ls_err_info-objtype = 'Domain'.
      ls_err_info-objname = lv_object_name.
      ls_err_info-msgid   = ls_bapireturn-id.
      ls_err_info-msgno   = ls_bapireturn-number.
      ls_err_info-msgty   = ls_bapireturn-type.

*     重构消息
      PERFORM frm_rebuild_msg USING ls_bapireturn
                           CHANGING ls_err_info-message.
      APPEND ls_err_info TO gt_err_info.
      CLEAR ls_err_info.
    ENDLOOP.

    gs_result-objtype   = 'Domain'.
    gs_result-objname   = lv_object_name.
    ADD 1 TO gs_result-objnumber.

    IF gt_err_info IS NOT INITIAL.
      ADD 1 TO gs_result-objnum_e.
    ELSE.
      ADD 1 TO gs_result-objnum_s.
    ENDIF.

    CLEAR:
      lv_valpos,
      lv_object_name,
      lt_object_new,
      lt_object_old,
      lv_devclass,
      lv_request_wb,
      lt_bapireturn,
      lt_transport,
      lt_object_fixvalues.

    IF gs_result-objnum_e > 0.
      gs_result-result   = icon_led_red.
    ELSE.
      gs_result-result   = icon_led_green.
    ENDIF.

    CONDENSE gs_result-objnum_e NO-GAPS.
    CONDENSE gs_result-objnum_s NO-GAPS.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_progress_show
*&---------------------------------------------------------------------*
*& 进度条显示
*&---------------------------------------------------------------------*
*&      --> UV_TYPE
*&---------------------------------------------------------------------*
FORM frm_progress_show  USING VALUE(uv_type) TYPE string.
  DATA:
    lv_text TYPE string.

  lv_text = |正在进行{ uv_type }创建...|.

  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      text = lv_text.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_UUID_32
*&---------------------------------------------------------------------*
*& 获取UUID
*&---------------------------------------------------------------------*
*&      <-- CV_UUID
*&---------------------------------------------------------------------*
FORM frm_get_uuid_32  CHANGING cv_uuid TYPE sysuuid-c.
  TRY.
      cv_uuid = cl_system_uuid=>if_system_uuid_static~create_uuid_c32( ).
    CATCH cx_uuid_error .
  ENDTRY.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_rebuild_msg
*&---------------------------------------------------------------------*
*& 重构消息内容
*&---------------------------------------------------------------------*
*&      --> US_BAPIRETURN
*&      <-- CV_ERR_INFO_MESSAGE
*&---------------------------------------------------------------------*
FORM frm_rebuild_msg  USING    us_bapireturn TYPE bapiret2
                      CHANGING cv_err_info_message TYPE bapi_msg.
  CALL FUNCTION 'BAPI_MESSAGE_GETDETAIL'
    EXPORTING
      id         = us_bapireturn-id
      number     = us_bapireturn-number
      textformat = 'ASC'
      message_v1 = us_bapireturn-message_v1
      message_v2 = us_bapireturn-message_v2
      message_v3 = us_bapireturn-message_v3
      message_v4 = us_bapireturn-message_v4
    IMPORTING
      message    = cv_err_info_message.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_sug_foreign
*&---------------------------------------------------------------------*
*& 获取建议外键字段列表
*&---------------------------------------------------------------------*
*&      --> UT_TABLE
*&      <-- CT_SUG_FOREIGN
*&---------------------------------------------------------------------*
FORM frm_get_sug_foreign USING ut_table       TYPE ty_tab_table
                      CHANGING ct_sug_foreign TYPE ty_tab_sug_foreign.

  DATA:
    lt_key_table TYPE ty_tab_key_table,
    ls_key_table TYPE ty_key_table.

  LOOP AT ut_table INTO DATA(ls_table) WHERE checktable IS NOT INITIAL.
    ls_key_table-tabname = ls_table-checktable.
    COLLECT ls_key_table INTO lt_key_table.
    CLEAR ls_key_table.
  ENDLOOP.

  CHECK lt_key_table IS NOT INITIAL.

* 获取检查表key信息
  SELECT tabname
         fieldname
         position AS primpos
    INTO TABLE  ct_sug_foreign
    FROM dd03l
     FOR ALL ENTRIES IN lt_key_table
   WHERE tabname  = lt_key_table-tabname
     AND as4local = 'A'
     AND keyflag  = 'X'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_make_foreign
*&---------------------------------------------------------------------*
*& 构建建议的外键信息mapping表
*&---------------------------------------------------------------------*
*&      --> UT_TABLE         表信息
*&      --> US_TABLE         当前行信息
*&      --> UT_SUG_FOREIGN   检查表主键信息
*&      --> UV_PARENT_KEY    父级UUID
*&      <-- CT_OBJECT_NEW    传入参数NEW
*&      <-- CT_OBJECT_OLD    传入参数OLD(用于覆盖旧的外键信息)
*&---------------------------------------------------------------------*
FORM frm_make_foreign  USING    ut_table       TYPE ty_tab_table
                                us_table       TYPE ty_table
                                ut_sug_foreign TYPE ty_tab_sug_foreign
                                uv_parent_key  TYPE comt_gox_key_guid
                       CHANGING ct_object_new  TYPE comt_gox_def_header
                                ct_object_old  TYPE comt_gox_def_header.
* BAPI变量
  DATA:
    ls_object_foreign         TYPE coms_gox_def_header,
    ls_object_foreign_details TYPE coms_gox_table_entry_fields.

* 其他变量
  DATA:
    lv_uuid        TYPE sysuuid-c.

  LOOP AT ut_sug_foreign INTO DATA(ls_sug_foreign)
    WHERE tabname = us_table-checktable.

*   获取UUID
    PERFORM frm_get_uuid_32 CHANGING lv_uuid.

    ls_object_foreign-object_type = 'TABLE_FIELD'.
    ls_object_foreign-object_name = ls_sug_foreign-fieldname. "检查表字段
    ls_object_foreign-key_guid    = lv_uuid.
    ls_object_foreign-parent_key  = uv_parent_key.            "父级UUID

    READ TABLE ut_table TRANSPORTING NO FIELDS
      WITH KEY fieldname = ls_sug_foreign-fieldname.
    IF sy-subrc = 0.
*     外键表
      ls_object_foreign_details-fieldname = 'FORTABLE'.
      ls_object_foreign_details-fieldvalue = p_tabnam.
    ELSE.
*     外键表
      ls_object_foreign_details-fieldname = 'FORTABLE'.
      ls_object_foreign_details-fieldvalue = '*'.
    ENDIF.
    APPEND ls_object_foreign_details TO ls_object_foreign-details.
    CLEAR ls_object_foreign_details.

*   检查表字段的位置
    ls_object_foreign_details-fieldname = 'PRIMPOS'.
    ls_object_foreign_details-fieldvalue = ls_sug_foreign-primpos.
    APPEND ls_object_foreign_details TO ls_object_foreign-details.
    CLEAR ls_object_foreign_details.

*   检查表名
    ls_object_foreign_details-fieldname = 'CHECKTABLE'.
    ls_object_foreign_details-fieldvalue = us_table-checktable.
    APPEND ls_object_foreign_details TO ls_object_foreign-details.
    CLEAR ls_object_foreign_details.

    APPEND ls_object_foreign TO ct_object_new.
    APPEND ls_object_foreign TO ct_object_old.
    CLEAR ls_object_foreign.

    IF ls_sug_foreign-fieldname = us_table-fieldname.
      EXIT.
    ENDIF.
  ENDLOOP.
ENDFORM.

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeveloperMrMeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值