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

1. 设计思路编辑

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

2. 实现步骤编辑

2.1 建立连接
通过ConnectSAPServer类实现与SAP的连接,类文件的代码如下:
  1. package com.fr.function;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.util.Properties;  
  6.   
  7. import com.sap.conn.jco.JCoDestination;  
  8. import com.sap.conn.jco.JCoDestinationManager;  
  9. import com.sap.conn.jco.JCoException;  
  10. import com.sap.conn.jco.ext.DestinationDataProvider;  
  11.   
  12. public class ConnectSAPServer {  
  13.     static String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL";  
  14.     static {  
  15.         Properties connectProperties = new Properties();  
  16.         connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST,  
  17.                 "SAP服务器IP地址");  
  18.         connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "系统编号");  
  19.         connectProperties  
  20.                 .setProperty(DestinationDataProvider.JCO_CLIENT, "客户端编号(SAP中的,和客户端没关系)");  
  21.         connectProperties.setProperty(DestinationDataProvider.JCO_USER,  
  22.                 "用户名");  
  23.         connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD,  
  24.                 "密码");  
  25.         connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH");  
  26.         connectProperties.setProperty(  
  27.                 DestinationDataProvider.JCO_POOL_CAPACITY, "10");  
  28.         connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,  
  29.                 "10");  
  30.         createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties);  
  31.     }  
  32.   
  33.     static void createDataFile(String name, String suffix, Properties properties) {  
  34.         File cfg = new File(name + "." + suffix);  
  35.         if (!cfg.exists()) {  
  36.             try {  
  37.                 FileOutputStream fos = new FileOutputStream(cfg, false);  
  38.                 properties.store(fos, "SAP连接配置文件");  
  39.                 fos.close();  
  40.             } catch (Exception e) {  
  41.                 throw new RuntimeException(  
  42.                         "Unable to create the destination file "  
  43.                                 + cfg.getName(), e);  
  44.             }  
  45.         }  
  46.     }  
  47.   
  48.     public static JCoDestination Connect() {  
  49.         JCoDestination destination = null;  
  50.         try {  
  51.             destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);  
  52.         } catch (JCoException e) {  
  53.             e.getCause();  
  54.         }  
  55.         return destination;  
  56.     }  
  57. }  
注:最新的代码链接fine-help
2.2 程序数据集调用
  • 定义程序数据集
数据库连接上之后,定义程序数据集,通过我们的程序数据源接口将数据转换成虚拟表,类文件具体代码如下:
  1. package com.fr.data;  
  2.   
  3. import com.fr.base.FRContext;  
  4. import com.fr.base.Parameter;  
  5. import com.fr.data.AbstractTableData;  
  6. import com.sap.conn.jco.JCoDestination;  
  7. import com.sap.conn.jco.JCoException;  
  8. import com.sap.conn.jco.JCoFunction;  
  9. import com.sap.conn.jco.JCoTable;  
  10. public class ParamSAPDataTest extends AbstractTableData  
  11. {  
  12.   private String[] columnNames = null;  
  13.   
  14.   private int columnNum = 3;  
  15.   
  16.   
  17.   private String[][] rowData;  
  18.   private static JCoDestination jCoDestination;  
  19.   
  20.   public ParamSAPDataTest()  
  21.   {  
  22.     this.parameters = new Parameter[] { new Parameter("LIFNR"),   
  23.       new Parameter("NAME1") };  
  24.   
  25.     this.columnNames = new String[this.columnNum];  
  26.     this.columnNames[0] = "供应商编码";  
  27.     this.columnNames[1] = "供应商名称";  
  28.     this.columnNames[2] = "供应商地址";  
  29.   }  
  30.   
  31.   public int getColumnCount() {  
  32.     return this.columnNum;  
  33.   }  
  34.   
  35.   public String getColumnName(int columnIndex) {  
  36.     return this.columnNames[columnIndex];  
  37.   }  
  38.   
  39.   public int getRowCount() {  
  40.     try {  
  41.       init();  
  42.     }  
  43.     catch (JCoException e) {  
  44.       FRContext.getLogger().info("失败");  
  45.     }  
  46.     return this.rowData.length;  
  47.   }  
  48.   
  49.   public Object getValueAt(int rowIndex, int columnIndex) {  
  50.     try {  
  51.       init();  
  52.     }  
  53.     catch (JCoException e) {  
  54.       FRContext.getLogger().info("失败");  
  55.     }  
  56.     if (columnIndex >= this.columnNum) {  
  57.       return null;  
  58.     }  
  59.     return this.rowData[rowIndex][columnIndex];  
  60.   }  
  61.   
  62.   public void init() throws JCoException {  
  63.     if (this.rowData != null) {  
  64.       return;  
  65.     }  
  66.     try  
  67.     {  
  68.     jCoDestination = ConnectSAPServer.Connect();  
  69.     }catch (Exception e) {  
  70.         FRContext.getLogger().info("失败");  
  71.       }  
  72.     JCoFunction function = jCoDestination.getRepository().getFunction("Z_LFA3_QUERY");  
  73.     if (function == null)  
  74.       throw new RuntimeException(  
  75.         "Function not found in SAP.");  
  76.     function.getImportParameterList().setValue("LIFNR""%"+this.parameters[0].getValue().toString().toUpperCase().trim()+"%");  
  77.     function.getImportParameterList().setValue("NAME1""%"+this.parameters[1].getValue().toString().toUpperCase().trim()+"%");  
  78.     function.execute(jCoDestination);  
  79.     JCoTable returnTable = function.getTableParameterList().getTable(  
  80.       "ZLFA1S3");  
  81.     rowData=new String[20][3];  
  82.     if (returnTable.getNumRows() > 0) {  
  83.       returnTable.firstRow();  
  84.       for (int i = 0; i < 20; )  
  85.       {  
  86.         String[] objArray = new String[this.columnNum];  
  87.         objArray[0] = returnTable.getString("LIFNR");  
  88.         objArray[1] = returnTable.getString("NAME1");  
  89.         objArray[2] = returnTable.getString("STRAS");  
  90.         this.rowData[i]=objArray;  
  91.   
  92.         i++; returnTable  
  93.           .nextRow();  
  94.       }  
  95.   
  96.       FRContext.getLogger().info(  
  97.         "Query SQL of ParamSAPDataTest: \n" + this.rowData.length +   
  98.         " rows selected");  
  99.     }  
  100.   }  
  101.   
  102.   public void release() throws Exception {  
  103.     super.release();  
  104.     this.rowData = null;  
  105.   }  
  106. }  
注:最新的代码链接fine-help
  • 配置程序数据集
详细配置步骤请查看:简单程序数据集

3. 总结编辑

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