BOM 复制功能

这个程序是根据条件把某些工厂的某些物料的某些BOM,Copy到别外的工厂,当目标工厂存在要复制的BOM的时候,用源BOM代替目标BOM,当目标BOM不存在的时候,就根据源BOM创建目标BOM。

这个程序用到了BOM的一些常用Function和BAPI
BAPI_MATERIAL_BOM_GROUP_CREATE
CSAP_MAT_BOM_READ
CSAP_MAT_BOM_OPEN
CSAP_BOM_ITEM_MAINTAIN
CSAP_MAT_BOM_CLOSE

REPORT  zppinf1001.

INCLUDE <icon>.

*----------------------------------------------------------------------*
*       变量定义
*----------------------------------------------------------------------*
TABLES mast.
TYPES: ty_tab_matnr TYPE mara-matnr OCCURS 0,
       ty_tab_plant TYPE marc-werks OCCURS 0,
       ty_tab_stpo2 TYPE stpo_api02 OCCURS 0,
       ty_tab_stko2 TYPE stko_api02 OCCURS 0,
       ty_tab_s_mat TYPE s_matnr OCCURS 0.
TYPES: BEGIN OF ty_mast,
        matnr TYPE mast-matnr,
        werks TYPE mast-werks,
        stlan TYPE mast-stlan,
        stlnr TYPE mast-stlnr,
        stlal TYPE mast-stlal,
       END OF ty_mast.
TYPES: BEGIN OF ty_material,
        matnr TYPE mara-matnr,
        werks TYPE marc-werks,
       END OF ty_material.
TYPES ty_tab_mast TYPE ty_mast OCCURS 0.
TYPES ty_tab_messages TYPE messages OCCURS 0.
TYPES ty_tab_material TYPE ty_material OCCURS 0.
DATA: g_valid_from TYPE csap_mbom-datuv.

*----------------------------------------------------------------------*
*       选择屏幕设计
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK blk WITH FRAME TITLE text-000.
SELECT-OPTIONS: s_matnr  FOR mast-matnr,
                s_stlan  FOR mast-stlan NO-EXTENSION NO INTERVALS OBLIGATORY,
                s_stlal  FOR mast-stlal NO-EXTENSION NO INTERVALS OBLIGATORY,
                s_source FOR mast-werks NO-EXTENSION NO INTERVALS OBLIGATORY.
SELECTION-SCREEN SKIP.
SELECT-OPTIONS: s_target FOR mast-werks,
                s_stlan2 FOR mast-stlan NO-EXTENSION NO INTERVALS OBLIGATORY,
                s_stlal2 FOR mast-stlal NO-EXTENSION NO INTERVALS OBLIGATORY.
PARAMETERS p_exist TYPE c AS CHECKBOX.
SELECTION-SCREEN END OF BLOCK blk.

