帆软数据决策平台连接SAP RFC实例

news2025/1/21 16:34:33

一、介绍

由于SAP ABAP开发出来的报表很单一,形式很有限,而且调整报表格式和形式都显得特别的鸡肋,所以现在将SAP系统通过RFC接口模式接入到帆软报表数据决策平台下展示。本文将详细介绍如何将数据从SAP传输到帆软平台上。

二、准备工作

  • 首先得先注册下载一个FineReport模板设计器,下载连接到官网下载就行。下载完之后傻瓜式安装,注意选择好自己的安装目录就行,这里不做介绍,有疑问的可以去帆软的官方文档看看。

  • 准备好编译JAVA文件的工具:JDK8,IDEA编译工具。JDK8去官网下载就行,下载完配置一下环境变量即可,这个教程我相信网上一抓一把,idea破解版网上也一大堆,这里我就不再啰嗦(若无idea编译工具留言博主给你发)

  • 准备java程序连接sap的jar包,没有的话这是链接,所需0积分,直接白嫖,下载解压出来就行。

三、开始整活

SAP模块

在SAP中先创建function接口,接口属性类型必须是 远程启用的模块

这是源码:

创建激活完成之后,重要的步骤来了,许多教程都没写这一步,这也是我为什么要多写这个教程的原因

先找相关管理人员开通RFC权限,首先确保你有RFC权限才能从sap获取数据。然后就是要创建RFC链接,教程如下:

事务码:SM59

创建RFC链接,填写连接名,链接类型选 3 为了搞懂这玩意我还特意去查了相关资料并整理起来(附:有关SAP RFC连接的相关知识点)根据各自需要选择类型,如果是新手练习跟着博主选 3 就行

填写目标主机的ip地址和实例号,这两个信息你在登录是就有,填进去即可,然后保存退出。

至此,SAP这块的工作就完成了

JAVA程序模块

前提:JDK8的配置已完成,有idea编译工具(其他的也行,博主用的是idea)

按照默认创建java项目就行,我们要的是 .class编译文件

然后创建工程目录,如下图:为了避免出错,请大家务必按照以下的目录创建,下面的目录也是帆软FineReport工程的目录,编译完成后我们需要将 .class文件迁移到FineReport工程目录下执行,为了避免包的路径有误,需要根据下面的来创建。

创建完成后,先拿一下连接程序所需的jar包:

红框就是我导进来的JAR包

在你安装FineReport模板设计器的目录下

%FineReport%\lib 全部包

%FineReport%\server\lib 全部包

%FineReport%\webapps\webroot\WBE-INF\lib 全部包

%JDK8%\lib\tools.jar JDK目录下的工具包

sapjco3.jar 这个是刚刚下载的连接sap的jar包,我是在工程目录下创建一个文件夹lib,把sapjco3.jar和sapjco3.dll两个文件都放里边了。

点击APPLY -点击 OK。

完成后,复制下面的代码,将自己的信息填上去,这是连接登录SAP的关键一步:

package com.fr.function;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.DestinationDataProvider;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;

public class ConnectSAPServer
{
    static String ABAP_AS_POOLED = "ZFM_01";
    static{
        Properties connectProperties = new Properties();
        connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "??.??.??.??");//SAP服务器IP地址
        connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR,  "??");        //系统编号
        connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "???");       //SAP集团
        connectProperties.setProperty(DestinationDataProvider.JCO_USER,   "???");       //SAP用户名
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "?????");     //密码
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG,   "zh");        //登录语言
        connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");  //最大连接数
        connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,"10");     //最大连接线程
//        connectProperties.setProperty(DestinationDataProvider.JCO_SAPROUTER, "");内网直接访问,无需配置SAP路由地址
        createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties);
    }

    //如果连接配置文件不存在,则创建一个配置文件,并把配置信息写入到文件中
    static void createDataFile(String name, String suffix, Properties properties)
    {
        File cfg = new File(name+"."+suffix);
        if(!cfg.exists()){
            try{
                FileOutputStream fos = new FileOutputStream(cfg, false);
                properties.store(fos, "for tests only !");
                fos.close();
            }
            catch (Exception e){
                throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e);
            }
        }
    }

    public static JCoDestination Connect(){
        JCoDestination destination =null;
        try {
            destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
        }
        catch (JCoException e)
        {
            e.getCause();
        }
        return destination;
    }
}

