主机参考:VPS测评参考推荐/专注分享VPS服务器优惠信息!若您是商家可以在本站进行投稿,查看详情!此外我们还提供软文收录、PayPal代付、广告赞助等服务,查看详情! |
我们发布的部分优惠活动文章可能存在时效性,购买时建议在本站搜索商家名称可查看相关文章充分了解该商家!若非中文页面可使用Edge浏览器同步翻译!PayPal代付/收录合作 |
前言
最近有读者在问easypoi & # 30340问题,抽空整理了一份文章。
正文
EasyPOI & # 21151能如同名字简单& # 65292;主打的功能就是容易,让一个没接触过POI & # 30340人员可以方便的写出Excel & # 23548出,Excel & # 27169板导出,Excel & # 23548入,Word & # 27169板导出。通过简单的注解和模板语言(熟悉的表达式语法),完成以前复杂的写法。
本文主要通过简单的分析让读者知道Excel & # 27169板该如何编写,EasyPOI & # 35201如何使用才能导出满足自己需要的Excel & # 25968据,从而简化编码。同时本文还会对一些不常见的功能如图片导出功能进行说明,让读者少踩坑。
版本及依赖说明easy poi 4 . 0 . 0 & # 21450;以后的版本依赖于阿帕奇POI & # 303404.0.0及以后版本。所以在maven & # 30340配置中,两者的版本号一定要匹配。
需要注意的是,阿帕奇POI & # 303404.0.0相对之前的版本有很大的变更,如果之前代码中Excel & # 25805作部分依赖于旧的版本,那么不建议使用4.0.0及之后的版本。当然,如果之前代码不涉及或很少涉及工作簿& # 30340;创建细节,使用新版也没有问题。
笔者需要改写的项目基于JEECG 3.7 & # 29256本,依赖的是3.9版本的阿帕奇POI & # 65292而JEECG & # 32500护的jeasypoi & # 29256本最高只有2.2.0,而该版本并不支持模板导出图片功能。说到这里又要吐槽以下JEECG & # 22242队,既然自己不打算维护jeasypoi & # 65292那项目中直接使用官方的EasyPOI & # 19981就好了,2.2.0版本的jeasypoi & # 32473开发者挖了多少坑啊!
为了和旧版本兼容,又想使用EasyPOI & # 24102来的图片导出功能,所以笔者最终采用的EasyPOI & # 29256本是3.3.0,对应的阿帕奇POI & # 20381赖是3.15。
Maven & # 37197置如下所示:
& lt属性& gt& ltpoi.version & gt3.15 & lt/poi . version & gt;& lteasypoi.version & gt3 . 3 . 0 & lt;/easy poi . version & gt;& lt/properties & gt;& lt依赖关系& gt& lt依赖性& gt& ltgroupId & gtorg . Apache . poi & lt;/groupId & gt;& ltartifactId & gtpoi & lt/artifact id & gt;& lt版本& gt$ { poi.version } & lt/version & gt;& lt/dependency & gt;& lt依赖性& gt& ltgroupId & gtorg . Apache . poi & lt;/groupId & gt;& ltartifactId & gtpoi-oo XML & lt;/artifact id & gt;& lt版本& gt$ { poi.version } & lt/version & gt;& lt/dependency & gt;& lt依赖性& gt& ltgroupId & gtorg . Apache . poi & lt;/groupId & gt;& ltartifactId & gtpoi-oo XML-schemas & lt;/artifact id & gt;& lt版本& gt$ { poi.version } & lt/version & gt;& lt/dependency & gt;& lt依赖性& gt& ltgroupId & gtorg . Apache . poi & lt;/groupId & gt;& ltartifactId & gt兴趣点便签簿& lt/artifact id & gt;& lt版本& gt$ { poi.version } & lt/version & gt;& lt/dependency & gt;& lt依赖性& gt& ltgroupId & gtcn.afterturn & lt/groupId & gt;& ltartifactId & gteasy poi-web & lt;/artifact id & gt;& lt版本& gt$ { easypoi.version } & lt/version & gt;& lt/dependency & gt;& lt/dependencies & gt;Excel & # 27169板的设计我们使用EasyPOI & # 30340模板导出功能就是不想通过编码的方式来设计Excel & # 25253表的样式,所以工作的第一步就是设计Excel & # 27169板,分清楚哪些部分是固定的,哪些是需要循环填充的。EasyPOI & # 26377自己的表达式语言,每种表达式的详细介绍请参考后文的参考链接。
一个简单的Excel & # 25253表模板一些简单的模板就不在这里详细解释了,只放一下效果图和模板配置内容。等读者明白了复杂的模板如何制作并如何填值的时候,简单的很快就能明白了。
先看看报表效果图:
再看看实际的模板:
看了上述两张图,是不是已经感受到模板导出功能的强大了呢?
一个复杂的Excel & # 25253表模板下面要介绍的这个模板比较复杂,不像是常见的那种一行是一条记录的情况,所以将详细介绍该模板的配置,顺带对EasyPOI & # 30340部分表达式进行简单介绍。
还是先看效果图:
再看看模板:
这两张图一对比,是不是有种知识改变命运的感觉?
复杂模板设计剖析从货品信息的模板图及效果图中我们发现,整个模板实际上分为上下两部分。其中上部分为不变的抬头信息,下部分为循环插入的货品明细信息。所以我们关注的重点是下半部分的语法。
下半部分的第一列图中没有显示完整,实际上是{{!fe:列出t.id & # 12290
注意,这里没有}}符号!根据EasyPOI & # 30340官方文档,{{}}代表的是表达式,根据表达式取里边的值。仔细看图可以发现,表达式的闭合符号{{}}出现在图中的右下角。也就是说,从第一列{{开始至右下角}}结束,这中间的所有内容都是表达式的一部分。
因为整个模板信息都是表达式的一部分,所以即使是普通字符串也需要专门标明。下面对表达式中的子表达式进行逐个说明。
!Fe:& # 36941;历数据不创建row & # 12290
官方文档中的这句话大家理解起来可能有点费解,什么叫不创建row & # 65311实际上,不创建row & # 26159相对于创建row & # 32780言的,创建row & # 30340表达式是Fe:& # 12290;
就像是数据库中每条记录对应着一个实体对象,创建row & # 34920示每行就是一个实体对象实体& # 65292;这个实体对象的属性用{{}}表达式包裹起来。
不创建row & # 34920示整个表达式中只有一个实体对象对象& # 65292;只不过这个对象& # 27604;较特别,它是由列表& # 20013;N & # 20010实体& # 25340;接起来的。每一个实体& # 19981;仅仅是指模型本身,也包含了Excel & # 30340样式,比如占用了几个单元格,单元格的坐标、排布顺序等。
列表& # 33258;定义的名称,表示表达式中的数据集合,由代码以列表& # 20026;键,从地图& lt字符串,对象& gt中获取值的集合。
列表& # 36825;个名字容易理解,就是一个占位符,可以随便取。EasyPOI & # 35299析到列表& # 23601;知道地图& lt字符串,对象& gt中存在着该键的值的集合,后边解析到数据就从该集合中取即可。
搜索Java & # 30693音公众号,回复& ldquo后端面试& rdquo,送你一份Java & # 38754试题宝典。可移植文档格式文件的扩展名(portable document format的缩写)
t & # 39044定义值,表示集合中的任意对象。
从模板中我们大致能感觉到,列表& # 20013;每个对象叫做t & # 65292t.name & # 23601代表t & # 30340姓名& # 23646;性,所以t & # 36825个名字就可以随便叫,反正它和列表& # 19968;样,作用是占位符。
但实际上这是一个大坑!如果你把t & # 25442成了其他值比如g & # 65292模板中其他地方写通用名称通用代码& # 31561;等,最终是解析不到的!官方文档对这一点并没有强调,而是作者实际踩了坑之后才发现的!
]] 换行符多行遍历导出。
对于这个符号的官方解释也是莫名其妙,什么叫换行符,多行遍历导出?实际上它的意思就是,当解析到表达式中含有这个符号,该行后边的内容就不解析了,管你后边有没有其他内容或者样式。
该符号一定要写在每行的最后一列,不然会出现每行列数不一样的情况,EasyPOI & # 20869部做赋值的时候就会报空指针异常了。
& lsquo& rsquo单引号表示常量值& lsquo& rsquo比如& rsquo1 & rsquo那么输出的就是一个
官方文档中这里的介绍也有坑。''是表示常量值,但实际上Excel & # 20013只是这么些是不对的,因为Excel & # 30340单元格中遇到'后会认为后面都是字符串,所以得在单元格中写''库别:',这样显示出来的才是'库别:',而不是字符串库别:'。
经过上述分析,图中的模板实际上就类似以下内容:
{{!fe:列出t.id & lsquo库别:& rsquot.bin & # 25442行& lsquo商品名称:& rsquot.name & # 25442行& lsquo商品编号:& rsquot.code t .条码& # 25442;行& lsquo生产日期:& rsquot.proDate & # 25442行& lsquo进货日期:& rsquot.recvDate}}
如果列表& # 20013;有多条记录,上述字符串就再循环拼接一些内容,最终都在一个{{}}表达式中。
至此,模板的设计已剖析完毕,读者可根据自己的需求结合官方文档自行设计模板。下面将对模板赋值进行介绍。
准备模板数据从上节的描述中可知,只需要准备一个地图& lt字符串,对象& gt的对象即可,其中键为列表& # 65292;值为一个列表& # 25968;组,数组中元素类型为地图& lt字符串,对象& gt。代码如下:
地图& lt字符串,对象& gttotal = new HashMap & lt& gt();列表& lt地图& lt字符串,对象& gt& gtmapList = new ArrayList & lt& gt();for(int I = 1;我& lt= 5;i++){ Map & lt;字符串,对象& gtmap = new HashMap & lt& gt();map.put("id ",I+" ");map.put("bin "," 001 1000 & # 21315;克");map.put("name "," & # 21830;品"+I);map.put("code "," goods "+I);map.put("proDate "," 2019-05-30 ");map.put("recvDate "," 2019-07-07 ");// 插入图片ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();BufferedImage buffer img = imageio . read(barcodeutil . generate tostream(" 001 "));ImageIO.write(bufferImg," jpg ",byteArrayOut);image entity image entity = new image entity(bytearrayout . tobytearray(),200,1000);map.put("barcode ",image entity);mapList.add(地图);}total.put("list ",mapList);图片数据导出上述代码中需要特殊关注的是图片导出部分。EasyPOI & # 23548出图片有两种方式,一种是通过图片的Url & # 65292还有一种是获取图片的字节[]& # 65292;毕竟图片的本质就是byte[]& # 12290;因为笔者的项目中图片不是存放在数据库之中,而是需要根据查询结果动态生成条码,所以通过字节[]& # 23548;出图片。
ImageEntity & # 26159EasyPOI & # 20869置的一个JavaBean & # 65292用于设定图片的宽度和高度、导出方式、RowSpan & # 21644ColumnSpan & # 31561。调试EasyPOI & # 30340源码可知,当设置了RowSpan & # 25110者ColumnSpan & # 20043后,图片的高度设置就失效了,图片大小会自动填充图片所在的单元格。
图片导出的坑点在于导出图片的大小。假设我们将四个单元格合成为一个,希望导出的图片能填充合并之后的单元格,但是对不起,EasyPOI & # 26242时做不到,它只会填充合并之前左上角的单元格,具体原因如下源码所示:
//baseexportservice . javaclientanchor锚点;if (type.equals(ExcelType。HSSF)){ anchor = new HSSFClientAnchor(0,0,0,0,(short) cell.getColumnIndex(),cell.getRow()。getRowNum(),(short) (cell.getColumnIndex() + 1),cell.getRow()。getRowNum()+1);} else { anchor = new XSSFClientAnchor(0,0,0,0,(short) cell.getColumnIndex(),cell.getRow()。getRowNum(),(short) (cell.getColumnIndex() + 1),cell.getRow()。getRowNum()+1);}可以看到,在创建图片插入位置的时候已经指定了图片的跨度为1行1列,即左上角的单元格。如果之前又设置了RowSpan & # 25110者ColumnSpan & # 65292那么图片高度的设置也会失效,最终导致导出的图片非常小。
搜索Java & # 30693音公众号,回复& ldquo后端面试& rdquo,送你一份Java & # 38754试题宝典。可移植文档格式文件的扩展名(portable document format的缩写)
个人认为ImageEntity & # 25552供的RowSpan & # 25110者ColumnSpan & # 30340set & # 26041法并没有什么用,因为我们动态创建的合并单元格并不能被赋值。所以,导出图片的最好方式就是直接指定它的高度,因为宽度会自动填充单元格,模板中单元格的宽度要合适。
//exlexportoftemplateutil . javaif(img . getrowspan()& gt;1 | | img . getcolspan()>;1){ img . set height(0);poimergecellutil . addmergedregion(cell . getsheet()、cell.getRowIndex()、cell . getrowindex()+img . getrowspan()-1、cell.getColumnIndex()、cell . getcolumnindex()+img . getcolspan()-1);}将数据导出至模板以上准备工作全部完成后就可以将模板和数据进行组装了,或者说是渲染,代码如下所示:
public static void exportByTemplate(String template name,Map & lt字符串,对象& gtdata,output stream fileOut){ TemplateExportParams params = new TemplateExportParams(" export/template/"+template name,true);try { Workbook Workbook = excel portutil . export excel(params,data);workbook . write(file out);} catch(Exception e){ logutil . error(",e);}}总结网上针对EasyPOI & # 30340介绍多限于最基本的行插入功能,但实际上Excel & # 27169板的需求可能各式各样。本文只是抛砖引玉,对EasyPOI & # 20013的部分概念做了详细介绍,希望帮助大家少踩坑。
如果想详细了解EasyPOI & # 30340各种功能,参考链接中的文档说明及测试项目源码就是最好的学习资料。希望大家都能得心应手地使用EasyPOI & # 65292大大提升开发效率!
参考链接EasyPOI & # 23448方文档
https://open source . after turn . cn/doc/easy poi . html easy poi & # 27979;试项目
https://gitee.com/lemur/easypoi-test一 & # 20123;坑近日有网友求助我解决EasyPOI & # 30340复杂模板配置问题,通过解决该网友的问题发现了EasyPOI & # 20013的几个坑点,补充说明几个问题。
在复杂模板设计剖析一节中已经描述了EasyPOI & # 25903持的复杂的模板该如何配置。该模板的配置是绝对正确的,但是有3个点没有说清楚,大家在照葫芦画瓢时容易出错:
{{!Fe:list & # 38656;要在一个单独的列中。EasyPOI & # 28304码中是根据该单元格的行、列跨度来决定列表& # 20013;的每个元素需要多少行的。比如上述图片中,该单元格的跨度是5行1列,也就是说,以后列表& # 20013;的每个元素都会占用5行。如果觉得该列不符合自定义模板的风格,可以把该列的列宽设置为0,但一定需要有{{!Fe:list & # 12290;在对象的起始和结束符号{{}}之间不能有任何空的单元格!代码中在解析到该单元格为空时会直接抛异常,如果就希望该单元格为空,得显示写入空字符串:& rsquo& rsquo& rsquo。换行符]]必须占用每行的最后一个单元格!比如说第一行有10个单元格,第二行只用了前5个,那么不能直接在第5个结束直接写换行符]],而是需要把6-10个单元格合并,然后写入]]。参考上述图片中生产日期所在行的最后一列。这么设置的原因是EasyPOI & # 35201求每行的单元格数目完全一致,因为源码中判断了每个单元格的列跨度,如果提前使用了]]换行符,那么该列的数目就和其他行不同,那么赋值的时候就乱掉了,会出现索引异常。以上是使用EasyPOI优雅导出Excel模板数据(包括图片)的细节。更多请关注主机参考其他相关文章!
这几篇文章你可能也喜欢:
- 暂无相关推荐文章
本文由主机参考刊发,转载请注明:使用EasyPOI优雅地导出Excel模板数据(包括图片) https://zhujicankao.com/96256.html
评论前必须登录!
注册