通过 RFC 与外部系统进行数据交换

作者:ABAP三叔 约 5 分钟阅读 更新日期:2025-03-02 1 年前更新 标签:ABAP, Data Engineering, SD, 开发, 数据工程, 销售分销
通过 RFC 与外部系统进行数据交换 - 封面图
通过 RFC 与外部系统进行数据交换 - 封面图

前言

SAP与外部系统进行数据交换的方法众多,如常见的PI、WSDL、HTTP等,如果外部系统是企业内部系统,源码自主,使用RFC也是一种可选的非常方便的方法。

SAP官方提供了标准的SDK,可供其它开发语言进行调用SAP中的RFC。

本文将分别介绍在JAVA、PYTHON、C#/.NET中如何进行编码来调用SAP的RFC方法。

RFC准备

FUNCTION zrfc_say_hello.*"----------------------------------------------------------------------*"*"本地接口:IV_VALUE

*" IMPORTING*" VALUE(IV_VALUE) TYPE STRING*" EXPORTING*" VALUE(EV_VALUE) TYPE STRING*" TABLES*" IT_INPUT STRUCTURE T001W*" ET_OUTPUT STRUCTURE T001W*"----------------------------------------------------------------------

ev_value = |Hello { iv_value }! From sap { sy-datum }{ sy-uzeit }|. SELECT * INTO TABLE @et_output FROM t001w UP TO 10 ROWS FOR ALL ENTRIES IN @it_input WHERE werks = @it_input-werks.

ENDFUNCTION.

传入一个字符串 IV_VA LUE 和一个 IT_INPUT 内表(只需WERKS字段赋值即可)

返回一个字符串 EV_VA LUE 和一个 ET_OUTPUT 内表

JAVA调用

1. 下载sapjco3.jar包,根据自己系统到SAP官方网站下载(需要SAP账号),或者网上找资源

https://support.sap.com/en/product/connectors.html?anchorId=section_125501632

通过 RFC 与外部系统进行数据交换 - 封面图
通过 RFC 与外部系统进行数据交换 - 封面图

2\. 创建JAVA项目,引入JAR包

通过 RFC 与外部系统进行数据交换 - 封面图
通过 RFC 与外部系统进行数据交换 - 封面图

3\. 示例程序

import com.sap.conn.jco.*;import com.sap.conn.jco.ext.DataProviderException;import com.sap.conn.jco.ext.DestinationDataEventListener;import com.sap.conn.jco.ext.DestinationDataProvider;

import java.util.Properties;

import static com.sap.conn.jco.ext.Environment.registerDestinationDataProvider;import static com.sap.conn.jco.ext.Environment.unregisterDestinationDataProvider;