这里说一下这个参数问题ABAP_AS_POOLED这个表示你刚刚创建的RFC连接名 类型为 3,博主刚开始就是傻乎乎的跟着别人填这玩意进去,ABAP_AS_POOLED = "ABAP_AS_POOLED",一直报错😭。其他信息的话照着填就行,DestinationDataProvider.JCO_SAPROUTER这个参数是路由地址,如果你的SAP是内网直连,没经过路由的话就不用配置,如果是走的路由,那就需要找管理人员要路由地址填上去即可。

这个文件是放在刚刚创建的function包下面。package com.fr.function;

还需要注意的是别导错包啦,害怕导错包的直接复制我的导包就行。

这一步完成后,在data包创建一个测试程序ParamSAPDataTestDemo,先测试一下能否能拿到数据

代码如下:

package com.fr.data;

import com.fr.function.ConnectSAPServer;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunction;

public class ParamSAPDataTestDemo  {
    public static void main(String[] args) throws JCoException {
        JCoDestination jCoDestination = ConnectSAPServer.Connect();
        jCoDestination.ping();
        System.out.println("连接sap成功");
        if (jCoDestination == null) System.out.println("jCoDestination is null , the program was end.");
        JCoFunction function = jCoDestination.getRepository().getFunction("ZFM_01"); //这是你在sap创建的函数接口名
        if (function == null) throw new RuntimeException("ZFM_01  not found in SAP.");
        //传入的参数
        function.getImportParameterList().setValue("INPUT_1",12);  // 传入的参数(大写)
        function.getImportParameterList().setValue("INPUT_2",12);  // 
        function.execute(jCoDestination);

        int result = function.getExportParameterList().getInt("RESULT");
        System.out.println("计算结果为:" + result);

    }
}

点击执行

输出如下结果:

至此,java程序连接SAP函数接口已实现。

帆软模块

对于以RFC连接SAP,帆软官网也有给出教程,但是太潦草了,对我来说用处不大,给大家奉上官网的教程连接,但是对于整合数据集还是挺有帮助的,下面是我整合数据集的代码实例,与上面的数据无关,仅供参考,有需要留言我再出一期教程详细说一下

package com.fr.data;

import com.fr.base.FRContext;
import com.fr.function.ConnectSAPServer;
import com.fr.stable.ParameterProvider;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoTable;

import java.util.ArrayList;

public class SAPParamDataTest extends AbstractTableData {
    private String[] columnNames = null;
    private int columnNum = 3;
    private String[][] rowData;
    private static JCoDestination jCoDestination;
    public SAPParamDataTest() {
        ArrayList<ParameterProvider> arrayList = new ArrayList<>();
//        arrayList.add(new Parameter("LIFNR"));
//        arrayList.add(new Parameter("NAME1"));
//        this.parameters = new XmlColConf<>(arrayList, ParameterProvider.class);
        this.columnNames = new String[this.columnNum];
        this.columnNames[0] = "物料编码";
        this.columnNames[1] = "工厂";
        this.columnNames[2] = "采购类型";
    }
    public int getColumnCount() {
        return this.columnNum;
    }
    public String getColumnName(int columnIndex) {
        return this.columnNames[columnIndex];
    }
    public int getRowCount() {
        try {
            init();
        } catch (JCoException e) {
            FRContext.getLogger().info("失败");
        }
        return this.rowData.length;
    }
    public Object getValueAt(int rowIndex, int columnIndex) {
        try {
            init();
        } catch (JCoException e) {
            FRContext.getLogger().info("失败");
        }
        if (columnIndex >= this.columnNum) {
            return null;
        }
        return this.rowData[rowIndex][columnIndex];
    }
    public void init() throws JCoException {
        if (this.rowData != null) {
            return;
        }
        try {
            jCoDestination = ConnectSAPServer.Connect();
        } catch (Exception e) {
            FRContext.getLogger().info("失败");
        }
        JCoFunction function = jCoDestination.getRepository().getFunction("ZFM_01");
        if (function == null)
            throw new RuntimeException(
                    "Function not found in SAP.");
        function.execute(jCoDestination);
        JCoTable returnTable = function.getTableParameterList().getTable(
                "GT_ITAB");
        rowData = new String[returnTable.getNumRows()][3];
        if (returnTable.getNumRows() > 0) {
            returnTable.firstRow();
            for (int i = 0; i < returnTable.getNumRows(); returnTable.nextRow()) {
                String[] objArray = new String[this.columnNum];
                objArray[0] = returnTable.getString("MATNR");
                objArray[1] = returnTable.getString("WERKS");
                objArray[2] = returnTable.getString("BESKZ");
                this.rowData[i] = objArray;
            }
            FRContext.getLogger().info(
                    "Query SQL of ParamSAPDataTest: \n" + this.rowData.length +
                            " rows selected");
        }
    }
    public void release() throws Exception {
        super.release();
        this.rowData = null;
    }

}

或者这样:

package com.fr.data;

import java.util.ArrayList;
import java.util.List;

import com.fr.function.ConnectSAPServer;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoTable;

public class ParamSAPDataTestDemo extends SimpleTableData {
    @Override
    public String[] initColumnNames() {
        return new String[] {"物料编号","工厂","采购类型"};
    }

    @Override
    public List<Object[]> loadData() {
        JCoDestination jCoDestination = ConnectSAPServer.Connect();
        if (jCoDestination == null) System.out.println("jCoDestination is null , the program was end.");
        JCoFunction function = null;
        try {
            function = jCoDestination.getRepository().getFunction("ZFM_01");
            function.execute(jCoDestination);
        } catch (JCoException e) {
            e.printStackTrace();
        }
        JCoTable returnTable = function.getTableParameterList().getTable("GT_ITAB");
        ArrayList<Object[]> valueList = new ArrayList();
        if (returnTable.getNumRows() > 0) {
            returnTable.firstRow();
            for (int i = 0; i < returnTable.getNumRows(); i++, returnTable.nextRow()) {
                String matnr = returnTable.getString("MATNR"); //物料编号
                String werks = returnTable.getString("WERKS"); //工厂
                String beskz = returnTable.getString("BESKZ"); //采购类型
                valueList.add(new Object[]{matnr,werks, beskz});
            }
        }
        return valueList;
    }

}

以上两个例子无需运行,编译一下就行,然后去工程目录下找.class文件

工程目录下的out文件夹下面的都是编译文件(.class)

找到对应路径下的文件即可

接下来打开FineReport模板设计器和目录,进入目录

%FineReport%\webapps\webroot\WEB-INF\classes\com\fr

在这个目录下可以找到data文件夹和function文件夹

把刚刚编译好的.class文件直接复制粘贴进来,若文件名重复点击覆盖就行

接下来还要导几个jar包进去FineReport目录下,否则程序报错:

sapjco3.jar 放在%FR_HOME%\lib路径下

sapjco3.dll 放在%FR_HOME%\jre\bin路径下

%JDK8%\lib\tools.jar JDK目录下的工具包 放到 %FR_HOME%\jre\lib

导完包之后,启动FineReport模板设计器,选择本地目录(默认目录)

新建模板

然后点击模板数据集- 程序

选择我们刚刚复制进去的 .class编译文件

点击确定

可以看到左侧已经有我们的数据集了

将数据拖动到模板的单元格里面

点击保存-预览效果

更多的报表展示方式博主还在学习中,请参考帆软的官网去学习如何使用帆软做报表

至此,流程就已经结束啦。总的思路就是,

先给SAP创建一个RFC连接接口和一个函数接口

然后用java程序连接这个RFC接口

