SAP_ABAP模块-批量导入货源清单

一、业务背景

        有个朋友做ECC 6.0的项目,期初上线时,有一个需求是批量导入货源清单,我问了好几个朋友,加上自己以前的积累,硬是没有找到一个完全能用的程序,下面我来说一下我遇到的问题;

        对货源清单不熟悉的小伙伴,可以先看一下我之前写过的一篇文章;

SAP_MM模块-货源清单_sap 货源清单-CSDN博客文章浏览阅读2.3k次,点赞27次,收藏33次。本文详细介绍了SAP系统中的货源清单定义、维护方式,包括手工创建、通过框架协议和信息记录创建,以及自动产生货源的过程。还重点讲解了货源清单的启用方式、优先级确定和在采购申请中的应用,以及与配额协议、框架协议的关系。https://blog.csdn.net/qq_40141758/article/details/136895836

二、遇到的问题;

(一)没有直接能用的程序;

        无论是自己手头上的,还是问朋友拿到的,很多都只有S4版本的程序,要知道,S4版本的代码,很多都是用了新语法的,根本就无法直接在ECC版本上使用,要改起来也感觉比较麻烦;

(二)LSMW录屏无法满足效果;

自己用LSMW录屏,存在以下几个问题;

(1)标准的录屏,发现没法区分表头和行项目,导致披导时,同一个物料 + 工厂,只能录入一条数据,这里比较简单,只截一个主要的图,如果对LSMW不熟悉的,可以网上随便搜一下资料看看,这里由于LSMW录入无法达到预期效果,就不重点讲了,找不到资料想了解LSMW的,可以私聊交流。

如上图所示,不同物料 +工厂(不同的表头数据),可以正常录入一条数据,但是不能录入多条,同一个物料 +工厂,维护多条供应商数据时,会被覆盖。

(2)自己手动区分表头和行项目(但是实际发现不可行,不知道如何匹配上,有知道的小朋友欢迎评论或者私信指导一下,不甚感激),下面记录一下我当时的想法:

A、录屏时,如果录入多行数据,由于当时想的是,录入的数据有可能是3行、4行等不固定的行数,所以下面02的部分数据就不要了,只保留01行的。

B、维护源结构:通过手动新增表头和行项目(类别用标准的BOM导入结构,H代表表头,I代表行项目,导入EXCEL时原本想着可以用同样的方法导进去系统)

C、维护源字段,把表头需要的字段和行项目需要的字段分别维护好

D、然而,在维护结构关系时,发现没有办法把源结构和源字段匹配上!!!

如下图所示,只能分配表头,无法分配行项目~~

我们来看一下,LSMW批量导入BOM时,这个地方是如下图所示的,但是这个用的是系统标准的Object-0030 BOM。

目前没有进一步研究,不清楚标准功能,是否可以录屏实现像BOM这种多层结构的数据录入,也就导致这个LSMW录屏的方式,目前无法正常达到我们的目的,有知道的小伙伴可以分享一下,感谢感谢~~

(三)拿到的数据无法直接用:

最终从一个朋友手中,拿到一个ECC版本的披导程序,但是测试发现,也是只能录入一条数据!!

1、源程序;

        看一下朋友发过来的程序中,以下BDC录屏部分的代码就知道,只能维护一条数据~~

2、优化后的代码;

        最终,经过一边让别的ABAP开发朋友指导,一边改,终于是改完了,以下附上完整的代码记录以及使用方法;

*&---------------------------------------------------------------------*
*& Program ID/Name: Z_TEST_ZGY    Date written: 2024-08-18
*& Author's name:   风沙        Last update:
*& Program title:   货源清单创建
*& Project Name:
*& Version: 1.0
*---------------------------------------------------------------------*
* Description: (Incl. Related Function Area and System)
*
*---------------------------------------------------------------------*
* Include:
*
*---------------------------------------------------------------------*
* Calls: (RFC and BPI)
*
*---------------------------------------------------------------------*
* Function Modules:
*
*---------------------------------------------------------------------*
* Table:
*
*---------------------------------------------------------------------*
* Change History
*---------------------------------------------------------------------*

***********************************************************************

REPORT Z_TEST_ZGY MESSAGE-ID zdev NO STANDARD PAGE HEADING.

