(轉)BDC技術

mmccking發表於2007-09-25
寫的很清晰~![@more@]
首先簡單解釋一下BDC(Batch Data Conversion):
在SAP系統裡,由於某種原因,可能需要重複輸入資料,(資料不同,但是操作是相同的,典型的情形就是切換系統的時候,舊系統的資料需要匯入SAP),大致過程不外乎是這樣: 輸入一個t-code,
進入一個某個螢幕,然後輸入一個值(有時還要加上一些附加的checkbox選項等),點執行或者確定按鈕,
進入另一個螢幕,在某些欄位輸入值(也可能是標註checkbox選中或者不選中)或者修改這些欄位裡的值。
然後按“Eneter”……
最後按“SAVE”……,
一條記錄完成了,繼續下一條,如此迴圈。

上面所述的情形,如果讓一個“人”來做的話,可能是真是受不了的。但是對於計算機來說,就很簡單了。

SAP透過一個特殊的程式(T-code:SHDB)把使用者的一次業務操作的所有過程記錄下來。

從使用者輸入transaction code(事務程式碼),點下“Start Recording”開始,對於使用者的來說是一次普通的業務操作,但是SAP卻在記錄:
1.游標放到哪個欄位,(在程式中不用改變)
2.填入了什麼值,(變數,迴圈中的Internal Table 某個欄位)
3.點選了什麼按鈕(在程式中不用改變)

本次操作的作為一個“代表”,是一個“模板”,告訴SAP系統以怎樣的方式來執行程式,也就是用計算機的語言來描述如果手工操作的話應該是怎樣的一個過程。


用BDC技術程式設計時,有以下幾個步驟:
1.把外部的資料來源(Txt,Excel等)用讀進internal table或者用do enddo迴圈。
2.在迴圈裡,把用SHDB記錄的步驟重複執行N次,(N = Dialog螢幕數量)這時實際上並沒行完成資料的入,系統只是在“填表”,填一個叫做“BDCData”的Internal Table。
填完bdcdata以後,用call transaction ‘XXXX’ using bdc……這個命令來真正的commit動作或者call function 'BDC_Insert'在建立一個session。並把執行的結果返回給messtab這個Internal Table

現在假想一種情境,來做一個演示的BDC程式。
由於業務上的需要,某公司打算將某些物料的描述都在後面加上指定的文字Group X,所以需要修改已經存在的物料資料,用T-code:MM02,

外部資料是TXT文字,記錄有N條,如下:

Material NO. Description
6000-00001 XXXXXXX(Group A)
2098-00001 fdfladsfladfl(Group B )
2059-00009 dfdsfreddfalfasfa(Group A)
2003-00003 iadfdafdf,adfasf(Group D)
……
……
下面是“錄”操作的過程,在命令欄裡輸入T-code :SHDB,進入如下螢幕:

點New Recodring,出現如下螢幕:

其中Recording 的名字是任意給的。MM02是需要錄的事務程式碼。

按下“Start Recording”,就會進入“Change Material”,這時,以下的操作對於使用者來說是一次普通修改物料描述操作,儘管系統在記錄所有的操作。


輸入一個物料後,點選“Select View(s)”



假設我們只選“Basic Data 1”和“Basic Data 1”
然後點選綠色的小勾“Enter”

我們在該物料後面新增一個“Group A”,描述改為:


……

然後點“SAVE”,儲存這次修改。

現在SAP回到了SHDB,

先點“SAVE”,儲存Recording :Ztest,然後點”Back”,返回SHDB的第一屏。

選中“Ztest”,然後點選“Program”,由SAP自動生成一個程式。


在上面的對話方塊中輸入程式的名字(注意SAP的命名規範,Y或者Z開頭),確認輸入

再輸入一些程式的屬性資訊如下:

點選“Source Code”,指定“Develop Class”等後,就可以進入ABAP Editor,產生如下程式碼:

report ZBDCTEST
no standard page heading line-size 255.

include bdcrecx1.

parameters: dataset(132) lower case.
*** DO NOT CHANGE - the generated data section - DO NOT CHANGE ***
*
* If it is nessesary to change the data section use the rules:
* 1.) Each definition of a field exists of two lines
* 2.) The first line shows exactly the comment
* '* data element: ' followed with the data element
* which describes the field.
* If you don't have a data element use the
* comment without a data element name
* 3.) The second line shows the fieldname of the
* structure, the fieldname must consist of
* a fieldname and optional the character '_' and
* three numbers and the field length in brackets
* 4.) Each field must be type C.
*
*** Generated data section with specific formatting - DO NOT CHANGE ***
data: begin of record,
* data element: MATNR
MATNR_001(018),
* data element: XFELD
KZSEL_01_002(001),
* data element: XFELD
KZSEL_02_003(001),
* data element: MAKTX
MAKTX_004(040),
* data element: MEINS
MEINS_005(003),
* data element: MTPOS_MARA
MTPOS_MARA_006(004),
* data element: GEWEI
GEWEI_007(003),
end of record.