最后用帆软去执行java程序的.class文件即可实现数据从SAP到帆软展示。

最后需要提醒一下的是JDK的版本不宜过高,jdk8就行,否则会有版本冲突问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/161068.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

色氨酸代谢与肠内外健康稳态

谷禾健康 色氨酸&#xff08;Tryptophan&#xff0c;简称 Try&#xff09;是人体必需氨基酸&#xff0c;也是唯一含有吲哚结构的氨基酸&#xff0c;由食物尤其膳食蛋白质提供&#xff0c;是正常细胞稳态所必需的&#xff0c;是维持细胞生长和协调机体对环境和饮食线索的反应&am…

Java基础06——字符串

Java基础06——字符串一、String1. 字符串特点2. 创建字符串对象的两种方式直接赋值new3. 字符串常用方法a. 比较b. 遍历c. 截取d. 替换二、StringBuilder1. StringBuilder概述2. StringBuilder构造方法3. StringBuilder常用方法三、StringJoiner1. StringJoiner概述2. StringJ…

mysqldump binlog增量恢复会导致数据重复

1. mysqldump时间很长&#xff0c;导出第一个表和导出最后一个表的时间可能过去几个小时&#xff0c;如果期间不锁库&#xff0c;使用binlog增量恢复的时候&#xff0c;如果从备份开始的binlog开始恢复&#xff0c;备份期间别的表的改动通过应用binlog日志会再次被应用一次。导…

如何做好舆情管控,TOOM舆情监控服务工作经验总结

网络舆情监测剖析是实时控制网络舆情动态的一项基本工作&#xff0c;也是妥当处置网络有害信息&#xff0c;制定有效宣扬策略&#xff0c;准确引诱舆论导向的主要前提与根据 。接下来简单了解如何做好舆情管控&#xff0c;TOOM舆情监控服务工作经验总结。 一、如何做好舆情管控…

priority_queue 优先级队列(堆) 的模拟实现

目录 一、优先级队列的模板参数列表 二、优先级队列的构造函数&#xff08;建堆 nlogn&#xff09; AdjustDown() 向下调整&#xff1a; 建堆的时间复杂度&#xff1a; 三、pop()接口 &#xff08;堆顶元素的删除&#xff1a; logn&#xff09; 四、push()接口 &#xff…

算法第九期——DFS(深度优先搜索)对树的应用

树 树是一种特殊的图 。 特点&#xff1a; 若树有n个点,则有n-1条边。树有连通性但没有回路。从一个点出发可以到达任意一个&#xff0c;而且路径是唯一的。树的重心u&#xff08;最平衡的点&#xff09;: 以树上任意一个结点为根计算它的子树的结点数&#xff0c;如果结点…

1578_AURIX_TC275_MTU中的ECC检测、错误追踪以及运行模式

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) EOV其实是体现了一个错误递增的概念&#xff0c;而且这个是积累到了一定的度。至于具体的规则&#xff0c;其实后面还有更加详细的信息。关于ECC错误纠正使能&#xff0c;相应的处理可能跟…

产品更新!数维图编辑器超10项功能升级

新的一年我们加紧了更新迭代的速度&#xff0c;覆盖数维图三大可视化编辑器产品&#xff0c;超10项功能升级优化。我们将继续保持每天更新的产品升级节奏&#xff0c;满足不同行业用户的更多需求&#xff0c;为用户带来极致的产品使用体验。以下是主要的亮点功能更新汇总&#…

用R语言理解连续性和导数

文章目录微分1 连续性2 求导微分 1 连续性 众所周知微分的几何意义是斜率&#xff0c;然而斜率最初的定义只涉及直线&#xff0c;指的是ykxbykxbykxb中的kkk&#xff0c;而对任意曲线yf(x)yf(x)yf(x)而言&#xff0c;若想谈其斜率&#xff0c;就必须先做出其切线&#xff0c;…

#A. 毛毛虫树

