1. 程式人生 > >ABAP增強總結

ABAP增強總結

  做過的增強不多,之前做過一次使用者登陸增強而已,增強點都是找好的,基本上就是照著文件一步步實現。早就看過很多增強的相關文件,每次都是零零星星的看看,再加上增強的需求做得少,導致很多東西僅僅停在知道的層面,打算明年年初換專案,最近也在忙著面試,增強又是面試問的比較多的知識點,於是打算系統的總結下!
注:本文參考sap師太部落格,在此感謝師太的部落格,知識在於分享!

開發人員所說的增強主要是標準系統事先預留好的介面,根據不同業務需求來進行開發,稱為增強,又叫出口(EXIT)。隨著SAP ABAP的迭代,一共推出了四代增強(ABAP貌似好多年沒更新迭代了)。
- 第一代:基於原始碼的增強
- 第二代:基於出口函式的增強
- 第三代:基於類的增強
- 第四代:基於增強點的增強

1. 第一代增強:基於原始碼的增強

​  第一代增強基於原始碼,是SAP系統提供一個空程式碼的子過程(subroutine:From)。在這個子過程中使用者可以新增自己的程式碼,控制自己的需求。這類增強都需要修改SAP標準程式碼,它們釋出時都是空的,集中在一些檔名倒數第二個字元為Z的包含程式中。由於是在標準程式中,所以所有程式的全域性資料都可以使用,但同時系統升級時會被新版本覆蓋

​  這種原始碼增強和螢幕增強的說明可以從事務碼SPRO後臺配置中相關模組的路徑中找到:一般是以UserExit_開頭的子模組,可形象的稱其為使用者出口

  Form原始碼增強事先要到 service marketplace

 申請物件鍵(ACCESS KEY),然後才能修改這些子程式,不過可以隱藏增強來實現,這樣就不需要直接修改原始碼了

查詢此類出口的方法:

  • 在增強主程式中找倒數第二個字元為Z的包含程式
  • 通過SPRO在後臺找對應的模組增強
  • 在程式中搜索USEREXIT_開頭的關鍵字子程式
  • 開啟想增強的程式,點選工具欄上的”Display Object List”按鈕,選擇Subroutine,查詢以”UserExit”開頭的子程式,根據子程式前面的註釋文件來查詢使用者出口

2. 第二代:基於出口函式的增強

​  第二代增強(基於函式模組的增強)用事務SAP增強管理(事務程式碼:SMOD)和增強編譯器(事務程式碼:CMOD)維護。在SAP釋出的版本中(如VA01對應的程式SAPMV45A的原始碼中),使用Call Customer-Function ‘XXX’ 呼叫函式模組,所以可以通過在程式中搜索Customer-Function來查詢第二代增強,第二代增強函式名構成為Exit_程式名_xxx_ (3 digital number)。它們在釋出的版本中只有一句程式碼 include “zxxxxxx”.

  針對資料表的增強出口是 “CI_ ”打頭的結構,這些結構將.INCLUDE 結構的形式包含到時相應的資料表中,使用者可以通過向這些結構中新增欄位從而達到對資料表字段的增加

​  第二代增強只能使用介面中傳遞進來的引數,不能像第一代增強一樣隨便使用全域性資料。

​  由於帶有關鍵字Customer,故被稱為Customer Exits(客戶出口)

第二代增強主要有四類:

  • E. Ehancement Exits (函式增強): 這些出口以Exit_開頭,可以在SE37中檢視,也可以在資料字典TFDIR中查詢Exit_開頭的函式
  • C. GUI codes (GUI增強): 用於區域選單和工具選單欄的增強
  • S. Subscreens (螢幕增強): 用於子螢幕設計增強
  • T. Include structure (表結構增強): 用於表結構的增強

    其中函式增強最常用,在SAP上線很多年後都會使用,如:銷售單VA02中,對PO長度限制在10-15位之間,且不能為中文與其他特殊字元,還有如對PO採購日期不能晚於交貨日期的檢驗等,這些都會用來函式增強;
    螢幕增強不常用,一般在上線初才會使用,上線後不常用;螢幕增強呼叫使用CALL CUSTOMER-SUBSCREEN

