BDC、CATT批量数据维护
BDC批量数据导入
BDC(Batch Data Communication),是SAP系统数据传输的主要技术之一,主要用于把数据大量大批输入到SAP系统。
BDC方法与ABAP编程的关系密切,因此相对于LSMW、CATT等其他数据传输方式,BDC方法更灵活。
BDC是模拟屏幕操作(与按键精灵相似),记录相关屏幕出现顺序和处理过程,产生数据录入的格式文件,通过调整数据文件后,再运行BDC产生ABAP程序,最后可能生成的ABAP程序进行修改,得到最终的数据录入代码片断
SM35(包含SHDB)录屏操作
该界面列出了所有通过BDC所执行的会话记录:
输入事务码AS02后,点击“开始记录”按钮,将会跳到AS02维护界面:
保存数据后,生成记录:
如果是触发PAI事件,则会使用 BDC_OKCODE 的字段来存储相应的FunctonCode
从生成的录屏记录来看,不能确认界面上哪些字段会被录入,哪些字段不会被录入:没输入的(“次级编号”)有的录了,但有的又没录上(“数量”等等没输入就没录进),但可以肯定一点的是不能编辑的输入框是不会被录入的。所以哪些录入哪些不录入,并没有找到规则。
生成程序
带服务器端测试数据文件
运行生成的报表程序如下:
REPORT
zas02
NO STANDARD PAGE
HEADING LINE-SIZE
255.
INCLUDE
bdcrecx1.
PARAMETERS:
dataset(132)
LOWER CASE DEFAULT
'AS02_FILE'.
*** 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: ANLN1
anln1_001(012),
* data element: ANLN2
anln2_002(004),
* data element: BUKRS
bukrs_003(004),
* data element: TXA50_ANLT
txt50_004(050),
* data element: ANLHTXT
anlhtxt_005(050),
* data element: AKTIVD
aktiv_006(010),
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
'SAPLAIST' '0100'.
PERFORM
bdc_field USING
'BDC_CURSOR'
'ANLA-BUKRS'.
PERFORM
bdc_field USING
'BDC_OKCODE'
'/00'.
PERFORM
bdc_field USING
'ANLA-ANLN1'
record-anln1_001.
PERFORM
bdc_field USING
'ANLA-ANLN2'
record-anln2_002.
PERFORM
bdc_field USING
'ANLA-BUKRS'
record-bukrs_003.
PERFORM
bdc_dynpro USING
'SAPLAIST' '1000'.
PERFORM
bdc_field USING
'BDC_OKCODE'
'=BUCH'.
PERFORM
bdc_field USING
'BDC_CURSOR'
'ANLA-TXT50'.
PERFORM
bdc_field USING
'ANLA-TXT50'
record-txt50_004.
PERFORM
bdc_field USING
'ANLH-ANLHTXT'
record-anlhtxt_005.
PERFORM
bdc_field USING
'ANLA-AKTIV'
record-aktiv_006.
"该Form实际上就是通过下面语句来实现的,同时包括了对运行
"过程中产生的消息进行了处理,调用该Form时不需要再对消息
"进行额外的处理。客制化(如消息状态以红绿灯方式来显示)消息处理可以参考《ABAP
Practical Example App.docx》文档
* CALL TRANSACTION TCODE USING BDCDATA
* MODE CTUMODE
* UPDATE CUPDATE
* MESSAGES INTO MESSTAB.
PERFORM
bdc_transaction USING
'AS02'.
ENDDO.
PERFORM
close_group.
PERFORM
close_dataset USING dataset."关闭文件
编辑服务器端上生成的测试数据文件
上一节生成的程序过程,选择了生成测试文件,该文件存入在服务器上。下面介绍如何查看SAP应用服务器上所生的文件信息。
在SM35界面上,点击会输入SHDB,在SHDB操作界面,打开文件监视器:
SAP会为每个文件夹存放的路径定义一个“目录参数的名称”,如用户所创建的文件存放在SAP应用服务器的“DIR_SAPUSERS”下:
双击即可看到该目录下的所有文件,如本例中创建的“AS02_FILE”:
双击该文件,即可查看该文件的内容,内容就是上面录屏时界面上录入的数据:
可以通过SAP提供的工具CG3Y,将此文件下载到本地后进行编辑:
修改好后,再通过工具CG3Z将文件上传到服务器上:
将文件上传到服务器上后,可以将录入程序在后台运行,适合于大批量需要耗时较长的数据处理。
CG3Y、CG3Z文件每行字符超长问题
CG3YDOWNLOAD服务器文件(如果是ASC模式下载,每行只能256个字符,解决方案是函数C13Z_FILE_DOWNLOAD_ASCII的L_DATA_TAB改为TYPE STRING)
CG3ZUPLOAD本地文件到服务器中(如果是ASC模式上传,每行只能256个字符,解决方案是函数C13Z_FILE_UPLOAD_ASCII的L_DATA_TAB改为TYPE STRING)
不带测试数据文件
如果在生成代码时选择的是“从记录中传输”,则生成的代码非常简单,但较之上面需要修改很多才能使用:
REPORT
zas022
NO STANDARD PAGE
HEADING LINE-SIZE
255.
INCLUDE
bdcrecx1.
START-OF-SELECTION.
PERFORM
open_group.
PERFORM
bdc_dynpro USING
'SAPLAIST' '0100'.
PERFORM
bdc_field USING
'BDC_CURSOR'
'ANLA-ANLN1'.
PERFORM
bdc_field USING
'BDC_OKCODE'
'/00'.
PERFORM
bdc_field USING
'ANLA-ANLN1'
'11000001'.
PERFORM
bdc_field USING
'ANLA-ANLN2'
'0'.
PERFORM
bdc_field USING
'ANLA-BUKRS'
'0005'.
PERFORM
bdc_dynpro USING
'SAPLAIST' '1000'.
PERFORM
bdc_field USING
'BDC_OKCODE'
'=BUCH'.
PERFORM
bdc_field USING
'BDC_CURSOR'
'ANLA-TXT50'.
PERFORM
bdc_field USING
'ANLA-TXT50'
'AAA'.
PERFORM
bdc_field USING
'ANLH-ANLHTXT'
'BBB'.
PERFORM
bdc_field USING
'ANLA-AKTIV'
'2006.04.19'.
PERFORM
bdc_transaction USING
'AS02'.
PERFORM
close_group.
从本地读取测试数据文件
从前面生成的程序来看,引用了系统标准的Include程序bdcrecx1,这里可以将BDC处理的核心代码拷贝出来,如存放到一个自定义的Include文件zbdcrecx1中,自定义程序中不再考虑DataSet及BDC Group的方法,主要需要拷贝的内表定义包括BDCDATA、MESSTAB;需要拷贝的Form如下:
精简后的Include文件zbdcrecx1:
*----------------------------------------------------------------------*
* data definition
*----------------------------------------------------------------------*
* 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."记录执行BDC过程中产生的消息
* message texts
TABLES:
t100.
*----------------------------------------------------------------------*
* Start new transaction according to parameters *
*----------------------------------------------------------------------*
FORM
bdc_transaction USING
tcode ctumode.
DATA:
l_mstring(480).
DATA:
l_subrc LIKE
sy-subrc.
A:代表无论出错与否每个画面都显示;
E:只是在出错时显示;
N:代表无论出错与否每个画面都不显示。
REFRESH
messtab.
CALL TRANSACTION
tcode USING
bdcdata
MODE
ctumode"A:调试
N:不显示 E:错误时调试
UPDATE
'A'"A:异步
B:同步 L:本地更新
MESSAGES INTO
messtab.
l_subrc =
sy-subrc.
WRITE:
/ 'CALL_TRANSACTION',
tcode,
'returncode:'(i05),
l_subrc,
'RECORD:',
sy-index.
LOOP AT
messtab.
SELECT SINGLE
* FROM
t100 WHERE
sprsl =
messtab-msgspra
AND
arbgb =
messtab-msgid
AND
msgnr =
messtab-msgnr.
IF
sy-subrc
= 0.
l_mstring =
t100-text.
IF
l_mstring CS
'&1'.
REPLACE
'&1'
WITH messtab-msgv1
INTO l_mstring.
REPLACE
'&2'
WITH messtab-msgv2
INTO l_mstring.
REPLACE
'&3'
WITH messtab-msgv3
INTO l_mstring.
REPLACE
'&4'
WITH messtab-msgv4
INTO l_mstring.
ELSE.
REPLACE
'&'
WITH messtab-msgv1
INTO l_mstring.
REPLACE
'&'
WITH messtab-msgv2
INTO l_mstring.
REPLACE
'&'
WITH messtab-msgv3
INTO l_mstring.
REPLACE
'&'
WITH messtab-msgv4
INTO l_mstring.
ENDIF.
CONDENSE
l_mstring.
WRITE:
/ messtab-msgtyp,
l_mstring(250).
ELSE.
WRITE:
/ messtab.
ENDIF.
ENDLOOP.
REFRESH
bdcdata.
ENDFORM.
*----------------------------------------------------------------------*
* 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.
CLEAR
bdcdata.
bdcdata-fnam
= fnam.
bdcdata-fval
= fval.
APPEND
bdcdata.
ENDFORM.
新创建一个XLS文件,并输入测试数据:
REPORT
zjzj_bdc_localfile.
TYPE-POOLS:
truxs.
DATA:it_raw
TYPE truxs_t_text_data."
PARAMETERS:
p_file LIKE
ibipparms-path.
INCLUDE:zbdcrecx1.
DATA:
BEGIN OF
record OCCURS
0,
anln1_001(012),
bukrs_002(004),
txt50_003(050),
anlhtxt_004(050),
END OF
record.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR
p_file."选择文件时弹出选择对话框
CALL FUNCTION
'F4_FILENAME'
EXPORTING
field_name =
'P_FILE'
IMPORTING
file_name =
p_file.
START-OF-SELECTION.
CALL FUNCTION
'TEXT_CONVERT_XLS_TO_SAP'
EXPORTING
i_line_header =
'X'
"表示测试文件的第一行为头,从第二行开始读取
i_tab_raw_data =
it_raw
i_filename =
p_file
TABLES
i_tab_converted_data =
record[].
CHECK NOT
record[] IS INITIAL.
LOOP AT
record.
PERFORM
bdc_dynpro USING
'SAPLAIST' '0100'.
PERFORM
bdc_field USING
'BDC_CURSOR'
'ANLA-BUKRS'.
PERFORM
bdc_field USING
'BDC_OKCODE'
'/00'.
PERFORM
bdc_field USING
'ANLA-ANLN1'
record-anln1_001.
PERFORM
bdc_field USING
'ANLA-BUKRS'
record-bukrs_002.
PERFORM
bdc_dynpro USING
'SAPLAIST' '1000'.
PERFORM
bdc_field USING
'BDC_OKCODE'
'=BUCH'.
PERFORM
bdc_field USING
'BDC_CURSOR'
'ANLH-ANLHTXT'.
PERFORM
bdc_field USING
'ANLA-TXT50'
record-txt50_003.
PERFORM
bdc_field USING
'ANLH-ANLHTXT'
record-anlhtxt_004.
PERFORM
bdc_transaction USING
'AS02' 'E'.
ENDLOOP.
BDC后台运行
先贴上,以后研究
BDC(batch data communication)是SAP常用的一种数据传输方法。用于一些数据量大,但是对速度又要求不高的数据传输。
在实施中,很多开发顾问都忽略了BDC的日志和出错管理。这给用户在使用中带来了很大的不便。比如:哪些数据是成功生成的,哪些是失败的?那些失败的,原因的是什么?程序问题还是数据问题?
我觉得,既然是要做一套程序,那就应该尽可能地为客户考虑,减少日后的维护量。对于BDC程序来讲,日志和出错管理应该是必备的。
下面讲一下,BDC的两种通用写法。
1. Call Transaction: 顾名思义,就是直接调用BDC进行数据批量导入。优点:方便快捷,程序处理方便。缺点:日志管理能力差,需自己建透明表来维护数据。我只是把它用作测试用途,不做正式使用。
2. BDC Insert(即CALL Function):这是一种不直接运行,而是将BDC程序生成session(但不立即运行,需要手工或通过RSBDCSUB专用程序来运行会话)。优点:通过T-code SM35可以进行运行管理及日志管理,方便查错。缺点:相对方法1来说实现起来比较繁琐。我主要是用这种方法来实现BDC功能。
下面主要来谈一下BDC Insert这种方法。
1. 需要在程序中调用 function 'BDC_INSERT'来把BDCDATA生成SESSION.
2. 通过程序RSBDCSUB来执行SESSION(后续建立JOB中使用,目前手动运行会话)
3. 建立BATCH JOB来定期执行RSBDCSUB,从而实现SESSION自动执行的目的
4. 当然,不使用程序RSBDCSUB和JOB,每次手工在SM35中执行SESSION也是可以的
下面是我写的一个实例:
TABLES: COAS, CEPC.
*-----------------------------------------------------------------------
* Internal Tables and Work Areas
*-----------------------------------------------------------------------
DATA:
BEGIN OF GT_TABLE
OCCURS 0,
"internal order table
AUART
LIKE AUFK-AUART,
"order type
AUFNR
LIKE AUFK-AUFNR,
"order number
KTEXT
LIKE AUFK-KTEXT,
"description
BUKRS
LIKE AUFK-BUKRS,
"company code
GSBER
LIKE AUFK-GSBER,
"business area
PRCTR
LIKE AUFK-PRCTR,
"profit center
FUNCA
LIKE AUFK-FUNC_AREA,
"function area
END OF
GT_TABLE.
DATA:
BEGIN OF GT_EXISTS
OCCURS 0.
"existed IO
INCLUDE STRUCTURE GT_TABLE.
DATA:
END OF GT_EXISTS.
DATA:
BEGIN OF GT_PRFT_CNTR
OCCURS 0."the
profit center not existing IO
INCLUDE STRUCTURE GT_TABLE.
DATA:
END OF GT_PRFT_CNTR.
DATA:
BEGIN OF GT_SUBMIT
OCCURS 0.
"the submitted IO
INCLUDE STRUCTURE GT_TABLE.
DATA:
END OF GT_SUBMIT.
DATA:
BEGIN OF GT_BDCDATA
OCCURS 0.
"BDC DATA
INCLUDE STRUCTURE BDCDATA.
DATA:
END OF GT_BDCDATA.
DATA:
BEGIN OF GT_MESSTAB
OCCURS 10.
"message table
INCLUDE STRUCTURE BDCMSGCOLL.
DATA:
END OF GT_MESSTAB.
DATA: GT_IMESG
LIKE MESG
OCCURS 0 WITH HEADER LINE.
*-----------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------
DATA: GV_GROUP(12)
TYPE C VALUE 'INTERNAL_ORD',
"BDC Name
GV_USER(12)
TYPE C,
"BDC User
GV_KEEP(1)
TYPE C VALUE 'X',
" ' '=Delete,'X'=keep after processing
GV_HOLDDATE
LIKE SY-DATUM.
"Date
DATA: GV_FLAG(1)
TYPE C,
GV_LIN
TYPE I.
"number of orders
DATA: GV_C170(170),
GV_C_ULINE(50)
VALUE '__________________________________________________'.
*
*
*
*-----------------------------------------------------------------------
* Selection Screen
*-----------------------------------------------------------------------
PARAMETERS: BDCTYPE(1)
TYPE C DEFAULT 'B' NO-DISPLAY,
BDCMODE
LIKE BDCRUN-BDC_AMODUS
DEFAULT 'A' NO-DISPLAY.
SELECTION-SCREEN COMMENT 10(70)
TEXT-001.
PARAMETERS: IN_FILE(128)
DEFAULT 'C:/TEMP/*.txt'.
SELECTION-SCREEN SKIP 1.
*-----------------------------------------------------------------------
* At Selection Screen
*-----------------------------------------------------------------------
*--------- AT SELECTION-SCREEN ON VALUE-REQUEST ----------
AT SELECTION-SCREEN ON VALUE-REQUEST
FOR IN_FILE.
CALL FUNCTION 'WS_FILENAME_GET'
EXPORTING
DEF_FILENAME =
'*.txt'
DEF_PATH =
'C:/DATA'
MASK =
',All Files,*.*,Text Files,*.txt;*.doc.'
MODE =
'O'
TITLE =
'Please choose file to use '
IMPORTING
FILENAME = IN_FILE
EXCEPTIONS
INV_WINSYS =
1
NO_BATCH =
2
SELECTION_CANCEL =
3
SELECTION_ERROR =
4
OTHERS =
5.
*
*
*
*--------- START-OF-SELECTION ----------
START-OF-SELECTION.
REFRESH GT_TABLE.
* Uploading the data which will be inserted into the internal table
CALL FUNCTION 'WS_UPLOAD'
EXPORTING
FILENAME = IN_FILE
FILETYPE =
'DAT'
TABLES
DATA_TAB = GT_TABLE
EXCEPTIONS
CONVERSION_ERROR =
1
FILE_OPEN_ERROR =
2
FILE_READ_ERROR =
3
INVALID_TABLE_WIDTH =
4
INVALID_TYPE =
5
NO_BATCH =
6
UNKNOWN_ERROR =
7
OTHERS =
8.
IF SY-SUBRC <>
0.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
'Unable to upload input file '
IN_FILE
'' ''.
ENDIF.
SORT GT_TABLE
BY AUFNR GSBER
DESCENDING.
DELETE ADJACENT DUPLICATES FROM
GT_TABLE COMPARING AUFNR.
PERFORM OPEN_GROUP.
PERFORM FILL_BDC_DATA.
PERFORM BDC_CLOSE_GROUP.
PERFORM WRITE_REPORT.
*--------- END-OF-SELECTION ----------
*
*
*
*&---------------------------------------------------------------------*
*& Form OPEN_GROUP
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM OPEN_GROUP.
GV_USER = SY-UNAME.
CALL FUNCTION 'BDC_OPEN_GROUP'
EXPORTING
CLIENT = SY-MANDT
GROUP = GV_GROUP
HOLDDATE = GV_HOLDDATE
KEEP = GV_KEEP
USER = GV_USER.
IF SY-SUBRC <>
0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM.
" OPEN_GROUP
*&---------------------------------------------------------------------*
*& Form FILL_BDC_DATA
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM FILL_BDC_DATA.
CLEAR GT_TABLE.
LOOP AT GT_TABLE.
CLEAR GT_MESSTAB.
CLEAR GT_BDCDATA.
REFRESH GT_BDCDATA.
REFRESH GT_MESSTAB.
CLEAR GV_FLAG.
* Check if Profit Center exists.
SELECT SINGLE *
FROM CEPC
WHERE PRCTR = GT_TABLE-PRCTR.
IF SY-SUBRC <>
0.
CLEAR GT_PRFT_CNTR.
MOVE-CORRESPONDING GT_TABLE
TO GT_PRFT_CNTR.
APPEND GT_PRFT_CNTR.
GV_FLAG =
'X'.
ENDIF.
* check if Internal Order has already been created.
SELECT SINGLE *
FROM COAS
WHERE AUFNR = GT_TABLE-AUFNR.
IF SY-SUBRC =
0.
CLEAR GT_EXISTS.
MOVE-CORRESPONDING GT_TABLE
TO GT_EXISTS.
APPEND GT_EXISTS.
GV_FLAG =
'X'.
ENDIF.
IF GV_FLAG <>
'X'.
PERFORM BDCDATA
USING:
'X' 'SAPMKAUF' '0100',
"order type
' ' 'COAS-AUART' GT_TABLE-AUART,
' ' 'BDC_OKCODE' '=KOKR'.
PERFORM BDCDATA
USING:
'X' 'SAPLSPO4' '0300',
"control area
' ' 'SVALD-VALUE(01)' '1000',
' ' 'BDC_OKCODE' '=FURT'.
PERFORM BDCDATA
USING:
'X' 'SAPMKAUF' '0100',
"ok code
' ' 'BDC_OKCODE' '/00'.
PERFORM BDCDATA
USING:
'X' 'SAPMKAUF' '0600',
"order master data
' ' 'COAS-AUFNR' GT_TABLE-AUFNR,
' ' 'COAS-KTEXT' GT_TABLE-KTEXT,
' ' 'COAS-BUKRS' GT_TABLE-BUKRS,
' ' 'COAS-GSBER' GT_TABLE-GSBER,
' ' 'COAS-PRCTR' GT_TABLE-PRCTR,
' ' 'COAS-FUNC_AREA' GT_TABLE-FUNCA,
' ' 'BDC_OKCODE' '=SICH'.
* PERFORM CALL_TRANSACTION. "for test purpose
PERFORM BDC_INSERT.
MOVE-CORRESPONDING GT_TABLE
TO GT_SUBMIT.
APPEND GT_SUBMIT.
ENDIF.
ENDLOOP.
ENDFORM.
" FILL_BDC_DATA
*&---------------------------------------------------------------------*
*& Form BDC_INSERT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM BDC_INSERT.
CALL FUNCTION 'BDC_INSERT'
EXPORTING
TCODE =
'KO01'
TABLES
DYNPROTAB = GT_BDCDATA.
IF SY-SUBRC <>
0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM.
" BDC_INSERT
*&---------------------------------------------------------------------*
*& Form BDC_CLOSE_GROUP
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM BDC_CLOSE_GROUP.
CALL FUNCTION 'BDC_CLOSE_GROUP'.
IF SY-SUBRC <>
0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM.
" BDC_CLOSE_GROUP
*&---------------------------------------------------------------------*
*& Form CALL_TRANSACTION
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM CALL_TRANSACTION.
CALL TRANSACTION 'KO01' USING
GT_BDCDATA
MODE BDCMODE
MESSAGES
INTO GT_MESSTAB.
* IF SYST-SUBRC <> 0.
* CALL FUNCTION 'WRITE_MESSAGE'
* EXPORTING
* MSGID = SY-MSGID
* MSGNO = SY-MSGNO
* MSGTY = SY-MSGTY
* MSGV1 = SY-MSGV1
* MSGV2 = SY-MSGV2
* MSGV3 = SY-MSGV3
* MSGV4 = SY-MSGV4
* MSGV5 = ' '
* IMPORTING
* ERROR = ERROR
* MESSG = MESSG
* MSGLN = MSGLN.
ENDFORM.
" CALL_TRANSACTION
*&---------------------------------------------------------------------*
*& Form BDCDATA
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_0310 text
* -->P_0311 text
*----------------------------------------------------------------------*
FORM BDCDATA
USING P_BEGIN P_FIELD1 P_FIELD2.
CLEAR GT_BDCDATA.
CASE P_BEGIN.
WHEN 'X'.
GT_BDCDATA-PROGRAM = P_FIELD1.
GT_BDCDATA-DYNPRO = P_FIELD2.
GT_BDCDATA-DYNBEGIN =
'X'.
WHEN SPACE.
GT_BDCDATA-FNAM = P_FIELD1.
GT_BDCDATA-FVAL = P_FIELD2.
ENDCASE.
APPEND GT_BDCDATA.
ENDFORM.
" BDCDATA
*&---------------------------------------------------------------------*
*& Form WRITE_REPORT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM WRITE_REPORT.
DESCRIBE TABLE GT_EXISTS
LINES GV_LIN.
IF GV_LIN >=
1.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
'The following Internal Orders already exist.' '' '' ''.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
LOOP AT GT_EXISTS.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GT_EXISTS-AUFNR
'' '' ''.
ENDLOOP.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
ENDIF.
DESCRIBE TABLE GT_PRFT_CNTR
LINES GV_LIN.
IF GV_LIN >=
1.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
'The following Profit centers do not exist.' '' '' ''.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
'Internal Order Profit Center.' '' '' ''.
LOOP AT GT_PRFT_CNTR.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GT_PRFT_CNTR-AUFNR
GT_PRFT_CNTR-PRCTR
'' ''.
ENDLOOP.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
ENDIF.
DESCRIBE TABLE GT_SUBMIT
LINES GV_LIN.
IF GV_LIN >=
1.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
'BDC was created for the following Internal Orders.'
'' '' ''.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
LOOP AT GT_SUBMIT.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GT_SUBMIT-AUFNR
'' '' ''.
ENDLOOP.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
ENDIF.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
'The following Internal Orders have no Business Area.'
'' '' ''.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
DELETE GT_TABLE
WHERE NOT GSBER =
' '.
LOOP AT GT_TABLE.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GT_TABLE-AUFNR
'' '' ''.
ENDLOOP.
PERFORM COLLECT_MESSAGES
USING 'Z3' 'I' '000'
GV_C_ULINE
'' '' ''.
ENDFORM.
" WRITE_REPORT
*&---------------------------------------------------------------------*
*& Form COLLECT_MESSAGES
*&---------------------------------------------------------------------*
* Collects messgaes into rep tree table and writes them to
* screen for regular reporting
*----------------------------------------------------------------------*
* -->P_MSGID message id
* -->P_MSGTY messgae type
* -->P_MSGNR msg number
* -->P_MSG1 text 1
* -->P_MSG2 text 2
* -->P_MSG3 text 3
* -->P_MSG4 text 4
*----------------------------------------------------------------------*
FORM COLLECT_MESSAGES
USING P_MSGID
P_MSGTY
P_MSGNR
P_MSGV1
P_MSGV2
P_MSGV3
P_MSGV4.
CLEAR GT_IMESG.
GT_IMESG-ARBGB = P_MSGID.
GT_IMESG-MSGTY = P_MSGTY.
GT_IMESG-TXTNR = P_MSGNR.
GT_IMESG-MSGV1+0(2)
= '@ '.
GT_IMESG-MSGV1+2(48)
= P_MSGV1.
GT_IMESG-MSGV2 = P_MSGV2.
GT_IMESG-MSGV3 = P_MSGV3.
GT_IMESG-MSGV4 = P_MSGV4.
APPEND GT_IMESG.
CONCATENATE P_MSGV1 P_MSGV2 P_MSGV3 P_MSGV4
INTO GV_C170
SEPARATED BY SPACE.
WRITE:/ GV_C170.
ENDFORM.
通过RSBDCSUB运行会话
DATA:
p_groupid LIKE
apqi-groupid.
DATA:
p_user LIKE
sy-uname.
* PERFORM bdc_open_group.
* PERFORM pre_bdc.
* PERFORM bdc_insert_group.
* PERFORM bdc_close_group .
* PERFORM get_session_state USING p_groupid .
* PERFORM write_error.
**************************************************************
FORM
bdc_open_group .
CONCATENATE
sy-datum sy-uzeit
INTO p_groupid.
CALL FUNCTION
'BDC_OPEN_GROUP'
"open session
EXPORTING
client
= sy-mandt
* DEST = FILLER8
group
= p_groupid
* HOLDDATE = FILLER8
keep =
'X'
user =
p_user
* RECORD = FILLER1
* IMPORTING
* QID =
EXCEPTIONS
client_invalid =
1
destination_invalid =
2
group_invalid =
3
group_is_locked =
4
holddate_invalid =
5
internal_error =
6
queue_error =
7
running =
8
system_lock_error =
9
user_invalid =
10
OTHERS
= 11.
ENDFORM.
" BDC_OPEN_GROUP
************************************************************
FORM
pre_bdc .
REFRESH
bdcdata.
PERFORM
bdc_dynpro USING
'SAPLMR1M' '0300'.
PERFORM
bdc_field USING
'BDC_CURSOR' 'G_BUDAT'.
PERFORM
bdc_field USING
'BDC_OKCODE' '=CANC'.
PERFORM
bdc_field USING
'RBKPV-BELNR'
i_belnr.
PERFORM
bdc_field USING
'RBKPV-GJAHR'
i_gjahr.
PERFORM
bdc_field USING
'UF05A-STGRD'
i_stgrd.
PERFORM
bdc_field USING
'G_BUDAT' i_budat.
ENDFORM.
*************************************************************
FORM
bdc_insert_group .
CALL FUNCTION
'BDC_INSERT'
EXPORTING
tcode =
tcode
TABLES
dynprotab =
bdcdata
EXCEPTIONS
internal_error =
1
not_open =
2
queue_error =
3
tcode_invalid =
4
printing_invalid =
5
posting_invalid =
6
OTHERS
= 7.
ENDFORM.
" BDC_INSERT_GROUP
*********************************************************
FORM
bdc_close_group .
CALL FUNCTION
'BDC_CLOSE_GROUP'
EXCEPTIONS
not_open =
1
queue_error =
2
OTHERS
= 3.
SUBMIT
rsbdcsub WITH
mappe EQ
p_groupid
WITH
von EQ
sy-datum
WITH
bis EQ
sy-datum
WITH
fehler EQ
'.'
EXPORTING
LIST TO MEMORY
AND RETURN.
WAIT UP TO
10 SECONDS
.
ENDFORM.
" BDC_CLOSE_GROUP
**********************************************************
FORM
get_session_state USING
p_session.
CLEAR:
itab1,itab1[].
itab1-groupid
= p_groupid.
itab1-belnr
= i_belnr.
itab1-gjahr
= i_gjahr.
itab1-stgrd
= i_stgrd.
itab1-budat
= i_budat.
itab1-erdat
= sy-datum.
itab1-uzeit
= sy-uzeit.
itab1-ernam
= sy-uname.
itab1-text
= i_text.
APPEND
itab1.
PERFORM
insert_zszd219.
SELECT SINGLE
apqi~mandant apqi~groupid
apqi~qid apqi~qstate
apql~temseid
INTO (ijob-mandant,ijob-groupid,ijob-qid,ijob-qstate,ijob-temseid)
FROM
apqi INNER JOIN
apql
ON apql~mandant
= apqi~mandant
AND apql~groupid
= apqi~groupid
AND apql~qid
= apqi~qid
WHERE apqi~groupid
= p_session
AND apqi~datatyp
= 'BDC'
AND
apqi~mandant
= sy-mandt
.
IF
sy-subrc
= 0
AND ijob-qstate
= 'F'.
READ TABLE
itab1 INDEX
1.
itab1-state
= 'F'.
MODIFY
itab1 INDEX
1.
PERFORM
insert_zszd219.
WRITE:
/ 'Cancel Invoice Sucessful'.
ELSEIF
sy-subrc
= 0
AND ijob-qstate <>
'F'.
PERFORM
read_bdc_log_plain TABLES
logtable USING
ijob-temseid ijob-mandant.
ELSEIF
sy-subrc <>
0.
WRITE:/
'Job name: ',p_session,'
has not finish.'.
ENDIF.
CHECK NOT
bdclm[] IS INITIAL.
LOOP AT
itab1.
READ TABLE
bdclm WITH KEY
tcode =
'MR8M'
tcnt =
sy-tabix.
CHECK
sy-subrc
= 0.
MOVE-CORRESPONDING
itab1 TO
errtab.
IF
bdclm-mart
= 'E'.
errtab-mess
= bdclm-longtext.
ELSE.
errtab-mess
= 'Cancel Invoice Sucessful'.
ENDIF.
APPEND
errtab.
CLEAR
errtab.
ENDLOOP.
ENDFORM.
*********************************************************
FORM
write_error .
DATA:
count TYPE i.
count
= 0.
LOOP AT
errtab.
IF count
= 0.
FORMAT COLOR
3 ON.
WRITE:
/01 errtab.
FORMAT COLOR
3 OFF.
SKIP
1.
ELSE.
WRITE:
/01 errtab.
ENDIF.
count
= 1.
ENDLOOP.
ENDFORM.
" WRITE_ERROR
CATT批量数据维护(SCAT、SCEM)
CATT 全称 Computer Aided Test Tool(计算机辅助测试工具),也是批量数据维护工具。与BDC类似的是,CATT的数据操作也是通过录制屏幕的方式来实现的,但是有自己的优势:
l BDC导入本地数据需要通过辅助开发程序来实现,而CATT则可以直接读取本地文件;
l BDC读取文件到内存后再进行处理,可以方便地通过ABAP代码来实现数据的检查或者转换,但是CATT则是比较直接的数据录入,相比之下,BDC的控制会更加灵活。
l CATT操作简单,可以由模块顾问录制好后再提供给用户直接使用,只需要用户按顾问提供的测试数据模板文件提供数据即可
若是基本的数据录入或修改的话,CATT实现起来会更加的简单
本实例还是以修改资产主数据事务AS02为例来演示
因AS02属于账务控制模块,所以选择C0:
点击“保存”按钮后,再修改“类型”为“C CATT”类型(注:如果不先保存,直接选 C CATT 时会报错):
保存后,再输入SCEM事务码,操作界面与SCAT基本类似:
点击“记录”按钮后,就是AS02事务操作界面了:
与上面BDC中的示例一样,修改后保存,会回到SCEM界面,此时记录框中有了“结束并复制”按钮:
点击“结束并复制”按钮后,将会看到测试界面修改界面,左边菜单项中为录制过程中的屏幕及操作的消息输出(这里为第三项):
SCEM操作完后,保存所有,然后再回到SCAT界面,并执行“导出”,将会导出本地数据录入模板:
导入的文件为Txt文件,可以使用Excel打开进行维护,新增的数据必须按文件中的位置来填写:
测试文件修改好后,进入执行界面:
执行后,输出日志: