SpringBoot水晶报表连接Oracle导出PDF教程

目录

一、系统环境以及测试内容

1.系统环境

2.测试内容

二、设计水晶报表

1.CR2008配置jdbc

(1)在数据库专家中创建新的连接

(2)输入JDBC连接信息

(3)输入用户名密码

(4)解决”未找到JDBC”驱动错误

(5)配置JDBC驱动

扫描二维码关注公众号,回复: 12975114 查看本文章

2.报表设计

(1)新建test.rpt报表

(2)添加参数字段

(3)设置图片地址

(4)报表预览

三、SpringBoot项目搭建

1.新建SpringBoot项目

(1)pom.xml配置

(2)添加水晶报表文件

2.SpringBoot添加水晶报表jar包

(1)下载jar包

(2)SpringBoot项目引入jar包

(3)拷贝ojdbc5.jar到lib

3.水晶报表开源项目-CRJavaHelper工具类

4.编写测试接口

四、项目测试

1.注意事项

2.浏览器测试

3.动态效果


一、系统环境以及测试内容

1.系统环境

  • IntelliJ IDEA 2019.1.2
  • JRE: 1.8.0_202-release-1483-b49 amd64
  • Windows 10 64位
  • CRYSTAL REPORTS 2008 版本12.0.0.549
  • SpringBoot 2.3.4.RELEASE
  • Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

2.测试内容

  • SpringBoot调用水晶报表文件导出PDF
  • 使用JDBC驱动连接oracle数据库
  • 参数传值
  • 数据筛选
  • 图片动态切换

 

二、设计水晶报表

1.CR2008配置jdbc

(1)在数据库专家中创建新的连接

注意:如果使用Oracle服务器,在SpringBoot项目中会报错:

com.businessobjects.reports.jdbinterface.common.DBException: 查找 JNDI 名称(orcl)时出错

 

(2)输入JDBC连接信息

jdbc:oracle:thin:@localhost:1521:orcl

oracle.jdbc.driver.OracleDriver

 

 

(3)输入用户名密码

 

(4)解决未找到JDBC驱动错误

如果没有配置ojdbc5.jar,会报错

 

(5)配置JDBC驱动

下载数据库版本对应的ojdbc5.jar

jar包下载地址(使用ojdbc6.jar没有效果)

http://www.oracle.com/technetwork/cn/articles/oem/jdbc-112010-094555-zhs.html

 

 

将ojdbc5.jar放在安装目录的...\java\lib目录下

C:\Program Files (x86)\Business Objects\Common\4.0\java\lib

 

修改配置文件CRConfig.xml,在<Classpath>中添加ojdbc5.jar文件路径,重启CR2008即可连接到数据库

C:\Program Files (x86)\Business Objects\Common\4.0\java\CRConfig.xml

 

 

修改配置文件

 

2.报表设计

(1)新建test.rpt报表

数据展示,连接jdbc,选择DEPT表,将字段拖动到详细资料;

插入图片并设置图形位置

设计选择公式筛选数据。

 

 

(2)添加参数字段

添加2个参数

deptNoPar:数据筛选

imagePath:动态更改图片

 

(3)设置图片地址

使用参数imagePath

 

 

(4)选择公式

数据筛选使用参数deptNoPar

 

(5)报表预览

 

三、SpringBoot项目搭建

1.新建SpringBoot项目

(1)pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.asyf</groupId>
    <artifactId>crytstal-report-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!--设置为 true 则跳过测试-->
                    <skip>true</skip>
                    <compilerArgs>
                        <arg>-extdirs</arg>
                        <arg>${project.basedir}/lib</arg>
                    </compilerArgs>

                </configuration>
            </plugin>

        </plugins>

        <resources>
            <!--拷贝jar-->
            <resource>
                <!--需要打包的jar路径-->
                <directory>lib</directory>
                <!--复制到的路径-->
                <targetPath>BOOT-INF/lib/</targetPath>
                <includes>
                    <include>**/*.jar</include>
                </includes>
            </resource>

            <!--不配置这个会丢失resources目录的文件-->
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
                <!--To prevent corrupting your binary files when filtering is enabled, you can configure a list of file extensions that will not be filtered.
                翻译:为了避免开启 filter后你的二进制文件被损毁,你可配置不被过滤的文件拓展名列表-->
                <!--必须设置成fasle否则rpt文件签名不一致,造成水晶报表无法正确显示-->
                <filtering>false</filtering>
            </resource>
        </resources>

    </build>

</project>

  1.  

(2)添加水晶报表文件

将第二步设计好的水晶报表文件拷贝到项目resources目录

 

2.SpringBoot添加水晶报表jar包

(1)下载jar包

链接地址

https://origin.softwaredownloads.sap.com/public/site/index.html

(2)SpringBoot项目引入jar包

将压缩包下面的lib拷贝到SpringBoot项目

(3)拷贝ojdbc5.jar到lib

SpringBoot项目添加本地jar

3.水晶报表开源项目-CRJavaHelper工具类

在这里面下载CRJavaHelper工具类使用,没有找到官网java文档

https://github.com/souvikduttachoudhury/CrystalReportsSpringBoot.git

src/com/businessobjects/samples/CRJavaHelper.java

使用CRJavaHelper工具类操作水晶报表,将其拷贝到项目中

CRJavaHelper .java

/**
 * This sample code is an example of how to use the Business Objects APIs. 
 * Because the sample code is designed for demonstration only, it is 
 * unsupported.  You are free to modify and distribute the sample code as needed.   
 */