按用途分類:

  • 功能模組出口(Funtion Module Exits):在SAP標準事務中新增業務邏輯,一般用於驗證標準事務中的欄位
  • 螢幕出口(Screen Exits):定義自己的子螢幕用以嵌入應用螢幕,在標準事務中新增子螢幕
  • 選單出口(Menu Exits):定義自己的選單項或啟用遮蔽標準事務中的選單項
  • 表出口(Table Exits):與上面的T型出口一樣,屬於同一型別
  • 資料元素出口(Data Element Exits):在ABAP/4字典的關鍵字元素中新增文件,結果是在使用這些資料元素的欄位處按鍵後會出現自定義的說明文件
  • 關鍵字出口(Keyword Exits):在ABAP/4字典中的關鍵字資料元素更改表示文字
  • 欄位出口(Field Exits):根據ABAP/4字典中域驗證某些標準事務的某些螢幕欄位

Enhancement比較重要的表

  • MODSAP:表中重要的欄位增強名(Name)、元件型別(TYPE:ECST)、元件功能模組名(Member)裡記錄了所有Enhancement的增強

  • TFDIR:所有的函式表、重要欄位FuncName(函式名)、功能模組啟用狀態MAND如果是C,代表此函式模組啟用)

  • TSDIR:動態程式區 CALL CUSTOMER SUBSCREEN(螢幕增強)

  • CUATEXTS:修改GUI介面,選單文字被客戶改變(GUI才單文字增強)

  • MODSAPA:SAP擴充套件的屬性

  • TADIR:資源庫物件的目錄

  • TFTIT:函式功能的短文字

查詢此類出口的方法:

  1. 查詢關鍵字
    在程式中搜索Customer-function(使用工具欄上的搜尋工具),找到後面的3位數字字尾,然後出口函式組成就是Exit_程式名_3位數字字尾;螢幕增強搜尋CALL CUSTOMER-SUBSCREEN
  2. 程式碼查詢增強

  3. 利用系統函式查詢增強

    常與出口相關的函式有:

    • DYNP_VALUES_READ
    • MODX_ALL_ACTIVE_MENUENTRIES(選單增強)
    • MODX_FUNCTION_ACTIVE_CHECK(出口函式增強)
    • MODX_MENUENTRY_ACTIVE_CHECK(選單增強)
    • MODX_SUBSCREEN_ACTIVE_CHECK(螢幕增強)

      可以在函式最後設定斷點,然後通過執行對應的增強程式就會呼叫這樣的函式,這樣就可以在除錯模式下找到對應的增強

    eg:去se80,在function-Module中搜索MODX_FUNCTION_ACTIVE_CHECK,在程式中打斷點,如圖:

    然後執行需要增強的事務碼,如果有增強會自動跳轉到debug介面,雙擊檢視l_funcname變數可以看到需要的增強出口函式

    然後根據這個出口函式去MODSAP表中查詢增強物件

    找到出口增強物件


    接著去SMOD輸入增強物件後單擊測試(F8)檢視有哪些增強

    從上面圖中可以看到增強MM06E005包含功能出口、螢幕出口、表出口三種增強。在SMOD介面雙擊後面對應的增強名可以進行增強功能的實現。

    SMOD包含具體的增強,而CMOD是包含一組SMOD編寫的增強.

    思路:確定增強出口函式,找到對應的增強物件,CMOD/SMOD

3. 第三代:基於類的增強

基於類的增強。主要技術是基於ABAP物件來實現增強。BADI維護是通過SE18、SE19事務來來維護的。SE18用於建立及維護BADI物件;SE19用於維護BADI的例項,即實現.SAP的BADI不但可以實現對標準系統的增強,也可以直接在自定義程式中進行呼叫

​  BADI與BTE。

​  BADI是基於ABAP的面向物件技術,可以被插入到SAP系統中,以適應使用者由於行業的不同需要不同的功能以滿足具體要求。

​  基於面對物件概念的增強BADI(Business Add-in),原始碼的釋出是通過介面的方法呼叫來實現使用的。使用者增強實際上是實現一個或多個基於這個介面的實現類,因為介面類實際上是一個抽象類,所以對同一個增強會出現不同的原始碼,這些不同的原始碼是通過過濾器(Adapter)來區別用於不同的業務場景,這種增強通過SE18和SE19來實現。

​  SAP預定義了一些介面(Interface),客戶可以自行定義實現Interface的類(Class),在標準程式中會使用呼叫客戶自定義類(Class)的例項(Instance),獲取例項的過程使用了工廠模式,因此獲取過程對使用者是未知的。不過BADI也有一些侷限性,就是有一些Interface是固定的,有時候會發現需要Mix客戶化程式碼的時候找不到Interface

