润乾集算报表提供了将图形、图像、报表、文字等内容按照指定顺序插入到word的功能,用户可以在word模板中设置多个书签、在配置文件中填入书签对应的插入内容,然后使用简单API就可以完成代码编写。目前该功能不仅支持书签插入,还可以替换word中的文本内容,可用于包括SmartArt图形中文字的替换。

下面通过示例介绍一下该功能的使用方法。

1准备word模板

首先准备要插入内容的word模板,确定各个位置需要插入的内容,需要根据实际需要设置书签或文本替换内容。下面是使用的模板、插入位置及要插入的内容标识如下(为了便于查看效果将要插入内容的位置进行编号):

wKiom1THDD7RLOGIAAFSwk0RiXk422.jpg

wKioL1THDR2zZi21AACJlGbFAHs578.jpg

   从上述模板可以看到,需要在该模板中插入图片、报表、文字等内容,除报表名称固定外,报表内容需要通过指定参数(年份)查询,而报告中涉及到的年份、报告人以及报告日期等均为动态内容。

  上述模板中使用的书签设置如下:

wKiom1THDD_iuly1AADsfOfk5MQ387.jpg

  其中,logo对应插入图片的位置,其他书签为插入报表位置。

2、修改配置文件

集算报表使用配置文件建立插入内容与书签和替换文本的对应关系。配置文件以xml格式存在,特别强调需使用UTF-8编码而不能用ANSI。文件中可以指定要插入的内容,包括文字、图片、报表和图像。配置文件中的设置分为两类:

第一类是基本不变的内容,可以是固定的文字、图片等,这类设置在配置文件中直接使用<bookmark name="markName" type="sType"file="fileName"/>标签来标识,其中type可以是p_w_picpath(图片)、text(文本)、report(报表)和value(值);如果仅仅是文本,还可以使用<text type=”value” old="oldText" new="newText"/>标签进行文本替换。

第二类则是在程序运行中动态改变的,如变化的文本、图形对象、报表参数,甚至报表本身,这类设置在配置文件中使用<bookmark name="markName" type="map"key="keyName"/>标签,特别的,动态文本还可以通过<texttype=”map” old="oldText" key="keyName" />标签进行替换,程序中会根据key读取内存动态存储的value

  针对上述模板,修改配置文件,内容如下:

<?xml version="1.0"encoding="UTF-8" standalone="yes"?>

 

<docx file="E:/XX年度销售汇总报告.docx"><!--  file表示模板docx文件名(绝对路径或相对于报表主路径的路径) -->

 

<!--   name表示docx书签, file表示绝对路径或相对于报表主路径的路径,name为空则不会插入 -->

<!--   type可以是文本、图片、报表或内存中的图像、报表对象等 -->

<bookmark name="logo"type="p_w_picpath" file="E:/logo.jpg"/>

 

<!-- text标签用来替换word中的文本,type="value"时用于替换静态文本;type="map"时用于替换动态文本-->

<text type="map"old="Title" key="title"/>

<text type="map"old="Date" key="date"/>

 

<!--  要插入报表模板,reportFile表示报表模板文件名 -->

<bookmark name="total"type="report" reportFile="E:/total.rpx">

    <!--  报表参数,typevalue表示报表参数值() -->

    <reportParam name="year" type="map"/>

    <reportParam name="qname" type="map"/>

</bookmark>

 

<bookmark name="employee"type="report" reportFile="E:/employee.rpx">

    <reportParam name="year" type="map"/>

</bookmark>

 

<bookmark name="top10"type="report" reportFile="E:/top10.rpx">

    <reportParam name="year" type="map"/>

</bookmark>

 

<bookmark name="type"type="report" reportFile="E:/type.rpx">

    <reportParam name="year" type="map"/>

</bookmark>

 

<bookmark name="area"type="report" reportFile="E:/area.rpx">

    <reportParam name="year" type="map"/>

</bookmark>

 

<text type="map"old="Person" key="person"/>

</docx>

    上述配置文件中,设置了静态和动态两类要插入的内容。

   其中静态内容的设置有:

使用书签插入(使用<bookmark>标签),插入了LOGO图片、5张报表;

 

动态内容的设置有:

(1)      报表参数,如:<reportParam name="qname"type="map"/>为报表total.rpx传递了内存中存储的qname值;

(2)       动态文本,如:<text type="map" old="Person"key="person" />,将程序中生成的动态文本内容插入模板;

 

所以要在word模板的指定位置插入内容,定位的方式有两种,如果是插入文本,可以直接使用文本替换(<text>标签)即可;而插入图片、报表等复杂对象则需要使用书签(<bookmark>标签)插入。