*----------------------------------------------------------------------*
*       CLASS lcl_bom DEFINITION
*----------------------------------------------------------------------*
*       BOM的处理类定义
*----------------------------------------------------------------------*
CLASS lcl_bom DEFINITION FINAL.
  PUBLIC SECTION.
    METHODS write_header_text  "输出结果列表的选择条件的相关信息
      IMPORTING
        pt_plant TYPE ty_tab_plant.
    METHODS check_exist_bom     "检验指定条件的物料是否存在BOM
      IMPORTING
        p_material    TYPE csap_mbom-matnr  "料号
        p_plant       TYPE csap_mbom-werks  "工厂
        p_bom_usage   TYPE csap_mbom-stlan  "BOM Usage
        p_alternative TYPE csap_mbom-stlal  "Alternative BOM
        pt_target     TYPE ty_tab_mast
      RETURNING
        value(p_flag) TYPE char01.        "检查结果返回标识,X代表存在
    METHODS get_data                      "根据条件查询数据
      EXPORTING
        value(pt_source) TYPE ty_tab_mast
        value(pt_target) TYPE ty_tab_mast.
    METHODS get_target_plant
      RETURNING
        value(pt_plant) TYPE ty_tab_plant.
    METHODS check_matnr                    "检查指定的物料是否在指定的工厂存在
      IMPORTING
        p_matnr       TYPE mast-matnr
        p_plant       TYPE mast-werks
      RETURNING
        value(p_flag) TYPE char01.
    METHODS check_component                "检查指定的组件是否在指定的工厂存在
      IMPORTING
        p_matnr       TYPE mast-matnr
        p_plant       TYPE mast-werks
        pt_stpo       TYPE ty_tab_stpo2
      RETURNING
        value(p_flag) TYPE char01.
    METHODS set_log.                        "设置Log,可以事务码SLG1查看
    METHODS get_current_log                 "取得当前Log信息
      RETURNING
        value(pt_messages) TYPE ty_tab_messages.
    METHODS read_bom                        "查看BOM信息
      IMPORTING
        p_material     TYPE csap_mbom-matnr
        p_plant        TYPE csap_mbom-werks
        p_bom_usage    TYPE csap_mbom-stlan
        p_alternative  TYPE csap_mbom-stlal
        p_valid_from   TYPE csap_mbom-datuv
      EXPORTING
        value(pt_stpo) TYPE ty_tab_stpo2
        value(pt_stko) TYPE ty_tab_stko2
        value(p_flag)  TYPE char01.
    METHODS create_bom                      "创建BOM
        IMPORTING
          p_material    TYPE csap_mbom-matnr
          p_plant       TYPE csap_mbom-werks
          pt_stpo       TYPE ty_tab_stpo2
          pt_stko       TYPE ty_tab_stko2
        RETURNING
          value(p_flag) TYPE char01.
    METHODS maintain_bom                      "维护BOM
        IMPORTING
          p_material    TYPE csap_mbom-matnr
          p_plant       TYPE csap_mbom-werks
          p_usage       TYPE csap_mbom-stlan
          p_alternative TYPE csap_mbom-stlal
          p_valid       TYPE csap_mbom-datuv
          pt_stpo       TYPE ty_tab_stpo2
          pt_stko       TYPE ty_tab_stko2
        RETURNING
          value(p_flag) TYPE char01.
    METHODS constructor.                      "构造方法
    "类的全局变量
    DATA: BEGIN OF lwa_mat_wer,
            matnr TYPE mara-matnr,
            werks TYPE marc-werks,
          END OF lwa_mat_wer.
    DATA: lt_mat_wer2  LIKE TABLE OF lwa_mat_wer.
  PRIVATE SECTION.
    DATA: lt_mat_wer  LIKE TABLE OF lwa_mat_wer.
ENDCLASS.                    "lcl_bom DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_bom IMPLEMENTATION
*----------------------------------------------------------------------*
*       BOM的处理类实现
*----------------------------------------------------------------------*
CLASS lcl_bom IMPLEMENTATION.
*输出结果列表的选择条件的相关信息
  METHOD write_header_text.
    DATA: l_temp TYPE i VALUE 1,
          l_plant TYPE marc-werks.
    FORMAT COLOR 1 ON.
    IF s_matnr IS INITIAL.
      WRITE: 'BOM Material: All'.
    ELSEIF s_matnr-low IS NOT INITIAL AND s_matnr-high IS NOT INITIAL.
      WRITE: / 'BOM Material:',s_matnr-low,'To',s_matnr-high.
    ELSEIF s_matnr-high IS INITIAL.
      WRITE: / 'BOM Material:',s_matnr-low.
    ENDIF.
    WRITE: / 'Source Plant:',s_source-low.
    WRITE: / 'BOM Usage:',s_stlan-low.
    WRITE: / 'Alternative BOM:',s_stlal-low.
    SKIP.
    WRITE / 'Target Plant:'.
    LOOP AT pt_plant INTO l_plant.
      IF l_temp > 15.
        WRITE /16 l_plant.
        l_temp = 2.
        CONTINUE.
      ENDIF.
      WRITE l_plant.
      l_temp = l_temp + 1.
    ENDLOOP.
    WRITE: / 'BOM Usage:',s_stlan2-low.
    WRITE: / 'Alternative BOM:',s_stlal2-low.
    IF p_exist = 'X'.
      WRITE / 'Skip if target plant exist'.
    ENDIF.
    FORMAT COLOR OFF.
    ULINE.
  ENDMETHOD.                    "wwrite_header_text

