承接上篇

上一章介绍了饼图,本章废话不多说了,准备给案例加个目录和封面,并且给案例排排版,做的好看一些!!!

案例回顾 — 以图为证

模板排版优化

1. 模板数据和列表展示更为合理

通过我们前面的讲解,将现有的模板布局设置的更为美观一些!!!通过调整各个组件的位置实现即可,这里不做过多介绍,可以自行设置,我去除了各个组件之间的距离,让组件和detail完全重合可以做到;

2. 目录添加

第一个就是分组之前的测试数据,添加目录一:测试数据;
第二个就是分组数据就以各个组名作为目录即可;
首先是目录一:测试数据
直接在demo2.jrxml模板中的测试数据(交叉表)上方添加一个动态文本作为目录一,设置如图,字体微软雅黑,字体16,靠左纵向居中,目录级别设置为1,跳转就找到最近数据 — 选择“测试数据”即可,这个可以参考之前的教程,点击finish即可,记得保存


其次将分组名做同样的设置,打开demo2_sub1.jrxml,设置分组名称,微软雅黑,字体16,靠左纵向居中,目录等级1,跳转同理选择分组名即可,如图设置:

然后重新编译demo2和demo2_sub1模板,看看目录是否生效;

这个我们前面说过,显示不全是因为目录页字体设置太大的原因,可以将字体设置小一些即可,保证你的边框中能显示文本

重新编译目录页TOC.jrxml,查看效果,然后点击页码或者小标题,可以实现页面的跳转,可跳转页面成功!!!


查看导出的pdf和word是否正常,word导出目录正常,pdf导出目录正常且pdf目录跳转正常,但是这里出现了一个新问题,word目录页不支持跳转

3. 解决word中目录页不能跳转的问题

word当中目录能够正常显示,但是不能跳转,问题在于word当中跳转不能识别中文开头的标题;

修改目录小标题,给每个小标题之前加一个前缀字符,都加字符a试试看跳转是否起作用,**这里可能有些小伙伴不能直接给跳转的小标题加上一个字符a,有个小技巧,先将模板中对应的标题前面加一个a,然后就能在最近使用的文本中发现我们刚刚修改过的小标题,这时候直接选中即可,选完之后再将模板中的动态文本的前缀字符a去掉,造成了只是改变跳转目录的错觉!!!**可能有些伙伴觉得,这两个不一样能实现跳转吗,实践出真知,试试就知道了!!!


重新编译demo2和demo2_sub1模板进行测试,看看是否目录正确显示,因为我们刚才加了个a所以目录前面自然多了一个a,目录正常跳转,主要看一下word:


word也正常显示了目录,此时按住ctrl进行跳转你会发现????无论点击哪个都跳转到了最后一个物联网,不可思议,原因就在于我们的前缀,word跳转的时候会默认跳转到相同前缀的最后一处,所以物联网是所有目录中的最后一个,自然就很顺利的跳转到了最后一个,但是在pdf中就不会存在这样的跳转问题,所以你得公司如果导出了word,记得避坑!!!

既然发现了问题所在就着手解决这个问题,所以我们在给每个小标题加一个前缀的时候,要保证每一个前缀不相同,而且保证加一个字符,所以这里跟之前的那个交叉表类似,所有的操作都在业务层实现,分组名作为标题的时候,给分组名称加一个数字或者阿拉伯字母类型(目前我就试了这个所以这边就提供了这个)a,b,c…1,2,3,4,5,6… 这样的,保证不重复,因为我是演示,所以就直接添加即可,如图;然后我们的模板中恢复原样;


重新编译查看跳转效果:


按住ctrl选中word中的小标题或者页码值,可以发现能够实现跳转,不会跳到同一个地方,所以切记小标题前缀不能相同;
另外还有一个问题就是前缀隐藏,前面我们说了截取,所以这里我们可以在doc.jrxml封面模板中对标题进行截取,只显示1号位往后的字符,还有就是你分组显示的标题也需要截取,因为是业务层加个前缀,设置如图:

重新编译封面doc模板,查看效果:


按住ctrl+页码值,发现能正常跳转了,目录显示也是正确的,成功解决了问题!!!

4. word目录小结

