SAP hana s/4 abap BOM批量修改添加程序

SAP通过EXCEL导入批量修改或添加物料BOM程序,如果BOM存则先删除BOM,如果BOM不存在则添加BOM。


REPORT zppb015.

*----------------------------------------------------------------------*
* 数据库表声明/Database Table Declaration
*----------------------------------------------------------------------*
TABLES: sscrfields.

*&---------------------------------------------------------------------*
*& ALV TYPE/ALV 类型定义                                                *
*&---------------------------------------------------------------------*
*&--- ALV 数据组,类型池
TYPE-POOLS: slis,
            vrm.

*&--- 定义 ALV 显示的字段列及其描述等属性
DATA: gt_fieldcat TYPE lvc_t_fcat, " 字段目录
      gs_fieldcat TYPE lvc_s_fcat, " 字段目录
      gs_layout   TYPE lvc_s_layo. " 布局结构

*----------------------------------------------------------------------*
* 结构声明类型/Structure Type Declaration
*----------------------------------------------------------------------*
*&--- 主表数据
TYPES: BEGIN OF ty_tab,
         matnr     TYPE  mast-matnr , " 产品编码
         matnr_o   TYPE  mast-matnr , " 旧产品编码
         fmaktx    TYPE  makt-maktx , " 产品描述
         werks     TYPE  mast-werks , " 工厂代码
         stlal     TYPE  mast-stlal , " 版本
         bmeng     TYPE  stko-bmeng , " 基本用量
         posnr     TYPE  stpo-posnr , " 项目编号
         postp     TYPE  stpo-postp , " 项目类别
         idnrk     TYPE  stpo-idnrk , " 组件编码
         idnrk_o   TYPE  stpo-idnrk , " 旧组件编码
         smaktx    TYPE  makt-maktx , " 组件描述
         menge     TYPE  stpo-menge , " 组件用量
         ausch     TYPE  stpo-ausch , " 损耗率
         kzkup     TYPE  stpo-kzkup , " 联产品
         lgort     TYPE  stpo-lgort , " 发货库位
         stlan     TYPE  mast-stlan , " BOM用途
         bmein     TYPE  stko-bmein , " 基本用量单位
         meins     TYPE  stpo-meins , " 组件单位

         stlbe     TYPE stzu-stlbe, "权限组

*         stktx   TYPE  stko-stktx , " 母件表头备注
*         sortf   TYPE  stpo-sortf , " 物料类型(排序字符串)
         alpgr     TYPE  stpo-alpgr , " 替代组
*         alprf   TYPE  stpo-alprf , " 优先级
*         aennr   TYPE  stpo-aennr , " ECN号
*         potx1   TYPE  stpo-potx1 , " 项目文本1
         "alpst   TYPE  stpo-alpst , " 策略
         ewahr     TYPE  stpo-ewahr , " 使用比例
*         potx2   TYPE  stpo-potx2 , " 项目文本2
*         itsob   TYPE  stpo-itsob , " 特殊采购
         Ztype(10),                   "导入类型
         check ,
         icon      TYPE char4       , " LIGHT
         type      TYPE bapi_mtype  , " 消息类型
         message   TYPE bapi_msg    , " 消息
         znumb     TYPE int4,
       END OF ty_tab.

*----------------------------------------------------------------------*
* 全局变量定义/Global Variable Definition
*----------------------------------------------------------------------*
*&--- 主数据表
DATA: gt_tab   TYPE TABLE OF ty_tab,
      gt_excel TYPE TABLE OF ty_tab WITH HEADER LINE,
      gs_tab   TYPE ty_tab.

*&--- Excel 数据存储
DATA: gt_xlstmp TYPE alsmex_tabline OCCURS 0.      " 保存 Excel 中读取的记录

*&--- 选择界面下载按钮参数
DATA: gs_functxt TYPE smp_dyntxt.

*&---------------------------------------------------------------------*
*& 字段串定义/Field-Symbols                                              *
*&---------------------------------------------------------------------*
FIELD-SYMBOLS:   LIKE alsmex_tabline. " Excel 单元格
FIELD-SYMBOLS:  TYPE any.

*&---------------------------------------------------------------------*
*& Macro 宏定义                                                         *
*&---------------------------------------------------------------------*
DEFINE mcr_set_catalog.
  CLEAR gs_fieldcat.

  gs_fieldcat-fieldname  = &1.  " 字段技术名称
  gs_fieldcat-coltext    = &2.  " 显示名称
  gs_fieldcat-no_zero    = &3.  " 为输出隐藏零
  gs_fieldcat-ref_table  = &4.  " 参照表
  gs_fieldcat-ref_field  = &5.  " 参照表字段

  APPEND gs_fieldcat TO gt_fieldcat.
END-OF-DEFINITION.

*&---------------------------------------------------------------------*
*& SELECTION SCREEN/选择屏幕                                            *
*&---------------------------------------------------------------------*
SELECTION-SCREEN:FUNCTION KEY 1.              " 在屏幕定义功能码

*&--- 选择屏幕块
SELECTION-SCREEN: BEGIN OF BLOCK blk1 WITH FRAME TITLE TEXT-101. " 选择条件
  PARAMETERS: p_file TYPE dxfields-longpath.  " 文件路径
SELECTION-SCREEN: END OF BLOCK blk1.