INCLUDE <icon>.

*--------------------------------------------------------------------*
* Data Declaration
*--------------------------------------------------------------------*
DATA: BEGIN OF ig_file OCCURS 0,
      matnr LIKE eord-matnr,"物料号
      werks LIKE eord-werks,"工厂
      vdatu(8),"有效从
      bdatu(8),"有效至
      lifnr LIKE eord-lifnr,"供应商
      ekorg LIKE eord-ekorg,"采购组织
      reswk LIKE eord-reswk,"供货工厂
      meins LIKE eord-meins,"单位
      feskz LIKE rm06w-feskz,"固定货源
      notkz LIKE eord-notkz,"冻结
      autet LIKE eord-autet,"MRP
      END OF ig_file.


DATA: BEGIN OF ig_out OCCURS 0,
      matnr LIKE eord-matnr,
      werks LIKE eord-werks,
      lifnr LIKE eord-lifnr,
      icn(4) TYPE c,
      msg TYPE string,
      END OF ig_out.

DATA: ig_bdcdata LIKE bdcdata OCCURS 0 WITH HEADER LINE .
DATA: ig_bdcmsg LIKE bdcmsgcoll OCCURS 0 WITH HEADER LINE.

TYPE-POOLS: slis.
DATA: fieldcat TYPE slis_t_fieldcat_alv WITH HEADER LINE.
DEFINE add2fc.
  fieldcat-fieldname = &1.
  fieldcat-seltext_l = &2.
  fieldcat-just = &3.
  fieldcat-icon = &4.
  append fieldcat.
  clear fieldcat.
END-OF-DEFINITION.

DATA: layout TYPE slis_layout_alv .
DATA: trans_mode TYPE c.

*--------------------------------------------------------------------*
* Selection Screen
*--------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: p_path LIKE rlgrap-filename OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-002.
PARAMETERS: p_n TYPE c DEFAULT 'X' RADIOBUTTON GROUP bdc,
            p_e TYPE c RADIOBUTTON GROUP bdc,
            p_a TYPE c RADIOBUTTON GROUP bdc.
SELECTION-SCREEN END OF BLOCK b2.

*--------------------------------------------------------------------*

* AT SELECTION-SCREEN
*--------------------------------------------------------------------*
AT SELECTION-SCREEN.
  IF p_n = 'X'.
    trans_mode = 'N'.
  ELSEIF p_e = 'X'.
    trans_mode = 'E'.
  ELSE.
    trans_mode = 'A'.
  ENDIF.

*--------------------------------------------------------------------*
* start-of-selection on value-request
*--------------------------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path.
  CALL FUNCTION 'WS_FILENAME_GET'
    EXPORTING
      def_filename     = ''
      def_path         = 'C:\'
      mask             = ',TXT FILES(*.TXT),*.TXT,'
      mode             = 'O'
      title            = '选择导入文件'
    IMPORTING
      filename         = p_path
    EXCEPTIONS
      inv_winsys       = 1
      no_batch         = 2
      selection_cancel = 3
      selection_error  = 4
      OTHERS           = 5.

*--------------------------------------------------------------------*
* start-of-selection
*--------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM frm_upload_txt.
  PERFORM frm_delete_data.
  PERFORM frm_run_bdc.
  PERFORM frm_show_alv.

*&---------------------------------------------------------------------*
*&      Form  frm_upload_execl
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_upload_txt .
* { add by yuanxin at 20130627 将函数WS_UPLOAD替换成GUI_UOLOAD
*  CALL FUNCTION 'WS_UPLOAD'
*    EXPORTING
*      filename                = p_path
*      filetype                = 'DAT'
*    TABLES
*      data_tab                = ig_file
*    EXCEPTIONS
*      conversion_error        = 1
*      file_open_error         = 2
*      file_read_error         = 3
*      invalid_type            = 4
*      no_batch                = 5
*      unknown_error           = 6
*      invalid_table_width     = 7
*      gui_refuse_filetransfer = 8
*      customer_error          = 9
*      no_authority            = 10
*      OTHERS                  = 11.

  DATA L_P_FILE TYPE STRING.
  L_P_FILE = p_path.

  CALL FUNCTION 'GUI_UPLOAD'
    EXPORTING
      FILENAME                = L_P_FILE
      FILETYPE                = 'ASC'
      HAS_FIELD_SEPARATOR     = 'X'
    TABLES
      DATA_TAB                = ig_file
    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.
* end }
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

  IF ig_file[] IS INITIAL.
    MESSAGE s001 WITH '没有读取到数据,程序将停止!'.
    STOP.
  ENDIF.

  SORT ig_file BY matnr werks.
