润乾集算报表提供了将图形、图像、报表、文字等内容按照指定顺序插入到word的功能,用户可以在word模板中设置多个书签、在配置文件中填入书签对应的插入内容,然后使用简单API就可以完成代码编写。目前该功能不仅支持书签插入,还可以替换word中的文本内容,可用于包括SmartArt图形中文字的替换。
下面通过示例介绍一下该功能的使用方法。
首先准备要插入内容的word模板,确定各个位置需要插入的内容,需要根据实际需要设置书签或文本替换内容。下面是使用的模板、插入位置及要插入的内容标识如下(为了便于查看效果将要插入内容的位置进行编号):
从上述模板可以看到,需要在该模板中插入图片、报表、文字等内容,除报表名称固定外,报表内容需要通过指定参数(年份)查询,而报告中涉及到的年份、报告人以及报告日期等均为动态内容。
上述模板中使用的书签设置如下:
其中,logo对应插入图片的位置,其他书签为插入报表位置。
集算报表使用配置文件建立插入内容与书签和替换文本的对应关系。配置文件以xml格式存在,特别强调需使用UTF-8编码而不能用ANSI。文件中可以指定要插入的内容,包括文字、图片、报表和图像。配置文件中的设置分为两类:
第一类是基本不变的内容,可以是固定的文字、图片等,这类设置在配置文件中直接使用<bookmark name="markName" type="sType"file="fileName"/>标签来标识,其中type可以是image(图片)、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="image" 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">
<!-- 报表参数,type为value表示报表参数值(串) -->
<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>标签)插入。
本报告中需要插入5个报表,报表(参数和模板)设计简单说明如下:
汇总表(total.rpx)
按部门统计表(employee.rpx)
销售额前十名统计表(top10.rpx)
按类别统计表(type.rpx)
按地区统计表(area.rpx)
定义报告下载页面:
<form action="../servlet/InsertWord2" method="post">
输入年份:<input type="text" name="year"/>
<input type="submit"value="确 定" >
</form>
输入年份参数,生成相应年度报告并下载到本地。
编写实现类:
集算报表提供了插入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结果文件截图如下(编号与模板中编号对应):
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","attachment; 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
}
}