*&---------------------------------------------------------------------*
*& INITIALIZATION/选择屏幕前初始化                                        *
*&---------------------------------------------------------------------*
INITIALIZATION.
*&---初始化选择屏幕值
*&---初始化变量
  gs_functxt-icon_id   = icon_mapped_relation.
  gs_functxt-icon_text = TEXT-102. " 模板下载
  sscrfields-functxt_01 = gs_functxt.
*----------------------------------------------------------------------*
*       At selection-screen                                            *
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
*&--- 下载模板
  CASE sscrfields-ucomm.
    WHEN 'FC01'." 系统预留的功能码
      " 下载模板文件
      PERFORM frm_download_excel.
    WHEN OTHERS.
  ENDCASE.

*&---------------------------------------------------------------------*
*& AT SELECTION-SCREEN OUTPUT/选择屏幕输出                               *
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.

*&---------------------------------------------------------------------*
*& AT SELECTION-SCREEN ON VALUE-REQUEST/ 选择屏幕搜索帮助                 *
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
*&--- 选择文件获取文件路径
  PERFORM frm_select_infile CHANGING p_file.

*&---------------------------------------------------------------------*
*& START-OF-SELECTION/开始选择屏幕                                       *
*&---------------------------------------------------------------------*
START-OF-SELECTION.

*-- 获取数据
  PERFORM frm_get_data.

*&---------------------------------------------------------------------*
*& END-OF-SELECTION/结束选择屏幕(程序结束处理,输出等)                      *
*&---------------------------------------------------------------------*
END-OF-SELECTION.
  IF gt_tab IS NOT INITIAL.
*-- ALV 显示
    PERFORM frm_display_alv.
  ELSE.
    MESSAGE s008(zpp001) DISPLAY LIKE 'E'. " 没有找到符合条件的数据
    LEAVE LIST-PROCESSING.
  ENDIF.
*&---------------------------------------------------------------------*
*& Form FRM_USER_STATUS
*&---------------------------------------------------------------------*
*& ALV 工具栏状态
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_set_pf_status USING ps_extab TYPE slis_t_extab.
  SET PF-STATUS 'STATUS_0500'. " 自定义状态名称
ENDFORM. "FRM_SET_PF_STATUS
*&---------------------------------------------------------------------*
*& Form FRM_USER_COMMAND
*&---------------------------------------------------------------------*
*& ALV 工具栏命令
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_usr_command USING pv_ucomm LIKE sy-ucomm
                                 ps_selfield TYPE slis_selfield.
  DATA: lr_alv_grid TYPE REF TO cl_gui_alv_grid.

  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lr_alv_grid.  " 获取全局变量

  CALL METHOD lr_alv_grid->check_changed_data. " 获取响应事件
  ps_selfield-refresh = 'X'.                " 刷新界面
  ps_selfield-row_stable = 'X'.
  ps_selfield-col_stable = 'X'.

*&--- 触发工具栏命令
  CASE pv_ucomm.
      " 触发「导入」按钮
    WHEN 'ZIMPORT'.
      PERFORM frm_call_bapi. " 调用 BAPI
    WHEN OTHERS.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_DATA
*&---------------------------------------------------------------------*
*& 获取上传 Excel 文件数据后校验数据
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data .
  DATA: ls_tab   TYPE ty_tab,
        lv_tabix TYPE sy-tabix,
        lv_lenht TYPE i,
        lv_ewahr TYPE ewahr.

  PERFORM frm_upload_data. " 上传数据

  IF gt_tab IS NOT INITIAL.
*&--- 物料工厂信息
    SELECT matnr,
           werks
      INTO TABLE @DATA(lt_matr)
      FROM marc
      FOR ALL ENTRIES IN @gt_tab
      WHERE ( matnr = @gt_tab-matnr AND werks = @gt_tab-werks )
    OR ( matnr = @gt_tab-idnrk AND werks = @gt_tab-werks ).

*&--- 备选物料清单
    SELECT matnr,
           werks,
           stlal
      INTO TABLE @DATA(lt_mast)
      FROM mast
      FOR ALL ENTRIES IN @gt_tab
      WHERE matnr = @gt_tab-matnr
        AND stlal = @gt_tab-stlal
    AND werks = @gt_tab-werks.

*&--- 基本用量单位
    SELECT mara~matnr,
           mara~meins
      INTO TABLE @DATA(lt_mara)
      FROM mara
      FOR ALL ENTRIES IN @gt_tab
      WHERE matnr = @gt_tab-matnr .

*&--- 组件用量单位
    SELECT mara~matnr,
           mara~meins
      INTO TABLE @DATA(lt_mara_sub)
      FROM mara
      FOR ALL ENTRIES IN @gt_tab
      WHERE matnr = @gt_tab-idnrk.

*&--- 发货库位校验
    SELECT
      werks,
      lgort
    FROM t001l
    FOR ALL ENTRIES IN @gt_tab
    WHERE werks = @gt_tab-werks AND
          lgort = @gt_tab-lgort
    INTO TABLE @DATA(lt_t001l).
  ENDIF.


  "获取权限参数
  RANGES:g_ranges FOR marc-werks.

  DATA:lt_us335 TYPE TABLE OF us335.
  CALL FUNCTION 'GET_AUTH_VALUES'
    EXPORTING
      object1           = 'M_MATE_WRK'
*     OBJECT2           = ' '
*     OBJECT3           = ' '
*     OBJECT4           = ' '
*     OBJECT5           = ' '
*     OBJECT6           = ' '
*     OBJECT7           = ' '
      user              = sy-uname