ENDFORM. " frm_upload_execl

*&---------------------------------------------------------------------*
*&      Form  frm_run_bdc
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_run_bdc .
  DATA wl_file LIKE LINE OF ig_file.

  DATA:BEGIN OF LT_SOURCE OCCURS 0,
      matnr LIKE eord-matnr,"物料号
      werks LIKE eord-werks,"工厂
      END OF LT_SOURCE.

  LOOP AT ig_file.
    MOVE ig_file-matnr to LT_SOURCE-matnr.
    MOVE ig_file-werks to LT_SOURCE-werks.
    APPEND LT_SOURCE.
    clear ig_file.
  ENDLOOP.

  DELETE ADJACENT DUPLICATES FROM LT_SOURCE COMPARING  matnr werks.

  data : lv_item TYPE numc2 VALUE 0."用于修改一个物料 +工厂,有多个供应商的情况,用于传值

  data:LV_EORD_VDATU type char50.
  data:LV_EORD_BDATU type char50.
  data:LV_EORD_LIFNR type char50.
  data:LV_EORD_EKORG type char50.
  data:LV_EORD_RESWK type char50.
  data:LV_EORD_MEINS type char50.
  data:LV_RM06W_FESKZ type char50.
  data:LV_EORD_NOTKZ type char50.
  data:LV_EORD_AUTET type char50.
  data:lv_erod_vdatu type char50.

  CLEAR: LT_SOURCE , ig_file.
  LOOP AT LT_SOURCE.

    CLEAR ig_bdcdata.
    REFRESH ig_bdcdata.

    PERFORM frm_fill_bdc USING:
            'X' 'SAPLMEOR' '0200',
            ''  'BDC_OKCODE' '/00',
            ''  'EORD-MATNR' LT_SOURCE-matnr,
            ''  'EORD-WERKS' LT_SOURCE-werks,
            'X' 'SAPLMEOR' '0205',
            ''  'BDC_OKCODE' '=BU'.

    CLEAR :lv_item."不清空的话,会一直累加。
    LOOP AT ig_file where matnr = LT_SOURCE-matnr and
                          werks = LT_SOURCE-werks.
      CLEAR wl_file.
      MOVE-CORRESPONDING ig_file TO wl_file.

      lv_item = lv_item + 1. " 计数器递增


      clear :LV_EORD_VDATU,LV_EORD_BDATU, LV_EORD_LIFNR, LV_EORD_EKORG, LV_EORD_RESWK, LV_EORD_MEINS, LV_RM06W_FESKZ, LV_EORD_NOTKZ, LV_EORD_AUTET.
      concatenate 'EORD-VDATU'  '('  lv_item  ')' into LV_EORD_VDATU.
      concatenate 'EORD-BDATU'  '('  lv_item  ')' into LV_EORD_BDATU.
      concatenate 'EORD-LIFNR'  '('  lv_item  ')' into LV_EORD_LIFNR.
      concatenate 'EORD-EKORG'  '('  lv_item  ')' into LV_EORD_EKORG.
      concatenate 'EORD-RESWK'  '('  lv_item  ')' into LV_EORD_RESWK.
      concatenate 'EORD-MEINS'  '('  lv_item  ')' into LV_EORD_MEINS.
      concatenate 'RM06W-FESKZ'  '('  lv_item  ')' into LV_RM06W_FESKZ.
      concatenate 'EORD-NOTKZ'  '('  lv_item  ')' into LV_EORD_NOTKZ.
      concatenate 'EORD-AUTET'  '('  lv_item  ')' into LV_EORD_AUTET.

      PERFORM frm_fill_bdc USING:

             ''  LV_EORD_VDATU wl_file-vdatu,
             ''  LV_EORD_BDATU wl_file-bdatu,
             ''  LV_EORD_LIFNR wl_file-lifnr,
             ''  LV_EORD_EKORG wl_file-ekorg,
             ''  LV_EORD_RESWK wl_file-reswk,
             ''  LV_EORD_MEINS wl_file-meins,
             ''  LV_RM06W_FESKZ wl_file-feskz,
             ''  LV_EORD_NOTKZ wl_file-notkz,
             ''  LV_EORD_AUTET wl_file-autet.
    clear:ig_file.
    endloop.

    CALL TRANSACTION 'ME01' USING ig_bdcdata
                            MODE trans_mode
                            UPDATE 'S'
                            MESSAGES INTO ig_bdcmsg.
    CLEAR ig_out.
    ig_out-matnr = wl_file-matnr.
    ig_out-werks = wl_file-werks.

    LOOP AT ig_bdcmsg.
      CASE ig_bdcmsg-msgtyp.
        WHEN 'S'.
          ig_out-icn = icon_led_green.
        WHEN 'E' OR 'A'.
          ig_out-icn = icon_led_red.
        WHEN 'I'.
          ig_out-icn = icon_led_inactive.
        WHEN 'W'.
          ig_out-icn = icon_led_yellow.
      ENDCASE.

      MESSAGE ID ig_bdcmsg-msgid
              TYPE ig_bdcmsg-msgtyp
              NUMBER ig_bdcmsg-msgnr
              WITH ig_bdcmsg-msgv1
                   ig_bdcmsg-msgv2
                   ig_bdcmsg-msgv3
                   ig_bdcmsg-msgv4
              INTO ig_out-msg.

      APPEND ig_out.
      CLEAR: ig_out-icn,ig_out-msg.
    ENDLOOP.

    CLEAR wl_file.
    CLEAR ig_out.
  ENDLOOP.
  SORT ig_out BY matnr werks lifnr.
  DELETE ADJACENT DUPLICATES FROM ig_out.