*** End generated data section ***

start-of-selection.

perform open_dataset using dataset.
perform open_group.

do.

read dataset dataset into record.
if sy-subrc <> 0. exit. endif.

perform bdc_dynpro using 'SAPLMGMM' '0060'.
perform bdc_field using 'BDC_CURSOR'
'RMMG1-MATNR'.
perform bdc_field using 'BDC_OKCODE'
'=AUSW'.
perform bdc_field using 'RMMG1-MATNR'
record-MATNR_001.
perform bdc_dynpro using 'SAPLMGMM' '0070'.
perform bdc_field using 'BDC_CURSOR'
'MSICHTAUSW-DYTXT(02)'.
perform bdc_field using 'BDC_OKCODE'
'=ENTR'.
perform bdc_field using 'MSICHTAUSW-KZSEL(01)'
record-KZSEL_01_002.
perform bdc_field using 'MSICHTAUSW-KZSEL(02)'
record-KZSEL_02_003.
perform bdc_dynpro using 'SAPLMGMM' '4004'.
perform bdc_field using 'BDC_OKCODE'
'=BU'.
perform bdc_field using 'BDC_CURSOR'
'MAKT-MAKTX'.
perform bdc_field using 'MAKT-MAKTX'
record-MAKTX_004.
perform bdc_field using 'MARA-MEINS'
record-MEINS_005.
perform bdc_field using 'MARA-MTPOS_MARA'
record-MTPOS_MARA_006.
perform bdc_field using 'MARA-GEWEI'
record-GEWEI_007.
perform bdc_transaction using 'MM02'.

enddo.

perform close_group.
perform close_dataset using dataset.

上面的程式的主要邏輯為:

open dataset “讀取外部資料來源

do.“迴圈

perform 填充BDCDATA子程式
perform bdc_transcation

endo.

Close dataset.

注意上面的Include程式裡有兩個重要的form.

*-------------------------------------------------------------------*
* Start new screen *
*-------------------------------------------------------------------*
form bdc_dynpro using program dynpro.
clear bdcdata.
bdcdata-program = program.
bdcdata-dynpro = dynpro.
bdcdata-dynbegin = 'X'.
append bdcdata.
endform.

*-------------------------------------------------------------------*
* Insert field *
*-------------------------------------------------------------------*
form bdc_field using fnam fval.
if fval <> nodata.
clear bdcdata.
bdcdata-fnam = fnam.
bdcdata-fval = fval.
append bdcdata.
endif.
endform.

另外還有兩個重要的internal table宣告。bdcdata及messtab

* Batchinputdata of single transaction
data: bdcdata like bdcdata occurs 0 with header line.
* messages of call transaction
data: messtab like bdcmsgcoll occurs 0 with header line.

選取部分最關鍵(典型)的程式碼如下:

do.

read dataset dataset into record.“逐行讀出txt文字中的記錄,
請參:read dataset
if sy-subrc <> 0. exit. endif. “如出錯就退出

以下執行子程式(粗斜體部分)

螢幕①
A、指定bdc_dynpro的實參,告知系統dialog程式名稱:SAPLMGMM,及screen number:0060
perform bdc_dynpro using 'SAPLMGMM' '0060'.

B、指定bdc_field的實參,告知系統把游標放在哪個欄位,這裡是“RMMG1-MATNR,物料”
perform bdc_field using 'BDC_CURSOR'
'RMMG1-MATNR'.
C、告知系統ok_code是什麼,也可以認為是去點哪個按鈕,這裡是左上角的“Select View(s)”
perform bdc_field using 'BDC_OKCODE'
'=AUSW'.
這裡是透過read dataset 讀取的外部的檔案中的記錄,record是一個用於臨時儲存資料的僅有一行的work area。程式在執行進,record-matnr_001應該是一個具體的物料程式碼。
perform bdc_field using 'RMMG1-MATNR'
record-MATNR_001.

螢幕②是類似的
perform bdc_dynpro using 'SAPLMGMM' '0070'.
perform bdc_field using 'BDC_CURSOR'
'MSICHTAUSW-DYTXT(02)'.
perform bdc_field using 'BDC_OKCODE'
'=ENTR'.
perform bdc_field using 'MSICHTAUSW-KZSEL(01)'
record-KZSEL_01_002.
perform bdc_field using 'MSICHTAUSW-KZSEL(02)'
record-KZSEL_02_003.

③同樣先指定程式名稱及螢幕號,然後指定游標位置,值,OK_Code
perform bdc_dynpro using 'SAPLMGMM' '4004'.
perform bdc_field using 'BDC_OKCODE'
'=BU'.
perform bdc_field using 'BDC_CURSOR'
'MAKT-MAKTX'.
perform bdc_field using 'MAKT-MAKTX'
record-MAKTX_004.
perform bdc_field using 'MARA-MEINS'
record-MEINS_005.
perform bdc_field using 'MARA-MTPOS_MARA'
record-MTPOS_MARA_006.
perform bdc_field using 'MARA-GEWEI'
record-GEWEI_007.