*     TCODE             = SY-TCODE
*     OPTIMIZE          =
    TABLES
      values            = lt_us335[]
    EXCEPTIONS
      user_doesnt_exist = 1
      OTHERS            = 2.
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ELSE.
    DATA:lv_flg TYPE char01.

    LOOP AT lt_us335 INTO DATA(ls_us335) WHERE field = 'WERKS'.
      IF ls_us335-lowval EQ '*'.
        DATA(lv_authority_flg) = 'X'.
        EXIT.
      ELSE.
*"单值
        g_ranges-sign = 'I'.
        g_ranges-option = 'EQ'.
        g_ranges-low = ls_us335-lowval.
        APPEND g_ranges.
      ENDIF.

    ENDLOOP.

  ENDIF.

  SORT gt_tab       BY matnr werks stlal posnr.
  SORT lt_matr      BY matnr werks.
  SORT lt_mast      BY matnr werks stlal.
  SORT lt_mara      BY matnr.
  SORT lt_t001l      BY werks lgort.
  SORT lt_mara_sub  BY matnr.

  CLEAR: gs_tab.
  LOOP AT gt_tab INTO gs_tab.
    lv_tabix = sy-tabix + 1.
    CLEAR gs_tab-message.


*&--- BOM 用途取值,默认为 1
    gs_tab-stlan = '1'.

*&--------权限校验
    IF lv_authority_flg NE 'X'.
      IF gs_tab-werks NOT IN g_ranges.
        gs_tab-message = gs_tab-message && TEXT-126.
      ENDIF.
    ENDIF.

*&--- 检查模版中头物料(MATNR)与组件物料(IDNRK)是否在工厂主数据中存在,系统报错,提示:物料XXX在工厂XX中不存在
    READ TABLE lt_matr INTO DATA(ls_matr) WITH KEY matnr = gs_tab-matnr
                                                   werks = gs_tab-werks BINARY SEARCH.
    IF sy-subrc NE 0.
      IF gs_tab-postp <> 'T'. " 项目类型为 T 时,不进行物料工厂校验
        gs_tab-message = gs_tab-message && TEXT-112 && TEXT-109 && gs_tab-matnr  && TEXT-110 && gs_tab-werks && TEXT-111.
      ENDIF.
    ENDIF.
    READ TABLE lt_matr INTO ls_matr WITH KEY matnr = gs_tab-idnrk
                                              werks = gs_tab-werks BINARY SEARCH.
    IF sy-subrc NE 0.
      IF gs_tab-postp <> 'T'. " 项目类型为 T 时,不进行物料工厂校验
        gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-109 && gs_tab-idnrk  && TEXT-110 && gs_tab-werks && TEXT-111.
      ENDIF.
    ENDIF.
* 2. 校验发货库位在工厂有没有存在,查询表T001L
    READ TABLE lt_t001l INTO DATA(ls_t001l) WITH KEY werks = gs_tab-werks
                                                     lgort = gs_tab-lgort BINARY SEARCH.
    IF sy-subrc <> 0 AND gs_tab-lgort IS NOT INITIAL.
      gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-122. " 发货库位在工厂中不存在
    ENDIF.
* 3. 检查模版中头物料(MATNR)+BOM版本(STLAL)是否在工厂BOM已存在,系统报错,提示:物料(MATNR)BOM版本(STLAL)在工厂XX
*    中已存在BOM 参考表 mast
*    READ TABLE LT_MAST INTO DATA(LS_MAST) WITH KEY MATNR = GS_TAB-MATNR
*                                                   WERKS = GS_TAB-WERKS
*                                                   STLAL = GS_TAB-STLAL BINARY SEARCH.
*    IF SY-SUBRC = 0.
*      GS_TAB-MESSAGE =  GS_TAB-MESSAGE && TEXT-112 && TEXT-109 && GS_TAB-MATNR && TEXT-113 && GS_TAB-STLAL && TEXT-110 && GS_TAB-WERKS && TEXT-114.
*    ENDIF.

* 4. 模版中如果出现相同的头物料(MATNR)与组件物料(IDNRK)相同,系统报错,提示:父物料与子物料不能相同。
    READ TABLE gt_tab INTO ls_tab WITH  KEY  matnr = gs_tab-matnr
                                             werks = gs_tab-werks
                                             stlan = gs_tab-stlan
                                             stlal = gs_tab-stlal
                                             idnrk = gs_tab-matnr BINARY SEARCH.
    IF sy-subrc = 0.
      gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-115. " 父物料与子物料不能相同
    ENDIF.

* 5. 模版中如果出现相同的头物料(MATNR)相同的行项(POSNR),系统报错,提示:父物料下面的组件行项目不可重复。
    READ TABLE gt_tab INTO ls_tab INDEX lv_tabix .
    IF sy-subrc = 0.
      IF ls_tab-posnr = gs_tab-posnr AND
         ls_tab-matnr = gs_tab-matnr AND
         ls_tab-werks = gs_tab-werks AND
         ls_tab-stlan = gs_tab-stlan AND
         ls_tab-stlal = gs_tab-stlal.

        gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-116. " 父物料下面的组件行项目不可重复
      ENDIF.
    ENDIF.