ENDFORM. " frm_run_bdc


*&---------------------------------------------------------------------*
*&      Form  frm_fill_bdc
*&---------------------------------------------------------------------*
*       BDC 公用
*----------------------------------------------------------------------*
FORM frm_fill_bdc USING v_1 v_2 v_3.
  IF v_1 = 'X' .
    ig_bdcdata-program = v_2 .
    ig_bdcdata-dynpro  = v_3 .
    ig_bdcdata-dynbegin = 'X' .
  ELSE.
    ig_bdcdata-fnam = v_2 .
    ig_bdcdata-fval  = v_3 .
  ENDIF .

  APPEND ig_bdcdata .
  CLEAR ig_bdcdata .
ENDFORM. " frm_fill_bdc

*&---------------------------------------------------------------------*
*&      Form  frm_show_alv
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_show_alv .
  REFRESH fieldcat.
  add2fc: 'MATNR' '物料号' 'L' '',
          'WERKS' '工厂' 'L' '',
          'LIFNR' '供应商' 'L' '',
          'ICN' '' '' 'X',
          'MSG' '' 'L' ''.

  layout-colwidth_optimize = 'X'.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      i_interface_check  = ''
      i_callback_program = sy-repid
      is_layout          = layout
      it_fieldcat        = fieldcat[]
    TABLES
      t_outtab           = ig_out
    EXCEPTIONS
      program_error      = 1
      OTHERS             = 2.
ENDFORM. " frm_show_alv

