ME21N 采购订单新增页签增强

文章描述了如何在采购订单界面中按需添加页签,包括增强结构、创建FunctionGroup和BADIME_PROCESS_PO_CUST的FIELDSELECTION_HEADER方法,以实现在ME23N中显示新增字段。同时涉及数据映射和传输过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、实现效果

根据客制化需求,要在采购订单中新增大量字段,所以要在界面上添加一个单独的页签。效果如下:

2、增强实现

2.1、增强结构

因为是在抬头上边添加,所以增强CI_EKKODB结构

2.2、函数组

仿照Function Group MEPOBADIEX建一个Function Group

函数组:

2.3、增强实施

2.3.1、BADI:ME_GUI_PO_CUST

方法:SUBSCRIBE

"--------------------@斌将军--------------------
method IF_EX_ME_GUI_PO_CUST~SUBSCRIBE.
  DATA: LS_SUBSCRIBERS TYPE MEPO_SUBSCRIBERS.
*1 抬头
  IF IM_APPLICATION = 'PO' AND IM_ELEMENT = 'HEADER'.
    CLEAR RE_SUBSCRIBERS[] .
    CLEAR LS_SUBSCRIBERS.
    LS_SUBSCRIBERS-NAME        = SUBSCREEN_H."屏幕名称
    LS_SUBSCRIBERS-DYNPRO      = '9001'."函数组的屏幕编号
    LS_SUBSCRIBERS-PROGRAM     = 'SAPLZMMPO001'."调用的函数组
    LS_SUBSCRIBERS-STRUCT_NAME = 'CI_EKKODB'."增强的结构
    LS_SUBSCRIBERS-LABEL       = '其他数据'."页签名称
    LS_SUBSCRIBERS-POSITION    = 30."页签处于的位置
    LS_SUBSCRIBERS-HEIGHT      = 7."页签高度
    APPEND LS_SUBSCRIBERS TO RE_SUBSCRIBERS.
  ENDIF.
*2 
*  IF IM_APPLICATION = 'PO' AND IM_ELEMENT = 'ITEM'.
*    CLEAR RE_SUBSCRIBERS[] .
*    CLEAR LS_SUBSCRIBERS.
*    LS_SUBSCRIBERS-NAME        = SUBSCREEN_I.
*    LS_SUBSCRIBERS-DYNPRO      = '9100'.
*    LS_SUBSCRIBERS-PROGRAM     = 'SAPLZMM003'.
*    LS_SUBSCRIBERS-STRUCT_NAME = 'CI_EKPODB'.
*    LS_SUBSCRIBERS-LABEL       = 'Badi增强行项目屏幕'.
*    LS_SUBSCRIBERS-POSITION    = 24.   "页签处于的位置
*    LS_SUBSCRIBERS-HEIGHT      = 4.
*    APPEND LS_SUBSCRIBERS TO RE_SUBSCRIBERS.
*  ENDIF.
  endmethod.
"--------------------@斌将军--------------------

定义相关属性

方法:MAP_DYNPRO_FIELDS

"--------------------@斌将军--------------------
method IF_EX_ME_GUI_PO_CUST~MAP_DYNPRO_FIELDS.
  FIELD-SYMBOLS: <mapping> LIKE LINE OF ch_mapping.

  LOOP AT ch_mapping ASSIGNING <mapping>.
    CASE <mapping>-fieldname.
    WHEN 'ZEJFL'. <mapping>-metafield = mmmfd_cust_01.  "抬头
*    WHEN 'ZHEAD02'. <mapping>-metafield = mmmfd_cust_02.
*    WHEN 'ZZ001'.   <mapping>-metafield = mmmfd_cust_03.  "明细
*    WHEN 'ZZ005'.   <mapping>-metafield = mmmfd_cust_04.
*      "自定义字段
*    WHEN 'ZFIELD3'.<mapping>-metafield = mmmfd_cust_05.
    ENDCASE.
  ENDLOOP.
  endmethod.
"--------------------@斌将军--------------------

方法:TRANSPORT_FROM_MODEL

"--------------------@斌将军--------------------
method IF_EX_ME_GUI_PO_CUST~TRANSPORT_FROM_MODEL.
  DATA: ls_header     TYPE REF TO if_purchase_order_mm,
        ls_mepoheader TYPE mepoheader,
        ls_item       TYPE REF TO if_purchase_order_item_mm,
        ls_mepoitem   TYPE mepoitem.
*1 抬头
  IF im_name = subscreen_h.
    mmpur_dynamic_cast ls_header im_model.
    IF ls_header IS NOT INITIAL.
      ls_mepoheader = ls_header->get_data( ).
      MOVE-CORRESPONDING ls_mepoheader TO dynp_data_pbo_h.
    ENDIF.
  ENDIF.