* 6. 模版中组件物料数量(MENGE)为空或等于零,系统报错,提示:组件物料数量错误。
    IF gs_tab-menge IS INITIAL.
      gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-117. " 组件物料数量错误
    ENDIF.

* 7. 如果有维护权限组,如不为空,又不等于WDF0,提示“权限组错误”
    IF gs_tab-stlbe IS NOT INITIAL AND ( gs_tab-stlbe NE 'WDF0' AND gs_tab-stlbe NE 'WDF1' ).
      gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-123. " 权限组错误
    ENDIF.

* 8. 1. BOM版本不能为空,
* 8. 2. 如BOM版本已存在,提示“该版本已存在”:MAST-MATNR = 产品编码,MAST-WERKS = 工厂,MAST-STLAN = 1,MAST-STLAL = BOM版本,查询记录>0
    IF gs_tab-stlal IS INITIAL.
      gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-124. " 权限组错误
    ENDIF.
*---修改导入BOM的判断是否已有BOM,有也可导入
*    IF gs_tab-stlal IS NOT INITIAL .
*      SELECT COUNT( * ) FROM mast WHERE matnr EQ @gs_tab-matnr AND werks EQ @gs_tab-werks AND stlal EQ @gs_tab-stlal.
*      IF sy-subrc EQ 0.
*        gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-125. " 权限组错误
*      ENDIF.
*
*    ENDIF.


*&--- 判定错误消息,赋值指示灯状态
    gs_tab-message = gs_tab-message+1.
    IF gs_tab-message IS NOT INITIAL.
      gs_tab-icon = '@0A@'.        " 红灯
      gs_tab-type = 'E'.
    ELSE.
      gs_tab-icon = '@08@'.        " 绿灯
      gs_tab-type = 'S'.
    ENDIF.
    IF gs_tab-stlal IS NOT INITIAL .
      SELECT COUNT( * ) FROM mast WHERE matnr EQ @gs_tab-matnr AND werks EQ @gs_tab-werks AND stlal EQ @gs_tab-stlal.
      IF sy-subrc EQ 0.
        "gs_tab-message =  gs_tab-message && TEXT-112 && TEXT-125. " 权限组错误
        gs_tab-ztype = '修改'.
      ELSE.
        gs_tab-ztype = '新增'.
      ENDIF.

    ENDIF.
*&--- 回写物料基础单位
    " 母件物料基础单位
    READ TABLE lt_mara INTO DATA(ls_mara1) WITH KEY matnr = gs_tab-matnr BINARY SEARCH.
    IF sy-subrc = 0.
      gs_tab-bmein = ls_mara1-meins.
    ENDIF.

    IF gs_tab-idnrk IS NOT INITIAL.
      " 组件基础单位
      READ TABLE lt_mara INTO DATA(ls_mara2) WITH KEY matnr = gs_tab-idnrk BINARY SEARCH.
      IF sy-subrc = 0.
        gs_tab-meins = ls_mara2-meins.
      ENDIF.
    ELSEIF gs_tab-idnrk IS INITIAL.
      CLEAR: gs_tab-meins.
    ENDIF.

    " 组件基础单位
    IF gs_tab-idnrk IS NOT INITIAL. " 不为空,正常获取
      READ TABLE lt_mara_sub INTO DATA(ls_mara_sub) WITH KEY matnr = gs_tab-idnrk BINARY SEARCH.
      IF sy-subrc = 0.
        gs_tab-meins = ls_mara_sub-meins.
      ENDIF.
    ELSEIF gs_tab-idnrk IS INITIAL. " 为空,默认 PC
      gs_tab-meins = 'ST'.
    ENDIF.

    MODIFY gt_tab FROM gs_tab.
    CLEAR: gs_tab.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DISPLAY_ALV
*&---------------------------------------------------------------------*
*& 配置 ALV 样式,字段目录并展示 内表数据
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_display_alv .
*&--- 设置字段目录
  PERFORM frm_build_fieldcat.
*&--- 设置布局属性
  PERFORM frm_build_layout.
*&--- ALV 展示数据
  PERFORM frm_build_alv.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_BUILD_FIELDCAT