public class saptest {

static String SAP_SERVER = "SAP_SERVER";

public static void main(String[] args) { class MyDestinationDataProvider implements DestinationDataProvider { private final Properties properties;

public MyDestinationDataProvider() {

properties = new Properties(); }

@Override public Properties getDestinationProperties(String s) throws DataProviderException {                String host = "xx.xx.xx.xx"; String router = "xxxx";                String clientName = "xxx";//200 String language = "ZH"; String userId = "xxxx"; String password = "xxx";                String system = "xx";//00 properties.clear(); properties.setProperty(DestinationDataProvider.JCO_ASHOST, host); properties.setProperty(DestinationDataProvider.JCO_SAPROUTER, router); properties.setProperty(DestinationDataProvider.JCO_SYSNR, system); properties.setProperty(DestinationDataProvider.JCO_CLIENT, clientName); properties.setProperty(DestinationDataProvider.JCO_USER, userId); properties.setProperty(DestinationDataProvider.JCO_PASSWD, password); properties.setProperty(DestinationDataProvider.JCO_LANG, language); properties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "30"); return properties; }

@Override public boolean supportsEvents() { return false; }

@Override public void setDestinationDataEventListener(DestinationDataEventListener destinationDataEventListener) {

} }

try { MyDestinationDataProvider myProvider = new MyDestinationDataProvider(); registerDestinationDataProvider(myProvider); JCoDestination destination = JCoDestinationManager.getDestination(SAP_SERVER); JCoRepository repos = destination.getRepository(); JCoFunction function = repos.getFunction("ZRFC_SAY_HELLO");//调用SAP接口 JCoParameterList importParameterList = function.getImportParameterList(); importParameterList.setValue("IV_VALUE", "JAVA");//设置入参 JCoParameterList tableParameterList = function.getTableParameterList();//获取表格参数 JCoTable inputTable = tableParameterList.getTable("IT_INPUT"); //获取输入表IT_INPUT的数据参数 for (int i = 0; i < 10; i++) { //往输入表中,给指定字段参数进行赋值 inputTable.appendRow(); inputTable.setRow(i); inputTable.setValue("WERKS", (1000 + i) + ""); } function.execute(destination); JCoParameterList exportParameterList = function.getExportParameterList(); System.out.println(exportParameterList.getString("EV_VALUE"));//获取出参 JCoTable outputTable = tableParameterList.getTable("ET_OUTPUT");//获取输出表ET_OUTPUT的数据 for (int i = 0; i < outputTable.getNumRows(); i++) { outputTable.setRow(i); System.out.println(outputTable.getString("WERKS") + " " + outputTable.getString("NAME1"));//获取输出结果中的两个字段 }

unregisterDestinationDataProvider(myProvider);

} catch (Exception e) { System.out.println(e.getMessage()); } }}

4\. 运行结果

通过 RFC 与外部系统进行数据交换 - 封面图
通过 RFC 与外部系统进行数据交换 - 封面图

Python调用

1. 下载SAP NetWeaver RFC SDK, 根据自己系统到SAP官方网站下载(需要SAP账号),或者网上找资源

https://support.sap.com/en/product/connectors.html?anchorId=section_125501632,另外根据https://github.com/SAP/PyRFC中的

‍ Requirements介绍设置环境变量。 ‍

2\. 安装pyrfc,这个直接使用pip安装就可以了 。

3\. 示例程序

from pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError, \ ExternalRuntimeError

def get_connection(connmeta=None): try: if not connmeta: connmeta = { 'user': 'xxx', 'passwd': 'xxx', 'ashost': 'xx.xx.xx.xx', 'saprouter': 'xxx', 'sysnr': 'xxx', #00                'client': 'xxx', #200                # 'trace': '3',  # optional, in case you want to trace 'lang': 'ZH' } return Connection(**connmeta)

except CommunicationError: print(u"Could not connect to server.") raise except LogonError: print(u"Could not log in. Wrong credentials?") raise except (ABAPApplicationError, ABAPRuntimeError): print(u"An error occurred.") raise

def main(): conn = get_connection() inputTable = [{"WERKS": str(1000 + i)} for i in range(10)] args = {'IV_VALUE': 'PYTHON', 'IT_INPUT': inputTable} try: result = conn.call('ZRFC_SAY_HELLO', **args) print(result["EV_VALUE"]) for row in result["ET_OUTPUT"]: print(row["WERKS"], row["NAME1"]) except ExternalRuntimeError as exc: print(exc.message) conn.close()

if __name__ == "__main__": main()

4\. 运行结果

通过 RFC 与外部系统进行数据交换 - 封面图
通过 RFC 与外部系统进行数据交换 - 封面图

C#调用

1. 下载sapnco.dll, 根据自己系统到SAP官方网站下载(需要SAP账号),或者网上找资源

https://support.sap.com/en/product/connectors.html?anchorId=section_125501632

2\. 创建C#程序,添加引用。

通过 RFC 与外部系统进行数据交换 - 封面图
通过 RFC 与外部系统进行数据交换 - 封面图

3\. 示例程序

using System;using SAP.Middleware.Connector;

namespace TEST_RFC{ class Program { static String SAP_SERVER = "SAP_SERVER"; static void Main(string[] args) { IDestinationConfiguration ID = new MyBackendConfig(); RfcDestinationManager.RegisterDestinationConfiguration(ID); RfcDestination prd = RfcDestinationManager.GetDestination(SAP_SERVER); RfcRepository repo; try { repo = prd.Repository; IRfcFunction function = repo.CreateFunction("ZRFC_SAY_HELLO"); //调用函数名 function.SetValue("IV_VALUE", ".NET"); //设置Import的参数 IRfcTable inputTable = function.GetTable("IT_INPUT"); //输入表 RfcStructureMetadata structMeta = inputTable.Metadata.LineType; for (int i = 0; i < 10; i++) { IRfcStructure import = structMeta.CreateStructure(); import.SetValue("

...

ABAP三叔

关于作者:ABAP三叔

企业信息化与 SAP 技术顾问,长期专注 SAP ABAP、FI/CO、MM、SD 等模块的技术分享与实战经验总结。查看更多介绍

来源说明:本文内容由「通过RFC与外部系统进行数据交换.md」整理生成,仅用于内部技术分享与学习交流。