*检验指定条件的物料是否存在BOM
  METHOD check_exist_bom.
    DATA l_alternative LIKE p_alternative.

    READ TABLE pt_target WITH KEY matnr = p_material
                                  werks = p_plant
                                  stlan = p_bom_usage
                                  stlal = p_alternative
                         TRANSPORTING NO FIELDS.
    IF sy-subrc = 0.
      p_flag = 'X'.
    ENDIF.
  ENDMETHOD.                    "check_exist_bom

*根据条件取得所有要复制到其他工厂的BOM的物料
  METHOD get_data.
    "取得表MAST的数据
    SELECT DISTINCT matnr
                    werks
                    stlan
                    stlnr
                    stlal
    INTO TABLE pt_source FROM mast
    WHERE matnr IN s_matnr.

    pt_target = pt_source.

    DELETE pt_source WHERE NOT ( werks IN s_source AND stlan IN s_stlan AND stlal IN s_stlal ).
    DELETE pt_target WHERE NOT ( werks IN s_target AND stlan IN s_stlan2 AND stlal IN s_stlal2 ).
  ENDMETHOD.                    "get_data

*根据条件取得目标工厂
  METHOD get_target_plant.
    SELECT werks INTO TABLE pt_plant FROM t001w
                 WHERE werks IN s_target.
  ENDMETHOD.                    "get_target_plant

*判断指定的料号在指定的工厂是否存在
  METHOD check_matnr.
    "根据条件取得物料和工厂的内表
    IF lt_mat_wer IS INITIAL.
      SELECT mara~matnr
             marc~werks
      INTO TABLE lt_mat_wer
      FROM mara
      INNER JOIN marc ON mara~matnr = marc~matnr
      WHERE mara~matnr IN s_matnr
        AND marc~werks IN s_target.
    ENDIF.

    "查询内表,判断指定料号是否在指定的工厂里
    READ TABLE lt_mat_wer WITH KEY matnr = p_matnr
                                   werks = p_plant
                          TRANSPORTING NO FIELDS.
    "存在
    IF sy-subrc = 0.
      p_flag = 'X'.
    ENDIF.
  ENDMETHOD.                    "check_matnr

*检查指定的组件是否在指定的工厂存在
  METHOD check_component.
    DATA: l_matnr TYPE mara-matnr,
          lt_matnr LIKE RANGE OF l_matnr,
          lwa_matnr LIKE LINE OF lt_matnr,
          lwa_stpo LIKE LINE OF pt_stpo.
    "组织选择内表
    LOOP AT pt_stpo INTO lwa_stpo.
      lwa_matnr-sign   = 'I'.
      lwa_matnr-option = 'EQ'.
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input  = lwa_stpo-component
        IMPORTING
          output = lwa_stpo-component.
      lwa_matnr-low    = lwa_stpo-component.
      lwa_matnr-high   = ''.
      APPEND lwa_matnr TO lt_matnr.
    ENDLOOP.
    "根据条件取得物料和工厂的内表
    IF lt_mat_wer2 IS INITIAL.
      SELECT mara~matnr
             marc~werks
      INTO TABLE lt_mat_wer2
      FROM mara
      INNER JOIN marc ON mara~matnr = marc~matnr
      WHERE mara~matnr IN lt_matnr
        AND marc~werks = p_plant.
    ENDIF.

    "查询内表,判断指定料号是否在指定的工厂里
    READ TABLE lt_mat_wer2 WITH KEY matnr = p_matnr
                           TRANSPORTING NO FIELDS.
    "存在
    IF sy-subrc = 0.
      p_flag = 'X'.
    ENDIF.
  ENDMETHOD.                    "check_component