​  業務交易事件(BTE, Business Transaction Events)是SAP的一種增強方式,技術上講介於第二代增強和BADIS之間的產物,BTE為會計模組獨有的增強,這種增強用於財務會計模組(Open FI)、總賬會計(FI-GL)、應收賬款和應付賬款(FI-AR/FI-AP)及銷售和分銷(SD)的元件

查詢此類出口的方法

BADI的查詢方法:

  1. BADI物件的資訊儲存在SXS_INTER,SXC_EXIT,SXC_CLASS和SXC_ATTR這四個表中。

  2. 主程式都會呼叫cl_exithandler=>get_instance來判斷物件是否存在,並返回例項。我們可以開啟類編輯器se24中,輸入類CL_EXITHANDLER,並進入get_instance方法,設定斷點,執行一個tcode,看一下exit_name的值,這就是要找的BADI。

  3. se37 檢視SXV_GET_CLIF_BY_NAME,設定斷點,檢視name的值。

  4. 它的呼叫方式是call method(instance), 可以通過exit_handler關鍵詞來查詢。

  5. ST05:
    1)選擇SQL trace、buffer trace,然後activate trace ,執行TCODE ,deactivate trace
    2)display trace,顯示display trace的對話方塊,在表的欄位上加上? V_EXT_IMP和 V_EXT_ACT
    3) 檢視以IF_EX_開頭的字串,這是interface class 的名字,IF_EX_後面的就是BADI。例如IF_EX_EQUI_UPDATE
  6. se18 查詢介面,se19 實現介面就可以實現使用者增強

BADI使用方法:
BADI Definition是通過SE18->Utilities->Create Classic BAdi,實現BAdi是通過SE19;
在屬性介面勾選多次使用(Multiple Use)只顯示兩個標籤頁,不勾選有四個標籤頁

一個badi包含著enhancement components,其主要包含下面幾種components:
- Program enhancements:program enhancements是通過interface methods來實現的,SAP程式來調取生成的badi class的interface methods。對應介面標籤頁(interface)
- Menu enhancements:同customer exit一樣,可以在badi中維護function code。這些menu entry在GUI definition中已經定義就可以在implemented badi看見。對應功能碼標籤頁(Fcode)
- Screen enhancements:同customer exit一樣你可以在badi中維護screen enhancements。對應子螢幕標籤頁(SUBSCREEN)

雙擊建立介面,並新增方法和引數

建立實現 Implementation->Create

在程式中呼叫badi,直接使用cl_exithandler=>get_instance
eg:

DATA: out TYPE string.
DATA: l_badi_instance TYPE REF TO zif_ex__badidef_baditest2.“zif_ex__badidef_baditest2是BAdi Definition的Interface name
CALL METHODcl_exithandler=>get_instanceCHANGINGinstance               = l_badi_instance.

IFl_badi_instanceISNOTINITIAL.
  CALLMETHODl_badi_instance->testEXPORTINGin = 'hello'
    CHANGINGout = out.
  WRITE: / out.
ENDIF.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

4. 第四代:基於增強點的增強

  其實是第三代的加強switch Framework;
  當sap進入newweaver 7.0以後推出的新增強體系,將BADI進行了改進,叫新BADI了。還新增Enhancement Spot 和 Enhancement Section 以及隱式增強點的概念,基本可以在面向物件的程式裡實現處處皆可增強的最高境界。

BADI使用方法(新式):
1. SE18建立一個自定義的BADI增強點(Enhancement Spot)物件

  1. 建立BADI物件

  1. BADI物件由介面和實現組成,建立一個介面

  1. 在新建的介面中新建方法,並新增引數

  1. 建立BADI實現並編輯實現類

確定後進入 Enhancement Implementation 頁面

雙擊實施類進行編輯

雙擊方法建立實施

  1. 在程式中直接呼叫BADI

使用GET BADI語句

parameters: filter(2) type c.
DATA: handle TYPE REF TO z_badi_calc_vat,"z_badi_calc_vat為BADI定義,不是介面也不是類
sum TYPE p,
vat TYPE p,
percent TYPE p.
sum = 50.

GET BADI handle
  FILTERS"SE18中定義的過濾器名作為這裡的引數名
    filter1 = 'C'.

CALL BADI handle->get_vat
  EXPORTING
    im_amount      = sum
  IMPORTING
    ex_amount_vat  = vat
    ex_percent_vat = percent.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Filter-Depend過濾器

  當BADI的某個實現版本有多個實現類時,這時在呼叫時如果想要呼叫指定的類,則需新增過濾器引數,該引數實質上由其代理類來使用,在執行時代理類會去例項化所對應的類。