3、设计报表

本报告中需要插入5个报表,报表(参数和模板)设计简单说明如下:

汇总表(total.rpx

wKioL1THDR7QcxhuAAG7RARNbIM796.jpg

    按部门统计表(employee.rpx

wKiom1THDEKRPS42AAF_u2yVrDo973.jpg

    销售额前十名统计表(top10.rpx

wKioL1THDSGT2eOsAAFWPudphqE254.jpg

按类别统计表(type.rpx

wKiom1THDETh_BXUAAGFdSQRWlE707.jpg

按地区统计表(area.rpx

wKioL1THDSSxKBpYAAGMKLB95ZI882.jpg

4、编写代码

  定义报告下载页面:

   <form action="../servlet/InsertWord2" method="post">

     输入年份:<input type="text" name="year"/>

     <input type="submit"value="  " >

  </form>

  输入年份参数,生成相应年度报告并下载到本地。

wKiom1THDEfTDUTpAACwgaPVhtc903.jpg

编写实现类:

集算报表提供了插入word的接口,用户可以根据实际需要进行调用。根据上述模板和配置,本例中的实现类主体代码如下:

 

//读入配置文件,可以是绝对路径或相对报表主目录的相对路径

String xmlConfig =DocxChanger.xmlFile2String("E:/batch.xml");

 

//定义map,用于存放动态改变的内容,如其他应用传递过来已计算好的报表、参数、图像、文本等

HashMap map = new HashMap();

 

map.put("title", year+"年度销售情况汇总表");

map.put("qname", qname);

map.put("date", date);

map.put("year",year);

map.put("person",qname);

 

//除了可以传递文本内容外,还可以传递对象,如报表对象、图形对象等,这里不再演示,可以参考集算报表相关文档

 

javax.servlet.ServletOutputStreamout = response.getOutputStream();

//定义输出流,根据map和配置文件内容,生成结果word文件

DocxChanger.insert(map,xmlConfig, out);

实现效果

生成的word结果文件截图如下(编号与模板中编号对应):

wKioL1THDSfA2cHAAAEkM1-JG1w372.jpg

wKiom1THDEnDDaiGAADgnxevqa4939.jpg

wKioL1THDSmxWhywAAFQWCnMQJo773.jpg

wKiom1THDEui7LkeAACrmt3WF78884.jpg


【附】完整代码

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.util.Calendar;

import java.util.HashMap;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

 

import com.raqsoft.report.model.ReportDefine;

import com.raqsoft.report.usermodel.Context;

import com.raqsoft.report.usermodel.Engine;

import com.raqsoft.report.usermodel.IReport;

import com.raqsoft.report.util.ReportUtils;

import com.raqsoft.report.view.oxml.word.DocxChanger;

 

publicclassInsertWord2 extends HttpServlet {

 

    privatestaticfinallongserialVersionUID= 1L;

 

    public InsertWord2() {

       super();

    }

 

    publicvoid destroy() {

       super.destroy(); // Just puts "destroy" string in log

       // Put your code here

    }

 

    publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException,IOException {

 

    }

 

    publicvoiddoPost(HttpServletRequest request, HttpServletResponse response)

           throws ServletException,IOException {

       try {

           int year = Integer.parseInt(request.getParameter("year"));

           HttpSessionsession = request.getSession();

           Stringqname = (String) session.getAttribute("qname");

 

           Calendarcal = Calendar.getInstance();

           int y = cal.get(Calendar.YEAR);

           int m = cal.get(Calendar.MONTH)+1;

           int d = cal.get(Calendar.DATE);

 

           Stringdate = y + "" + m + "" + d + "";

 

           Stringfilename = "report.docx";

 

           Stringpath = "E:/";

           StringxmlConfig = DocxChanger.xmlFile2String(path + "batch.xml");

 

           HashMapmap = newHashMap();

 

           map.put("title",year+"年度销售情况汇总表");

           map.put("qname",qname);

           map.put("date", date);

           map.put("year",year);

           map.put("person",qname);

 

           javax.servlet.ServletOutputStreamout = response.getOutputStream();

           response.setContentType("application/x-msdownload");

           response.setHeader("Content-Disposition","p_w_upload; filename="

                  +newString(filename.getBytes("gb2312"), "iso8859-1") + "");

 

           DocxChanger.insert(map,xmlConfig, out);

           out.close();

           System.out.println("execute finished.");

       }catch(Throwable x) {

           x.printStackTrace();

       }

    }

 

    publicvoid init() throws ServletException {

       // Put your code here

    }

}