首先简单解释一下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’通常可以不用写。不过,据说有时候去了也会出问题,加上去就没了,这个我就不知道了。呵~
come from : http://lz357502668.blog.163.com/blog/static/1649674320110215555292/