*&---------------------------------------------------------------------*
*& 配置 ALV 字段目录
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_build_fieldcat .
  CLEAR gt_fieldcat.

  mcr_set_catalog: 'ICON '    TEXT-c01 '' '' '' ,          " 状态
                   'MESSAGE'  TEXT-c02 '' '' '' ,          " 消息
                   'ZTYPE'    TEXT-c34 '' '' '' ,          " 导入类型
                   'MATNR'    TEXT-c03 '' 'MAST' 'MATNR' , " 产品编码
                   'MATNR_O'  TEXT-c04 '' 'MAST' 'MATNR' , " 旧产品编码
                   'FMAKTX'   TEXT-c05 '' 'MAKT' 'MAKTX' , " 产品描述
                   'WERKS'    TEXT-c06 '' 'MAST' 'WERKS' , " 工厂代码
                   'STLAL'    TEXT-c07 '' 'MAST' 'STLAL' , " 版本
                   'BMENG'    TEXT-c08 '' 'STKO' 'BMENG' , " 基本数量
                   'POSNR'    TEXT-c09 '' 'STPO' 'POSNR' , " 项目编号
                   'POSTP'    TEXT-c10 '' 'STPO' 'POSTP' , " 项目类别
                   'IDNRK'    TEXT-c11 '' 'STPO' 'IDNRK' , " 组件编码
                   'IDNRK_O'  TEXT-c12 '' 'STPO' 'IDNRK' , " 旧组件编码
                   'SMAKTX'   TEXT-c13 '' 'MAKT' 'MAKTX' , " 组件描述
                   'MENGE'    TEXT-c14 '' 'STPO' 'MENGE' , " 组件用量
                   'KZKUP'    TEXT-c15 '' 'STPO' 'KZKUP' , " 联产品
                   'AUSCH'    TEXT-c18 '' 'STPO' 'AUSCH' , " 损耗率
                   'LGORT'    TEXT-c16 '' 'STPO' 'LGORT' , " 发货库位
                   'STLBE'    TEXT-c33 '' 'STZU' 'STLBE' . " 权限组

ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_BUILD_LAYOUT
*&---------------------------------------------------------------------*
*& 配置 ALV 样式
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_build_layout .
  CLEAR gs_layout.
  gs_layout-sel_mode   = 'A'.     " 设置行模式
  gs_layout-cwidth_opt = 'X'.     " 优化列宽设置
  gs_layout-zebra      = 'X'.     " 设置斑马线
  gs_layout-box_fname  = 'CHECK'. " 选择字段
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SELECT_INFILE
*&---------------------------------------------------------------------*
*& 获取上传文件路径
*&---------------------------------------------------------------------*
*& <-- P_FILE
*&---------------------------------------------------------------------*
FORM frm_select_infile CHANGING pv_file.
*&--- 定义传出文件名内表 和传出参数
  DATA: lt_upfile     TYPE filetable,
        lv_rc         TYPE i,
        lv_window     TYPE string,
        lv_filefilter TYPE string,
        lv_default    TYPE string.

*&--- 默认值赋值
  lv_window     = TEXT-106. " 请选择本地文件
  lv_filefilter = TEXT-107. " EXCEL文件 (*.xlsx)|*.xlsx|EXCEL文件 (*.xls)|*.xls|文本|*.txt|
  lv_default    = TEXT-108. " *.xlsx

*&--- 调用类方法
  CALL METHOD cl_gui_frontend_services=>file_open_dialog
    EXPORTING
      window_title     = lv_window     " 请选择本地文件
      file_filter      = lv_filefilter " EXCEL文件 (*.xlsx)|*.xlsx|EXCEL文件 (*.xls)|*.xls|文本|*.txt|
      default_filename = lv_default    " *.xlsx
    CHANGING
      file_table       = lt_upfile
      rc               = lv_rc.

*&--- 读取成功,赋值文件路径
  IF sy-subrc = 0 AND lv_rc = 1.
    READ TABLE lt_upfile INTO p_file INDEX 1.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DOWNLOAD_EXCEL
*&---------------------------------------------------------------------*
*& 下载模板文件
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_download_excel .
  DATA: lv_name(128), lv_type(3), lv_size TYPE i.
  DATA: lv_num TYPE i.
  DATA: lv_user_act   TYPE i.        " 文件保存对话框,用户行为
  DATA: lv_filename   TYPE string,   " 下载文件名
        lv_wintitle   TYPE string,   " 下载对话框标题名
        lv_filepath   TYPE string,   " 文件路径
        lv_fullpath   TYPE string,   " 全文件路径
        lv_file       TYPE rlgrap-filename,
        lv_title      TYPE string,
        lv_window     TYPE string,
        lv_filefilter TYPE string,
        lv_xlsname    TYPE wwwdatatab-objid VALUE 'ZPPB004',  " 模板名称
        lv_key        TYPE wwwdatatab,
        lv_subrc      TYPE sy-subrc.
  DATA: lv_def_file_name TYPE string.  " 默认文件名

*&--- 默认值赋值
  lv_def_file_name = TEXT-103.          " BOM主数据批导模板.xls
  lv_filefilter = TEXT-104.          " EXCEL 文档|*.
  lv_window     = TEXT-105.          " 请选择路径
*&--- 文件保存对话框,获得保存路径
  CALL METHOD cl_gui_frontend_services=>file_save_dialog
    EXPORTING
      window_title      = lv_window        " 请选择路径
      default_file_name = lv_def_file_name " 默认文件名
      file_filter       = lv_filefilter    " 文件类型过滤(只显示本地文件夹)
    CHANGING
      filename          = lv_filename      " 保存的文件名
      path              = lv_filepath      " 文件路径
      fullpath          = lv_fullpath      " 全文件路径
      user_action       = lv_user_act
    EXCEPTIONS
      cntl_error        = 1
      error_no_gui      = 2
      OTHERS            = 3.
  IF sy-subrc <> 0.
    MESSAGE e011(zpp001).   " 文件保存失败
    RETURN.
  ENDIF.

*&--- 取消下载
  IF lv_user_act = '9'.
    MESSAGE s001(zpp001).   " 下载已取消
    RETURN.
  ENDIF.

  lv_file = lv_fullpath.
  lv_key-relid = 'MI'.
  lv_key-objid = lv_xlsname. " SMW0 中对象 ID
