普通业务我们导出的excel文件大多是有规则的表记录导出,即表头+表记录。但是如果业务上让我们去导出一些复杂的excel结构,比如导出结算单,申请单这些,如下:

类似这种excel文件格式的导出,现有的框架并不能很友好的支持,我们需要些一堆复杂的代码,而且还不能复用。

针对这种业务本人编写了以下的excel处理工具,希望可以帮助到大家。

ZlExcel类


import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;/*** cell*/
public class ZlCell {/*** 单元格ID*/private String cellNo;private int cellIndex;/*** 行*/private ZlRow row;//单元格格式private CellStyle style;//单元格private Cell cell ;//工作簿private XSSFWorkbook wb;private ZlSheet sheet;/*** 字体*/private Font font;private Object content;/*** 背景色*/private IndexedColors background;/*** 字体颜色*/private IndexedColors fontColor;private BorderStyle borderTop;private BorderStyle borderLeft;private BorderStyle borderBottom;private BorderStyle borderRight;public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,int width,String url){this.wb = wb;this.sheet = sheet;this.row = row;this.cell = row.getRow().createCell(index);this.cellIndex = index;//宽度if(width > 0){setColumnWidth(width);}//设置图片addImage(url);}public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content){this(wb,sheet,row,index,content,false,0,(short)11);}public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold){this(wb,sheet,row,index,content,hold,0,(short)11);}public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold,int width){this(wb,sheet,row,index,content,hold,width,(short)11);}public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold,short fontSize){this(wb,sheet,row,index,content,hold,0,fontSize);}public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold,int width,short fontSize){this.wb = wb;this.sheet = sheet;this.row = row;this.cell = row.getRow().createCell(index);this.cellIndex = index;this.style = wb.createCellStyle();this.font = wb.createFont();//默认宋体this.font.setFontName("宋体");this.font.setBold(hold);this.font.setFontHeightInPoints(fontSize);this.style.setFont(font);//默认横 纵向居中this.style.setAlignment(HorizontalAlignment.CENTER);this.style.setVerticalAlignment(VerticalAlignment.CENTER);//默认添加边线this.style.setBorderTop(BorderStyle.THIN);this.style.setBorderBottom(BorderStyle.THIN);this.style.setBorderLeft(BorderStyle.THIN);this.style.setBorderRight(BorderStyle.THIN);this.cell.setCellStyle(style);this.cellNo = UUID.randomUUID().toString();setCellValue(content);//宽度if(width > 0){setColumnWidth(width);}}public void setContent(Object content) {this.content = content;setCellValue(content);}private void setCellValue(Object content){this.content = content;if(content instanceof  Number){this.cell.setCellValue(((Number) content).doubleValue());}else if(content instanceof String){this.cell.setCellValue((String) content);}else if(content instanceof Date){this.cell.setCellValue((Date) content);}else if(content instanceof Boolean){this.cell.setCellValue((Boolean) content);}else{this.cell.setCellValue(String.valueOf(content));}}/*** 设置字体类型 如宋体*/public ZlCell setFontName(String font){this.font.setFontName(font);return this;}/*** 设置是否为粗体*/public ZlCell setFontBold(boolean bold){this.font.setBold(bold);return this;}/*** 设置字体高度*/public ZlCell setFontHeight(short height){this.font.setFontHeightInPoints(height);return this;}/*** 设置横向内容方向*/public ZlCell setHorizontalAlignment(HorizontalAlignment alignment){this.style.setAlignment(alignment);this.cell.setCellStyle(style);return this;}/*** 设置纵向内容方向*/public ZlCell setVerticalAlignment(HorizontalAlignment alignment){this.style.setAlignment(alignment);this.cell.setCellStyle(style);return this;}/*** 上边线*/public ZlCell setBorderTop(BorderStyle borderStyle){this.style.setBorderTop(borderStyle);this.cell.setCellStyle(style);return this;}/*** 下边线*/public ZlCell setBorderBottom(BorderStyle borderStyle){this.style.setBorderBottom(borderStyle);this.cell.setCellStyle(style);return this;}/*** 左边线*/public ZlCell setBorderLeft(BorderStyle borderStyle){this.style.setBorderLeft(borderStyle);this.cell.setCellStyle(style);return this;}/*** 右边线*/public ZlCell setBorderRight(BorderStyle borderStyle){this.style.setBorderRight(borderStyle);this.cell.setCellStyle(style);return this;}public ZlCell mergeCell(String endRowNo,String endCellNo){int firstRow = this.row.getRowIndex();int firstCell = this.getCellIndex();List<ZlRow> rows =  this.sheet.getRows();ZlRow endRow = rows.stream().filter(r->r.getRowNo().equalsIgnoreCase(endRowNo)).findFirst().orElse(null);if(endRow == null){return this;}ZlCell endCell = endRow.getCells().stream().filter(c->c.getCellNo().equalsIgnoreCase(endCellNo)).findFirst().orElse(null);if(endCell == null){return this;}if(firstRow == endRow.getRowIndex()){//如果是同行的列合并for(int i = firstCell ; i<= endCell.getCellIndex() ; i++){for(ZlCell cell : endRow.getCells()){if(cell.getCellIndex() == i){cell.setCellNo(this.cellNo);}}}}endCell.setCellNo(this.cellNo);CellRangeAddress region = new CellRangeAddress(firstRow, endRow.getRowIndex(), firstCell, endCell.getCellIndex());this.sheet.getSheet().addMergedRegion(region);return this;}public ZlCell setColumnWidth(int width){this.sheet.getSheet().setColumnWidth(this.cell.getColumnIndex(),width * 256);return this;}public String getCellNo() {return cellNo;}public void setCellNo(String cellNo) {this.cellNo = cellNo;}public int getCellIndex() {return cellIndex;}public void setCellIndex(int cellIndex) {this.cellIndex = cellIndex;}public Object getContent() {return content;}public ZlCell setBackground(IndexedColors background) {this.background = background;for(ZlCell cell :this.row.getCells()){if(cell.getCellNo().equalsIgnoreCase(this.cellNo)){cell.getCell().getCellStyle().setFillBackgroundColor(background.getIndex());}}return this;}public ZlCell setFontColor(IndexedColors fontColor) {this.fontColor = fontColor;this.font.setColor(fontColor.getIndex());this.cell.getCellStyle().setFont(this.font);return this;}public Cell getCell() {return cell;}public ZlCell addImage(String filePath){try {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();File file = new File(filePath);BufferedImage bufferImg = ImageIO.read(file);String imageType = filePath.substring(filePath.length()-3);ImageIO.write(bufferImg, imageType, outputStream);XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0,this.cellIndex, this.row.getRowIndex(),  this.cellIndex+1, this.row.getRowIndex() +1);anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);//插入图片this.sheet.getPatriarch().createPicture(anchor, wb.addPicture(outputStream.toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));} catch (IOException e) {e.printStackTrace();}return this;}private ByteArrayOutputStream inputToOutput(InputStream inputStream){ByteArrayOutputStream baos = new ByteArrayOutputStream();try {byte[] buffer = new byte[1024];int len;while ((len = inputStream.read(buffer)) > -1) {baos.write(buffer, 0, len);}}catch (Exception e){e.printStackTrace();}return baos;}
}

