package com.example.demo.hutool;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import lombok.Data;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Test;
import java.util.*;
/**
* @Description Hutool-poi是针对Apache POI的封装
*
* 使用Hutool的方法操作Office文件,Hutool提供的类有:
* ExcelUtil Excel工具类,读取的快捷方法都被封装于此。
* ExcelReader Excel读取器,Excel读取的封装,可以直接构造后使用。
* ExcelWriter Excel生成并写出器,Excel写出的封装(写出到流或者文件),可以直接构造后使用。
*
* Excel 写入器 此工具用于通过POI将数据写出到Excel,此对象可完成以下两个功能:
* 1. 编辑已存在的Excel,可写出原Excel文件,也可写出到其它地方(到文件或到流)
* 2. 新建一个空的Excel工作簿,完成数据填充后写出(到文件或到流)
*
* ExcelWriter类的主要方法:
* 构造器:
* ExcelWriter() 默认生成xls格式的Excel文件
* 此构造不传入写出的Excel文件路径,只能调用flush(OutputStream)方法写出到流
* 若写出到文件,还需调用setDestFile(File)方法自定义写出的文件,然后调用flush()方法写出到文件
* ExcelWriter(boolean isXlsx) 此构造不传入写出的Excel文件路径,只能调用flush(OutputStream)方法写出到流
* 若写出到文件,需要调用flush(File) 写出到文件
* ExcelWriter(boolean isXlsx, String sheetName) 此构造不传入写出的Excel文件路径,只能调用flush(OutputStream)方法写出到流
* 若写出到文件,需要调用flush(File) 写出到文件
* ExcelWriter(org.apache.poi.ss.usermodel.Sheet sheet) 此构造不传入写出的Excel文件路径,只能调用flush(OutputStream)方法写出到流
* 若写出到文件,还需调用setDestFile(File)方法自定义写出的文件,然后调用flush()方法写出到文件
* ExcelWriter(org.apache.poi.ss.usermodel.Workbook workbook, String sheetName) 此构造不传入写出的Excel文件路径,只能调用flush(OutputStream)方法写出到流
* 若写出到文件,还需调用setDestFile(File)方法自定义写出的文件,然后调用flush()方法写出到文件
* ExcelWriter(File destFile) 默认写出到第一个sheet,第一个sheet名为sheet1
* ExcelWriter(File destFile, String sheetName)
* ExcelWriter(String destFilePath) 默认写出到第一个sheet,第一个sheet名为sheet1
* ExcelWriter(String destFilePath, String sheetName)
*
* 方法:
* ExcelWriter addHeaderAlias(String name, String alias) 增加标题别名
* ExcelWriter addSelect(org.apache.poi.ss.util.CellRangeAddressList regions, String... selectList) 增加下拉列表
* ExcelWriter addSelect(int x, int y, String... selectList) 增加下拉列表
* ExcelWriter addValidationData(org.apache.poi.ss.usermodel.DataValidation dataValidation)
* 增加单元格控制,比如下拉列表、日期验证、数字范围验证等
* ExcelWriter autoSizeColumn(int columnIndex) 设置某列为自动宽度,不考虑合并单元格
* 此方法必须在指定列数据完全写出后调用才有效。
* ExcelWriter autoSizeColumnAll() 设置所有列为自动宽度,不考虑合并单元格
* 此方法必须在指定列数据完全写出后调用才有效。
* 列数计算是通过第一行计算的
* org.apache.poi.ss.usermodel.Font createFont() 创建字体
* ExcelBase.createCellStyle(int, int)
*
* ExcelWriter flush() 将Excel Workbook刷出到预定义的文件
* ExcelWriter flush(File destFile) 将Excel Workbook刷出到文件
* ExcelWriter flush(OutputStream out) 将Excel Workbook刷出到输出流
* ExcelWriter flush(OutputStream out, boolean isCloseOut) 将Excel Workbook刷出到输出流
*
* org.apache.poi.ss.usermodel.CellStyle getCellStyle() 获取单元格样式,获取样式后可自定义样式
* int getCurrentRow() 获得当前行
* String getDisposition(String fileName, Charset charset) 获取Content-Disposition头对应的值,可
* 以通过调用以下方法快速设置下载Excel的头信息
* org.apache.poi.ss.usermodel.CellStyle getHeadCellStyle() 获取头部样式,获取样式后可自定义样式
*
* StyleSet getStyleSet() 获取样式集,样式集可以自定义包括 ☆☆☆☆☆
*
* ExcelWriter merge(int lastColumn) 合并当前行的单元格 样式为默认标题样式,可使用getHeadCellStyle()方法调用后自定义默认样式
* ExcelWriter merge(int lastColumn, Object content) 合并当前行的单元格,并写入对象到单元格
* ExcelWriter merge(int lastColumn, Object content, boolean isSetHeaderStyle)
* ExcelWriter merge(int firstRow, int lastRow, int firstColumn, int lastColumn, Object content, boolean isSetHeaderStyle)
*
* ExcelWriter passCurrentRow() 跳过当前行
* ExcelWriter passRows(int rows) 跳过指定行数
* ExcelWriter renameSheet(int sheet, String sheetName) 重命名sheet
* ExcelWriter renameSheet(String sheetName) 重命名当前sheet
* ExcelWriter reset() 重置Writer
* ExcelWriter resetRow() 重置当前行为0
*
* ExcelWriter setColumnWidth(int columnIndex, int width) 设置列宽(单位为一个字符的宽度,例如传入width为10,表示10个字符的宽度)
* ExcelWriter setCurrentRow(int rowIndex) 设置当前所在行
* ExcelWriter setCurrentRowToEnd() 定位到最后一行的后边,用于追加数据
* ExcelWriter setDefaultRowHeight(int height) 设置默认行高,值为一个点的高度
* ExcelWriter setDestFile(File destFile) 设置写出的目标文件
* ExcelWriter setFreezePane(int rowSplit) 设置窗口冻结,之前冻结的窗口会被覆盖,如果rowSplit为0表示取消冻结
* ExcelWriter setFreezePane(int colSplit, int rowSplit) 设置窗口冻结,之前冻结的窗口会被覆盖,如果colSplit和rowSplit为0表示取消冻结
* ExcelWriter setHeaderAlias(Map headerAlias) 设置标题别名,key为Map中的key,value为别名
* ExcelWriter setHeaderOrFooter(String text, Align align, boolean isFooter) 设置Excel页眉或页脚
* ExcelWriter setRowHeight(int rownum, int height) 设置行高,值为一个点的高度
* ExcelWriter setRowStyle(int y, org.apache.poi.ss.usermodel.CellStyle style) 设置行样式
* ExcelWriter setSheet(int sheetIndex) 自定义需要读取或写出的Sheet,如果给定的sheet不存在,创建之(命名为默认)
* 在读取中,此方法用于切换读取的sheet,在写出时,此方法用于新建或者切换sheet
* ExcelWriter setSheet(String sheetName)
* ExcelWriter setStyleSet(StyleSet styleSet) 设置样式集,如果不使用样式,传入null
*
* ExcelWriter write(Iterable> data) 写出数据,本方法只是将数据写入Workbook中的Sheet,并不写出到文件
* 写出的起始行为当前行号,可使用getCurrentRow()方法调用,根据写出的的行数,当前行号自动增加样式为默认样式,
* 可使用getCellStyle()方法调用后自定义默认样式默认的,当当前行号为0时,写出标题(如果为Map或Bean),否则不写标题。
* ExcelWriter write(Iterable> data, boolean isWriteKeyAsHead)
* ExcelWriter writeCellValue(int x, int y, Object value) 给指定单元格赋值,使用默认单元格样式
* ExcelWriter writeCellValue(String locationRef, Object value) 给指定单元格赋值,使用默认单元格样式
* ExcelWriter writeHeadRow(Iterable> rowData) 写出一行标题数据
* ExcelWriter writeRow(Iterable> rowData) 写出一行数据
* ExcelWriter writeRow(Map,?> rowMap, boolean isWriteKeyAsHead) 将一个Map写入到Excel,isWriteKeyAsHead为true写出两行,
* Map的keys做为一行,values做为第二行,否则只写出一行values 如果rowMap为空(包括null),则写出空行。
* ExcelWriter writeRow(Object rowBean, boolean isWriteKeyAsHead)
*
*
* @Auther guofeng.xie
* @Date 2020/11/15 16:10
*/
public class TestExcelWriter {
/**
* ExcelWriter类的使用
*
* Hutool针对将数据写出到Excel做了封装
*
* Hutool将Excel写出封装为ExcelWriter,原理为包装了Workbook对象,
* 每次调用merge(合并单元格)或者write(写出数据)方法后只是将数据写入到Workbook,并不写出文件,
* 只有调用flush或者close方法后才会真正写出文件。
*/
//1. 将行列对象写出到Excel
@Test
public void testExcelWriter() {
//① 我们先定义一个嵌套的List,List的元素也是一个List,内层的一个List代表一行数据,每行都有4个单元格,最终list对象代表多行数据。
List row1 = CollUtil.newArrayList("aa", "bb", "cc", "dd");
List row2 = CollUtil.newArrayList("aa1", "bb1", "cc1", "dd1");
List row3 = CollUtil.newArrayList("aa2", "bb2", "cc2", "dd2");
List row4 = CollUtil.newArrayList("aa3", "bb3", "cc3", "dd3");
List row5 = CollUtil.newArrayList("aa4", "bb4", "cc4", "dd4");
List> rows = CollUtil.newArrayList(row1, row2, row3, row4, row5);
//② 然后我们创建ExcelWriter对象后写出数据
//通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter("E:/test/writeTest.xlsx");
//通过构造方法创建writer
//ExcelWriter writer = new ExcelWriter("d:/writeTest.xls");
//跳过当前行,既第一行,非必须,在此演示用
writer.passCurrentRow();
//合并单元格后的标题行,使用默认标题样式
writer.merge(row1.size() - 1, "测试标题");
//一次性写出内容,强制输出标题
writer.write(rows, true);
//关闭writer,释放内存
writer.close();
}
//2. 写出Map数据
@Test
public void testExcelWriter2() {
//① 构造数据
Map row1 = new LinkedHashMap<>();
row1.put("姓名", "张三");
row1.put("年龄", 23);
row1.put("成绩", 88.32);
row1.put("是否合格", true);
row1.put("考试日期", DateUtil.date());
Map row2 = new LinkedHashMap<>();
row2.put("姓名", "李四");
row2.put("年龄", 33);
row2.put("成绩", 59.50);
row2.put("是否合格", false);
row2.put("考试日期", DateUtil.date());
ArrayList