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 $*$*
*$*$----------------------------------------------------------------$*$*
*-----------------------------------------------------------------------
* 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.
*$*$----------------------------------------------------------------$*$*
*$*$ Main Program $*$*
*$*$----------------------------------------------------------------$*$*
*--------- 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 ----------
*$*$----------------------------------------------------------------$*$*
*$*$ Subroutines $*$*
*$*$----------------------------------------------------------------$*$*
*&---------------------------------------------------------------------*
*& 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打开进行维护,新增的数据必须按文件中的位置来填写:
测试文件修改好后,进入执行界面:
执行后,输出日志: