SAP R/3系统是业界最先进、最稳定的ERP系统,国际和国内大型企业采用该系统的比例遥遥领先于其它ERP系统的总和。SAP R/3内建了二次开发平台,使用的开发语言叫做ABAP,是一种类似于COBOL的编程语言。ABAP在报表输出方面功能相对较弱(只能按行打印在屏幕上或者导出到Excel中处理),所以日常工作中经常需要在外部开发程序。通过程序接口自动读取SAP R/3的数据表(视图),在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。
SAP R/3的接口方式主要有RFC、IDOC、BAPI三种,本文要介绍的是相对比较简单的RFC(Romote Function Call,远程函数调用)。SAP系统RFC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接口调用SAP内部的标准或自定义函数,获得函数返回的数据进行处理后显示或打印。下面是RFC调用的模型:
本文主要不是讨论SAP R/3函数的开发,因为使用SAP的公司一般都有专门的ABAP开发人员。大家如果有机会接触ABAP平台,可以通过事务代码SE37进入ABAP开发平台的"函数编制器"进行函数开发测试。
下面主要以VB为例介绍一下SAP接口RFC的开发思路。在SAP客户端SAP Gui Client安装的时候,注意选择安装附带的SDK包(最保险是选择完全安装)。RFC接口程序开发,主要用的是"SAP.Functions"这个控件,通过控件在外部程序模拟SAP Gui Client的用户登录和函数调用,然后返回函数的值。请看下面的程序片段和重点注解(尤其是CmdAdd_Click()):
VB 代码:
'---QUERY / SELECTALL / CREATE / EDIT / DELETE /
Private Sub CmdAdd_Click()
'添加记录
On Error GoTo myer
Dim Functions As Object
Dim Connect As Object
Dim logname As String,password As String
Dim xi
Dim func As Object
Dim TT As Object
Set Functions = CreateObject("Sap.Functions.Unicode") ' 创建RFC的本地对象
Set Connect = Functions.Connection ' 设置连接
Connect.ApplicationServer = "192.168.1.108"
Connect.Client = "811"
Connect.SystemNumber = "00"
Connect.Language = "ZH"
Connect.User = "LIANXI02"
Connect.password = "sap123"
If Not Connect.logon(0,True) Then ' 软件登录SAP并判断
MsgBox "登录SAP R/3失败,请重新登录!" + Err.Description,vbOKOnly + vbExclamation,"系统提示"
Exit Sub
Else ' 登录SAP成功
Set func = Functions.Add("ZRFC_01") '--ZRFC_01 是SAP里的函数 se37
Set TT = func.tables("ZTEMPTABLE")
func.Exports("ACTION") = "CREATE"
With TT
'Next we set fields to obtain
'Refresh table
TT.FreeTable
'Then set values,类似与ADDNEW
'xi是获取当前表的行数,以便定位记录行
'此处在赋值时,用字段名称来表示列,也可以用数字来表示,比如TT(xi,1) = "iii"
'注意:行和列都是从1开始,不是从0开始计数
TT.Rows.Add
xi = TT.rowcount
TT(xi,"MATNR") = "Z1001"
TT(xi,"MAKTX") = "单机头"
TT.Rows.Add
xi = TT.rowcount
TT(xi,"MATNR") = "Z1002"
TT(xi,"MAKTX") = "包材1"
TT.Refresh
End With
If func.call = True Then
x = func.imports("RETURN")
y = func.imports("ERRNUM")
Debug.Print "x:" & x
Debug.Print "y:" & y
Else
MsgBox "call Failed!"
End If
End If
Connect.logoff
Exit Sub
myer:
MsgBox Err.Description,vbInformation,"Info"
End Sub
SAP 里的函数
FUNCTIONZRFC_01.
*"----------------------------------------------------------------------
*"*"Localinterface:
*"IMPORTING
*"VALUE(ACTION)TYPE/1SAP1/CL_ACH0001
*"VALUE(WHEREUSERID)TYPE/GC1/DTE_MSG_TXTOPTIONAL
*"EXPORTING
*"VALUE(RETURN)TYPE/AIN/ACT_PUB_PARAMNAME
*"VALUE(ERRNUM)TYPE/AIN/ACTIVITY_COUNTER
*"TABLES
*"ZTEMPTABLESTRUCTUREZTEST2
*"----------------------------------------------------------------------
tables:ZTEST2.
DATA:
WA_ZTEMPTABLELIKEZTEMPTABLE,
TRANSACTION_IDLIKEARFCTID,
V_VAILD(1)TYPEC.
V_VAILD='X'.
*OPENADATATRANSACTION
CALLFUNCTION'TRANSACTION_BEGIN'
IMPORTING
TRANSACTION_ID=TRANSACTION_ID.
CASEACTION.
*按照关键字ZUSERID查询
WHEN'QUERY'.
SELECT*FROMZTEST2INTOTABLEZTEMPTABLEwhereMATNR=WHEREUSERID.
IFSY-SUBRC=0.
ELSE.
V_VAILD=''.
ERRNUM=SY-SUBRC.
ENDIF.
*选择所有的记录
WHEN'SELECTALL'.
SELECT*FROMZTEST2INTOTABLEZTEMPTABLE.
IFSY-SUBRC=0.
ELSE.
V_VAILD=''.
ERRNUM=SY-SUBRC.
ENDIF.
*插入记录
WHEN'CREATE'.
LOOPATZTEMPTABLEINTOWA_ZTEMPTABLE.
INSERTZTEST2FROMWA_ZTEMPTABLE.
IFSY-SUBRC=0.
ELSE.
V_VAILD=''.
ERRNUM=SY-SUBRC.
ENDIF.
ENDLOOP.
*修改记录
WHEN'EDIT'.
LOOPATZTEMPTABLEINTOWA_ZTEMPTABLE.
UPDATEZTEST2FROMWA_ZTEMPTABLE.
IFSY-SUBRC=0.
ELSE.
V_VAILD=''.
ERRNUM=SY-SUBRC.
ENDIF.
ENDLOOP.
*删除记录
WHEN'DELETE'.
LOOPATZTEMPTABLEINTOWA_ZTEMPTABLE.
DELETEZTEST2FROMWA_ZTEMPTABLE.
IFSY-SUBRC=0.
ELSE.
V_VAILD=''.
ERRNUM=SY-SUBRC.
ENDIF.
ENDLOOP.
WHENOTHERS.
ENDCASE.
*如果V_VALID为X,则表示成功,否则表示失败,并返回RETURN错误代码
IFV_VAILD='X'.
CALLFUNCTION'TRANSACTION_END'
EXPORTING
TRANSACTION_ID=TRANSACTION_ID.
RETURN=''.
ELSE.
CALLFUNCTION'TRANSACTION_ABORT'
EXPORTING
TRANSACTION_ID=TRANSACTION_ID.
RETURN='THECURRENTACTIONISFAILURE!'.
ENDIF.
ENDFUNCTION.
说明: ZTEST2表是我自己定义的,包含了这三个字段:MANDT / MATNR / MAKTX
你也可以换成你自己写的表或用SAP里的表。