前言
对于简单excel报表导出,有很多简单的工具如easypoi,而且现在网上已经有很多工具类整合easypoi使用起来非常方便。但是简单的弊端往往无法适配一些负责场景,而我们实际生产中面临的都是客户自定以的一个负责报表导出,这是利用原始的poi去操作,不仅思路上清晰而且实现起来并不复杂。
比如导出下面格式报表:
这个表格算是典型的各个复杂场景都包含,有表头占两行、有表头占三列、有两级表头。。。
easypoi可以实现,但我们需要在实体类注解控制,甚至表格在复杂一些就处理不了了。
下面我们使用poi实现这种类型表格导出,包括表格内各种样式、字体等,理论上学会这套任何复杂报表都能实现,牛~~~
思路
POI操作Excel文档核心五步,文档操作都离不开这五步。
1、创建workbook,XSSFWorkbook创建的是.xlsx后缀文件,HSSFWorkbook创建的是.xls后缀文件
XSSFWorkbook workbook = new XSSFWorkbook();
2、根据workboot创建sheet
XSSFSheet sheet = workbook.createSheet("用户信息");
3、根据sheet创建行
XSSFRow row = sheet.createRow(0);
4、根据行创建单元格
XSSFCell cell = row.createCell(0);
5、往单元格填充数据
cell.setCellValue("测试");
过上面五步,我们就往excel中第一行第一个单元格插入了“测试”数据,任何复杂操作都是基于上面过程实现。
代码
public void export(HttpServletResponse response) {
// 创建workbook,XSSFWorkbook创建的是.xlsx后缀文件,HSSFWorkbook创建的是.xls后缀文件
XSSFWorkbook workbook = new XSSFWorkbook();
// 创建sheet,并命名
XSSFSheet sheet = workbook.createSheet("用户信息");
// 创建标题行,坐标从0开始
XSSFRow row0 = sheet.createRow(0);
// 创建0行中第一个单元格,坐标从0开始
XSSFCell cell00 = row0.createCell(0);
// 填充当前单元格数据
cell00.setCellValue("用户信息表");
// 表头行占6列,需要合并,参数介绍:开始行、结束行、开始列、结束列。
// 通过设置当前参数,合并单元格,比如下面表示行合并0-0行,列合并0-5列
CellRangeAddress cellAddresses0 = new CellRangeAddress(0, 0, 0, 5);
sheet.addMergedRegion(cellAddresses0);
// 创建第二行表头
XSSFRow row1 = sheet.createRow(1);
// 填充表头数据
XSSFCell cell10 = row1.createCell(0);
cell10.setCellValue("编号");
XSSFCell cell11 = row1.createCell(1);
cell11.setCellValue("姓名");
XSSFCell cell12 = row1.createCell(2);
cell12.setCellValue("年龄");
XSSFCell cell13 = row1.createCell(3);
cell13.setCellValue("兴趣");
// 对第二行表头进行单元格合并
CellRangeAddress cellAddresses1 = new CellRangeAddress(1, 2, 0, 0);
sheet.addMergedRegion(cellAddresses1);
CellRangeAddress cellAddresses2 = new CellRangeAddress(1, 2, 1, 1);
sheet.addMergedRegion(cellAddresses2);
CellRangeAddress cellAddresses3 = new CellRangeAddress(1, 2, 2, 2);
sheet.addMergedRegion(cellAddresses3);
CellRangeAddress cellAddresses4 = new CellRangeAddress(1, 1, 3, 5);
sheet.addMergedRegion(cellAddresses4);
// 创建第三行表头
XSSFRow row2 = sheet.createRow(2);
// 填充表头数据
XSSFCell cell23 = row2.createCell(3);
cell23.setCellValue("兴趣1");
XSSFCell cell24 = row2.createCell(4);
cell24.setCellValue("兴趣2");
XSSFCell cell25 = row2.createCell(5);
cell25.setCellValue("兴趣3");
// 填充数据(根据具体业务)
for (int i = 0; i < 10; i++) {
// 创建数据行(数据行是从第四行开始)
XSSFRow rowTemp = sheet.createRow(i + 3);
// 按顺序往单元格填充数据
XSSFCell cell0 = rowTemp.createCell(0);
cell0.setCellValue(i);
XSSFCell cell1 = rowTemp.createCell(1);
cell1.setCellValue("z" + i);
XSSFCell cell2 = rowTemp.createCell(2);
cell2.setCellValue(18 + i);
XSSFCell cell3 = rowTemp.createCell(3);
cell3.setCellValue("兴趣" + i);
XSSFCell cell4 = rowTemp.createCell(4);
cell4.setCellValue("兴趣" + i);
XSSFCell cell5 = rowTemp.createCell(5);
cell5.setCellValue("兴趣" + i);
}
response.reset();
try {
ServletOutputStream outputStream = response.getOutputStream();
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户信息表.xlsx", "UTF-8"));
workbook.write(outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
导出后:
当然这还没有完全结束,实际生产中我们都是需要对表格格式去处理,比如我们需要把标题居中对齐,可以在基础上通过添加下面代码实现:
通过workboot创建样式=》设置当前样式类型(居中还是左对齐之类的)=》哪个单元格需要就设置哪个单元格
比如我们想要添加标题背景颜色,可以添加下面格式:
下面是一些常见的格式,总结给出:
/**
* 设置单元格样式
*
*/
public void setCellStyle(Workbook workbook){
//设置单元格背景颜色
Sheet sheet=workbook.getSheetAt(0);
Row row=sheet.getRow(0);
Cell cell=row.getCell(0);
CellStyle style = workbook.createCellStyle();
style.cloneStyleFrom(cell.getCellStyle());
//设置背景颜色
style.setFillForegroundColor(IndexedColors.BLUE_GREY.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//设置自动换行
style.setWrapText(true);
//设置字体样式
Font font= row.getSheet().getWorkbook().createFont();
//默认字体为宋体
font.setFontName("宋体");
//设置字体大小
font.setFontHeight((short) 18);
//设置字体颜色
font.setColor(IndexedColors.BLUE_GREY.getIndex());
//设置字体加粗
font.setBold(true);
//设置字体斜体
font.setItalic(true);
//设置字体下划线
font.setUnderline(Font.U_SINGLE);
//设置字体上标下标
font.setTypeOffset(Font.SS_SUPER);
//设置字体删除线
font.setStrikeout(true);
style.setFont(font);
//边框样式
//设置上边框线条类型
style.setBorderTop(BorderStyle.THIN);
//设置右边框线条类型
style.setBorderRight(BorderStyle.THIN);
//设置下边框线条类型
style.setBorderBottom(BorderStyle.THIN);
//设置左边框线条类型
style.setBorderLeft(BorderStyle.THIN);
//设置上边框线条颜色
style.setTopBorderColor(IndexedColors.BLUE_GREY.getIndex());
//设置右边框线条颜色
style.setRightBorderColor(IndexedColors.BLUE_GREY.getIndex());
//设置下边框线条颜色
style.setBottomBorderColor(IndexedColors.BLUE_GREY.getIndex());
//设置左边框线条颜色
style.setLeftBorderColor(IndexedColors.BLUE_GREY.getIndex());
//对齐方式
//设置水平对齐方式
style.setAlignment(HorizontalAlignment.CENTER);
//设置垂直对齐方式
style.setVerticalAlignment(VerticalAlignment.CENTER);
//设置列宽行高
//设置自适应列宽
sheet.setDefaultColumnWidth(0);
//自定义列宽
sheet.setColumnWidth(0,10);
//自定义行高
row.setHeight((short)10);
//冻结行和列
sheet.createFreezePane(1, 1);
//合并单元格
CellRangeAddress cellRangeAddress = new CellRangeAddress(1, 1, 1, 2);
sheet.addMergedRegionUnsafe(cellRangeAddress);
}
总结,通过核心五步就可以实现创建excel并往对应单元格填充数据,中间通过合并或相应格式实现复杂表格设计。