package com.asyf.demo.utils;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Locale;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;

import com.crystaldecisions.sdk.occa.report.application.DataDefController;
import com.crystaldecisions.sdk.occa.report.application.ReportClientDocument;
import com.crystaldecisions.sdk.occa.report.data.FieldDisplayNameType;
import com.crystaldecisions.sdk.occa.report.data.IConnectionInfo;
import com.crystaldecisions.sdk.occa.report.data.ITable;
import com.crystaldecisions.sdk.occa.report.data.ParameterField;
import com.crystaldecisions.sdk.occa.report.data.ParameterFieldDiscreteValue;
import com.crystaldecisions.sdk.occa.report.data.ParameterFieldRangeValue;
import com.crystaldecisions.sdk.occa.report.data.RangeValueBoundType;
import com.crystaldecisions.sdk.occa.report.data.Tables;
import com.crystaldecisions.sdk.occa.report.data.Values;
import com.crystaldecisions.sdk.occa.report.document.PaperSize;
import com.crystaldecisions.sdk.occa.report.document.PaperSource;
import com.crystaldecisions.sdk.occa.report.document.PrintReportOptions;
import com.crystaldecisions.sdk.occa.report.document.PrinterDuplex;
import com.crystaldecisions.sdk.occa.report.exportoptions.CharacterSeparatedValuesExportFormatOptions;
import com.crystaldecisions.sdk.occa.report.exportoptions.DataOnlyExcelExportFormatOptions;
import com.crystaldecisions.sdk.occa.report.exportoptions.EditableRTFExportFormatOptions;
import com.crystaldecisions.sdk.occa.report.exportoptions.ExportOptions;
import com.crystaldecisions.sdk.occa.report.exportoptions.PDFExportFormatOptions;
import com.crystaldecisions.sdk.occa.report.exportoptions.RTFWordExportFormatOptions;
import com.crystaldecisions.sdk.occa.report.exportoptions.ReportExportFormat;
import com.crystaldecisions.sdk.occa.report.lib.IStrings;
import com.crystaldecisions.sdk.occa.report.lib.PropertyBag;
import com.crystaldecisions.sdk.occa.report.lib.ReportSDKException;
import com.crystaldecisions.sdk.occa.report.lib.ReportSDKExceptionBase;

/**
 * Crystal Reports Java Helper Sample
 * ************************
 * Please note that you need to define a runtime server in order for this class
 * to compile.
 * ************************
 * @author Business Objects
 */
public class CRJavaHelper {

    /**
     * Logs on to all existing datasource
     * 
     * @param clientDoc The reportClientDocument representing the report being used
     * @param username    The DB logon user name
     * @param password    The DB logon password
     * @throws ReportSDKException
     */
    public static void logonDataSource(ReportClientDocument clientDoc, 
                String username, String password) throws ReportSDKException {
        clientDoc.getDatabaseController().logon(username, password);
    }

    /**
     * Changes the DataSource for each Table
     * @param clientDoc The reportClientDocument representing the report being used
     * @param username  The DB logon user name
     * @param password  The DB logon password
     * @param connectionURL  The connection URL
     * @param driverName    The driver Name
     * @param jndiName        The JNDI name
     * @throws ReportSDKException
     */
    public static void changeDataSource(ReportClientDocument clientDoc,
                String username, String password, String connectionURL,
                String driverName,String jndiName) throws ReportSDKException {

        changeDataSource(clientDoc, null, null, username, password, connectionURL, driverName, jndiName);
    }