总结3的解决方式:
第一种是直接在目录中添加,手动更改你目录的标题,在标题前面加一个字母或者是数字,但是有个比较不好的地方就是遇到分组,会有多个小组你不方便动态去给分组名前面加个不同的前缀,所以这种方式只适合所有标题全部是不分组的情况;
第二种就是业务层添加目录前缀,建议所有的目录标题都在业务层中用变量进行注入,当然有些文本直接在模板中写了更好,业务层中少一些变量也不错,但是值得注意的是所有的小标题前缀不能重复,然后就是对各个小标题显示的截取问题了,默认显示从1号下标开始;
还有一点值得注意的是小标题的文本都是动态文本,只有动态文本才会存在设置目录这种东西,千万不要用静态文本,不然你发现找不到设置!

5. 关于在封面的图片上动态添加时间

这个问题我们在目录页的章节中提到过,因为特殊的关系,word导出的图片和文本不能同时在一个网格中显示,所以只会显示其一,故决定将文本写入到图片中,生成一个新的图片作为背景图;
背景效果如图,我们在右下角的位置加一个2022-05-31也就是当天日期,当然这个时间格式大家根据自己的实际情况进行添加!!!

原型图是我们的之前的背景图片,日期:2022-05-31,两者合二为一变成一张新图,原理是这样:我们要将时间嵌入到图片的合适位置,这就需要坐标,所以我们需要本地进行一次次的位置调试,最终变成的合适的图片,然后在写入我们的逻辑当中。