以上的步驟實際上在一個叫做bdcdata的internal table中填入了一些關於呼叫哪個程式(包括螢幕號碼),在哪些欄位中,填入什麼值,點選什麼按鈕等資訊。
下面的一個步驟才真正的向系統寫入資料
call function 'BDC_Insert',建立session,一般是後臺執行,能給出Log資訊

call transaction不建立session,直接執行。
執行後返回的訊息儲存在messtab中。

perform bdc_transaction using 'MM02'.

enddo.

perform close_group.
perform close_dataset using dataset.



再給一個簡明的非SAP自動生成的程式如下(舊版SAP31I),這個程式略去了讀取外部資料的程式,沒有用迴圈,只是用Matnr從螢幕上接收使用者輸入的一個物料。

REPORT ZBDC1 .

TABLES:MARA.

DATA:BEGIN OF BDCDATA OCCURS 0.
INCLUDE STRUCTURE BDCDATA.
DATA:END OF BDCDATA.

PARAMETERS:MATNR LIKE MARA-MATNR.
PARAMETERS:P_MODE TYPE C DEFAULT 'N'.

START-OF-SelectION.
PERform PROCESS_CC02.
PERform PROCESS_CC03.
PERform PROCESS_CC04.
PERform PROCESS_CC05.
CALL TRANSACTION 'MM02' USING BDCDATA MODE P_MODE Update 'S'.
END-OF-SelectION.

form PROCESS_CC02.
PERform BDC_DYNPRO USING 'SAPLMGMM' '0060'.
PERform BDC_FIELD USING 'BDC_OKCODE' '/00'.
PERform BDC_FIELD USING 'RMMG1-MATNR' MATNR.
ENDform. "process_cc02

form PROCESS_CC03.
PERform BDC_DYNPRO USING 'SAPLMGMM' '0070'.
PERform BDC_FIELD USING 'BDC_OKCODE' 'ENTR'.
PERform BDC_FIELD USING 'MSICHTAUSW-KZSEL(11)' 'X'.
ENDform. "process_cc03

form PROCESS_CC04.
PERform BDC_DYNPRO USING 'SAPLMGMM' '0080'.
PERform BDC_FIELD USING 'BDC_OKCODE' 'ENTR'.
PERform BDC_FIELD USING 'RMMG1-WERKS' 'TH10'.
ENDform. "process_cc04

form PROCESS_CC05.
PERform BDC_DYNPRO USING 'SAPLMGMM' '3000'.
PERform BDC_FIELD USING 'BDC_OKCODE' 'BU'.
ENDform. "process_cc05

form BDC_DYNPRO USING PROGRAM DYNPRO.
CLEAR BDCDATA.
BDCDATA-PROGRAM = PROGRAM.
BDCDATA-DYNPRO = DYNPRO.
BDCDATA-DYNBEGIN = 'X'.
APPEND BDCDATA.
ENDform.

form BDC_FIELD USING FNAM FVAL.
CLEAR BDCDATA.
BDCDATA-FNAM = FNAM.
BDCDATA-FVAL = FVAL.
APPEND BDCDATA.
ENDform.


總結一下:
對於一個BDC程式來說,

有兩個固定的internal table 需要宣告:bdcdata和messtab,名稱可以變,但是宣告時一定要
* Batchinputdata of single transaction
data: abc like bdcdata occurs 0 with header line.
* messages of call transaction
data: def like bdcmsgcoll occurs 0 with header line.
Like 後面的table type(這裡是一個structure)是不能改變的。

有兩個固定功能的form:bdc_dynapro和 bdc_field
名稱同樣是任意的,但是程式程式碼應該是相同的,

(強烈建議不要改動,因為會給自己新增麻煩)

另個還有一個Internal Table或者work area是用來放從外部讀進來的資料的,結構應該和你的外部檔案的有相關的欄位結構。

一次讀進全部的記錄然後迴圈處理 loop at [internal table] …… process……endloop。
或者一條一條讀進並處理,然後迴圈讀下一條 do …… process…… enddo。

其中Process 分為兩個部分:1.填充bdcdata表。
2.Call transaction or Call Function ‘BDC_Inser’返回訊息放入Messtab.

另外有一個經驗之談:

1、錄“操作”的時候,不要有“多餘”的操作,(什麼是多餘的操作?自己思考吧)如果有,就重新錄吧,不然這些操作也被記錄下來,程式每次都要做一些不必要的動作。
2、儘量用滑鼠去點選按鈕,而不要只是敲“Enter”。
3、游標的位置一般也可以不指定,也就是perform bdc_field using ‘BDC_CURSOR’ ‘XXXX-XXXX’通常可以不用寫。不過,據說有時候去了也會出問題,加上去就沒了,這個我就不知道了。呵~

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8356764/viewspace-972231/,如需轉載,請註明出處,否則將追究法律責任。

相關文章