*设置Log,可以用事务码SLG1查看
  METHOD set_log.
    CALL FUNCTION 'CALO_INIT_API'
      EXCEPTIONS
        log_object_not_found     = 1
        log_sub_object_not_found = 2
        other_error              = 3
        OTHERS                   = 4.
  ENDMETHOD.                    "set_log

*取得当前Log信息
  METHOD get_current_log.
    CALL FUNCTION 'CALO_LOG_READ_MESSAGES'
      TABLES
        messages_and_parameters = pt_messages
      EXCEPTIONS
        warning                 = 1
        error                   = 2
        OTHERS                  = 3.
  ENDMETHOD.                    "get_current_log

*读取指定的BOM
  METHOD read_bom.
    "调用FM查看指定的物料的BOM
    CALL FUNCTION 'CSAP_MAT_BOM_READ'
      EXPORTING
        material    = p_material
        plant       = p_plant
        bom_usage   = p_bom_usage
        alternative = p_alternative
        valid_from  = p_valid_from
      TABLES
        t_stpo      = pt_stpo
        t_stko      = pt_stko
      EXCEPTIONS
        error       = 1.
    "判断是否查看bom数据成功
    IF sy-subrc = 0.
      p_flag = 'X'.
    ELSE.
      p_flag = ''.
    ENDIF.
  ENDMETHOD.                    "read_bom