    /**
     * Changes the DataSource for a specific Table
     * @param clientDoc The reportClientDocument representing the report being used
     * @param reportName    "" for main report, name of subreport for subreport, null for all reports
     * @param tableName        name of table to change.  null for all tables.
     * @param username  The DB logon user name
     * @param password  The DB logon password
     * @param connectionURL  The connection URL
     * @param driverName    The driver Name
     * @param jndiName        The JNDI name
     * @throws ReportSDKException
     */
    public static void changeDataSource(ReportClientDocument clientDoc,
                String reportName, String tableName,
                String username, String password, String connectionURL,
                String driverName,String jndiName) throws ReportSDKException {

        PropertyBag propertyBag = null;
        IConnectionInfo connectionInfo = null;
        ITable origTable = null;
        ITable newTable = null;

        // Declare variables to hold ConnectionInfo values.
        // Below is the list of values required to switch to use a JDBC/JNDI
        // connection
        String TRUSTED_CONNECTION = "false";
        String SERVER_TYPE = "JDBC (JNDI)";
        String USE_JDBC = "true";
        String DATABASE_DLL = "crdb_jdbc.dll";
        String JNDI_DATASOURCE_NAME = jndiName;
        String CONNECTION_URL = connectionURL;
        String DATABASE_CLASS_NAME = driverName;

        // The next few parameters are optional parameters which you may want to
        // uncomment
        // You may wish to adjust the arguments of the method to pass these
        // values in if necessary
        // String TABLE_NAME_QUALIFIER = "new_table_name";
        // String SERVER_NAME = "new_server_name";
        // String CONNECTION_STRING = "new_connection_string";
        // String DATABASE_NAME = "new_database_name";
        // String URI = "new_URI";

        // Declare variables to hold database User Name and Password values
        String DB_USER_NAME = username;
        String DB_PASSWORD = password;

        // Obtain collection of tables from this database controller
        if (reportName == null || reportName.equals("")) {
            Tables tables = clientDoc.getDatabaseController().getDatabase().getTables();
            for(int i = 0;i < tables.size();i++){
                origTable = tables.getTable(i);
                if (tableName == null || origTable.getName().equals(tableName)) {
                    newTable = (ITable)origTable.clone(true);

                    // We set the Fully qualified name to the Table Alias to keep the
                    // method generic
                    // This workflow may not work in all scenarios and should likely be
                    // customized to work
                    // in the developer's specific situation. The end result of this
                    // statement will be to strip
                    // the existing table of it's db specific identifiers. For example
                    // Xtreme.dbo.Customer becomes just Customer
                    newTable.setQualifiedName(origTable.getAlias());

                    // Change properties that are different from the original datasource
                    // For example, if the table name has changed you will be required
                    // to change it during this routine
                    // table.setQualifiedName(TABLE_NAME_QUALIFIER);

                    // Change connection information properties
                    connectionInfo = newTable.getConnectionInfo();

                    // Set new table connection property attributes
                    propertyBag = new PropertyBag();

                    // Overwrite any existing properties with updated values
                    propertyBag.put("Trusted_Connection", TRUSTED_CONNECTION);
                    propertyBag.put("Server Type", SERVER_TYPE);
                    propertyBag.put("Use JDBC", USE_JDBC);
                    propertyBag.put("Database DLL",DATABASE_DLL );
                    propertyBag.put("JNDI Datasource Name",JNDI_DATASOURCE_NAME );
                    propertyBag.put("Connection URL", CONNECTION_URL);
                    propertyBag.put("Database Class Name", DATABASE_CLASS_NAME);
                    // propertyBag.put("Server Name", SERVER_NAME); //Optional property
                    // propertyBag.put("Connection String", CONNECTION_STRING); //Optional property
                    // propertyBag.put("Database Name", DATABASE_NAME); //Optional property
                    // propertyBag.put("URI", URI); //Optional property
                    connectionInfo.setAttributes(propertyBag);

                    // Set database username and password
                    // NOTE: Even if the username and password properties do not change
                    // when switching databases, the
                    // database password is *not* saved in the report and must be set at
                    // runtime if the database is secured.
                    connectionInfo.setUserName(DB_USER_NAME);
                    connectionInfo.setPassword(DB_PASSWORD);

                    // Update the table information
                    clientDoc.getDatabaseController().setTableLocation(origTable, newTable);
                }
            }
        }
        // Next loop through all the subreports and pass in the same
        // information. You may consider
        // creating a separate method which accepts
        if (reportName == null || !(reportName.equals(""))) {
            IStrings subNames = clientDoc.getSubreportController().getSubreportNames();
            for (int subNum=0;subNum<subNames.size();subNum++) {
                Tables tables = clientDoc.getSubreportController().getSubreport(subNames.getString(subNum)).getDatabaseController().getDatabase().getTables();
                for(int i = 0;i < tables.size();i++){
                    origTable = tables.getTable(i);
                    if (tableName == null || origTable.getName().equals(tableName)) {
                        newTable = (ITable)origTable.clone(true);

                        // We set the Fully qualified name to the Table Alias to keep
                        // the method generic
                        // This workflow may not work in all scenarios and should likely
                        // be customized to work
                        // in the developer's specific situation. The end result of this
                        // statement will be to strip
                        // the existing table of it's db specific identifiers. For
                        // example Xtreme.dbo.Customer becomes just Customer
                        newTable.setQualifiedName(origTable.getAlias());

                        // Change properties that are different from the original
                        // datasource
                        // table.setQualifiedName(TABLE_NAME_QUALIFIER);

                        // Change connection information properties
                        connectionInfo = newTable.getConnectionInfo();

                        // Set new table connection property attributes
                        propertyBag = new PropertyBag();

                        // Overwrite any existing properties with updated values
                        propertyBag.put("Trusted_Connection", TRUSTED_CONNECTION);
                        propertyBag.put("Server Type", SERVER_TYPE);
                        propertyBag.put("Use JDBC", USE_JDBC);
                        propertyBag.put("Database DLL",DATABASE_DLL );
                        propertyBag.put("JNDI Datasource Name",JNDI_DATASOURCE_NAME );
                        propertyBag.put("Connection URL", CONNECTION_URL);
                        propertyBag.put("Database Class Name", DATABASE_CLASS_NAME);
                        // propertyBag.put("Server Name", SERVER_NAME); //Optional property
                        // propertyBag.put("Connection String", CONNECTION_STRING); //Optional property
                        // propertyBag.put("Database Name", DATABASE_NAME); //Optional property
                        // propertyBag.put("URI", URI); //Optional property
                        connectionInfo.setAttributes(propertyBag);

                        // Set database username and password
                        // NOTE: Even if the username and password properties do not
                        // change when switching databases, the
                        // database password is *not* saved in the report and must be
                        // set at runtime if the database is secured.
                        connectionInfo.setUserName(DB_USER_NAME);
                        connectionInfo.setPassword(DB_PASSWORD);

                        // Update the table information
                        clientDoc.getSubreportController().getSubreport(subNames.getString(subNum)).getDatabaseController().setTableLocation(origTable, newTable);
                    }
                }
            }
        }
    }
    
