2.问题描述由于一张报销单可能存在多条报销内容,可以看到,当超过模板中预先给定的一条时,则会自动换行,但换行时并不会自动依照模板中的样式进行单元格合并,如下所示。
3.原因分析:首先可以直观的看到excel进行数据插入并自动换行的时候,换行的数据并没有按照上一行的样式进行自动合并。
于是便想着用代码把这几列手动合并,然后再加上边框样式就可以解决了。
4.解决方案:
需要注意的是,按照以上的思路,直接进行单元格合并,然后加上边框并不能直接解决问题。
需要将后边空的每一个单元格先创建出来,然后将其一块合并才可以解决,创建单元格代码在下方customcellwritehandler类中说明。
这也算是耗费一整天时间踩的坑。。。
public static void outexcelbalance(string modelfile, string newfile, map<string, object> map, list<filldataexpense> filldata, httpservletresponse response, string filename){ //定义model模板中默认的行数 int firstrow = 7; //excel中表示第八行,即模板中默认的一条 int lastrow = 7; inputstream is = null; file file = new file(modelfile); file file1 = new file(newfile); //string file1name = file1.getname(); bufferedinputstream bis = null; try { if (!file.exists()) { copyfileusingjava7files(file, file1); } //todo 单元格样式 set<integer> rowsborderset= new hashset<>(); customcellwritehandler customcellwritehandler = null; //todo 单元格合并 list<cellrangeaddress> cellrangeaddresss = new arraylist<>(); if (listutils.isnotnull(filldata)){ if (filldata.size() > 1){ //合并每条报销单的第3-10列 for (int i = 1; i < filldata.size(); i++) { firstrow++; lastrow++; cellrangeaddresss.add(new cellrangeaddress(firstrow, lastrow, 2, 9)); cellrangeaddresss.add(new cellrangeaddress(firstrow, lastrow, 10, 11)); rowsborderset.add(firstrow); } } } customcellwritehandler = new customcellwritehandler(rowsborderset); mymergestrategy mymergestrategy = new mymergestrategy(cellrangeaddresss); excelwriter excelwriter = easyexcel.write(newfile) //注册单元格式 .registerwritehandler(customcellwritehandler) //注册合并策略 .registerwritehandler(mymergestrategy) .withtemplate(modelfile).build(); writesheet writesheet = easyexcel.writersheet().build(); fillconfig fillconfig = fillconfig.builder().forcenewrow(boolean.true).build(); if (!listutil.listisempty(filldata)){ excelwriter.fill(filldata, fillconfig, writesheet); //excelwriter.fill(filldata, fillconfig, writesheet); } excelwriter.fill(map, writesheet); excelwriter.finish(); response.setheader("content-type", "text/plain"); response.setheader("content-type", "application/x-msdownload;"); response.setcontenttype("text/plain; charset=utf-8"); response.setheader("content-disposition", "attachment; filename=" + new string(filename.getbytes("utf-8"),"iso8859-1")); byte[] buff = new byte[1024]; outputstream os = null; os = response.getoutputstream(); bis = new bufferedinputstream(new fileinputstream(file1)); int i = bis.read(buff); while (i != -1) { os.write(buff, 0, buff.length); os.flush(); i = bis.read(buff); } } catch (exception e){ logger.error(e.getmessage()); } finally { if (bis != null) { try { bis.close(); } catch (ioexception e) { e.printstacktrace(); } } // 删除生成文件 /*if (file1.exists()) { file1.delete(); }*/ } }
单元格合并mymergestrategy类代码:
public class mymergestrategy extends abstractmergestrategy { //合并坐标集合 private list<cellrangeaddress> cellrangeaddresss; //构造 public mymergestrategy(list<cellrangeaddress> cellrangeaddresss) { this.cellrangeaddresss = cellrangeaddresss; } @override protected void merge(sheet sheet, cell cell, head head, integer integer) { if (listutils.isnotnull(cellrangeaddresss)) { if (cell.getrowindex() == 7 ) { for (cellrangeaddress item : cellrangeaddresss) { sheet.addmergedregionunsafe(item); } } } }}
单元格样式customcellwritehandler类代码:
public class customcellwritehandler implements cellwritehandler { private static final logger logger = loggerfactory.getlogger(customcellwritehandler.class); //标黄行宽集合 private set<integer> rowindexs; //构造 public customcellwritehandler(set<integer> rowindexs) { this.rowindexs = rowindexs; } public customcellwritehandler() { } @override public void beforecellcreate(writesheetholder writesheetholder, writetableholder writetableholder, row row, head head, integer columnindex, integer relativerowindex, boolean ishead) { logger.info("beforecellcreate~~~~"); } @override public void aftercellcreate(writesheetholder writesheetholder, writetableholder writetableholder, cell cell, head head, integer relativerowindex, boolean ishead) { logger.info("aftercellcreate~~~~"); } @override public void aftercelldataconverted(writesheetholder writesheetholder, writetableholder writetableholder, celldata celldata, cell cell, head head, integer integer, boolean aboolean) { } @override public void aftercelldispose(writesheetholder writesheetholder, writetableholder writetableholder, list<celldata> celldatalist, cell cell, head head, integer relativerowindex, boolean ishead) { //获取工作簿// hssfworkbook wb = new hssfworkbook();// //获取sheet// hssfsheet sheet = wb.createsheet();// hssfrow row = sheet.createrow();// hssfcellstyle style = wb.createcellstyle(); // 这里可以对cell进行任何操作 if (collectionutils.isnotempty(rowindexs)) { workbook workbook = writesheetholder.getsheet().getworkbook(); cellstyle cellstyle = workbook.createcellstyle(); sheet sheet = writesheetholder.getsheet(); cellstyle.setalignment(new hssfworkbook().createcellstyle().getalignment()); cellstyle.setborderbottom(borderstyle.thin); //下边框 cellstyle.setbottombordercolor(indexedcolors.black.getindex()); cellstyle.setborderleft(borderstyle.thin);//左边框 cellstyle.setbordertop(borderstyle.thin);//上边框 cellstyle.setborderright(borderstyle.thin);//右边框 cellstyle.setwraptext(true);//自动换行 //字体// font cellfont = workbook.createfont();// cellfont.setbold(true);// cellstyle.setfont(cellfont);// //标黄,要一起设置// cellstyle.setfillpattern(fillpatterntype.solid_foreground); //设置前景填充样式// cellstyle.setfillforegroundcolor(indexedcolors.yellow.getindex());//前景填充色 if (rowindexs.contains(cell.getrowindex())) { row row = null; //循环创建空白单元格 for (int i = 0; i < rowindexs.size(); i++) { for (integer rowindex : rowindexs){ //创建4-10列的空白格 row = sheet.getrow(rowindex.intvalue()); if (row == null){ row = sheet.createrow(rowindex.intvalue()); } for (int j = 3; j <= 9; j++) { //获取8行的cell列 cell = row.createcell(j); cell.setcellstyle(cellstyle); cell.setcellvalue(" "); logger.info("第{}行,第{}列创建空白格。", cell.getrowindex(), j); } //创建12列的红白格 cell = row.createcell(11); cell.setcellstyle(cellstyle); cell.setcellvalue(" "); logger.info("第{}行,第11列创建空白格。", cell.getrowindex()); //创建21列的空白格 cell = row.createcell(21); cell.setcellstyle(cellstyle); cell.setcellvalue(" "); logger.info("第{}行,第21列创建空白格。", cell.getrowindex()); } } } } }}
5.总结核心步骤:
1. //创建单元格样式 customcellwritehandler customcellwritehandler = new customcellwritehandler(参数按需给定);2. //单元格进行合并 list<cellrangeaddress> cellrangeaddresss = new arraylist<>(); //例如:从firstrow行到lastrow行的2列到9列合并 cellrangeaddresss.add(new cellrangeaddress(firstrow, lastrow, 2, 9)); cellrangeaddresss.add(new cellrangeaddress(firstrow, lastrow, 10, 11)); mymergestrategy mymergestrategy = new mymergestrategy(cellrangeaddresss);3. //注册以上两种策略 excelwriter excelwriter = easyexcel.write(newfile) //注册单元格式 .registerwritehandler(customcellwritehandler) //注册合并策略 .registerwritehandler(mymergestrategy) .withtemplate(modelfile).build();
说明:刚开始修复的时候,并没有想过后边每个空的单元格需要先创建出来,才可以进行合并。一直以为是工具类的问题,后来不断的翻阅解决方案,看到有说需要先进行创建空白单元格,然后再进行合并,最终完美解决了。
关于代码部分,由于是业务代码,中间夹杂了许多不需要的。
以上就是java怎么使用easyexcel进行单元格合并的详细内容。