*2 明细
*  IF im_name = subscreen_i.
*    mmpur_dynamic_cast ls_item im_model.
*    IF ls_item IS NOT INITIAL.
*      ls_mepoitem = ls_item->get_data( ).
*      MOVE-CORRESPONDING ls_mepoitem TO dynp_data_pbo_i.
*    ENDIF.
*  ENDIF.
  endmethod.
"--------------------@斌将军--------------------

方法:TRANSPORT_TO_DYNP

"--------------------@斌将军--------------------
METHOD IF_EX_ME_GUI_PO_CUST~TRANSPORT_TO_DYNP.
    CASE IM_NAME.
*1 抬头
      WHEN SUBSCREEN_H.
        call function 'ZMMPO001_PUSH'
          EXPORTING
            IM_DYNP_DATA = DYNP_DATA_PBO_H.
*2 明细
*  WHEN subscreen_i.
*    CALL FUNCTION 'ZMMPO002_PUSH'
*    EXPORTING
*      im_dynp_data = dynp_data_pbo_i.
      WHEN OTHERS.
    ENDCASE.
  ENDMETHOD.
"--------------------@斌将军--------------------

方法:TRANSPORT_FROM_DYNP

"--------------------@斌将军--------------------
METHOD IF_EX_ME_GUI_PO_CUST~TRANSPORT_FROM_DYNP.
    CASE IM_NAME.
*1 抬头
      WHEN SUBSCREEN_H.
        call function 'ZMMPO001_POP'
          IMPORTING
            EX_DYNP_DATA = DYNP_DATA_PAI_H.
        IF DYNP_DATA_PAI_H <> DYNP_DATA_PBO_H.
          RE_CHANGED = MMPUR_YES.
        ENDIF.
*2 明细
*  WHEN subscreen_i.
*    CALL FUNCTION 'ZMMPO002_POP'
*    IMPORTING
*      ex_dynp_data = dynp_data_pai_i.
*    IF dynp_data_pai_i <> dynp_data_pbo_i.
*      re_changed = mmpur_yes.
*    ENDIF.
      WHEN OTHERS.
    ENDCASE.
  ENDMETHOD.
"--------------------@斌将军--------------------

方法:TRANSPORT_TO_MODEL

"--------------------@斌将军--------------------
method IF_EX_ME_GUI_PO_CUST~TRANSPORT_TO_MODEL.
  DATA: ls_header           TYPE REF TO if_purchase_order_mm,
        ls_mepoheader       TYPE mepoheader,
        ls_po_head_customer TYPE ci_ekkodb,
        ls_po_header_handle TYPE REF TO cl_po_header_handle_mm,
        ls_item             TYPE REF TO if_purchase_order_item_mm,
        ls_mepoitem         TYPE mepoitem,
        ls_po_item_customer TYPE ci_ekpodb,
        ls_po_item_handle   TYPE REF TO cl_po_item_handle_mm.

  CASE im_name.
*1 抬头
  WHEN subscreen_h.
    mmpur_dynamic_cast ls_header im_model.
    IF ls_header IS NOT INITIAL.
      ls_mepoheader = ls_header->get_data( ).
      IF  dynp_data_pbo_h-ZEJFL <> dynp_data_pai_h-ZEJFL.
*      OR dynp_data_pbo_h-zhead02 <> dynp_data_pai_h-zhead02.
        ls_mepoheader-ZEJFL = dynp_data_pai_h-ZEJFL.
*        ls_mepoheader-zhead02 = dynp_data_pai_h-zhead02.
        CALL METHOD ls_header->set_data
        EXPORTING
          im_data = ls_mepoheader.
      ENDIF.
    ENDIF.
*2 明细
*  WHEN subscreen_i.
*    mmpur_dynamic_cast ls_item im_model.
*    IF ls_item IS NOT INITIAL.
*      ls_mepoitem = ls_item->get_data( ).
*      IF  dynp_data_pbo_i-zz001 <> dynp_data_pai_i-zz001
*      OR dynp_data_pbo_i-zz005 <> dynp_data_pai_i-zz005.
*
*        ls_mepoitem-zz001 = dynp_data_pai_i-zz001.
*        ls_mepoitem-zz005 = dynp_data_pai_i-zz005.
*
*        CALL METHOD ls_item->set_data
*        EXPORTING
*          im_data = ls_mepoitem.
*      ENDIF.
*    ENDIF.
  WHEN OTHERS.
  ENDCASE.
  endmethod.
"--------------------@斌将军--------------------

2.3.2、BADI:ME_PROCESS_PO_CUST