*&---------------------------------------------------------------------*
*&      Form  frm_delete_data
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_delete_data .
  DATA: BEGIN OF il_a017 OCCURS 0,
        matnr LIKE a017-matnr,
        werks LIKE a017-werks,
        lifnr LIKE a017-lifnr,
        END OF il_a017.
  DATA: vl_index LIKE sy-tabix.

  SELECT matnr werks lifnr
    INTO TABLE il_a017
    FROM a017
     FOR ALL ENTRIES IN ig_file
   WHERE matnr = ig_file-matnr
     AND werks = ig_file-werks
     AND lifnr = ig_file-lifnr.
  SORT il_a017 BY matnr werks lifnr.

  LOOP AT ig_file.
    vl_index = sy-tabix.
    READ TABLE il_a017 WITH KEY matnr = ig_file-matnr
                                werks = ig_file-werks
                                lifnr = ig_file-lifnr
                                BINARY SEARCH.
    IF sy-subrc <> 0.
      ig_out-matnr = ig_file-matnr.
      ig_out-werks = ig_file-werks.
      ig_out-lifnr = ig_file-lifnr.
      ig_out-icn = icon_led_red.
      CONCATENATE  '该物料的工厂级别' ig_out-lifnr  '采购信息不存在' INTO ig_out-msg.
      APPEND ig_out.
      DELETE ig_file INDEX vl_index.
    ENDIF.
    CLEAR: ig_out,ig_file.
  ENDLOOP.
  IF ig_file[] IS INITIAL.
    MESSAGE s000 WITH '没有合适的数据,程序将停止!'.
    STOP.
  ENDIF.
ENDFORM. " frm_delete_data

*Text elements
*----------------------------------------------------------
* 001 导入文件路径
* 002 模式


*Selection texts
*----------------------------------------------------------
* P_A         A 单步处理
* P_E         E 出错处理
* P_N         N 批量处理
* P_PATH         文件名称


*Messages
*----------------------------------------------------------
*
* Message class: ZDEV
*000   & & & & &
*001   重复:序列号-&在地点&下已经存在!

3、前台操作界面;

这三个不同模式,对应事务码SM35执行批处理的那三个模式

A:单步处理,也就是SM35的处理/前台,执行的时候弹出操作对话框

E:出错处理,也就是SM35的仅显示错误,执行的时候,有错误的才会有弹框显示错误信息

N:批量处理,也就是SM35的不可见,执行的时候,全部后台执行,直到执行完。

该代码注意的地方;
(1)以下的PERFORM frm_delete_data中,会把物料没有维护采购信息记录的数据删除;譬如说,同一个物料 + 工厂下,需要维护三个供应商,但是其中一个供应商没有维护采购信息记录,那么这条数据会单独剥离出来,并且在ALV输出时会提示。

然后只会导入进去两条其他的数据。

4、注意事项;

(1)MRP字段与固定供应商字段的影响

货源清单,不维护MRP字段的时候,是可以不需要维护采购信息记录的;但是如果维护了MRP字段,那么采购信息记录是必须要有的。

注意,如果维护了固定供应商字段,那么也必须要要有采购信息记录;

综上所述,该程序也可以优化成,就算该供应商不维护对应的采购信息记录,也可以导入进去,但是就不能维护MRP字段和固定供应商字段了,否则就会报错,根据实际情况优化。

(2)批导过程注意事项;

A、批导模板要用带分隔符的TXT文档,不能带标题,如下图所示的字段顺序,放到TXT时,需要去掉标题行

B、同一个物料 +工厂的货源清单中,如果有多个供应商时,MRP字段尽量只维护一个供应商,如果维护多个供应商时,会显示警告信息; 提示       

记录 被冻结。处理是不可能的

消息号 06705

该问题原因就是同时维护了MRP字段,然后有效期又有重叠部分,就会出现警告消息。

最开始以为是供应商主数据或者物料或者是哪里冻结住了,后面网上看了一下资料,再切换了一下英文环境下操作,发现错误提示如下“Several sources MRP-relevant on one date”,就是说一个日期与多个MRP相关

如果这里不注意这个问题,那么使用这个批导程序录入时,就会提示这个“记录被冻结”的错误消息~~但是实际上也能录入进去,就是会给用户一些错觉而已。

3、S4版本的货源清单批量导入程序,由于是朋友给的,不是自己开发的成品,就不拿出来分享了,有需要的小伙伴可以私信交流。

三、总结:

1、LSMW这个功能有空还是要再研究下,看看多层结构的数据录入,如果标准的LSMW不存在时,是否可以自己单独录入;

2、货源清单录入功能,需要注意维护采购信息记录;

3、同一个物料 +工厂的货源清单,有效期有重叠时,注意MRP字段不要全部都维护;

        最后,预告一个批量处理SAP数据的工具,RPA相关的工具,可以批量录入主数据或者MIGO过帐等操作的,但是目前还没仔细研究完,后续研究完会再分享出来~~

  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值