ZlRow类


import lombok.Data;
import org.apache.poi.ss.usermodel.Row;
import java.util.LinkedList;
import java.util.UUID;
/*** row*/
@Data
public class ZlRow {/*** 行ID*/private String rowNo;//行private Row row;//sheet对象private ZlSheet sheet;private int rowIndex;/*** 所有列*/private LinkedList<ZlCell> cells = new LinkedList<>();public ZlRow(ZlSheet sheet,Integer index){this(sheet,index,23);}public ZlRow(ZlSheet sheet,Integer index,Integer height){this.rowIndex = index;this.sheet = sheet;this.row = this.sheet.getSheet().createRow(index);//默认设置行数为23this.row.setHeightInPoints(height);this.rowNo = UUID.randomUUID().toString();}private ZlRow addCell(ZlCell cell){this.cells.addLast(cell);return this;}}

ZlSheet类


import lombok.Data;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;/*** sheet*/
@Data
public class ZlSheet {/*** 工作簿*/private XSSFWorkbook wb;private XSSFSheet sheet;/*** 当前行*/private int rowIndex = 0;/*** 当前列*/private int cellIndex = 0;/*** 当前操作的row*/private ZlRow nowRow;/*** 当前操作的cell*/private ZlCell nowCell;private XSSFDrawing patriarch;/*** 所有行*/private LinkedList<ZlRow> rows = new LinkedList<>();public ZlSheet(XSSFWorkbook wb){this(wb,"sheet");}public ZlSheet(XSSFWorkbook wb,String sheetName){this.wb = wb;this.sheet = this.wb.createSheet(sheetName);//隐藏网格线  是否显示网格线  true显示,false 不显示this.sheet.setDisplayGridlines(false);this.patriarch = sheet.createDrawingPatriarch();}public List<ZlRow> getRows() {return rows;}/*** 创建下一个cell*/public ZlSheet createNextCell(Object content){if(this.nowRow == null){nextRow();}ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content);this.cellIndex = this.cellIndex + 1;this.nowCell = cell;this.nowRow.getCells().addLast(cell);return this;}/*** 创建下一个cell*/public ZlSheet createNextCell(Object content,boolean hold){ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold);this.cellIndex = this.cellIndex + 1;this.nowCell = cell;this.nowRow.getCells().addLast(cell);return this;}/*** 创建下一个cell*/public ZlSheet createNextCell(Object content,boolean hold,int width){ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold,width);this.cellIndex = this.cellIndex + 1;this.nowCell = cell;this.nowRow.getCells().addLast(cell);return this;}/*** 创建下一个cell*/public ZlSheet createNextCell(Object content,boolean hold,int width,short fontSize){ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold,width,fontSize);this.cellIndex = this.cellIndex + 1;this.nowCell = cell;this.nowRow.getCells().addLast(cell);return this;}/*** 创建下一个图片cell*/public ZlSheet createNextImageCell(int width,String url){ZlCell cell = new ZlCell(this.wb,this,this.nowRow,this.cellIndex,width,url);this.cellIndex = this.cellIndex + 1;this.nowCell = cell;this.nowRow.getCells().addLast(cell);return this;}/*** 创建下一个cell 用多个单元格合并* @param indexNumber  下一个单元格的结束索引* @param content   单元格内容* @param hold   是否粗体*/public ZlSheet createCell(Integer indexNumber,Object content,boolean hold){this.createCell(indexNumber,content,hold,0,(short)13);return this;}/*** 创建下一个cell 用多个单元格合并* @param indexNumber  下一个单元格的结束索引* @param content   单元格内容* @param hold   是否粗体* @param fontSize  字体大小*/public ZlSheet createCell(Integer indexNumber,Object content,boolean hold,short fontSize){this.createCell(indexNumber,content,hold,0,fontSize);return this;}/*** 创建下一个cell 用多个单元格合并* @param indexNumber  下一个单元格的结束索引* @param content   单元格内容* @param width   单元格宽度* @param hold   是否粗体*/public ZlSheet createCell(Integer indexNumber,Object content,int width,boolean hold){this.createCell(indexNumber,content,hold,width,(short)13);return this;}/*** 创建一个大的cell单元格,合并多个横向单元格*/public ZlSheet createCell(Integer indexNumber,Object content,boolean hold,int width,short fontSize){ZlCell firstCell = null;ZlCell lastCell = null;for(int i = this.cellIndex ; i < indexNumber ; i ++){ZlCell cell = new ZlCell(this.wb,this,this.nowRow,i,content,hold,width,fontSize);if(firstCell == null) {firstCell = cell;}if(i == indexNumber - 1){lastCell = cell;}this.nowRow.getCells().addLast(cell);}if(firstCell != null && lastCell != null) {firstCell.mergeCell(this.nowRow.getRowNo(), lastCell.getCellNo());}this.nowCell = firstCell;this.cellIndex = indexNumber;return this;}/*** 供 newCell使用的方法*/public ZlSheet createNextCell(ZlCell cell){this.cellIndex = this.cellIndex + 1;this.nowCell = cell;this.nowRow.getCells().addLast(cell);return this;}/*** 创建一个可以自定义cell各种风格*/public ZlCell newCell(Object content,boolean hold,int width,short fontSize){return new ZlCell(this.wb,this,this.nowRow,this.cellIndex,content,hold,width,fontSize);}public ZlCell newMergeCell(Integer indexNumber,Object content,boolean hold){return newMergeCell(indexNumber,content,hold,0,(short)13);}public ZlCell newMergeCell(Integer indexNumber,Object content,boolean hold,short fontSize){return newMergeCell(indexNumber,content,hold,0,fontSize);}/*** 创建一个大的cell单元格,合并多个横向单元格 newCell使用的方法*/public ZlCell newMergeCell(Integer indexNumber,Object content,boolean hold,int width,short fontSize){ZlCell firstCell = null;ZlCell lastCell = null;for(int i = this.cellIndex ; i < indexNumber ; i ++){ZlCell cell = new ZlCell(this.wb,this,this.nowRow,i,content,hold,width,fontSize);if(firstCell == null) {firstCell = cell;}if(i == indexNumber - 1){lastCell = cell;}this.nowRow.getCells().addLast(cell);}if(firstCell != null && lastCell != null) {firstCell.mergeCell(this.nowRow.getRowNo(), lastCell.getCellNo());}this.nowCell = firstCell;this.cellIndex = indexNumber;return firstCell;}/*** 供 newCell使用的方法*/public ZlSheet createCell(ZlCell cell){this.nowCell = cell;this.nowRow.getCells().addLast(cell);return this;}/*** 合并上方单元格*/public ZlSheet mergeTop(Integer indexNumber){ZlCell topCell  = this.rows.get(this.rowIndex - 1 - indexNumber).getCells().get(this.cellIndex - 1);topCell.setContent(this.nowCell.getContent());topCell.mergeCell(this.nowRow.getRowNo(),this.nowCell.getCellNo());return this;}/*** 下一行*/public ZlSheet nextRow(){this.nextRow(23);return this;}/*** 下一行*/public ZlSheet nextRow(int height){ZlRow row = new ZlRow(this,this.rowIndex,height);this.rows.addLast(row);this.nowRow = row;this.cellIndex = 0;this.rowIndex = this.rowIndex + 1;return this;}/*** 写入文件*/public void writeFile(String path){ByteArrayOutputStream stream = new ByteArrayOutputStream();try {this.wb.write(stream);File file = new File(path);if(!file.exists()){file.createNewFile();}FileOutputStream outputStream = new FileOutputStream(file);stream.writeTo(outputStream);} catch (IOException e) {e.printStackTrace();}}}

下面是测试:

import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class BaseEntity {private String username;private String projectName;private String startTime;private String calMoney;private String remark;public static void main(String[] args) {List<BaseEntity> entities = new ArrayList<>();BaseEntity entity = new BaseEntity().setUsername("张无忌").setStartTime("2022-04-01").setProjectName("启航计划").setCalMoney("10000").setRemark("备注");BaseEntity entity1 = new BaseEntity().setUsername("杨潇").setStartTime("2021-05-01").setProjectName("学业辅导").setCalMoney("20000").setRemark("你好世界");entities.add(entity);entities.add(entity1);//1.创建Excel对象XSSFWorkbook wb = new XSSFWorkbook();ZlSheet sheet = new ZlSheet(wb);sheet.nextRow(34).createCell(sheet.newMergeCell(11,"应收结算单",true,(short)18).setBackground(IndexedColors.BLUE)).nextRow(34).createNextCell(sheet.newCell("结算公司名称:",true,30,(short)14).setBackground(IndexedColors.BLUE)).createCell(4,"上海至和教育",false,(short)15).nextRow().nextRow(25).createNextCell("渠道负责人:",true,25,(short)13).createCell(3,"张三",false,15,(short)13).createNextCell("结算总金额",true,25,(short)13).createCell(6, BigDecimal.valueOf(1000),false,15,(short)13).createCell(9,"结算日期",true,10,(short)13).createCell(11,"2022-03-01",false,15,(short)13).nextRow().nextRow(25).createCell(11,"项目明细",true,(short)18).nextRow(23).createNextCell("学生姓名",true,25,(short)13).createCell(3,"项目名称",true,15,(short)13).createCell(5,"服务开始时间",true,18,(short)13).createCell(7,"项目结算金额",true,15,(short)13).createCell(11,"其他备注",true,15,(short)13);for(BaseEntity en : entities){sheet.nextRow(23).createNextCell(en.getUsername(),false,25,(short)13).createCell(3,en.getProjectName(),false,15,(short)13).createCell(5,en.getStartTime(),false,18,(short)13).createCell(7,en.getCalMoney(),false,15,(short)13).createCell(11,en.getRemark(),false,15,(short)13).createNextImageCell(30,"D:\\图片\\IMG_6180.JPG");}sheet.nextRow().nextRow(25).createCell(11,"结算信息",true,(short)18).nextRow(23).createNextCell("付款方名称",true,25,(short)13).createCell(5,"",true,15,(short)13).createCell(7,"收款方名称",true,15,(short)13).createCell(11,"上海天华科技有限公司",true,0,(short)13).nextRow(23).createNextCell("税号",true,25,(short)13).createCell(5,"",true,15,(short)13).createCell(7,"税号",true,15,(short)13).createCell(11,"49872587324879285",true,0,(short)13).nextRow(23).createNextCell("银行账号",true,25,(short)13).createCell(5,"",true,15,(short)13).createCell(7,"银行账号",true,15,(short)13).createCell(11,"3597824878256328",true,0,(short)13).nextRow(23).createNextCell("银行支行信息",true,25,(short)13).createCell(5,"",true,15,(short)13).createCell(7,"银行支行信息",true,15,(short)13).createCell(11,"中国银行上海浦东分行营业部",true,0,(short)13).nextRow(23).createNextCell("签字",true,25,(short)13).createCell(5,"",true,15,(short)13).createCell(7,"签字",true,15,(short)13).createCell(11,"",true,0,(short)13);sheet.writeFile("D:\\文档\\test\\test1.xlsx");}}

Java导出无规则excel,如报销单,申请单,结算单等相关推荐

  1. Java导出数据到Excel文件

    Java导出数据到Excel文件 前言 如何导出 导出的基本流程 测试结果 测试数据及结果 测试代码 ExcelExportUtil.class 遇到的问题 lombok的问题 解决 Cell.set ...

  2. Java导出多个excel压缩成zip下载

    Java导出多个excel压缩成zip下载 maven <!--hutoos工具类根据需要可以导入不同的模块,我这里是导入全部的模块--><dependency><gro ...

  3. 使用Java导出数据到Excel

    一.excel数据导出限制 1. Excel 2003及以下的版本.一张表最大支持**65536**行数据,256列.也就是说excel2003完全不可能满足百万数据导出的需求. 2. Excel 2 ...

  4. java导出大数据excel表格,导出数据

    常规的java导出excel表格最大的数据量是65535行. package com.sf.module.timeManagement.biz; import java.io.ByteArrayInp ...

  5. java导出数据到excel表格的最简单实现

    导出excel整理 开发中难免会遇到要导出数据到excel的,网上有很多方法,但是看起来都很复杂的样子,写得又非常多代码,让人望而止步.我做一个简单的导出excel表格功能.这是我在工作上用到的. 1 ...

  6. JAVA 导出大批量数据EXCEL

    转自http://www.itboth.com/d/MjI3Ef/excel-java 参考资料:http://bbs.51cto.com/thread-1074293-1-1.html http:/ ...

  7. java导出多个excel并打成zip包

    这里主要是要针对数据量过大,通过生成多个excel文件并打成一个zip压缩包提供下载. 压缩excel的类  ZipUtil: Java代码   import java.io.*; import ja ...

  8. java导出数据到excel模板_springboot+jxls 根据Excel模板 填写数据并导出

    项目结构 pom.xml net.sf.jxls jxls-core 1.0.6compile 学生信息表模板: ExcelUtiles package cn.bdqn.utils;import ne ...

  9. Java导出多个excel并打包压缩成.zip文件

    1.先获取到数据,并将数据导出excel到指定位置 public void downPoliceZip(WorksitePoliceApiInfo worksitePoliceApiInfo) thr ...

最新文章

  1. Python Day18
  2. KVM(Keyboard、Video、Mouse)
  3. 有关 Conversion to Dalvik format failed with error 1
  4. 53pagecontext对象
  5. 多标签分类_多标签分类文献阅读(8)
  6. 1191 消灭兔子(贪心+优先队列)
  7. java 正则表达式案例
  8. C#两种创建快捷方式的方法
  9. 《企业架构的数字化转型》10000字有感
  10. 计算机不用鼠标怎么移动,如何在不使用鼠标的情况下拖动文件
  11. Spark入门(一篇就够了)
  12. linux 用户搬家后安装的软件,linux软件搬家
  13. 格物斯坦:机器人高手决战申城,IRM开启孩子新视界
  14. 中国版Second Life前途难料
  15. dojo 下载官方网址
  16. 【源码】基于心电图的数据分析
  17. IDEA修改背景颜色(护眼绿)
  18. 原创 | 连面拼多多、美团、头条、快手后给大家划下重点
  19. 读懂“法定准备金、超额准备金、备付金、超储率”及其政策含义
  20. 苹果cmsV10仿韩剧网响应式视频影视电影网站源码

热门文章

  1. Linkin Park - The Catalyst
  2. dbisam数据库主从表结构的使用方法
  3. 重装系统出现了计算机意外的重新启动或遇到错误.
  4. PYNQ-Z1开发板通过QSPI FALSH启动UBOOT
  5. htc g2 tim 刷机
  6. python操作画图软件_Python绘图工具matplotlib的使用(图形并茂)
  7. 阿里云服务器ECS通用型g5和g6实例差别在哪?
  8. 如何制作出准确无误的视频字幕?
  9. [px4仿真]px4的STIL仿真中添加向下的摄像头
  10. 干货分享-刷票如此简单,一句js代码搞定