    /**
     * Passes a populated java.sql.Resultset object to a Table object
     * 
     * @param clientDoc The reportClientDocument representing the report being used
     * @param rs        The java.sql.Resultset used to populate the Table
     * @param tableAlias    The alias of the table
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @throws ReportSDKException
     */
    public static void passResultSet(ReportClientDocument clientDoc, java.sql.ResultSet rs,
            String tableAlias, String reportName) throws ReportSDKException {
        if(reportName.equals(""))
            clientDoc.getDatabaseController().setDataSource(rs, tableAlias,tableAlias);
        else
            clientDoc.getSubreportController().getSubreport(reportName).getDatabaseController().setDataSource(rs, tableAlias,tableAlias);

    }

    /**
     * Passes a populated collection of a Java class to a Table object
     * 
     * @param clientDoc     The reportClientDocument representing the report being used
     * @param dataSet        The java.sql.Resultset used to populate the Table
     * @param className        The fully-qualified class name of the POJO objects being passed
     * @param tableAlias        The alias of the table
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @throws ReportSDKException
     */
    public static void passPOJO(ReportClientDocument clientDoc, @SuppressWarnings("rawtypes") Collection dataSet, 
            String className, String tableAlias, String reportName) throws ReportSDKException,ClassNotFoundException{
        if(reportName.equals(""))
            clientDoc.getDatabaseController().setDataSource(dataSet, Class.forName(className),tableAlias,tableAlias);
        else
            clientDoc.getSubreportController().getSubreport(reportName).getDatabaseController().setDataSource(dataSet, Class.forName(className),tableAlias,tableAlias);

    }

    /**
     * Passes a single discrete parameter value to a report parameter
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @param parameterName    The name of the parameter
     * @param newValue        The new value of the parameter 
     * @throws ReportSDKException
     */
    public static void addDiscreteParameterValue(ReportClientDocument clientDoc, String reportName, String parameterName, Object newValue) throws ReportSDKException{
        DataDefController dataDefController = null;
        if(reportName.equals(""))
            dataDefController = clientDoc.getDataDefController();
        else
            dataDefController = clientDoc.getSubreportController().getSubreport(reportName).getDataDefController();

        ParameterFieldDiscreteValue newDiscValue = new ParameterFieldDiscreteValue();
        newDiscValue.setValue(newValue);

        ParameterField paramField = (ParameterField)dataDefController.getDataDefinition().getParameterFields().findField(parameterName, FieldDisplayNameType.fieldName, Locale.getDefault());
        System.out.println(paramField.getName());
        boolean multiValue = paramField.getAllowMultiValue();

        if(multiValue) {
            Values newVals = (Values)paramField.getCurrentValues().clone(true);
            newVals.add(newDiscValue);
            clientDoc.getDataDefController().getParameterFieldController().setCurrentValue(reportName, parameterName ,newVals);
        } else {
            clientDoc.getDataDefController().getParameterFieldController().setCurrentValue(reportName, parameterName , newValue);
        }
    }