*&--- 从 SAP 资源库中下载文件
  CALL FUNCTION 'DOWNLOAD_WEB_OBJECT'
    EXPORTING
      key         = lv_key
      destination = lv_file
    IMPORTING
      rc          = lv_subrc.
  IF lv_subrc <> 0.
    MESSAGE s003(zpp001) DISPLAY LIKE 'E'. " 模板下载失败,请上传模板
    STOP.
  ELSEIF lv_subrc = 0.
    MESSAGE s012(zpp001). " 模板下载成功
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_UPLOAD_DATA
*&---------------------------------------------------------------------*
*& 上传数据
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_upload_data .
  DATA: lv_filename   LIKE rlgrap-filename, " 文件名
        lt_raw        TYPE truxs_t_text_data,
        lv_path       TYPE rlgrap-filename,     " 路径
        lt_line       TYPE c VALUE 1,
        lv_value(255) TYPE c.

  IF p_file IS INITIAL.
    MESSAGE s013(zpp001) DISPLAY LIKE 'E'. " 文件名不能为空
    LEAVE LIST-PROCESSING.
  ENDIF.

  lv_path = p_file . " 赋值路径
  REFRESH gt_xlstmp.
  " 读取 EXCEL 文件数据
  CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
    EXPORTING
      filename                = lv_path   " 路径
      i_begin_col             = 1
      i_begin_row             = 6        "  从第 4 行开始 读取
      i_end_col               = 20        " 结束列
      i_end_row               = 65536     " 结束行
    TABLES
      intern                  = gt_xlstmp " 存储读取的记录 行、列、值
    EXCEPTIONS
      inconsistent_parameters = 1
      upload_ole              = 2
      OTHERS                  = 3.
  IF sy-subrc <> 0 .
    MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno DISPLAY LIKE sy-msgty
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    STOP.
  ENDIF.
*&--- 将读取到的记录存储到 GT_DATA 内表中
  CLEAR gt_excel.
  SORT gt_xlstmp BY row col .
  " 循环赋值
  LOOP AT gt_xlstmp ASSIGNING .
    ASSIGN COMPONENT -col  OF STRUCTURE  TO  .
    lv_value = -value .
    CONDENSE lv_value.
    gt_excel-znumb = -row.
    CASE -col. " 判断当前列,并赋值到对应技术字段
      WHEN 2.
        gt_excel-matnr = lv_value.
      WHEN 3.
        gt_excel-matnr_o = lv_value.
      WHEN 4.
        gt_excel-fmaktx = lv_value.
      WHEN 5.
        gt_excel-werks = lv_value.
      WHEN 6.
        gt_excel-stlal = lv_value.
      WHEN 7.
        gt_excel-bmeng = lv_value.
      WHEN 8.
        gt_excel-posnr = lv_value.
      WHEN 9.
        gt_excel-postp = lv_value.
      WHEN 10.
        gt_excel-idnrk = lv_value.
      WHEN 11.
        gt_excel-idnrk_o = lv_value.
      WHEN 12.
        gt_excel-smaktx = lv_value.
      WHEN 13.
        gt_excel-menge = lv_value.
      WHEN 14.
        gt_excel-kzkup = lv_value.
      WHEN 15.
        gt_excel-ausch = lv_value.
      WHEN 16.
        gt_excel-lgort = lv_value.
      WHEN 17.
        gt_excel-stlbe = lv_value.
      WHEN 18.
        gt_excel-alpgr = lv_value.
      WHEN 19.
        gt_excel-ewahr = lv_value.

    ENDCASE.
    AT END OF row.
      APPEND gt_excel.
      CLEAR gt_excel.
    ENDAT.
  ENDLOOP.
  IF gt_excel[] IS INITIAL.
    MESSAGE s008(zpp001) DISPLAY LIKE 'E'. " 没有找到符合条件的数据
    STOP.
  ENDIF.

*&--- gt_excel 赋值给 gt_tab
  CLEAR: gt_tab.
  MOVE-CORRESPONDING gt_excel[] TO gt_tab.
  LOOP AT gt_tab ASSIGNING FIELD-SYMBOL().
    CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
      EXPORTING
        input        = -matnr
      IMPORTING
        output       = -matnr
      EXCEPTIONS
        length_error = 1
        OTHERS       = 2.
    CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
      EXPORTING
        input        = -idnrk
      IMPORTING
        output       = -idnrk
      EXCEPTIONS
        length_error = 1
        OTHERS       = 2.
    CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
      EXPORTING
        input  = -stlal
      IMPORTING
        output = -stlal.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_CALL_BAPI
*&---------------------------------------------------------------------*
*& 调用对应 BAPI 导入
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_call_bapi .
*&--- BAPI 参数声明
  DATA: lt_head  TYPE TABLE OF ty_tab,
        ls_head  TYPE ty_tab,
        lt_item  TYPE TABLE OF ty_tab,
        ls_item  TYPE ty_tab,
        lv_type,
        lv_msg   TYPE bapi_msg,
        lv_matnr TYPE marc-matnr,
        lv_stlal TYPE mast-stlal.

  DATA: lt_bomg  TYPE TABLE OF bapi1080_bgr_c,
        ls_bomg  TYPE bapi1080_bgr_c,
        lt_var   TYPE TABLE OF bapi1080_bom_c,
        ls_var   TYPE bapi1080_bom_c,
        lt_matr  TYPE TABLE OF bapi1080_mbm_c,
        ls_matr  TYPE bapi1080_mbm_c,
        lt_items TYPE TABLE OF bapi1080_itm_c,
        ls_items TYPE bapi1080_itm_c,
        lt_itas  TYPE TABLE OF bapi1080_rel_itm_bom_c,
        ls_itas  TYPE bapi1080_rel_itm_bom_c,
        lt_ret   TYPE TABLE OF bapiret2,
        ls_ret   TYPE bapiret2.

  DATA: lv_lines TYPE sposn. " 行项值

