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