*创建BOM
  METHOD create_bom.
    DATA: lwa_bomgroup TYPE bapi1080_bgr_c,
          lt_bomgroup  LIKE TABLE OF lwa_bomgroup,
          lwa_variant  TYPE bapi1080_bom_c,
          lt_variant   LIKE TABLE OF lwa_variant,
          lwa_items    TYPE bapi1080_itm_c,
          lt_items     LIKE TABLE OF lwa_items,
          lwa_mbm      TYPE bapi1080_mbm_c,
          lt_mbm       LIKE TABLE OF lwa_mbm,
          lwa_itemass  TYPE bapi1080_rel_itm_bom_c,
          lt_itemass   LIKE TABLE OF lwa_itemass,
          lwa_return   TYPE bapiret2,
          lt_return    LIKE TABLE OF lwa_return.
    DATA: l_alternative TYPE stpo_api02-bom_alt,
          l_component   TYPE stpo_api02-component,
          l_error       TYPE string.
    CONSTANTS: bom_group_identification TYPE bapi1080_bgr_c-bom_group_identification
                                        VALUE 'BAPI_SMP_COL4',
               object_id TYPE bapi1080_bgr_c-object_id VALUE 'SIMPLE1'.
    FIELD-SYMBOLS: <fs_stko> LIKE LINE OF pt_stko,
                   <fs_stpo> LIKE LINE OF pt_stpo.

    "循环内表pt_stpo
    LOOP AT pt_stpo ASSIGNING <fs_stpo>.
      "在Component前面添零
      CLEAR l_component.
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input  = <fs_stpo>-component
        IMPORTING
          output = l_component.

      "添加BOM Items
      CLEAR lwa_items.
      lwa_items-bom_group_identification = bom_group_identification.
      lwa_items-object_type = 'ITM'.
      lwa_items-object_id = object_id.
      lwa_items-item_no = <fs_stpo>-item_no.
      lwa_items-item_cat = <fs_stpo>-item_categ.
      lwa_items-component = l_component.
      lwa_items-comp_qty = <fs_stpo>-comp_qty.
      lwa_items-comp_unit = <fs_stpo>-comp_unit.
      lwa_items-valid_from_date = sy-datum.
      APPEND lwa_items TO lt_items.
    ENDLOOP.

    "循环内表
    LOOP AT pt_stko ASSIGNING <fs_stko>.
      "添加BOM Group信息
      CLEAR lwa_bomgroup.
      lwa_bomgroup-bom_group_identification = bom_group_identification.
      lwa_bomgroup-object_type = 'BGR'.
      lwa_bomgroup-object_id = object_id.
      lwa_bomgroup-bom_usage = s_stlan2-low.
      lwa_bomgroup-bom_group = <fs_stko>-bom_group.
      lwa_bomgroup-created_in_plant = p_plant.
      lwa_bomgroup-auth_group = <fs_stko>-auth_group.
      lwa_bomgroup-technical_type = ' '.
      lwa_bomgroup-ltxt_lang = sy-langu.
      lwa_bomgroup-bom_text = <fs_stko>-bom_text.
      APPEND lwa_bomgroup TO lt_bomgroup.

      "添加Variant信息
      CLEAR lwa_variant.
      lwa_variant-bom_group_identification = bom_group_identification.
      lwa_variant-object_type = 'BOM'.
      lwa_variant-object_id = object_id.
      lwa_variant-alternative_bom = s_stlal2-low.
      lwa_variant-bom_status = <fs_stko>-bom_status.
      lwa_variant-deletion_ind = <fs_stko>-delete_ind.
      lwa_variant-base_qty = <fs_stko>-base_quan.
      lwa_variant-base_unit = <fs_stko>-base_unit.
      lwa_variant-lab_design = <fs_stko>-laboratory.
      lwa_variant-ltxt_lang = sy-langu.
      lwa_variant-alt_text = <fs_stko>-alt_text.
      lwa_variant-valid_from_date = sy-datum.
      lwa_variant-change_no = <fs_stko>-chg_no.
      lwa_variant-function = 'NEW'.
      APPEND lwa_variant TO lt_variant.
    ENDLOOP.

    CLEAR lwa_mbm.
    lwa_mbm-bom_group_identification = bom_group_identification.
    lwa_mbm-material = p_material.
    lwa_mbm-bom_usage = s_stlan2-low.
    lwa_mbm-plant = p_plant.
    lwa_mbm-alternative_bom = s_stlal2-low.
    APPEND lwa_mbm TO lt_mbm.

    CLEAR lwa_itemass.
    lwa_itemass-bom_group_identification = bom_group_identification.
    lwa_itemass-sub_object_type = 'ITM'.
    lwa_itemass-sub_object_id = object_id.
    lwa_itemass-super_object_type = 'BOM'.
    lwa_itemass-super_object_id = object_id.
    lwa_itemass-valid_from_date = sy-datum.
    lwa_itemass-function = 'NEW'.
    APPEND lwa_itemass TO lt_itemass.

    "调用BAPI创建BOM
    CALL FUNCTION 'BAPI_MATERIAL_BOM_GROUP_CREATE'
      EXPORTING
        all_error         = 'X'
      TABLES
        bomgroup          = lt_bomgroup
        variants          = lt_variant
        items             = lt_items
        materialrelations = lt_mbm
        itemassignments   = lt_itemass
        return            = lt_return.

    p_flag = 'X'.
    LOOP AT lt_return INTO lwa_return WHERE type = 'A' OR type = 'E'.
      p_flag = ''.
      l_error = lwa_return-message.
      EXPORT p1 = l_error TO MEMORY ID 'CREATE'.
      EXIT.
    ENDLOOP.

    IF p_flag = 'X'.
      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
    ELSE.
      CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
    ENDIF.

    FREE: lt_bomgroup,
          lt_variant,
          lt_items,
          lt_mbm,
          lt_itemass,
          lt_return.
  ENDMETHOD.                    "create_bom