*&--- 判断有误数据提示修改
  LOOP AT gt_tab INTO gs_tab WHERE type NE 'S' AND check = abap_true .
    MESSAGE e014(zpp001). " 请修改有误数据
  ENDLOOP.

*&--- 有效数据赋值对应 抬头 & 行项
  LOOP AT gt_tab INTO gs_tab WHERE check = abap_true.
    APPEND gs_tab TO lt_head.
    APPEND gs_tab TO lt_item.
  ENDLOOP.

*&--- 抬头排序去重
  SORT lt_head BY matnr werks stlan stlal.
  DELETE ADJACENT DUPLICATES FROM lt_head COMPARING  matnr werks stlan stlal.

  LOOP AT lt_head INTO ls_head WHERE check = abap_true.
    CLEAR: lt_bomg  ,
           ls_bomg  ,
           lt_var   ,
           ls_var   ,
           lt_matr  ,
           ls_matr  ,
           lt_items ,
           ls_items ,
           lt_itas  ,
           ls_itas  ,
           lt_ret   ,
           ls_ret   ,
           lv_type  ,
           lv_msg   ,
           lv_matnr ,
           lv_stlal ,
           lv_lines .

*&--- 补前导零
    CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
      EXPORTING
        input  = ls_head-matnr
      IMPORTING
        output = lv_matnr.
*&--- 补前导零
    CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
      EXPORTING
        input  = ls_head-stlal
      IMPORTING
        output = lv_stlal.

*&--- 检验同 备选 BOM 是否已存在,如果存在,则删除(实现覆盖)
    SELECT mast~matnr,
           mast~werks,
           mast~stlan,
           mast~stlal
      INTO TABLE @DATA(lt_mast)
      FROM mast
      WHERE matnr = @lv_matnr
        AND werks = @ls_head-werks
        AND stlan = @ls_head-stlan
        AND stlal = @lv_stlal.

    IF lt_mast IS NOT INITIAL.
      " 存在,即删除 BOM
      CALL FUNCTION 'CSAP_MAT_BOM_DELETE'
        EXPORTING
          material           = ls_head-matnr
          plant              = ls_head-werks
          bom_usage          = ls_head-stlan
          alternative        = ls_head-stlal
          fl_no_change_doc   = 'X'
          fl_commit_and_wait = 'X'
        EXCEPTIONS
          error              = 1
          OTHERS             = 2.
      IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno DISPLAY LIKE sy-msgty
                  WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.

    ENDIF.

    CLEAR ls_bomg.
    ls_bomg-bom_group_identification = 'BAPI_SMP_COL1'.  " 标识物料单组
    ls_bomg-object_type              = 'BGR'.            " BOM 组中对象标识
    ls_bomg-object_id                = 'SIMPLE1'.        " BOM 组中对象标识
    ls_bomg-bom_usage                = ls_head-stlan.    " BOM 用途
    ls_bomg-ltxt_lang                = sy-langu.         " 语言
    ls_bomg-created_in_plant         = ls_head-werks.    " 工厂
    ls_bomg-auth_group               = ls_head-stlbe.    " 权限组

    APPEND ls_bomg TO lt_bomg.

    CLEAR ls_var.
    ls_var-bom_group_identification = 'BAPI_SMP_COL1'.
    ls_var-object_type              = 'BOM'.
    ls_var-object_id                = 'SIMPLE1'.
    ls_var-alternative_bom          = lv_stlal.          " 可选BOM
*    LS_var-bom_status               = '01'.             " BOM状态
    ls_var-base_qty                 = ls_head-bmeng.     " 数量

    ls_var-base_unit                = ls_head-bmein.    " 计量单位
    ls_var-valid_from_date          = sy-datum.     " 有效期起始日期
*    ls_var-change_no                = ls_head-aennr.     " ECN
    ls_var-function                 = 'NEW'.
*    ls_var-alt_text                 = ls_head-stktx.     " BOM 表头备注

    APPEND ls_var TO lt_var.

    CLEAR ls_matr.
    ls_matr-bom_group_identification = 'BAPI_SMP_COL1'.
    ls_matr-material                 = lv_matnr.       " 物料编码
    ls_matr-plant                    = ls_head-werks.  " 工厂
    ls_matr-bom_usage                = ls_head-stlan.  " BOM 用途
    ls_matr-alternative_bom          = lv_stlal.       " 可选 BOM
    APPEND ls_matr TO  lt_matr.

*&--- 循环行项转码&赋值
    LOOP AT lt_item INTO ls_item WHERE  matnr = ls_head-matnr AND
                                        werks = ls_head-werks AND
                                        stlan = ls_head-stlan AND
                                        stlal = ls_head-stlal .
      CLEAR ls_items.

      lv_lines += 10.
      ls_item-posnr = lv_lines.
      CALL FUNCTION 'CONVERSION_EXIT_NUMCV_INPUT'
        EXPORTING
          input  = ls_item-posnr
        IMPORTING
          output = ls_item-posnr.
      ls_items-bom_group_identification   = 'BAPI_SMP_COL1'.
      ls_items-object_type                = 'ITM'.
      ls_items-object_id                  = 'SIMPLE1'.
      ls_items-item_no                    = ls_item-posnr.      " 行号
      ls_items-item_cat                   = 'L'.                " 类别

      IF ls_item-postp IS NOT INITIAL.
        ls_items-item_cat                 = ls_item-postp.      " 类别
      ENDIF.

*&--- 转码
      CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
        EXPORTING
          input  = ls_item-idnrk
        IMPORTING
          output = ls_items-component.

      ls_items-component                  = ls_item-idnrk.      " 组件物料
      ls_items-comp_qty                   = ls_item-menge.      " 组件数量 (BTCI)

*&--- 行项目赋值
      ls_items-comp_unit                  = ls_item-meins.      " 组件计量单位
      ls_items-comp_scrap                 = ls_item-ausch .
      ls_items-ltxt_lang                  = sy-langu.
      ls_items-valid_from_date            = sy-datum.           " 有效起始日期
      ls_items-cost_rel                   = 'X'.                " 与成本相关
      ls_items-iss_st_loc                 = ls_item-lgort.      " 库存地点
      ls_items-co_product                 = ls_item-kzkup.       " 联产品
      ls_items-alt_item_group             = ls_item-alpgr.       " 替代组

      SELECT COUNT( * ) FROM marc WHERE matnr EQ @ls_item-idnrk AND werks EQ @ls_head-werks
        "AND disgr EQ 'ZP01'.
        AND sbdkz EQ '1' OR sbdkz IS INITIAL.
      IF sy-subrc EQ 0.
        ls_items-expl_type                  = 'D1'.       " 展开类型
      ENDIF.
      IF ls_item-alpgr IS NOT INITIAL.
        ls_items-alt_item_strategy          = '2'.       " 策略
      ENDIF.
      ls_items-usage_prob                 = ls_item-ewahr.       " 使用概率

      APPEND ls_items TO lt_items.

    ENDLOOP.
    CLEAR ls_itas.
    ls_itas-bom_group_identification = 'BAPI_SMP_COL1'.
    ls_itas-sub_object_type          = 'ITM'.
    ls_itas-sub_object_id            = 'SIMPLE1'.
    ls_itas-super_object_type        = 'BOM'.
    ls_itas-super_object_id          = 'SIMPLE1'.
    ls_itas-valid_from_date          = sy-datum.
    ls_itas-function = 'NEW'.
    APPEND ls_itas TO lt_itas.

*&--- 创建物料 BOM
    CALL FUNCTION 'BAPI_MATERIAL_BOM_GROUP_CREATE'
      EXPORTING
        all_error         = 'X'
      TABLES
        bomgroup          = lt_bomg
        variants          = lt_var
        items             = lt_items
        materialrelations = lt_matr
        itemassignments   = lt_itas
        return            = lt_ret.

    CLEAR lv_msg.
    READ TABLE lt_ret INTO ls_ret WITH KEY type = 'E'.
    IF sy-subrc = 0.
*&--- 回滚
      CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
      LOOP AT lt_ret INTO ls_ret .
        lv_msg = lv_msg && TEXT-112 && ls_ret-message.
      ENDLOOP.
      ls_head-type = 'E'.
      ls_head-message = lv_msg+1.
    ELSE.
*&--- 提交事务操作
      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
        EXPORTING
          wait = 'X'.
      READ TABLE lt_ret INTO ls_ret WITH KEY type = 'W'.

      IF ls_ret IS NOT INITIAL. " 提示警告信息
        ls_head-type = 'W'.
        LOOP AT lt_ret INTO ls_ret .
          lv_msg = lv_msg && TEXT-112 && ls_ret-message.
        ENDLOOP.
        ls_head-message = lv_msg+1.
      ELSE.
        ls_head-type = 'S'.
        ls_head-message = TEXT-121. " 创建成功
      ENDIF.
    ENDIF.
    MODIFY lt_head FROM ls_head.
  ENDLOOP.

*&--- 循环内表判断消息类型
  LOOP AT lt_head INTO ls_head.
    LOOP AT gt_tab INTO gs_tab WHERE matnr = ls_head-matnr AND
                                     werks = ls_head-werks AND
                                     stlan = ls_head-stlan AND
                                     stlal = ls_head-stlal AND
                                     check = abap_true.
      gs_tab-type = ls_head-type.
      gs_tab-message = ls_head-message.

*&--- 根据消息类型修改指示灯
      IF gs_tab-type = 'E'.
        gs_tab-icon = '@0A@'.        " 红灯
      ELSE.
        gs_tab-icon = '@08@'.        " 绿灯
      ENDIF.
      MODIFY gt_tab FROM gs_tab.
    ENDLOOP.
  ENDLOOP.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form frm_build_alv
*&---------------------------------------------------------------------*
*& ALV 展示导入数据
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_build_alv .
*&--- ALV 展示导入数据
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid                " 当前程序
      i_callback_pf_status_set = 'FRM_SET_PF_STATUS'
      i_callback_user_command  = 'FRM_USR_COMMAND'
      is_layout_lvc            = gs_layout               " 界面格式
      it_fieldcat_lvc          = gt_fieldcat             " 字段属性
    TABLES
      t_outtab                 = gt_tab
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno DISPLAY LIKE sy-msgty
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.

导入EXCEL模板:

SAP hana s/4 abap BOM批量修改添加程序_第1张图片

你可能感兴趣的:(ABAP,ERP,SAP,数据库,java,服务器,linux,intellij-idea,spring,boot,log4j)