到此处,ME23N就可以看到新增的页签,但是ME21N和ME22N看不到,还需要实现一个BADI:ME_PROCESS_PO_CUST的FIELDSELECTION_HEADER方法。

该BADI只能创建一个实施,如果已经有多个实施,必须将其他实施停用,否则将达不到效果。

"--------------------@斌将军--------------------
method IF_EX_ME_PROCESS_PO_CUST~FIELDSELECTION_HEADER.
DATA:ex_data TYPE mepoheader.
  DATA: LV_PERSISTENT TYPE MMPUR_BOOL.
  FIELD-SYMBOLS: <FS> LIKE LINE OF CH_FIELDSELECTION.

  DEFINE SET_INPUT.
    READ TABLE ch_fieldselection ASSIGNING <fs> WITH TABLE KEY metafield = &1.
    IF sy-subrc = 0.
      IF im_header->is_changeable( ) = mmpur_yes.
        <fs>-fieldstatus = '+'."'-'代表hidden, '+'或'.'表示editable, '*'代表display
      ELSE.
        <fs>-fieldstatus = '*'.
      ENDIF.
    ENDIF.
  END-OF-DEFINITION.

  LV_PERSISTENT = IM_HEADER->IS_PERSISTENT( ).

  SET_INPUT MMMFD_CUST_01.
    "获取订单数据
    CLEAR:ex_data.
*   ex_data = im_header->get_data( ).
*  SET_INPUT MMMFD_CUST_02.
endmethod.
"--------------------@斌将军--------------------

对抬头和行项目输入数据的检查可放在方法:PROCESS_HEADER和PROCESS_ITEM中,激活后就成功了。

定期更文,欢迎关注