*维护BOM
  METHOD maintain_bom.
    DATA: lwa_stpo      LIKE LINE OF pt_stpo,
          l_material    LIKE p_material,
          lt_stpo2      TYPE ty_tab_stpo2,
          lt_stpo2_temp TYPE ty_tab_stpo2,
          lt_messages   TYPE ty_tab_messages,
          lwa_messages  LIKE LINE OF lt_messages,
          l_error       TYPE string.
    FIELD-SYMBOLS <fs_stpo> LIKE LINE OF pt_stpo.
    "补0
    CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
      EXPORTING
        input  = p_material
      IMPORTING
        output = l_material.

    p_flag = 'X'.

    "Log
    CALL METHOD me->set_log.
    "打开BOM维护
    CALL FUNCTION 'CSAP_MAT_BOM_OPEN'
      EXPORTING
        material    = l_material
        plant       = p_plant
        bom_usage   = p_usage
        alternative = p_alternative
        valid_from  = p_valid
      TABLES
        t_stpo      = lt_stpo2
      EXCEPTIONS
        error       = 1.

    IF sy-subrc = 0.
      "先把所有目标工厂的BOM数据打上删除标记
      lwa_stpo-fldelete = 'X'.
      MODIFY lt_stpo2 FROM lwa_stpo TRANSPORTING fldelete WHERE fldelete <> 'X'.

      LOOP AT pt_stpo INTO lwa_stpo.
        READ TABLE lt_stpo2 ASSIGNING <fs_stpo> WITH KEY component = lwa_stpo-component.
        IF sy-subrc = 0.
          "找到则是需要修改的
          lwa_stpo-itm_ident  = <fs_stpo>-itm_ident.
          lwa_stpo-bom_no     = <fs_stpo>-bom_no.
          lwa_stpo-item_node  = <fs_stpo>-item_node.
          lwa_stpo-item_count = <fs_stpo>-item_count.
          lwa_stpo-valid_from = p_valid.
          APPEND lwa_stpo TO lt_stpo2_temp.
          "删除lt_stpo3里修改的记录,剩下的就是删除的
          DELETE lt_stpo2 WHERE itm_ident = <fs_stpo>-itm_ident.
        ELSE.
          "找不到的则是新增的
          lwa_stpo-itm_ident = ''.
          lwa_stpo-bom_no = ''.
          lwa_stpo-item_node = ''.
          lwa_stpo-item_count = ''.
          lwa_stpo-valid_from = p_valid.
          APPEND lwa_stpo TO lt_stpo2_temp.
        ENDIF.
      ENDLOOP.
      "把lt_stpo2剩下的,即是删除的添加内表lt_stpo2_temp
      APPEND LINES OF lt_stpo2 TO lt_stpo2_temp.
    ELSE.
      p_flag = ''.
      lt_messages = me->get_current_log( ).
      LOOP AT lt_messages INTO lwa_messages WHERE msg_type = 'E'
                                            OR msg_type = 'A'.
        l_error = lwa_messages-msg_txt.
        EXPORT p1 = l_error TO MEMORY ID 'MAINTAIN'.
        EXIT.
      ENDLOOP.
      EXIT.
    ENDIF.

    "循环处理BOM Item
    LOOP AT lt_stpo2_temp INTO lwa_stpo.
      "补零
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input  = lwa_stpo-component
        IMPORTING
          output = lwa_stpo-component.
      CALL FUNCTION 'CSAP_BOM_ITEM_MAINTAIN'
        EXPORTING
          i_stpo = lwa_stpo
        EXCEPTIONS
          error  = 1.
      IF sy-subrc <> 0.
        p_flag = ''.
        lt_messages = me->get_current_log( ).
        LOOP AT lt_messages INTO lwa_messages WHERE msg_type = 'E'
                                              OR msg_type = 'A'.
          EXPORT p1 = lwa_messages-msg_txt TO MEMORY ID 'MAINTAIN'.
          EXIT.
        ENDLOOP.
        EXIT.
      ENDIF.
    ENDLOOP.
    "关闭BOM维护
    CALL FUNCTION 'CSAP_MAT_BOM_CLOSE'
      EXCEPTIONS
        error = 1.
    IF sy-subrc <> 0.
      p_flag = ''.
      EXIT.
    ENDIF.

    FREE: lt_stpo2,
          lt_stpo2_temp.
  ENDMETHOD.                    "maintain_bom

*构造方法
  METHOD constructor.
    "格式化有限日期
    CONCATENATE sy-datum+6(2)
                sy-datum+4(2)
                sy-datum+0(4)
    INTO g_valid_from SEPARATED BY '.'.
  ENDMETHOD.                    "contructor

ENDCLASS.                    "lcl_bom IMPLEMENTATION

