历史版本5 :SAP的RFC接口调用 返回文档
编辑时间: 内容长度:图片数:目录数: 修改原因:
SAP作为独立的系统,与其它系统进行交互的时候,主要是两种方式:1:底层数据库直接交互;2:通过SAP专门的RFC接口进行数据调用。
SAP现在主要的数据库平台有两种关系型数据库,Oracle和DB2,第一种方式FineReport通过JDBC的方式直连SAP数据库来解决,详细请查看数据库连接,但是使用这种方式,制作人员需要对SAP数据库了解比较深,并且数据库可以对其他软件开放。下面主要介绍第二种方式。

1. 设计思路编辑

首先通过java类文件建立和SAP的连接,然后通过程序数据集接口,将RFC调出来的数据进行虚拟二维表封装,调用虚拟二维表,进行报表的制作。

2. 实现步骤编辑

2.1 建立连接
通过ConnectSAPServer类实现与SAP的连接,类文件的代码如下:
HTML/XML代码
package com.fr.function;  
  
import java.io.File;  
import java.io.FileOutputStream;  
import java.util.Properties;  
  
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;  
  
public class ConnectSAPServer {  
    static String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL";  
    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,  
                "用户名");  
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD,  
                "密码");  
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH");  
        connectProperties.setProperty(  
                DestinationDataProvider.JCO_POOL_CAPACITY, "10");  
        connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,  
                "10");  
        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, "SAP连接配置文件");  
                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;  
    }  
}  
注:最新的代码链接fine-help
2.2 程序数据集调用
  • 定义程序数据集
数据库连接上之后,定义程序数据集,通过我们的程序数据源接口将数据转换成虚拟表,类文件具体代码如下:
HTML/XML代码
package com.fr.data;  
  
import com.fr.base.FRContext;  
import com.fr.base.Parameter;  
import com.fr.data.AbstractTableData;  
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 ParamSAPDataTest extends AbstractTableData  
{  
  private String[] columnNames = null;  
  
  private int columnNum = 3;  
  
  
  private String[][] rowData;  
  private static JCoDestination jCoDestination;  
  
  public ParamSAPDataTest()  
  {  
    this.parameters = new Parameter[] { new Parameter("LIFNR"),   
      new Parameter("NAME1") };  
  
    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("Z_LFA3_QUERY");  
    if (function == null)  
      throw new RuntimeException(  
        "Function not found in SAP.");  
    function.getImportParameterList().setValue("LIFNR", "%"+this.parameters[0].getValue().toString().toUpperCase().trim()+"%");  
    function.getImportParameterList().setValue("NAME1", "%"+this.parameters[1].getValue().toString().toUpperCase().trim()+"%");  
    function.execute(jCoDestination);  
    JCoTable returnTable = function.getTableParameterList().getTable(  
      "ZLFA1S3");  
    rowData=new String[20][3];  
    if (returnTable.getNumRows() > 0) {  
      returnTable.firstRow();  
      for (int i = 0; i < 20; )  
      {  
        String[] objArray = new String[this.columnNum];  
        objArray[0] = returnTable.getString("LIFNR");  
        objArray[1] = returnTable.getString("NAME1");  
        objArray[2] = returnTable.getString("STRAS");  
        this.rowData[i]=objArray;  
  
        i++; returnTable  
          .nextRow();  
      }  
  
      FRContext.getLogger().info(  
        "Query SQL of ParamSAPDataTest: \n" + this.rowData.length +   
        " rows selected");  
    }  
  }  
  
  public void release() throws Exception {  
    super.release();  
    this.rowData = null;  
  }  
}  
注:最新的代码链接fine-help
  • 配置程序数据集
详细配置步骤请查看:简单程序数据集

3. 总结编辑

通过RFC接口这种方式避免了直连数据库的问题,而这些RFC参数和调用表结构网上或者SAP供应商都会提供,不过缺点在于需要写类文件来获取数据,报表多的时候比较麻烦,如果要达到一些图表联动等效果,需要在类里面写参数,修改起来不是很方便,需要技术人员进行报表制作,业务人员比较困难。