<think>我们正在处理一个关于SAP BAPI的问题:用户想要通过BAPI修改采购订单,特别是新增行项目。根据引用内容,我们注意到有关于BAPI_PO_CREATE1创建采购订单的信息,但用户需要的是修改采购订单新增行项目)。在SAP中,修改采购订单(包括新增行项目)通常使用BAPI_PO_CHANGE。步骤:1.我们需要使用BAPI_PO_CHANGE函数。2.在修改采购订单时,新增行项目需要填充相应的结构,特别是POITEM结构(用于行项目数据)和POITEMX结构(用于标识哪些字段需要更新)。3.注意:POITEMX结构中,对于每个字段,如果要更新,需要设置为'X'(表示更新),否则不更新。4.在新增行项目时,我们需要指定一个新的行项目号(通常是一个新的10位数字,比如原订单最大行项目号+10),并设置相应的数据(如物料号、数量、价格等)。5.然后调用BAPI_PO_CHANGE,并处理返回消息。另外,引用[2]提到了BAPI增强自定义字段,如果用户需要新增的字段是自定义字段,那么还需要在扩展结构中进行处理(例如,在POITEM结构中可能包含Z字段,并在POITEMX中设置对应的标记)。具体步骤:a.准备采购订单号(要修改的订单号)。 b.准备行项目数据(POITEM)和更新标识(POITEMX)的表格。c.对于新增的行项目,在POITEM表中设置新的行项目号(ITEM)和相应的数据(如物料、工厂、数量等)。d.在POITEMX表中,为同一行项目号设置每个需要更新的字段的标识为'X'。e.调用BAPI_PO_CHANGE,传入采购订单号和行项目数据表。 f.检查返回消息,如果成功则提交事务(BAPI_TRANSACTION_COMMIT),如果有错误则回滚(BAPI_TRANSACTION_ROLLBACK)。注意:新增行项目时,行项目号必须是唯一的,且不能与现有行项目号重复。示例代码(ABAP)可能如下: ```abapDATA:lt_poitemTYPETABLE OFbapimepoitem,lt_poitemxTYPETABLE OFbapimepoitemx,ls_poitemTYPEbapimepoitem,ls_poitemxTYPEbapimepoitemx. DATA: lv_ebeln TYPEebeln."采购订单号"设置要修改的采购订单号lv_ebeln ='4500000010'. "示例订单号"准备新增行项目数据ls_poitem-po_item='00010'."新的行项目号(确保唯一) ls_poitem-material='MAT-001'."物料号ls_poitem-plant= '1000'. "工厂ls_poitem-quantity=10."数量ls_poitem-net_price ='10.00'. "净价APPENDls_poitemTO lt_poitem."设置更新标识(对于每个要更新的字段,都需要在POITEMX中设置X) ls_poitemx-po_item='00010'."行项目号ls_poitemx-material= 'X'."更新物料ls_poitemx-plant= 'X'."更新工厂ls_poitemx-quantity='X'. "更新数量ls_poitemx-net_price= 'X'."更新净价APPEND ls_poitemxTO lt_poitemx. "调用BAPI修改采购订单CALLFUNCTION 'BAPI_PO_CHANGE'EXPORTINGpurchaseorder =lv_ebelnTABLESreturn= lt_return "返回消息表poitem= lt_poitempoitemx=lt_poitemx."检查返回消息READTABLE lt_return WITHKEY type= 'E'TRANSPORTINGNO FIELDS. IFsy-subrc =0."有错误,回滚CALL FUNCTION'BAPI_TRANSACTION_ROLLBACK'.ELSE."成功,提交CALLFUNCTION 'BAPI_TRANSACTION_COMMIT'EXPORTINGwait ='X'. ENDIF.```注意:在实际使用中,行项目号需要根据订单现有行项目自动生成(比如查询该订单现有最大行项目号,然后增加10)。另外,还需要考虑其他字段(如账户分配、交货日期等)以及可能的增强字段。如果用户需要新增自定义字段,那么需要在POITEM结构中找到对应的字段(通常以Z开头),并在POITEMX中同样设置该字段的更新标识。参考引用[2]中提到的BAPI增强自定义字段,如果用户需要新增自定义字段,那么需要在上述结构中包含这些字段,并在POITEMX中设置更新标识。因此,回答用户的问题:使用BAPI_PO_CHANGE,通过填充POITEM和POITEMX表来新增行项目。生成相关问题:1.如何获取采购订单现有的行项目信息?2.在新增行项目时如何确定行项目号?3.BAPI_PO_CHANGE中如何处理自定义字段?4.如何检查BAPI调用的返回消息?5.修改采购订单时还可以修改哪些部分?</think>### 在SAP中通过BAPI新增采购订单行项目 在SAP中修改采购订单新增行项目,需使用 **BAPI_PO_CHANGE** 函数。以下是关键步骤和代码实现: #### 核心步骤 1. **准备数据结构** - `POITEM`:存储新增行项目数据(物料、数量、价格等) - `POITEMX`:标记需更新的字段(X=更新) - `RETURN`:接收BAPI执行结果 2. **设置行项目号** 新增行项目号需**大于现有最大行号**(如现有最大为`00010`,新增建议`00020`) 3. **调用BAPI** 使用`BAPI_PO_CHANGE`传入采购订单号和新行项目数据 4. **事务控制** - 成功时:`BAPI_TRANSACTION_COMMIT` - 失败时:`BAPI_TRANSACTION_ROLLBACK` #### 示例代码 (ABAP) ```abap DATA: lt_poitem TYPE TABLE OF bapimepoitem, " 行项目数据 lt_poitemx TYPE TABLE OF bapimepoitemx, " 更新标识 lt_return TYPE TABLE OF bapiret2. " 返回消息 " 1. 新增行项目数据 APPEND VALUE #( po_item = '00020' " 新行号(需大于现有行号) material = 'MAT-001' " 物料号 plant = '1000' " 工厂 quantity = 100 " 数量 po_unit = 'EA' " 单位 net_price = '25.50' " 单价 ) TO lt_poitem. " 2. 设置更新字段标识(X表示更新) APPEND VALUE #( po_item = '00020' material = 'X' plant = 'X' quantity = 'X' po_unit = 'X' net_price = 'X' ) TO lt_poitemx. " 3. 调用BAPI修改采购订单 CALL FUNCTION 'BAPI_PO_CHANGE' EXPORTING purchaseorder = '4500001234' " 需修改的采购订单号 TABLES return = lt_return " 返回消息表 poitem = lt_poitem " 新增行项目数据 poitemx = lt_poitemx. " 更新标识 " 4. 检查执行结果 READ TABLE lt_return WITH KEY type = 'E' TRANSPORTING NO FIELDS. IF sy-subrc = 0. " 存在错误:回滚事务 CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ELSE. " 成功:提交事务 CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'. MESSAGE '行项目新增成功' TYPE 'S'. ENDIF. ``` #### 关键注意事项 1. **行项目号规则** 新行号必须为 **10位字符**(如`00010`),且不能与现有行号重复。可通过函数`ME_GET_NEXT_ITEM`获取下一个可用行号。 2. **自定义字段增强** 如需新增自定义字段(如`ZXXXX`): - 在`POITEM`中填充自定义字段值 - 在`POITEMX`中设置对应字段为`X` - 需提前通过BADI增强BAPI结构(参考引用[^2]) 3. **错误处理** 必须检查`RETURN`表: - `TYPE = 'E'`:业务错误(如物料不存在) - `TYPE = 'A'`:应用错误(需回滚事务) 4. **权限要求** 用户需有采购订单修改权限(事务代码`ME22N`) > **提示**:测试时建议在测试系统操作,并使用`BAPI_TRANSACTION_ROLLBACK`避免误提交。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值