    /**
     * Passes multiple discrete parameter values to a report parameter
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @param parameterName    The name of the parameter
     * @param newValues        An array of new values to get set on the parameter
     * @throws ReportSDKException
     */
    public static void addDiscreteParameterValue(ReportClientDocument clientDoc, String reportName, String parameterName, Object[] newValues) throws ReportSDKException{
        clientDoc.getDataDefController().getParameterFieldController().setCurrentValues(reportName, parameterName ,newValues);
    }

    /**
     * Passes a single range parameter value to a report parameter.  The range is assumed to
     * be inclusive on beginning and end.
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @param parameterName    The name of the parameter
     * @param beginValue    The value of the beginning of the range
     * @param endValue        The value of the end of the range
     * @throws ReportSDKException
     */
    public static void addRangeParameterValue(ReportClientDocument clientDoc, String reportName, String parameterName, Object beginValue, Object endValue) throws ReportSDKException{
        addRangeParameterValue(clientDoc, reportName, parameterName, beginValue, RangeValueBoundType.inclusive, endValue, RangeValueBoundType.inclusive);
    }

    /**
     * Passes multiple range parameter values to a report parameter.
     *
     * This overload of the addRangeParameterValue will only work if the
     * parameter is setup to accept multiple values.
     * 
     * If the Parameter does not accept multiple values then it is expected that
     * this version of the method will return an error
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @param parameterName    The name of the parameter
     * @param beginValues    Array of beginning values.  Must be same length as endValues.
     * @param endValues        Array of ending values.  Must be same length as beginValues.
     * @throws ReportSDKException
     */
    public static void addRangeParameterValue(ReportClientDocument clientDoc, String reportName, String parameterName, Object[] beginValues, Object[] endValues) throws ReportSDKException{
        addRangeParameterValue(clientDoc, reportName, parameterName, beginValues, RangeValueBoundType.inclusive, endValues, RangeValueBoundType.inclusive);
    }
    
    /**
     * Passes a single range parameter value to a report parameter
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @param parameterName    The name of the parameter
     * @param beginValue    The value of the beginning of the range
     * @param lowerBoundType    The inclusion/exclusion range of the start of range.
     * @param endValue        The value of the end of the range
     * @param upperBoundType    The inclusion/exclusion range of the end of range.
     * @throws ReportSDKException
     */
    public static void addRangeParameterValue(ReportClientDocument clientDoc, String reportName, String parameterName, Object beginValue, RangeValueBoundType lowerBoundType,Object endValue, RangeValueBoundType upperBoundType) throws ReportSDKException{
        DataDefController dataDefController = null;
        if(reportName.equals(""))
            dataDefController = clientDoc.getDataDefController();
        else
            dataDefController = clientDoc.getSubreportController().getSubreport(reportName).getDataDefController();

        ParameterFieldRangeValue newRangeValue = new ParameterFieldRangeValue();
        newRangeValue.setBeginValue(beginValue);
        newRangeValue.setLowerBoundType(lowerBoundType);
        newRangeValue.setEndValue(endValue);
        newRangeValue.setUpperBoundType(upperBoundType);

        ParameterField paramField = (ParameterField)dataDefController.getDataDefinition().getParameterFields().findField(parameterName, FieldDisplayNameType.fieldName, Locale.getDefault());
        boolean multiValue = paramField.getAllowMultiValue();

        if (multiValue) {
            Values newVals = (Values)paramField.getCurrentValues().clone(true);
            newVals.add(newRangeValue);
            clientDoc.getDataDefController().getParameterFieldController().setCurrentValue(reportName, parameterName , newVals);
        } else {
            clientDoc.getDataDefController().getParameterFieldController().setCurrentValue(reportName, parameterName , newRangeValue);
        }
    }