加上該選項後,介面與實現類中的所有方法都會自動的加上一個必輸引數:FLT_VAL

DATA: out TYPE string.
DATA: l_badi_instance TYPE REF TO zif_ex__badidef_baditest2.
CALL METHODcl_exithandler=>get_instanceCHANGINGinstance = l_badi_instance.

IFl_badi_instanceISNOTINITIAL.
  CALLMETHODl_badi_instance->testEXPORTING
      "flt_val引數是由l_badi_instance例項來使用的,從這裡可以推斷
      "l_badi_instance應該屬於代理物件,由它在執行時根據過濾器值
      "來選擇性的呼叫相應實現類的方法
      flt_val = '800'
      in      = 'hello'
    CHANGINGout     = out.
  WRITE: / out.
ENDIF.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

Filter type擴充套件性侷限於以下幾個方面:
- Filter type參考的domain必須符合下面的幾個條件:
- Domain要指向cross client value table。這個value table只有一個使用的data element的domain是這個domain的key field。
- Domain有一個兩個key field的text table,一個key field使用的是這個domain本身,另一個key field是language field。其必須還得有一個text field,這個text field的型別為TEXT或TXT。在ABAP DICTIONARY中必須給text field指定一個value table。
- 這兩個table的delivery class必須是E或S

BAdi總結

如果badi被啟用,當呼叫程式執行時,相應的implementation methods也會被執行。一旦diactivate這個implementation,相應的方法就不會被呼叫。然而應用程式中的相關呼叫仍然會被執行。不同的是adapter class的instance不會找到啟用的implementations。並不像CALL CUSTOMER-FUNCTION,CALL METHOD CL_EXITHANDLER=>GET_INSTANCE即使沒用implementations,仍然會被呼叫。只有在original system(開發系統)中才可以activate或deactivate implementations,而subsequent systems則只能transport。如果badi只能有一個implementation,那麼系統中仍然可以存在這個badi的多個implementation,只不過只能有一個啟用版本。

同customer exit一樣badi中也有menu enhancements。但是必須滿足以下兩個條件:1,必須預留了menu enhancement。2,必須在Badi的implementation中實現。Menu enhancements的function codes必須以+開始。如果相應的enhancement的badi implementation被啟用,那麼menu就會顯示出來。你只能為single use badi建立function code,而且badi不能是filter dependent。這樣就保證了一個或多個的badi不出現矛盾。如果使用者在程式中選擇了相應的以+開始的function code,那麼系統就會呼叫相應的method。Method call和Menu enhancement是不可分離的,它們只能屬於同一個badi。

通過badi builder SE18來建立badi。Badi有兩個重要的屬性,Reusable和filter-dependent。如果想讓你的badi支援多個啟用的implementation那麼就要選擇reusable。不過implementations的執行順序不能被定義。即使badi本身不支援mulitiple use也可以同時存在多個implementations,只不過只能有一個啟用的implementation。Badi如果filter dependent的,這樣就可以設定呼叫的條件。Filter type必須是data element或者ABAP dictionary structure。Data element使用的domain的value table包含了implementation所需要的valid values。如果filter type使用的是structure,那麼這適用於structure的每個欄位。當呼叫enhancement method時,filter value必須傳給interface。Badi中可以包含function code,需要輸入program name,function code以及short description。侷限性是不能夠建立只包含function code的badi,menu enhancement既不能filter dependent也不能reusable。

系統提供了badi的interface和生成class的name。理論上可以將這些name改成任何你喜歡的name,但是保留系統推薦的name會使badi更加容易理解。生成的class的name遵循以下規則:namespace prefix(Z/Y) + CL_ + EX_(代表 exit) + badi name。雙擊interface name就會進入class builder,就可以定義interface method。一個badi indterface可以有多個interface method。Class bulder的所有功能都可以使用,如定義interface method,定義method的interface parameters以及宣告interface的attributes等。如果badi是filter dependent的,必須給他的每個method定義一個import parameter flt_val(具體怎麼做請參著這裡)。一旦完成了interface的定義就要啟用它。一旦修改了interface,badi class也會重新生成。也可以在badi維護事務中通過utilities->Regenerate來重新生成adapter class。Badi在程式中的呼叫過程:首先宣告一個badi interface的reference variable。呼叫service class CL_EXITHANDLER的static method GET_INSTANCE。這個method返回required object的instance。這裡屬於narrow cast(窄化),所以通過這個variable只能呼叫interface methods。然後你就可以呼叫badi的方法了