最近公司开发一套数据汇报导出要求支持导出pdf,网上搜了一下 发现 jasperreport 比较适合
于是开始使用开发, web 使用的是 springmvc ,现将 引用依赖导入工程
jasperreport 相关的
<!-- JasperReports -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.4.0</version>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports-chart-customizers</artifactId>
<version>6.4.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.11</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext-asian-base</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext-asian-cf</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-svggen</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-bridge</artifactId>
<version>1.9</version>
</dependency>
<!-- 注意以下3个jar 由于集成环境是 从aliayun 仓库下载的jar导致 不能下载,需要在此单独引进 -->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-constants</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>xmlgraphics-commons</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-i18n</artifactId>
<version>1.9</version>
</dependency>
<!-- end JasperReports -->
以上是 涉及到的 所有相关jar,需要注意
1.itext-asian-base 网上找到的资源 需本地单独安装一下 【maven 库 的某个版本】
2.itext-asian-cf 使用报表工具 导出的 中文 微软雅黑字体 jar 【不用担心 服务器找不到 字体】 window -属性-字体 导出
3.jasperreports-chart-customizers 可有可无, 当 图表 chart 定制化时 必须要有
这三个jar 的下载地址:http://download.csdn.net/download/renqingen/9880559
注意 以上jar 含有 svg 工具包 是是为了导出 html 格式 使用 不用配置 什么图片地址
图表html 显示格式是svg 不用配置serviet url
生成 图表 发现问题
原来 当数据变多时 图表 height 维持不变 ,导致柱状图 的 柱子 愈来愈细 甚至看不清晰 ,怎么解决?
发现说可以使用
renderer.setMaximumBarWidth(0.16);
来设置宽度,其实没鸟用
没办法,自己动手丰衣足食,查api 发现可以设置 height 但没用
最后 想到用一招
既然 图表高度是在设计时已经固定好的,那么可不可以从程序角度 后面展示时对其进行修改呢?
答案时可以的。
步骤:
1.将自己的报表 中 的每一张 stackedbarchart 单独出来 放到一个 jrxml 文件
2. 将自己原来的报表 内 stackedbarchart 删除 替换成 subreport
3. 程序 从后台 读取 子报表源文件【其实是 一张 stackedbarchart.jrxml】成 String 字符串
4.解析 xml 字符串 成 document 使用 dom4j
5.根据 后台 从数据库 中查询的 数据量 重新 计算 子报表的 高度 图表的高度 summary band 高度 等 【否则高度不对会出错 很简单的道理】
6. 根据新的xml document 生成新的 子报表文件【因为该文件自有一张图表 所以结构很简单】
7.使用代码 jasperReport=JasperCompileManager.compileReport 生成 一个子报表对象
8.在主报表中定义参数 类型为 net.sf.jasperreports.engine.JasperReport 将该参数传入子报表
9.根据以上步骤 动态的新报表 就完成类,具体参数怎么传网上也有很多,我就不说了
10. 在主报表中查看 子报表 属性 修改 内容 布局 默认是 bottom 选择false , 位置 选择 float
根据以上 图表的高度问题就解决了 ,一下是我 图表高度的计算方法,仅供参考 ,理解就行
/**堆栈类图表 动态计算工具类*/
public class StackedBarDynamicMaker {
/**根据jaspser report 源文件 和 数据个数 动态计算图表高度*/
public static String format(String srcFilePath , int itemSize ,int itemBarHeight){
//定义返回
String xml=null;
SAXReader reader = new SAXReader();
try {
Document document = reader.read(new InputStreamReader(new FileInputStream(srcFilePath),"utf8"));
Element rootEle = document.getRootElement();
//报表总高度
int pageHeight=Integer.parseInt(rootEle.attributeValue("pageHeight"));
//summary中 band高度
Element summaryEle=rootEle.element("summary");
Element bandEle=summaryEle.element("band");
//图表的 坐标偏移值
Element reportEle=bandEle.element("stackedBarChart").element("chart").element("reportElement");
int pointY=Integer.parseInt(reportEle.attributeValue("y"));
//根据报表设计经验:
//为了解决数据多时排名条形图高度自适应(高度时柱状图变细)
//int summaryBandHeight=Integer.parseInt(bandEle.attributeValue("height"));
//需重新计算 summaryBandHeight 和 chartHeight 最大值均不超过pageHeight 否则报错
//由于设置报表时是 以 左上角 0,0 坐标 为开始的 , 为了包子 图表尺寸 刚好填充报表尺寸
//其中 pointY 为负数
//实际图表的高度 chartHeight=summaryBandHeight-pointY;
//推荐每个柱子高度40
//动态计算图表高度值
int dynChartHeight=itemSize*itemBarHeight+100;
//加上限制最大高度
if(dynChartHeight>=pageHeight){
dynChartHeight=pageHeight-50;
}
int dynSummaryBandHeight=dynChartHeight+pointY;
//设置新的动态计算值
bandEle.addAttribute("height", String.valueOf(dynSummaryBandHeight));
reportEle.addAttribute("height",String.valueOf(dynChartHeight));
//重新写回xml文件
StringWriter strWtr = new StringWriter();
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter xmlWriter =new XMLWriter(strWtr, format);
xmlWriter.write(document);
xml = strWtr.toString();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
//返回
return xml;
}
我的子报表 布局图如下:
只需理解原理相信对于编程java 老手的你们不是什么难事。