Description给你一棵树希望你找出一条链来&#xff0c;这条链上的点&#xff0c;及这些点直接相连的点&#xff0c;加起来点数尽可能的多FormatInput第一行两个整数N&#xff0c;M&#xff0c;分别表示树中结点个数和树的边数。接下来M行&#xff0c;每行两个整数a, b表示点a和…

lombok快速入门

lombok快速入门 1.安装idea lombok插件 2.加入 maven 依赖 lombok常用注解 1. Getter/Setter 自动产生 getter/setter 2. ToString 自动重写 toString() 方法&#xff0c;会打印出所有变量 3. EqualsAndHashCode 自动生成 equals(Object other) 和 hashcode() 方法&#x…

MATLAB实验四

1.求方程2x5−3x371x2−9x1302x^5-3x^371x^2-9x1302x5−3x371x2−9x130 的全部根 >> p[2 0 -3 71 -9 13]; >> pkg load symbolic >> poly2sym(p) Symbolic pkg v3.0.0: Python communication link active, SymPy v1.10.1. ans (sym)5 3 22*x -…

FPGA图像处理HLS实现sobel边沿检测,提供HLS工程和vivado工程源码

目录一、sobel边沿检测原理二、HLS方案实现sobel边沿检测三、HLS在线仿真并导出IP四、Kintex7开发板vivado工程验证五、zynq7100开发板vivado工程验证六、板级调试验证七、福利&#xff1a;工程源码获取一、sobel边沿检测原理 所谓边缘是指其周围像素灰度急剧变化的那些象素的…

CS架构 企业ERP系统源码 Winform财务设备生产采购进销存源码

淘源码&#xff1a;国内知名的源码免费下载平台 推荐环境&#xff1a;vs2019 sql server 2008 r2以上 源码简介 本系统属于中小型企业ERP管理系统&#xff0c;可以对中小型生产企业或商业企业进行有效管理。 系统包含进销存、财务、生产、委外、财务、设备管理、权限管理等模…

【可解释性机器学习】基于ELI5使用解读LIME算法以及实战案例

LIME算法解读与实战案例LIME论文简介LIME算法原理LIME算法要点LIME的注意事项LIME的代码实现对Pytorch搭建的模型进行解释使用LIME解释Pytorch构建的模型参考资料LIME论文简介 LIME的全称为Local Interpretable Model-agnostic Explanations. 尽管被广泛采用&#xff0c;机器…

模板进阶篇

一、非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。如图&#xff1a; 非类型形参&#xff1a;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可…

Mybatis 原理之启动阶段

文章目录1.MyBatis 核心流程2.启动准备阶段流程3.创建 SQlSessionFactory4.创建XMLConfigBuilder5.创建 XPathParser6.解析并设置 configuration 中的属性7.解析Mappers标签1.MyBatis 核心流程 Mybatis的核心流程氛围两个阶段&#xff0c;启动准备阶段和执行SQL阶段。 加载配…

Day858.高性能网络应用框架Netty -Java 并发编程实战

高性能网络应用框架Netty Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于高性能网络应用框架Netty的内容。 Netty 是一个高性能网络应用框架&#xff0c;应用非常普遍&#xff0c;目前在 Java 领域里&#xff0c;Netty 基本上成为网络程序的标配了。 Netty 框架功…

win10录屏软件哪款比较好用?一款不限时长的录屏软件

现在大部分人的电脑都是win10系统的电脑&#xff0c;也有许多小伙伴会经常会问&#xff1a;“win10电脑怎么录屏&#xff1f;”录制电脑屏幕&#xff0c;需要使用到录屏软件&#xff0c;那win10录屏软件哪款比较好用&#xff1f;小编今天给大家分享一款试用版即可不限录制时长的…

【区间合并】洛谷 P1496 火烧赤壁

P1496 火烧赤壁 文章目录题目背景题目描述输入格式&#xff1a;输出格式&#xff1a;数据范围输入样例输出样例方法&#xff1a;区间合并解题思路代码复杂度分析&#xff1a;题目背景 曹操平定北方以后&#xff0c;公元 208 年&#xff0c;率领大军南下&#xff0c;进攻刘表。…