java excel 导出图片_年薪百万大佬教你excel如何导出PDF并保持原大小,只需Java联动?

作为一个后端仔,工作中不仅仅要面临着crud的折磨,更是会经常接到excel报表导出PDF生成等可以提升友军工作效率的需求。

但是Excel可比前端组件难用多了,特别是在遇到一些比较追求完美的友军的时候一些想法让人在不能拒绝的同时甚是难受。所以总结了两个比较烦的需求的解决方案:复杂表头和图片保持原大小

复杂表头实践

工作中表格是我们显示数据的最常用排版,无论是在前端还是excel都离不开表格结构。表格分为表头和内容两部分,当我们接到只有一行表头的excel导出需求时,此时我们的内心是这样的

9a2b0d44f008d9b61b49af4b10ffc9ed.png


但当我们被追问 "为什么前端小哥可以显示你后端就不能?"从而被要求导出这种格式的excel时

14ea8badef785067964148bec4f8955b.png


此时对于一个Java在我们的内心是可能是这样的

cc81319174ca7800a0229ed9d0596790.png


带着一丝迷茫 我们打开了百度/谷歌开始了漫长的搜索之旅 "Java导出Excel", "Java创建复杂表头"....


最终你会找到JXL、POI等操作excel的工具,然后找到合并单元格的api,然后变成"算法"工程师,展现你强大的计算能力。

计算出你需要多少个单元格以及每个单元格的跨度,然后开始merge单元格之旅,最终完成了设计。但是作为一个有追求(会偷懒)的后端仔,这种重复性的工作可是会要了我们老命,所以想出了一个粗浅的解决方案和大家分享下,给其他有同样困扰的职场新人一个小思路。哦,本文以JXL为例子进行试验

观察表头

从上面表头的格式来看,再结合我那easy水准的力扣水平,我们要想构造一个这种有父子、层级关系的表头,还是需要递归来帮我们解决。

@Datapublic class TableHeader {    private String title;     private int col;    private int width;    private int row;    private int height;    private int depth;     private int colStart = 0;    private int rowStart = 0;    private int colEnd = 0;    private int rowEnd = 0;     private List children;     public TableHeader() {        reset();    }     public TableHeader(String title) {        reset();        this.title = title;    }     public void reset() {        title = null;        col = 0;        width = 1;        row = 0;        height = 1;        depth = 1;        colStart = 0;        rowStart = 0;        colEnd = 0;        rowEnd = 0;    }     public void addChildren(TableHeader header) {        if (header == null) {            return;        }        if (children == null) {            children = Lists.newArrayList();        }        children.add(header);    }     public TableHeader addSubTitle(String title) {        if (StringUtils.isBlank(title)) {            return null;        }        TableHeader subHeader = new TableHeader(title);        addChildren(subHeader);        return subHeader;    }}

整个表头中的一个单元格 可以看成一个TableHeader对象,其子单元格也可以看做一个TableHeader对象。说了这些你可能会吐槽,别BB了,先上个例子。好那我们就上个实际使用的例子。

783ba6f790bc8b4cef56f8b69ea9a61f.png

这就是我们最终要生成的excel表格的表头。如果要使用上面的数据结构,我们应该怎么表示呢?问的好:

7f20cfdc4369ac0f93b854031b74053a.png

只需要这几行代码就可以。表格的最上面的一个单元格为顶级单元格,其他的直接和其链接的都为其子单元格。如图中的部门全部漏洞有效漏洞都是部门漏洞统计的子单元格,所以直接使用addSubTitle方法添加即可,该方法会返回当前单元格,所以可以继续给子单元格添加子单元格,如图中的有效漏洞。从个人使用角度来讲,还是很方便的。

713e986d5d4dac1e0c06e6549d3785a2.png

从上图中可以看到一些基本思路,构造表头单元格主要分为两步,即两个功能函数

1、调整坐标

在阅读了JXL的相关API后,我们可以了解到excel表格是没有浏览器那种流特性的。所以本质是还是要我们事先计算好每个单元格所占据的范围,然后进行从左上角坐标到右下角坐标的merge操作,来创建一个复杂的表头。TableHeader类中我们能看到这些基本的属性

31381cb80c107d97a6b603bce7d17fa4.png

(row, col) 就代表了一个单元格左上角的坐标,接下来就是对这个单元格的高度和宽度进行计算。

fab6a244b5a10a1016ffab200d8ef1cb.png

首先是计算整个表头中各个单元格的跨度,即宽和高知道了宽高才能设置左上角的坐标

92b507541a6079559cc36a62adde0bca.png

宽度的设置很简单,就是子元素宽度之和

3d3004fd89ce805c7e64bcf7ac48894b.png

高度稍微有点绕,因为高度主要是同级元素的最高高度减去自己的子元素最高高度

ec7f9b65bdf91a6104c0d9333f801815.png

至此我们已经调整好了表头中所有单元格的宽度和高度,然后就可以设置单元格起始坐标了和结束坐标了,思路很简单 ,根据自己的宽度和高度,进行简单的加减乘除计算就行。其中兄弟元素的col和子元素的row受到当前单元格的限制

6bc2af71e6b51a969dfffd19d8646bf8.png

2、创建真正的单元格

经过上面的操作,一个调整好坐标的表头对象已经构造好。我们直接拿来使用就行了。
由于其不具有流的特性,所以我们还是要分为两步 先根据坐标merge单元格 然后再往里面填充Label对象(单元格)

294027522dfef41cc06ea78ac2d61cbe.png

其中有个单元格列的宽度设置 是根据经验来的 并没有深入去了解他是如何换算的单位。

59902acc3a06c69f315b2d09c087dde3.png

另外单元格的样式 我们不能用静态对象 这是一个BUG 否则会在现持久化的时候抛出IO异常 需要注意下 每次使用都应该返回一个新的对象

d798cd93af0e6d170d77f33f1f67cb89.png

至此 我们的构造复杂表头的功能就完成了,最终我们还是将图片原模原样的插入到了excel中。

虽然作为服务端的我们都幻想着能够高并发大流量,但是难免会接到一些不那么让人舒服的需求。
但作为一名员工,这是我们不可推卸的职责,从小事做起吧~希望可以帮到同为职场新人的你。


私信来聊天!

因今日头条推荐流问题...为了避免【一起来Java】消失在大家的信息流中,小编这里欢迎大家多评论点赞关注哦~关注完之后大家就可以每天正常收到我们的推送,愉快学习愉快聊天啦!

大家也可以将学习使用Java过程中不懂的困惑提出来,小编也会为大家解决疑惑的哦!

最近我也整理了一些Java资料,包含面经分享、模拟试题和视频干货,都是免费的哦!如果感兴趣的话,欢迎来私信~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值