    /**
     * Passes multiple range parameter values to a report parameter.
     *
     * This overload of the addRangeParameterValue will only work if the
     * parameter is setup to accept multiple values.
     * 
     * If the Parameter does not accept multiple values then it is expected that
     * this version of the method will return an error
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param reportName    The name of the subreport.  If tables in the main report
     *                         is to be used, "" should be passed
     * @param parameterName    The name of the parameter
     * @param beginValues    Array of beginning values.  Must be same length as endValues.
     * @param lowerBoundType    The inclusion/exclusion range of the start of range.
     * @param endValues        Array of ending values.  Must be same length as beginValues.
     * @param upperBoundType    The inclusion/exclusion range of the end of range.
     * 
     * @throws ReportSDKException
     */
    public static void addRangeParameterValue(ReportClientDocument clientDoc, String reportName, String parameterName, Object[] beginValues,RangeValueBoundType lowerBoundType, Object[] endValues, RangeValueBoundType upperBoundType) throws ReportSDKException{
        // it is expected that the beginValues array is the same size as the
        // endValues array
        ParameterFieldRangeValue[] newRangeValues = new ParameterFieldRangeValue[beginValues.length];
        for(int i=0;i<beginValues.length;i++){
            newRangeValues[i] = new ParameterFieldRangeValue();
            newRangeValues[i].setBeginValue(beginValues[i]);
            newRangeValues[i].setLowerBoundType(lowerBoundType);
            newRangeValues[i].setEndValue(endValues[i]);
            newRangeValues[i].setUpperBoundType(upperBoundType);
        }
        clientDoc.getDataDefController().getParameterFieldController().setCurrentValues(reportName, parameterName , newRangeValues);

    }
    