5.1 图片和文字生成代码

 /*** 封面生成图片 根据传入的路径生成新的图片*/public static boolean createHeaderImage(InputStream stream, String markContent, String outPath) {try {Image headerImage = ImageIO.read(stream);ImageIcon imgIcon = new ImageIcon(headerImage);Image theImg = imgIcon.getImage();int width = theImg.getWidth(null) == -1 ? 200 : theImg.getWidth(null);int height = theImg.getHeight(null) == -1 ? 200 : theImg.getHeight(null);BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g = image.createGraphics();Color color = Color.BLACK;g.setColor(color);g.setBackground(Color.white);g.drawImage(theImg, 0, 0, null);//字体、字型、字号g.setFont(new Font("Microsoft YaHei", Font.BOLD, 80));//画文字g.drawString(markContent, 1900, 1200);g.dispose();//输出图片File sf = new File(outPath);// 保存图片ImageIO.write(image, "png", sf);} catch (Exception e) {return false;}return true;}

5.2 测试方法

public static void main(String[] args) throws IOException {ResourceLoader resourceLoader = new DefaultResourceLoader();// 生成图片 将时间和图片合二为一InputStream imageIs = resourceLoader.getResource("classpath:/jasper/student/wave.png").getInputStream();File headerImage = File.createTempFile("headerImage", ".png");String time = DateTime.now().toString();StudentFactory.createHeaderImage(imageIs, time, headerImage.getPath());}

5.3 最终的图片预览效果

可以看到我将2022-05-31最后嵌入到了右下角,坐标我最后定在了(1900,1200)分别对应x轴和y轴,当然这个坐标需要自己慢慢调试,不停的去修改坐标达到合适的效果,最后我们在模板中使用我们的背景图即可,这里模板中的背景图就需要进行路径填充

5.4 模板背景图添加路径和背景图代码添加

1. 首先将图片生成代码放在我们的StudentFactory中,这个合适的位置即可,反正是静态方法,到时候直接调用;

2. 修改导出代码 — 添加图片生成
生成代码变动如下:
添加了导出图片的代码,以及在map中添加了一个headerImage变量用于给模板添加一个动态图片路径

@GetMapping(value = "/reportStudent")public void reportStudent(HttpServletRequest request, HttpServletResponse response) throws IOException {try {OutputStream os = response.getOutputStream();String reportName ="student.jasper";response.setContentType("application/pdf; charset=utf-8");response.setDateHeader("Expires", 0);JasperReport jasperReport = (JasperReport)JRLoader.loadObject(resourceLoader.getResource("classpath:/jasper/student/"+reportName).getInputStream());String subPath = resourceLoader.getResource("classpath:/jasper/student/").getURL().toString();JRBeanCollectionDataSource studentFactory = new JRBeanCollectionDataSource(StudentFactory.getStudentInfo());// 生成图片 将时间和图片合二为一InputStream imageIs = resourceLoader.getResource("classpath:/jasper/student/wave.png").getInputStream();File headerImage = File.createTempFile("headerImage", ".png");String time = DateTime.now().toString();StudentFactory.createHeaderImage(imageIs, time, headerImage.getPath());HashMap<String, Object> hashMap = new HashMap<>(16);hashMap.put("headerImage", headerImage.getPath());hashMap.put("subPath", subPath);hashMap.put("studentFactory", studentFactory);JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, hashMap, new JREmptyDataSource());// 页面预览pdfJasperExportManager.exportReportToPdfStream(jasperPrint,os);// 导出pdf到具体路径JasperExportManager.exportReportToPdfFile(jasperPrint,"D:/report/测试.pdf");// 导出word到具体路径List<JasperPrint> test1 = new ArrayList<>();test1.add(jasperPrint);JRDocxExporter exporter = new JRDocxExporter();exporter.setExporterInput(SimpleExporterInput.getInstance(test1));exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(new File("D:/report/测试.doc")));exporter.exportReport();System.out.println("导出word文件成功");} catch (Exception e) {e.printStackTrace();}}

3. 修改模板中的封面背景图加载方式 — 修改为路径获取
第一步: 在主模板中添加图片路径变量headerImage,如图:

第二步:将变量注入到封面模板中,如图设置,注意变量名称要和map中的一致,点击finish完成,记得保存!!!前面教程中说过,不多说了!!!

第三步:打开封面cover模板,在parameter中添加我们注入的图片路径变量headerImage — 用于接收刚才注入的变量;

第四步:修改封面中的图片加载方式 — 改为变量headerImage加载,如图设置,保存一下

最后:重新编译主模板student.jrxml和封面模板cover.jrxml,因为我们就改了这两个模板所以仅需要编译这两个,放入项目中重新编译项目,测试效果:

效果图算是出来了,然后这里有个稍微注意一些的地方,就是你的背景原型图最好是那种全覆盖的,不然就容易重新生成图片,像我这个一样某些区域是黑色的,这一点需要注意一下。
很好的一点就是,后面如果有图片和数据叠加的情况都可以用这种方式进行填充,效果也是ok的

5.5 小彩蛋(闭坑)

  1. 如果你是在linux部署服务,记得你的模板字体一定要修改成常见的字体方式,不然linux上面可能识别不到一些模板中默认的字体,很容易报错,你会发现你的项目在本地很好使,但是一上服务器就gg,可能是因为字体;
  2. 另外是图片加载方式采用我这里的流加载方式,我这个也是和别人学习的,一开始我才用的是静态路径加载的方式,不是采用stream方式加载图片会导致服务器上找不到路径,但是本地很好使!!!

6. 总结summary

常言道,十年磨一剑,台上三分钟,台下十年功;千里之行始于足下;优秀的报表需要不断的调试和摸索,本人终于赶在六一之前完成了算是所有教程的讲解,也是作为送给各位伙伴六一的礼物,希望大家能在六一过个好节,天天开心,少掉头发,虽然我们每天面对着大量的代码和bug,但是我们始终不忘记我们曾经学习的日日夜夜,静待花开!
抒情就到这吧,希望以后能多多扫地,争取称为扫地界的一枚新星,也希望各位伙伴在看我的教程多提出一些问题,我们一起交流,让jasperreport越来越好,让报表之路不再磕磕绊绊,做到一气呵成!!!!
我会将我的代码和模板放到我的百度链接当中作为参考,欢迎伙伴们评论区留言提问,一起进步,祝csdn越来越好!!!
百度云地址(模板和代码):
链接:https://pan.baidu.com/s/1WP4md5Ixdd4sIJ29rApp2A
提取码:6666

Jasperreport_6.18的回血终结篇之案例目录、封面相关推荐

  1. 解决死锁之路(终结篇) - 再见死锁

    解决死锁之路(终结篇) - 再见死锁 一.开启锁监控 1. 基于系统表 2. 基于系统参数 二.读懂死锁日志 三.常见死锁分析 3.1 死锁案例一 3.2 死锁案例二 3.3 死锁案例三 3.4 如何 ...

  2. 看看C# 6.0中那些语法糖都干了些什么(终结篇)

    终于写到终结篇了,整个人像在梦游一样,说完这一篇我得继续写我的js系列啦. 一:带索引的对象初始化器 还是按照江湖老规矩,先扒开看看到底是个什么玩意. 1 static void Main(strin ...

  3. android中英文混合,搜狗手机输入法Android3.3中英混输无障碍之终结篇

    搜狗手机输入法Android3.3中英混输无障碍之终结篇 (2012-10-30 18:23:42) 标签: 娱乐 本周小编对于搜狗.百度两款手机输入法在中英文混输功能上进行了两轮测试,通过测试我们会 ...

  4. 在没有DOM操作的日子里,我是怎么熬过来的(终结篇)

    前言 在我写终结篇的日子里,Vue版本稳定在2.5.10.当我摸清Vue的脉络之后,以一个爬坑无数的亲历者的身份,谈谈我在MVVM时代里遇到的那些事儿. 接下来,正文从这开始~ 好多童鞋学习Vue都有 ...

  5. 22.【终结篇】poco/airtest+pytest+allure+jenkins框架篇

    如果这些内容对你有帮助,也可以打开微信扫一扫,加关注: ​ 前几篇文章已分享了所有代码层相关内容,并提供了源码文件,接下来看下怎么和jenkins配合使用. 为了更方便获取框架源码,下面再汇总下前面几 ...

  6. 视频教程-微信小程序开发【初级篇 / 附案例】-微信开发

    微信小程序开发[初级篇 / 附案例] 北风网讲师!瓢城Web俱乐部创始人,教学总监! 李炎恢 ¥129.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 APP订阅课程, ...

  7. 用XAML做网页!!—终结篇

    原文:用XAML做网页!!-终结篇 迄今为止的设计都很顺利,但这次就不得不接触我前面所说的非常糟糕的流文档了,但在此之前先来把标题弄好: <Border BorderBrush="#6 ...

  8. 第十四篇 数据分析案例

    经过前面的学习,下面来看⼀些真实世界的数据集.对于每个数据集,我们会⽤之前介绍的⽅法,从原始数据中提取有意义的内容.展示的⽅法适⽤于其它数据集,也包括你的.本篇包含了⼀些各种各样的案例数据集,可以⽤来 ...

  9. 分布式事务科普(终结篇)

    <分布式事务科普>是我在YiQing期间整理的一篇科普型文章,内容共计两万五千字左右,应该算是涵盖了这个领域的大多数知识点.篇幅较长,遂分为上下两篇发出.上篇为<分布式事务科普--初 ...

最新文章

  1. 8 Django 模型层(2)
  2. activiti mysql 版本_Mysql8.0.17版本不能自动创建activiti表的坑
  3. 前端学习(2168):url的hash和html的history
  4. python常用函数的用法_python3 文件操作常用函数用法示例
  5. 注册表在各个系统中保存路径
  6. [过年菜谱之]清蒸鲈鱼
  7. HtmlAgilityPack.dll的使用 获取HTMLid
  8. 常见英文缩写 (持续更新……)
  9. 每一个都能笑抽的39个奇葩代码注释
  10. 从0开始构建一个属于你自己的PHP框架
  11. SQL截取字符串和替换字段
  12. 2022年R2移动式压力容器充装上岗证题库及在线模拟考试
  13. STM32MP157 Linux系统移植开发篇16:Linux内核音频驱动移植
  14. 快速切换ip没必要用工具
  15. miui11开发版升级Android10,小米10 手机 MIUI 11 开发版升级 DXOMARK 相机版本
  16. 柱状图怎么设置xy轴_excel表格xy轴数据-怎么做用excel设置xy轴
  17. 000 Python教程
  18. 今日头条能干掉微信么? | 畅言
  19. 千里之行,始于足下。python 爬虫 requestes模块(2)
  20. 计算机十大算法应用 知乎,2019 智源·知乎看山杯算法大赛收官:7 支团队脱颖而出,单人队荣摘桂冠!...

热门文章

  1. 【微机原理与汇编语言】输出n位十进制数
  2. 这么骚的SQL进阶技巧,不怕被揍么?
  3. 中国计算机大赛游戏,我校在第10届全国大学生计算机设计大赛第暨4届中国大学生动漫游戏设计大赛,“星雨杯”福建省级赛的表现优异...
  4. 广工anyview数据结构第四章(2021.12)
  5. 使用Python评估一支股票的价格
  6. 如何使用远程桌面连接远程计算机?
  7. 实验四——恶意代码技术
  8. 在WebGL场景中管理多个卡牌对象的实验
  9. 路由器上的usb接口有什么用_解决USB接口不够用,毕亚兹Type-C扩展坞体验测评
  10. qrcode二维码实现