【ABAP增强】基于源代码的增强
基于源代码的增强实质上是对SAP所预留的空的子过程进行编码,用户可以编辑此子过程,并在这个子过程中添加自定义的代码,以增加SAP标准程序的控制功能。
1、通过系统IMG信息查找基于源代码的用户出口
一般相近的功能的子程序出口都会放在一个统一的INCLUDE程序中,SAP的程序执行会调用该子程序,可以通过SAP的IMG(系统配置工具)获取相关的出口程序的信息。
输入事务代码SPRO进入IMG界面,以查找销售相关的出口信息为例,可依次选择“销售与分销”-“系统修正”-“用户出口”命令,如下图所示:
单击菜单中的按钮,可以看到SAP所提供的该节点所对应的功能介绍,类似于F1的帮助,会对所提供的用户出口程序类型、名称和功能做简单的介绍,如下图所示:
通过说明文档可以获取SAP预定义的出口名称,如上图在IMG可以看到包含的源码出口Include包括MV45ATZZ、MV45AOZZ、MV45AIZZ、MV45AFZZ等。
2、通过开发类来查找基于源代码的用户出口
大部分销售及分销的程序都是基于源码控制来实现增强的,该类增强包含在开发类VMOD中,通过SE80可以查找该开发类所包含的所有对象。
执行事务代码SE80,在对象类型下面选择Package表示以开发类为条件,在对象名称中输入开发类名称VMOD,回车,可以看到在列表中将带出该开发类所包含的所有对象,包括字典对象、函数组、Include程序等等,该开发类所对应的出口程序都在“包含”列表中,具体如下图所示:
3、基于源码的用户出口应用
以出口程序MV45AFZZ为例,该出口程序主要是在销售订单执行时候被调用,通过ABAP编辑打开并查看源代码,可以发现该程序中包含了很多空的子程序,在程序中会对这些子程序做一些简单的注释说明,具体代码如下:
***INCLUDE MV45AFZZ .
************************************************************************
* *
* This include is reserved for user modifications *
* *
* Forms for sales document processing *
* *
* The name of modification modules should begin with 'ZZ'. *
* *
************************************************************************
*---------------------------------------------------------------------*
* FORM ZZEXAMPLE *
*---------------------------------------------------------------------*
* text...................................... *
*---------------------------------------------------------------------*
*FORM ZZEXAMPLE.
* ...
*ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_DELETE_DOCUMENT *
*---------------------------------------------------------------------*
* This userexit can be used to delete data in additional tables *
* when a sales document is deleted. *
* *
* This form is called in dialog at the end of form BELEG_LOESCHEN*
* just before form BELEG_SICHERN is performed to delete the *
* datas on the database. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_DELETE_DOCUMENT.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_FIELD_MODIFICATION *
*---------------------------------------------------------------------*
* This userexit can be used to modify the attributes of *
* screen fields. *
* This form is processed for each field in the screen. *
* *
* The use of the fields screen-group1 to screen-group4 is: *
* *
* Screen-group1: Automatic modification contolles by transaction*
* MFAW. *
* Screen-group2: Contents 'LOO' for steploop-fields. *
* Screen-group3: Used for modififaction, which are dependent on *
* control tables or other fix information. *
* Screen-group4: Unused *
* *
* For field mofifications, which are dependent on the document *
* status, you can use the status field in the workareas *
* XVBAP for item status and XVBUK for header status. *
* *
* This form is called from module FELDAUSWAHL. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_FIELD_MODIFICATION.
* CASE SCREEN-GROUP3.
* WHEN '900'.
* IF VBAK-VBTYP NE 'A'.
* SCREEN-ACTIVE = 0.
* ENDIF.
* ENDCASE.
* CASE SCREEN-NAME.
* WHEN 'VBAK-VBELN'.
* SCREEN-ACTIVE = 0.
* ENDCASE.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_MOVE_FIELD_TO_VBAK *
*---------------------------------------------------------------------*
* This userexit can be used to move some fields into the sales *
* dokument header workaerea VBAK. *
* *
* SVBAK-TABIX = 0: Create header *
* SVBAK-TABIX > 0: Change header *
* *
* This form is called at the end of form VBAK_FUELLEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_MOVE_FIELD_TO_VBAK.
* vbak-zzfield = xxxx-zzfield2.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_MOVE_FIELD_TO_VBAP *
*---------------------------------------------------------------------*
* This userexit can be used to move some fields into the sales *
* dokument item workaerea VBAP *
* *
* SVBAP-TABIX = 0: Create item *
* SVBAP-TABIX > 0: Change item *
* *
* This form is called at the end of form VBAP_FUELLEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_MOVE_FIELD_TO_VBAP.
* VBAP-zzfield = xxxx-zzfield2.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_MOVE_FIELD_TO_VBEP *
*---------------------------------------------------------------------*
* This userexit can be used to move some fields into the sales *
* dokument schedule line workaerea VBEP *
* *
* SVBEP-TABIX = 0: Create schedule line *
* SVBEP-TABIX > 0: Change schedule line *
* *
* This form is called at the end of form VBEP_FUELLEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_MOVE_FIELD_TO_VBEP.
* VBEP-zzfield = xxxx-zzfield2.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_MOVE_FIELD_TO_VBKD *
*---------------------------------------------------------------------*
* This userexit can be used to move some fields into the sales *
* dokument business data workaerea VBKD *
* *
* SVBKD-TABIX = 0: Create data *
* SVBKD-TABIX > 0: Change data *
* *
* This form is called at the end of form VBKD_FUELLEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_MOVE_FIELD_TO_VBKD.
* VBKD-zzfield = xxxx-zzfield2.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_NUMBER_RANGE *
*---------------------------------------------------------------------*
* This userexit can be used to determine the numberranges for *
* the internal document number. *
* *
* US_RANGE_INTERN - internal number range *
* *
* This form is called from form BELEG_SICHERN *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_NUMBER_RANGE USING US_RANGE_INTERN.
* Example: Numer range from TVAK like in standard
* US_RANGE_INTERN = TVAK-NUMKI.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_PRICING_PREPARE_TKOMK *
*---------------------------------------------------------------------*
* This userexit can be used to move additional fields into the *
* communication table which is used for pricing: *
* *
* TKOMK for header fields *
* *
* This form is called from form PREISFINDUNG_VORBEREITEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_PRICING_PREPARE_TKOMK.
* TKOMK-zzfield = xxxx-zzfield2.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_PRICING_PREPARE_TKOMP *
*---------------------------------------------------------------------*
* This userexit can be used to move additional fields into the *
* communication table which is used for pricing: *
* *
* TKOMP for item fields *
* *
* This form is called from form PREISFINDUNG_VORBEREITEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_PRICING_PREPARE_TKOMP.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_READ_DOCUMENT *
*---------------------------------------------------------------------*
* This userexit can be used to read data in additional tables *
* when the program reads a sales document. *
* *
* This form is called at the end of form BELEG_LESEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_READ_DOCUMENT.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_SAVE_DOCUMENT *
*---------------------------------------------------------------------*
* This userexit can be used to save data in additional tables *
* when a document is saved. *
* *
* If field T180-TRTYP contents 'H', the document will be *
* created, else it will be changed. *
* *
* This form is called at from form BELEG_SICHERN, before COMMIT *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_SAVE_DOCUMENT.
* Example:
* CALL FUNCTION 'ZZ_EXAMPLE'
* IN UPDATE TASK
* EXPORTING
* ZZTAB = ZZTAB.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_SAVE_DOCUMENT_PREPARE *
*---------------------------------------------------------------------*
* This userexit can be used for changes or checks, before a *
* document is saved. *
* *
* If field T180-TRTYP contents 'H', the document will be *
* created, else it will be changed. *
* *
* This form is called at the beginning of form BELEG_SICHERN *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_SAVE_DOCUMENT_PREPARE.
ENDFORM.
*eject
双击某一个子程序名,如USEREXIT_MOVE_FIELD_TO_VBAK,可以看到其在主程序中被调用的具体位置,如下图所示:
(现在好像该功能已经失效)
4、如何查找基于源码的用户出口的默认参数
出口程序通过通过ABAP来进行修改,在ABAP编辑器中可以直接在所定义的子程序中添加代码。
做出口程序开发需要特别注意,仅能在指定的子程序中间穿插代码,不能对子程序的结构或者名称做任何改变,而且必须保证所编译代码可以正常**,否则可能导致正常的业务发生异常。
出口开发必须要了解业务需求以及该处增强在系统中所对应的功能组,以确定对哪一部分代码进行更改,并能找到程序中所能使用到的系统参数,以上面的MV45AFZZ为例,其主要的功能包括销售订单的创建、检查以及保存。SAP的销售订单数据主要保存在VBAK和VBAP表中,而且SAP程序执行中会对这些数据临时存放于内表XVBAK和XVKAP中。
查找出口中能使用到哪些内表是整个开发的关键,可以通过网络资源来找到SAP官方提供的一些信息。
●查找出口程序所对应的主程序,通过ABAP编辑器能找到该出口程序的所处清单,即查看该出口程序具体由哪些程序调用。首先在ABAP编辑器中输入出口程序名称“MV45AFZZ”,单击工具栏的“所用处清单”,将提示需要比较程序类型,默认即可。
●单击确定按钮后将看到该出口程序被主程序SAPMV45A所调用,如下图所示:
●选中命中清单中的程序名称,单击工具栏中的“查看”按钮,查看该程序的源代码。
SAP的程序规则一般会把不同的功能代码封装在不同的Include中,如变量定义一般存放在程序以TOP结尾的Include中,主程序SAPMV45A中包含Include程序MV45ATOP,如下图所示:
●双击Include程序mv45atop,即可查看该程序所对应的代码。mv45atop中也包含了很多Include程序,例如其下级程序copydata中包含了部分内表及变量的定义,如图所示:
5、通过源码出口来增强VA01功能实例
程序中所看到的变量及内表数据都可以在用户出口对应的子程序中直接引用,系统执行中的一些业务数据会被暂时存在指定的内表中供出口程序判断和使用。根据这些子程序的名称及简介可以初步判断其调用的过程,例如子程序USEREXIT_SAVE_DOCUMENT_PREPARE则会在订单维护(VA01和VA02)保存前调用,下面以实例来介绍出口应用。
例如:在SAP标准功能中,保存销售订单一般不会判断采购订单编码,本例中需要实现在订单创建时,若订单类型为ZOR1,要求必须填入采购订单号,否则无法保存。
通过F1键查找屏幕字段的技术信息,在订单创建事务代码VA01中可以找到订单类型在屏幕中的字段名称为VBAK-AUART,采购订单编码在屏幕中的字段名称为VBKD-BSTKD,对应字段可以直接在用户出口中进行引用,出口代码如下所示:
*---------------------------------------------------------------------*
* FORM USEREXIT_SAVE_DOCUMENT_PREPARE *
*---------------------------------------------------------------------*
* This userexit can be used for changes or checks, before a *
* document is saved. *
* *
* If field T180-TRTYP contents 'H', the document will be *
* created, else it will be changed. *
* *
* This form is called at the beginning of form BELEG_SICHERN *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_SAVE_DOCUMENT_PREPARE.
if vbak-auart = 'ZOR1' and vbak-bstkd is initial.
message '该类型下必输采购订单编号' type 'E'.
endif.
ENDFORM.
程序中还包含了其他很多出口,用户可以在程序中通过设置断点Debug的方式来查找程序执行时不同功能所对应的出口。