    /**
     * Exports a report to PDF
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param response        The HttpServletResponse object
     * @param startPage        Starting page
     * @param endPage        Ending page
     * @param attachment    true to prompts for open or save; false opens the report
     *                         in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportPDF(ReportClientDocument clientDoc, HttpServletResponse response, boolean attachment) throws ReportSDKExceptionBase, IOException {
        // PDF export allows page range export. The following routine ensures
        // that the requested page range is valid
        PDFExportFormatOptions  pdfOptions = new PDFExportFormatOptions();
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.PDF);        
        exportOptions.setFormatOptions(pdfOptions);

        export(clientDoc, exportOptions, response, attachment, "application/pdf", "pdf");
    }
    
    /**
     * Exports a report to PDF for a range of pages
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param response        The HttpServletResponse object
     * @param startPage        Starting page
     * @param endPage        Ending page
     * @param attachment    true to prompts for open or save; false opens the report
     *                         in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportPDF(ReportClientDocument clientDoc, HttpServletResponse response, ServletContext  context, int startPage, int endPage,boolean attachment) throws ReportSDKExceptionBase, IOException {
        // PDF export allows page range export. The following routine ensures
        // that the requested page range is valid
        PDFExportFormatOptions  pdfOptions = new PDFExportFormatOptions();
        pdfOptions.setStartPageNumber(startPage);
        pdfOptions.setEndPageNumber(endPage);
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.PDF);        
        exportOptions.setFormatOptions(pdfOptions);

        export(clientDoc, exportOptions, response, attachment, "application/pdf", "pdf");

    }
    
    /**
     * Exports a report to RTF
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param response        The HttpServletResponse object
     * @param attachment    true to prompts for open or save; false opens the report
     *                         in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportRTF(ReportClientDocument clientDoc, HttpServletResponse response, boolean attachment) throws ReportSDKExceptionBase, IOException {
        // RTF export allows page range export. The following routine ensures
        // that the requested page range is valid
        RTFWordExportFormatOptions  rtfOptions = new RTFWordExportFormatOptions();
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.RTF);        
        exportOptions.setFormatOptions(rtfOptions);

        export(clientDoc, exportOptions, response, attachment, "text/rtf", "rtf");
    }
    
    /**
     * Exports a report to RTF for a range of pages
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param response        The HttpServletResponse object
     * @param startPage        Starting page
     * @param endPage        Ending page.  
     * @param attachment    true to prompts for open or save; false opens the report
     *                         in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportRTF(ReportClientDocument clientDoc, HttpServletResponse response, ServletContext  context, int startPage, int endPage, boolean attachment) throws ReportSDKExceptionBase, IOException {
        // RTF export allows page range export. The following routine ensures
        // that the requested page range is valid
        RTFWordExportFormatOptions  rtfOptions = new RTFWordExportFormatOptions();
        rtfOptions.setStartPageNumber(startPage);
        rtfOptions.setEndPageNumber(endPage);
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.RTF);        
        exportOptions.setFormatOptions(rtfOptions);

        export(clientDoc, exportOptions, response, attachment, "text/rtf", "rtf");
    }

    /**
     * Exports a report to RTF
     * 
     * @param clientDoc     The reportClientDocument representing the report being used
     * @param response      The HttpServletResponse object
     * @param attachment    true to prompts for open or save; false opens the report
     *                      in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportRTFEditable(ReportClientDocument clientDoc, HttpServletResponse response, boolean attachment) throws ReportSDKExceptionBase, IOException {
        // RTF export allows page range export. The following routine ensures
        // that the requested page range is valid
        EditableRTFExportFormatOptions  rtfOptions = new EditableRTFExportFormatOptions();
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.editableRTF);      
        exportOptions.setFormatOptions(rtfOptions);

        export(clientDoc, exportOptions, response, attachment, "text/rtf", "rtf");
    }    
    
    /**
     * Exports a report to RTF for a range of pages
     * 
     * @param clientDoc     The reportClientDocument representing the report being used
     * @param response      The HttpServletResponse object
     * @param startPage     Starting page
     * @param endPage       Ending page.  
     * @param attachment    true to prompts for open or save; false opens the report
     *                      in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportRTFEditable(ReportClientDocument clientDoc, HttpServletResponse response, ServletContext  context, int startPage, int endPage,boolean attachment) throws ReportSDKExceptionBase, IOException {
        // RTF export allows page range export. The following routine ensures
        // that the requested page range is valid
        EditableRTFExportFormatOptions  rtfOptions = new EditableRTFExportFormatOptions();
        rtfOptions.setStartPageNumber(startPage);
        rtfOptions.setEndPageNumber(endPage);
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.editableRTF);      
        exportOptions.setFormatOptions(rtfOptions);

        export(clientDoc, exportOptions, response, attachment, "text/rtf", "rtf");
    }
    
    /**
     * Exports a report to Excel (Data Only)
     * 
     * @param clientDoc     The reportClientDocument representing the report being used
     * @param response      The HttpServletResponse object
     * @param attachment    true to prompts for open or save; false opens the report
     *                      in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportExcelDataOnly(ReportClientDocument clientDoc, HttpServletResponse response, boolean attachment) throws ReportSDKExceptionBase, IOException {
        DataOnlyExcelExportFormatOptions excelOptions = new DataOnlyExcelExportFormatOptions();
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.recordToMSExcel);      
        exportOptions.setFormatOptions(excelOptions );

        export(clientDoc, exportOptions, response, attachment, "application/excel", "xls");
    }

    /**
     * Exports a report to CSV
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param response        The HttpServletResponse object
     * @param attachment    true to prompts for open or save; false opens the report
     *                         in the specified format after exporting.
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    public static void exportCSV(ReportClientDocument clientDoc, HttpServletResponse response, boolean attachment) throws ReportSDKExceptionBase, IOException {
        CharacterSeparatedValuesExportFormatOptions csvOptions = new CharacterSeparatedValuesExportFormatOptions();
        csvOptions.setSeparator(",");
        csvOptions.setDelimiter("\n");
        ExportOptions exportOptions = new ExportOptions();
        exportOptions.setExportFormatType(ReportExportFormat.characterSeparatedValues);        
        exportOptions.setFormatOptions(csvOptions);

        export(clientDoc, exportOptions, response, attachment, "text/csv", "csv");
    }
    
    /**
     * Exports a report to a specified format
     * 
     * @param clientDoc       The reportClientDocument representing the report being used
     * @param exportOptions   Export options
     * @param response        The response object to write to
     * @param attachment      True to prompts for open or save; false opens the report
     *                        in the specified format after exporting.
     * @param mimeType        MIME type of the format being exported
     * @param extension       file extension of the format (e.g., "pdf" for Acrobat)
     * @throws ReportSDKExceptionBase
     * @throws IOException
     */
    private static void export(ReportClientDocument clientDoc, ExportOptions exportOptions, HttpServletResponse response, boolean attachment, String mimeType, String extension)
        throws ReportSDKExceptionBase, IOException {
        
        InputStream is = null;
        try {
            is = new BufferedInputStream(clientDoc.getPrintOutputController().export(exportOptions));
            
            byte[] data = new byte[1024];
            response.setContentType(mimeType);
            if (attachment)
            {
                String name = clientDoc.getReportSource().getReportTitle();
                if (name == null)
                {
                    name = "CrystalReportViewer";
                }
                else
                {
                    name = name.replaceAll("\"", "");
                }
                
                response.setHeader("Content-Disposition",
                        "attachment; filename=\"" + name + "."+extension+"\"");
            }
            OutputStream os = response.getOutputStream();
            while (is.read(data) > -1) {
                os.write(data);
            }
        } finally {
            if (is != null) {
                is.close();
            }
        }

    }
    