*&---------------------------------------------------------------------*
*&      Form  f_set_clock
*&---------------------------------------------------------------------*
*       程序处理时状态栏显示的小时钟
*----------------------------------------------------------------------*
*      -->P_PERCENTAGE  时钟显示的百分比
*----------------------------------------------------------------------*
FORM f_set_clock USING p_percentage.
  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      percentage = p_percentage.
ENDFORM.                    "f_set_clock

*&---------------------------------------------------------------------*
*&      Form  f_main
*&---------------------------------------------------------------------*
*       子程序。整合所有方法,执行并输出结果
*----------------------------------------------------------------------*
FORM f_main.
  DATA: lt_source TYPE ty_tab_mast,
        lwa_source LIKE LINE OF lt_source,
        lt_target  TYPE ty_tab_mast,
        lwa_target LIKE LINE OF lt_target,
        lt_plant   TYPE ty_tab_plant,
        lt_stpo2   TYPE ty_tab_stpo2,
        lwa_stpo2  LIKE LINE OF lt_stpo2,
        lt_stko2   TYPE ty_tab_stko2.
  DATA: l_flag,
        l_error  TYPE string,
        l_count  TYPE string,
        l_count1 TYPE i,    "成功的记录数
        l_count2 TYPE i,    "失败的记录数
        l_werks  LIKE LINE OF lt_plant.
  DATA: lr_bom   TYPE REF TO lcl_bom.

*创建类LCL_BOM对象
  CREATE OBJECT lr_bom.

*筛选选择的物料
  CALL METHOD lr_bom->get_data
    IMPORTING
      pt_source = lt_source
      pt_target = lt_target.

  PERFORM f_set_clock USING 10.

*取得目标工厂内表
  lt_plant = lr_bom->get_target_plant( ).

  IF lt_source IS INITIAL
    OR lt_plant IS INITIAL.
    MESSAGE s003(zmm).
    EXIT.
  ENDIF.
  PERFORM f_set_clock USING 50.
*输出选择条件文本
  lr_bom->write_header_text( lt_plant ).

  SORT lt_source BY werks.

  "按工厂处理BOM
  LOOP AT lt_plant INTO l_werks.
    CLEAR: l_count1,l_count2.
    "如果源BOM和目标BOM相同,跳过
    IF s_source-low = l_werks
      AND s_stlan-low = s_stlan2-low
      AND s_stlal-low = s_stlal2-low.
      CONTINUE.
    ENDIF.
    WRITE:/ 'Start plant',l_werks.
    "循环源物料内表,处理指定工厂的物料
    LOOP AT lt_source INTO lwa_source.
      "查看BOM数据
      CALL METHOD lr_bom->read_bom
        EXPORTING
          p_material    = lwa_source-matnr
          p_plant       = s_source-low
          p_bom_usage   = s_stlan-low
          p_alternative = s_stlal-low
          p_valid_from  = g_valid_from
        IMPORTING
          pt_stpo       = lt_stpo2
          pt_stko       = lt_stko2
          p_flag        = l_flag.
      "查得数据成功
      IF sy-subrc = 0 AND l_flag = 'X'.
        "如果BOM的Item为空
        IF lt_stpo2 IS INITIAL.
          FORMAT COLOR 6 ON.
          WRITE: /3 icon_cancel AS ICON,
                    'Material',
                    lwa_source-matnr+10(8),
                    'BOM Usage',
                    s_stlan-low,
                    'not found in source plant',
                    s_source-low.
          FORMAT COLOR 6 OFF.
          l_count2 = l_count2 + 1.
          CONTINUE.
        ENDIF.

        "判断当前物料是否在目标工厂中存在
        l_flag = lr_bom->check_matnr(
          p_matnr = lwa_source-matnr
          p_plant = l_werks
        ).
        "物料不在目标工厂就跳过
        IF l_flag <> 'X'.
          WRITE: /3 icon_skip AS ICON,
                    'Material',
                    lwa_source-matnr+10(8),
                    'not found in target plant',
                    l_werks.
          l_count2 = l_count2 + 1.
          CONTINUE.
        ENDIF.

        " 判断组件是否在目标工厂中存在
        CLEAR lr_bom->lt_mat_wer2.
        LOOP AT lt_stpo2 INTO lwa_stpo2.
          "补零
          CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
            EXPORTING
              input  = lwa_stpo2-component
            IMPORTING
              output = lwa_stpo2-component.
          l_flag = lr_bom->check_component(
            p_matnr = lwa_stpo2-component
            p_plant = l_werks
            pt_stpo = lt_stpo2
          ).
          IF l_flag <> 'X'.
            WRITE: /3 icon_skip AS ICON,
                      'Component',
                      lwa_stpo2-component+10(8),
                      'not found in target plant',
                      l_werks.
            l_count2 = l_count2 + 1.
            EXIT.
          ENDIF.
        ENDLOOP.
        "如果组件在目标工厂不存在,跳过
        CHECK l_flag = 'X'.

        "判断目标BOM是否存在
        l_flag = lr_bom->check_exist_bom(
          p_material    = lwa_source-matnr
          p_plant       = l_werks
          p_bom_usage   = s_stlan2-low
          p_alternative = s_stlal2-low
          pt_target     = lt_target
        ).
        "目标BOM存在
        IF l_flag = 'X'.
          "存在是否跳过
          IF p_exist <> 'X'.
            "维护BOM
            l_flag = lr_bom->maintain_bom(
                p_material = lwa_source-matnr
                p_plant = l_werks
                p_usage = s_stlan2-low
                p_alternative = s_stlal2-low
                p_valid = g_valid_from
                pt_stpo = lt_stpo2
                pt_stko = lt_stko2
             ).
            IF l_flag = 'X'.
