目录
1.前言:
2.什么是增强:
3.增强类型:
4.增强查找方式:
USER-EXIT的快速查找
①基于源码查找
②基于SPRO查找
③通过SAT运行分析进行查找
Customer-Exit的快速查找
①使用MODX_FUNCTION_ACTIVE_CHECK查找
②使用/H Debug方式进行查找
③借助增强查找程序进行查找
BTE的快速查找
①在源代码中通过搜索字符串'OPEN_FI_PERFORM'或者'OUTBOUND_CALL_'
②直接在FIBF中根据描述查找
③通过在函数BF_FUNCTIONS_FIND(对应P/S接口)或者PC_FUNCTION_FIND(对应Process接口)中打断点来进行查找
BADI的快速查找
①通过CL_EXITHANDLER=>GET_INSTANCE方法进行查找经典BADI
②通过CALL BADI断点的方法进行查找NEW BADI
③通过ST05跟踪的方式查找
Source Code Enhancements的快速查找
显示增强查找
隐式增强查找
5.增强实施的注意点
1.前言:
之前培训时总结的内容,应该算是比较全面的了,本文章目的在于让ABAPer掌握如何靠自己查找SAP系统中的增强,不依靠一些第三方查找程序或者谷歌,毕竟掌握方法才是最重要的。
2.什么是增强:
虽然SAP随着时间的推移核心逻辑已经设计的比较完善,但是考虑到企业实际的流程可能和默认标准流程不同,所以在标准流程框架下专门为客户预留了很多接口,在该接口中有用户根据企业实际需求来编写客户化的逻辑代码,来满足适合本企业的流程逻辑,简单来讲,非SAP标准功能所能实现的逻辑都算作增强。
SAP的增强概念允许我们将自己的功能添加到 SAP 的标准业务应用程序中,而无需修改原始应用程序。
要根据客户要求修改标准SAP行为,我们可以通过多种类型的增强方式实现。
3.增强类型:
- USER-EXIT: 是SAP 提供的首批机制之一,最初为SD模块开发的系统增强功能,用于在标准 SAP 控制流之间执行自定义代码,作为子例程调用,所有的USER-EXIT都以“USEREXIT_XXXX”开头,一个典型的示例是SO保存时的处理模块MV45AFZZ。
- Customer-Exit: 比USER-EXIT更完善,使用功能模块实现,具有明确定义的参数接口,由SMOD和CMOD进行管理和实施。
- Business Transaction Events(BTE): 这是为财务会计组件开发的增强技术,一般当其他增强或者财务替代功能不能实现时,会使用这种方式来进行实现。
- BADI(Business Add-Ins): 这是增强ABAP系统的第一个面向对象的方法,允许在有限的过滤器的支持下进行多种实现,分为Classic BADI和NEW BADI。
- 经典BADI使用cl_exithandler=>get_instance进行调用;
- 新BADI通过get badi/call badi来进行调用。
- •Source Code Enhancements: 这是基于源代码的一种增强选项,可以是显示的,也可以是隐式的。
- 显示增强由SAP开发人员在代码中通过ENHANCEMENT-POINT进行定义,由增强点管理,并由增强实现增强;
- 隐式增强则始终存在,不需要分配给增强点,存在于子例程、函数或者类的开始或者结尾处。
4.增强查找方式:
USER-EXIT的快速查找
①基于源码查找
以VA01销售订单创建为例,VA01进入界面,点击“系统”->“状态”
双击程序名进入标准程序源码界面,所有标准事务代码同理均可进入源码界面。
倒数第二位为Z的均为用户出口包含程序,USEREXIT_开头的子例程即为系统预留的增强点。
②基于SPRO查找
根据说明文档来确定自己需要使用哪个出口
③通过SAT运行分析进行查找
以VA02为例
根据form的名称或者双击进入源代码查看注释说明,判断所需要的出口。
Customer-Exit的快速查找
主要分为四类:
- E. Function exits:函数增强 以函数模块形式发布,在SAP的发布的版本中,使用 CALL CUSTOMER-FUNCTION ‘XXX’调用这些函数模块。出口函数名称由三部分组成:EXIT_<主程序名>_<3位数字>,根据这个规则可以找到对应的出口函数,然后在SE37中查看函数详细信息;通过该出口函数名到MODSAP表里查找对应的出口对象(即增强点)。这些函数在发布时只有一句代码 INCLUDE xxxx,xxxx 名称已预留,但还未创建。进行功能模块增强时,只能使用函数中传递的参数,不能使用调用程序的全局变量。
- C. GUI Codes:GUI增强,用于区域菜单和工作菜单栏的增强。
- S. Screens:屏幕增强 SAP使用 CALL CUSTOMER-SCREEN 调用这些子屏幕,已预留了子屏幕编号,程序已经创建,但子屏幕还未创建。所以可以通过在程序中查找 customer-screen 来查找此类增强。
- T. Tables:表结构增强 include structure,SAP已预留了结构名称,以CI_**打头,但结构字段还未创建。这些结构将以.include的形式包含到相应的数据表中,用户可以通过向这些结构中添加字段从而达到对数据表字段的增加。
相关的函数和表:
Function:
① DYNP_VALUES_READ
② MODX_ALL_ACTIVE_MENUENTRIES(菜单增强)
③ MODX_FUNCTION_ACTIVE_CHECK(E类:出口函数增强)
④ MODX_MENUENTRY_ACTIVE_CHECK(C类:菜单增强)
⑤ MODX_SUBSCREEN_ACTIVE_CHECK(S类:屏幕增强)
Table:
- ① TFDIR:记录所有函数,重要字段:funcname函数名,mand激活状态(c代表激活)
- ② MODSAP:记录所有enhancement的增强,重要字段:name增强名,type组件类型(E-功能、C-菜单、S-屏幕、T-表),member组件功能模块名
- ③MODACTT: 记录增强组件被包含在哪些项目中,重要字段:name项目名,member组件功能模块名。
- ④TSDIR:CALL CUSTOMER SUBSCREEN(屏幕增强)
-
①使用MODX_FUNCTION_ACTIVE_CHECK查找
- 以CO02为例,预先在函数中设置好断点
- 所有Customer-Exit的命名规则都是一样,EXIT_+主程序名+_三位函数编号
-
②使用/H Debug方式进行查找
-
以查找生产订单保存增强点为例
-
设置好断点后,按F8执行,代码会自动停在有客户出口的地方,可能会有多个出口,需要根据参数以及描述自行判断是否可用。
-
EXIT_主程序名_编号 得到出口函数名之后,可以去SMOD根据上面提到的方法查找,也可以直接在MODSAP这张表中进行查找,要查找是否已经有对应实现,可以去MODACTT这张表。
-
③借助增强查找程序进行查找
- 网上一抓一大把的代码,自己掌握方法后,其实就不需要这个代码了。
REPORT Z_FIND_ENHANCEMENT
NO STANDARD PAGE HEADING
MESSAGE-ID zhuxy
LINE-COUNT 65
LINE-SIZE 120.
*** Global Date declear
TABLES:tstc,tadir,modsapt,modact,trdir,tfdir,enlfdir,sxs_attrt,tstct.
DATA : jtab LIKE tadir OCCURS 0 WITH HEADER LINE.
DATA : field1(30).
DATA : v_devclass LIKE tadir-devclass.
DATA : wa_tadir TYPE tadir.
PARAMETERS : p_tcode LIKE tstc-tcode,
p_pgmna LIKE tstc-pgmna .
*======================================================================*
* Selection Screen Events
*======================================================================*
*** maintain selection screen output
AT SELECTION-SCREEN OUTPUT.
*** F4 value help
*AT SELECTION-SCREEN ON VALUE-REQUEST for <para/sel-opt>.
*** check input data
AT SELECTION-SCREEN.
*AT SELECTION-SCREEN ON <f>.
*AT SELECTION-SCREEN ON BLOCK <>.
****CHECK ON SELECT SCREEN INPUT
*======================================================================*
* Report Events
*======================================================================*
*** initial data
INITIALIZATION.
*** prepare report data
START-OF-SELECTION.
*########
PERFORM get_data.
**#ò######
* PERFORM write_data.
*** output report
END-OF-SELECTION.
*======================================================================*
* List Events
*======================================================================*
*** page header
TOP-OF-PAGE.
*** page header after first list
TOP-OF-PAGE DURING LINE-SELECTION.
*** page footer
END-OF-PAGE.
*** when double click
AT LINE-SELECTION.
PERFORM line_sel.
*** when click some icon (function code)
*at user-command.
*&---------------------------------------------------------------------*
*& Form get_data
*&---------------------------------------------------------------------*
* ########
*----------------------------------------------------------------------*
FORM get_data .
IF NOT p_tcode IS INITIAL.
SELECT SINGLE * FROM tstc WHERE tcode EQ p_tcode.
ELSEIF NOT p_pgmna IS INITIAL.
tstc-pgmna = p_pgmna.
ENDIF.
IF sy-subrc EQ 0.
SELECT SINGLE * FROM tadir
WHERE pgmid = 'R3TR'
AND object = 'PROG'
AND obj_name = tstc-pgmna.
MOVE : tadir-devclass TO v_devclass.
IF sy-subrc NE 0.
SELECT SINGLE * FROM trdir
WHERE name = tstc-pgmna.
IF trdir-subc EQ 'F'.
SELECT SINGLE * FROM tfdir
WHERE pname = tstc-pgmna.
SELECT SINGLE * FROM enlfdir
WHERE funcname = tfdir-funcname.
SELECT SINGLE * FROM tadir
WHERE pgmid = 'R3TR'
AND object = 'FUGR'
AND obj_name EQ enlfdir-area.
MOVE : tadir-devclass TO v_devclass.
ENDIF.
ENDIF.
SELECT * FROM tadir INTO TABLE jtab WHERE pgmid = 'R3TR' AND
object IN ('SMOD', 'SXSD') AND
devclass = v_devclass.
SELECT SINGLE * FROM tstct WHERE sprsl EQ sy-langu AND
tcode EQ p_tcode.
FORMAT COLOR COL_POSITIVE INTENSIFIED OFF.
WRITE:/(19) 'Transaction Code - ',
20(20) p_tcode,
45(50) tstct-ttext.
SKIP.
IF NOT jtab[] IS INITIAL.
WRITE:/(105) sy-uline.
FORMAT COLOR COL_HEADING INTENSIFIED ON.
SORT jtab BY object.
DATA : wf_txt(60) TYPE c,
wf_smod TYPE i ,
wf_badi TYPE i ,
wf_object2(30) TYPE c.
CLEAR : wf_smod, wf_badi , wf_object2.
LOOP AT jtab INTO wa_tadir.
AT FIRST.
FORMAT COLOR COL_HEADING INTENSIFIED ON.
WRITE:/1 sy-vline,
2 'Enhancement/ Business Add-in',
41 sy-vline ,
42 'Description',
105 sy-vline.
WRITE:/(105) sy-uline.
ENDAT.
CLEAR wf_txt.
AT NEW object.
IF wa_tadir-object = 'SMOD'.
wf_object2 = 'Enhancement' .
ELSEIF wa_tadir-object = 'SXSD'.
wf_object2 = ' Business Add-in'.
ENDIF.
FORMAT COLOR COL_GROUP INTENSIFIED ON.
WRITE:/1 sy-vline,
2 wf_object2,
105 sy-vline.
ENDAT.
CASE wa_tadir-object.
WHEN 'SMOD'.
wf_smod = wf_smod + 1.
SELECT SINGLE modtext INTO wf_txt
FROM modsapt
WHERE sprsl = sy-langu
AND name = wa_tadir-obj_name.
FORMAT COLOR COL_NORMAL INTENSIFIED OFF.
WHEN 'SXSD'.
* * for badis
wf_badi = wf_badi + 1 .
SELECT SINGLE text INTO wf_txt
FROM sxs_attrt
WHERE sprsl = sy-langu
AND exit_name = wa_tadir-obj_name.
FORMAT COLOR COL_NORMAL INTENSIFIED ON.
ENDCASE.
WRITE:/1 sy-vline,
2 wa_tadir-obj_name HOTSPOT ON,
41 sy-vline ,
42 wf_txt,
105 sy-vline.
AT END OF object.
WRITE : /(105) sy-uline.
ENDAT.
ENDLOOP.
WRITE:/(105) sy-uline.
SKIP.
FORMAT COLOR COL_TOTAL INTENSIFIED ON.
WRITE:/ 'No.of Exits:' , wf_smod.
WRITE:/ 'No.of BADis:' , wf_badi.
ELSE.
FORMAT COLOR COL_NEGATIVE INTENSIFIED ON.
WRITE:/(105) 'No userexits or BADis exist'.
ENDIF.
ELSE.
FORMAT COLOR COL_NEGATIVE INTENSIFIED ON.
WRITE:/(105) 'Transaction does not exist'.
ENDIF.
ENDFORM. " get_data
*&---------------------------------------------------------------------*
*& Form line_sel
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM line_sel .
DATA : wf_object TYPE tadir-object.
CLEAR wf_object.
GET CURSOR FIELD field1.
CHECK field1(8) EQ 'WA_TADIR'.
READ TABLE jtab WITH KEY obj_name = sy-lisel+1(20).
MOVE jtab-object TO wf_object.
CASE wf_object.
WHEN 'SMOD'.
SET PARAMETER ID 'MON' FIELD sy-lisel+1(10).
CALL TRANSACTION 'SMOD' AND SKIP FIRST SCREEN.
WHEN 'SXSD'.
SET PARAMETER ID 'EXN' FIELD sy-lisel+1(20).
CALL TRANSACTION 'SE18' AND SKIP FIRST SCREEN.
ENDCASE.
ENDFORM. " line_sel
*Extracted by Mass Download version 1.4.1 - E.G.Mellodew. 1998-2019. Sap Release 731
BTE的快速查找
BTE 通常存在于总账会计 (FI-GL)、应收账款和应付账款(FI-AR 和 FI-AP)以及销售和分销组件中。
BTE 有一个预定义的接口,允许您以服务功能模块的形式附加附加功能。您必须使用您之前指定的参数创建功能模块。BTE 由 SAP 标准程序通过调用函数 OPEN_FI_PERFORM_ 或 OUTBOUND_CALL_ 来调用。此函数根据自定义检查是否有任何活动的 BTE。
BTE的接口类型有以下两种:
使用或者达到数据检查的目的。
在标准程序中查找String ‘OPEN_FI_PERFORM’,
如果找到的函数末尾是’_E’,则说明这是Publishand Subscribe Interface:,
如果找到的函数末尾是’_P’,则是ProcessInterface。
①在源代码中通过搜索字符串'OPEN_FI_PERFORM'或者'OUTBOUND_CALL_'
以FB02为例:
②直接在FIBF中根据描述查找
③通过在函数BF_FUNCTIONS_FIND(对应P/S接口)或者PC_FUNCTION_FIND(对应Process接口)中打断点来进行查找
在FIBF的清单中根据这里找到的编号就能确定具体哪个BTE可以使用。
BADI的快速查找
- 第三代增强 BADI(business add-in),基于面向对象概念的增强,源代码发布以接口的方式,通过接口的方法调用来实现。
- 用户增强实际上是实现一个或多个基于这个接口的实现类,因为接口类实际上是一个抽象类,所以对同一个增强可以实现不同的源代码,这些不同的源代码是通过过滤器(adapter)来区别用于不同的业务场景的。
- BADI中一个接口可以被实现多次(即定义多个实现类),如果勾选了“可重用”选项,则所有实现都会被执行,如果没有勾选,虽然可以有多个实现,但只能有一个被激活,否则会发生运行时异常。
- BADI对象的信息存储在 SXS_INTER,SXC_EXIT,SXC_CLASS 和 SXC_ATTR 这四个表中(位于SECE包中)。
- SAP程序都会调用 cl_exithandler=>get_instance 来判断 BADI 对象是否存在,存在则返回实例; get_instance 其实就是对上述几个表和他们的视图(V_EXT_IMP和V_EXT_ACT)进行查询和搜索。
- 可以使用ST05来跟踪一个TCODE的执行过程,然后选择查找有关上述几个表和视图的操作,来获得相关BADI信息。
- NEW BADI则是基于GET BADI来判断BADI对象是否存在,通过CALL BADI进行调用。
①通过CL_EXITHANDLER=>GET_INSTANCE方法进行查找经典BADI
SE24输入类名CL_EXITHANDLER,并在方法GET_INSTANCE对应位置打上断点后,执行要查找增强的TCODE。
EXIT_NAME即为BADI名称,SE18输入对应BADI名称,根据描述及对应方法的参数判断是否适用。
②通过CALL BADI断点的方法进行查找NEW BADI
先输入/H回车,激活调试模式,然后操作完之后点击保存。
设置好断点后,F8执行,经过所有增强点时,都会停止。
CLASS后面的即为增强点,SE18输入对应增强点,根据描述及对应方法的参数判断是否适用。
SE18输入增强点名称,查看对应方法以及是否可以使用。
③通过ST05跟踪的方式查找
执行ST05事务代码,选中Buffer Trace后,点击激活跟踪,然后执行标准前台操作。
前台操作完之后,回到ST05,按顺序点击按钮,查看跟踪结果信息。
Source Code Enhancements的快速查找
显式增强:由SAP开发人员定义到程序源码中的 Enhancement options,分为两种方式。
- 标记增强选项的位置:
ENHANCEMENT-POINT <name> SPOTS <spot1> [<spot2>] [STATIC] ...
静态增强语句=>附加声明
动态增强语句=>附加源代码
- 标记增强选项的部分:
ENHANCEMENT-SECTION <name> SPOTS <spot1> [<spot2>] [STATIC]
...
END-ENHANCEMENT-SECTION.
静态增强语句=>替换现有声明
动态增强语句=>替换现有源代码
隐式增强:始终存在,并且不会分配给增强点。
在 ABAP 程序中,隐式增强选项在以下位置预定义:
- 在包含的末尾。有一些限制,例如,不在方法末尾包含。
- 在局部类的末尾。PUBLIC-PROTECTED-PRIVATE-SECTION。
- 在类的实现部分的末尾。ENDCLASS CLASS … IMPLEMENTATION。
- 在接口定义的末尾。ENDINTERFACE。
- 在结构定义的末尾。TYPES END OF DATA END OF CONSTANTS END OF STATICS END OF。
- 在过程的开头和结尾 。FORM FUNCTION METHOD ENDFORM ENDFUNCTION ENDMETHOD。
显示增强查找
以VL10C为例,通过菜单栏“系统”->“状态”,找到标准程序名称,双击进入程序源码。
点击GUI状态栏 按钮
此时程序最左侧箭头所指的行即为显示增强点,将光标置于目标行,点击上方创建按钮,即可创建对应的增强实施。
隐式增强查找
以VL10C为例,通过菜单“编辑”->“增强操作”->“显示,隐式增强选项”来显示隐式增强位置。
点击GUI状态栏按钮,显示出可操作隐式增强的位置。
选中想要增强的位置,点击上方“创建”按钮,即可进行增强实施的创建。
5.增强实施的注意点
- 仅在标准配置无法实现的情况下再考虑增强,不要无脑使用增强。
- 仅在USER-EXIT、CMOD/SMOD、BADI都无法实现时再考虑显示或隐式增强。
- 尽量避免直接修改源码的方式进行增强,会在系统升级后被覆盖。
- 尽量避免使用隐式增强,因为可能会在系统升级后丢失。
- 关于“声明”和“代码”的区别,这里有一篇帖子做了详细的介绍,简单来讲“声明”不受业务功能开关控制,“代码”则受业务功能开关控制。
- Static Enhancement vs Dynamic Enhancement | SAP Blogs
- 在开发初期测试增强时,最好以IF SY-UNAME = ‘XXX’包裹代码,避免影响系统中其他人的使用。
- 在BADI实施时,最好在一开始将所有类方法都激活后再针对某一类方法去做编码,避免后续请求传输报错。
- 关于增强中需要针对创建、更改、查看进行逻辑区分的,尽量使用系统标准字段T180-TRTYP来区分,H创建,V更改,A显示,避免用TCODE去判断。
以上,希望对各位读者有所帮助。