    /**
     * Prints to the server printer
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param printerName    Name of printer used to print the report
     * @throws ReportSDKException 
     */
    public static void printToServer(ReportClientDocument clientDoc,String printerName)throws ReportSDKException {
        PrintReportOptions printOptions = new PrintReportOptions();
        // Note: Printer with the <printer name> below must already be
        // configured.
        printOptions.setPrinterName(printerName);
        printOptions.setJobTitle("Sample Print Job from Crystal Reports.");
        printOptions.setPrinterDuplex(PrinterDuplex.useDefault);
        printOptions.setPaperSource(PaperSource.auto);
        printOptions.setPaperSize(PaperSize.paperLetter);
        printOptions.setNumberOfCopies(1);
        printOptions.setCollated(false);

        // Print report
        clientDoc.getPrintOutputController().printReport(printOptions);
    }
    
    /**
     * Prints a range of pages to the server printer
     * 
     * @param clientDoc        The reportClientDocument representing the report being used
     * @param printerName    Name of printer used to print the report
     * @param startPage        Starting page
     * @param endPage        Ending page.
     * @throws ReportSDKException 
     */
    public static void printToServer(ReportClientDocument clientDoc,String printerName,int startPage, int endPage)throws ReportSDKException {
        PrintReportOptions printOptions = new PrintReportOptions();
        // Note: Printer with the <printer name> below must already be
        // configured.
        printOptions.setPrinterName(printerName);
        printOptions.setJobTitle("Sample Print Job from Crystal Reports.");
        printOptions.setPrinterDuplex(PrinterDuplex.useDefault);
        printOptions.setPaperSource(PaperSource.auto);
        printOptions.setPaperSize(PaperSize.paperLetter);
        printOptions.setNumberOfCopies(1);
        printOptions.setCollated(false);
        PrintReportOptions.PageRange printPageRange = new PrintReportOptions.PageRange(startPage,endPage);
        printOptions.addPrinterPageRange(printPageRange);

        // Print report
        clientDoc.getPrintOutputController().printReport(printOptions);
    }

}

4.编写测试接口

package com.asyf.demo.controller;

import com.asyf.demo.utils.CRJavaHelper;
import com.crystaldecisions.sdk.occa.report.application.DataDefController;
import com.crystaldecisions.sdk.occa.report.application.ReportClientDocument;
import com.crystaldecisions.sdk.occa.report.data.Fields;
import com.crystaldecisions.sdk.occa.report.data.IParameterField;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

/**
 * @Author admin
 * <p>
 * 开源项目地址,CRJavaHelper的来源
 * https://github.com/souvikduttachoudhury/CrystalReportsSpringBoot
 */
@RestController
@RequestMapping(value = "/")
public class CrystalReportDemo {


    //请求地址需要转码,http://localhost:8080/test?deptNoPar=10&imagePath=C%3A%5CUsers%5CAdministrator%5CDesktop%5Cc.png
    @RequestMapping(value = "test", method = RequestMethod.GET)
    public void test2(HttpServletResponse response, Integer deptNoPar, String imagePath) throws Exception {
        //加载报表文件
        ReportClientDocument r = new ReportClientDocument();
        r.open("static/test.rpt", 0);

        //更换数据源
        String username = "scott";
        String password = "root";
        String driverName = "oracle.jdbc.OracleDriver";
        String connectionURL = "jdbc:oracle:thin:@localhost:1521:orcl";
        String jndiName = "JDBC(JNDI)";
        CRJavaHelper.changeDataSource(r, username, password, connectionURL, driverName, jndiName);

        //查询参数
        DataDefController dataDefController = r.getDataDefController();
        Fields<IParameterField> fields = dataDefController.getDataDefinition().getParameterFields();
        System.out.println("参数数量:" + fields.size());
        for (IParameterField field : fields) {
            System.out.println("参数 - " + field.getName());
        }

        //给参数赋值
        //第二个参数代表子报表,设置主报表参数,设置为空串
        CRJavaHelper.addDiscreteParameterValue(r, "", "deptNoPar", deptNoPar);
        CRJavaHelper.addDiscreteParameterValue(r, "", "imagePath", imagePath);

        //导出PDF
        CRJavaHelper.exportPDF(r, response, false);
    }

}

四、项目测试

1.注意事项

(1)请求地址中的imagePath内容需要转码

可以在线转码,推荐网址:http://www.jsons.cn/urlencode/

(2)输入不存在的imagePath地址,会使用水晶报表的默认图片

2.浏览器测试

3.动态效果

 

 

猜你喜欢

转载自blog.csdn.net/cs373616511/article/details/109269674
今日推荐