*              WRITE: /3 icon_okay AS ICON,
*                        'Material',
*                        lwa_source-matnr+10(8),
*                        'copy success to plant',
*                        l_werks.
              l_count1 = l_count1 + 1.
            ELSE.
              "从内存取得错误文本
              IMPORT p1 = l_error FROM MEMORY ID 'MAINTAIN'.
              IF sy-subrc = 0.
                FORMAT COLOR 6 ON.
                WRITE: /3 icon_cancel AS ICON,l_error.
                FORMAT COLOR 6 OFF.
                FREE MEMORY ID 'MAINTIAN'.
                l_count2 = l_count2 + 1.
                CONTINUE.
              ENDIF.
            ENDIF.
          ELSE.
            WRITE: /3 icon_skip AS ICON,
                      'Material',
                      lwa_source-matnr+10(8),
                      'BOM exists and skip copy to plant',
                      l_werks.
            l_count2 = l_count2 + 1.
          ENDIF.
        ELSE.
          "BOM不存在,创建BOM
          l_flag = lr_bom->create_bom(
              p_material = lwa_source-matnr
              p_plant = l_werks
              pt_stpo = lt_stpo2
              pt_stko = lt_stko2
          ).
          IF l_flag = 'X'.
*            "输出成功创建BOM的信息
*            WRITE: /3 icon_okay AS ICON,
*                      'Material',
*                      lwa_source-matnr+10(8),
*                      'copy success to plant',
*                      l_werks.
            l_count1 = l_count1 + 1.
          ELSE.
            IMPORT p1 = l_error FROM MEMORY ID 'CREATE'.
            IF sy-subrc = 0.
              FORMAT COLOR 6 ON.
              WRITE: /3 icon_cancel AS ICON,
                        l_error.
              FREE MEMORY ID 'CREATE'.
              l_count2 = l_count2 + 1.
            ENDIF.

            FORMAT COLOR 6 OFF.
            CONTINUE.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.
    l_count = l_count1.
    WRITE:/ l_count,'material copied success'.
    l_count = l_count2.
    WRITE:/ l_count,'material copied fail'.
    SKIP.
  ENDLOOP.
  WRITE / '-- End of Report --'.

  FREE: lt_source,
        lt_target,
        lt_plant,
        lt_stpo2,
        lt_stko2.
ENDFORM.                    "f_main

*----------------------------------------------------------------------*
*       执行事件
*----------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM f_main.

原文地址:https://www.cnblogs.com/eric0701/p/3566575.html