通用数据生成 后面不会重复写
  1. private List<DemoData> data() {
  2. List<DemoData> list = new ArrayList<DemoData>();
  3. for (int i = 0; i < 10; i++) {
  4. DemoData data = new DemoData();
  5. data.setString("字符串" + i);
  6. data.setDate(new Date());
  7. data.setDoubleData(0.56);
  8. list.add(data);
  9. }
  10. return list;
  11. }

示例代码

DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java

最简单的写

excel示例

写 - 图1

对象
  1. @Data
  2. public class DemoData {
  3. @ExcelProperty("字符串标题")
  4. private String string;
  5. @ExcelProperty("日期标题")
  6. private Date date;
  7. @ExcelProperty("数字标题")
  8. private Double doubleData;
  9. /**
  10. * 忽略这个字段
  11. */
  12. @ExcelIgnore
  13. private String ignore;
  14. }

代码
  1. /**
  2. * 最简单的写
  3. * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
  4. * <p>2. 直接写即可
  5. */
  6. @Test
  7. public void simpleWrite() {
  8. // 写法1
  9. String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  10. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  11. // 如果这里想使用03 则 传入excelType参数即可
  12. EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
  13. // 写法2
  14. fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
  15. // 这里 需要指定写用哪个class去写
  16. ExcelWriter excelWriter = null;
  17. try {
  18. excelWriter = EasyExcel.write(fileName, DemoData.class).build();
  19. WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
  20. excelWriter.write(data(), writeSheet);
  21. } finally {
  22. // 千万别忘记finish 会帮忙关闭流
  23. if (excelWriter != null) {
  24. excelWriter.finish();
  25. }
  26. }
  27. }

根据参数只导出指定列

excel示例

写 - 图2

对象

参照:对象

代码
  1. /**
  2. * 根据参数只导出指定列
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link DemoData}
  5. * <p>
  6. * 2. 根据自己或者排除自己需要的列
  7. * <p>
  8. * 3. 直接写即可
  9. *
  10. * @since 2.1.1
  11. */
  12. @Test
  13. public void excludeOrIncludeWrite() {
  14. String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
  15. // 根据用户传入字段 假设我们要忽略 date
  16. Set<String> excludeColumnFiledNames = new HashSet<String>();
  17. excludeColumnFiledNames.add("date");
  18. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  19. EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板")
  20. .doWrite(data());
  21. fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
  22. // 根据用户传入字段 假设我们只要导出 date
  23. Set<String> includeColumnFiledNames = new HashSet<String>();
  24. includeColumnFiledNames.add("date");
  25. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  26. EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板")
  27. .doWrite(data());
  28. }

指定写入的列

excel示例

写 - 图3

对象
  1. @Data
  2. public class IndexData {
  3. @ExcelProperty(value = "字符串标题", index = 0)
  4. private String string;
  5. @ExcelProperty(value = "日期标题", index = 1)
  6. private Date date;
  7. /**
  8. * 这里设置3 会导致第二列空的
  9. */
  10. @ExcelProperty(value = "数字标题", index = 3)
  11. private Double doubleData;
  12. }

代码
  1. /**
  2. * 指定写入的列
  3. * <p>1. 创建excel对应的实体对象 参照{@link IndexData}
  4. * <p>2. 使用{@link ExcelProperty}注解指定写入的列
  5. * <p>3. 直接写即可
  6. */
  7. @Test
  8. public void indexWrite() {
  9. String fileName = TestFileUtil.getPath() + "indexWrite" + System.currentTimeMillis() + ".xlsx";
  10. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  11. EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(data());
  12. }

复杂头写入

excel示例

写 - 图4

对象
  1. @Data
  2. public class ComplexHeadData {
  3. @ExcelProperty({"主标题", "字符串标题"})
  4. private String string;
  5. @ExcelProperty({"主标题", "日期标题"})
  6. private Date date;
  7. @ExcelProperty({"主标题", "数字标题"})
  8. private Double doubleData;
  9. }

代码
  1. /**
  2. * 复杂头写入
  3. * <p>1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
  4. * <p>2. 使用{@link ExcelProperty}注解指定复杂的头
  5. * <p>3. 直接写即可
  6. */
  7. @Test
  8. public void complexHeadWrite() {
  9. String fileName = TestFileUtil.getPath() + "complexHeadWrite" + System.currentTimeMillis() + ".xlsx";
  10. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  11. EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data());
  12. }

重复多次写入(写到单个或者多个Sheet)

excel示例

写 - 图5

对象

参照:对象

代码
  1. /**
  2. * 重复多次写入
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
  5. * <p>
  6. * 2. 使用{@link ExcelProperty}注解指定复杂的头
  7. * <p>
  8. * 3. 直接调用二次写入即可
  9. */
  10. @Test
  11. public void repeatedWrite() {
  12. // 方法1 如果写到同一个sheet
  13. String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
  14. ExcelWriter excelWriter = null;
  15. try {
  16. // 这里 需要指定写用哪个class去写
  17. excelWriter = EasyExcel.write(fileName, DemoData.class).build();
  18. // 这里注意 如果同一个sheet只要创建一次
  19. WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
  20. // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
  21. for (int i = 0; i < 5; i++) {
  22. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  23. List<DemoData> data = data();
  24. excelWriter.write(data, writeSheet);
  25. }
  26. } finally {
  27. // 千万别忘记finish 会帮忙关闭流
  28. if (excelWriter != null) {
  29. excelWriter.finish();
  30. }
  31. }
  32. // 方法2 如果写到不同的sheet 同一个对象
  33. fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
  34. try {
  35. // 这里 指定文件
  36. excelWriter = EasyExcel.write(fileName, DemoData.class).build();
  37. // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
  38. for (int i = 0; i < 5; i++) {
  39. // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
  40. WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
  41. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  42. List<DemoData> data = data();
  43. excelWriter.write(data, writeSheet);
  44. }
  45. } finally {
  46. // 千万别忘记finish 会帮忙关闭流
  47. if (excelWriter != null) {
  48. excelWriter.finish();
  49. }
  50. }
  51. // 方法3 如果写到不同的sheet 不同的对象
  52. fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
  53. try {
  54. // 这里 指定文件
  55. excelWriter = EasyExcel.write(fileName).build();
  56. // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
  57. for (int i = 0; i < 5; i++) {
  58. // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变
  59. WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();
  60. // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
  61. List<DemoData> data = data();
  62. excelWriter.write(data, writeSheet);
  63. }
  64. } finally {
  65. // 千万别忘记finish 会帮忙关闭流
  66. if (excelWriter != null) {
  67. excelWriter.finish();
  68. }
  69. }
  70. }

日期、数字或者自定义格式转换

excel示例

写 - 图6

对象
  1. @Data
  2. public class ConverterData {
  3. /**
  4. * 我想所有的 字符串起前面加上"自定义:"三个字
  5. */
  6. @ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class)
  7. private String string;
  8. /**
  9. * 我想写到excel 用年月日的格式
  10. */
  11. @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
  12. @ExcelProperty("日期标题")
  13. private Date date;
  14. /**
  15. * 我想写到excel 用百分比表示
  16. */
  17. @NumberFormat("#.##%")
  18. @ExcelProperty(value = "数字标题")
  19. private Double doubleData;
  20. }

代码
  1. /**
  2. * 日期、数字或者自定义格式转换
  3. * <p>1. 创建excel对应的实体对象 参照{@link ConverterData}
  4. * <p>2. 使用{@link ExcelProperty}配合使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解
  5. * <p>3. 直接写即可
  6. */
  7. @Test
  8. public void converterWrite() {
  9. String fileName = TestFileUtil.getPath() + "converterWrite" + System.currentTimeMillis() + ".xlsx";
  10. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  11. EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());
  12. }

图片导出

excel示例

写 - 图7

对象
  1. @Data
  2. @ContentRowHeight(100)
  3. @ColumnWidth(100 / 8)
  4. public class ImageData {
  5. private File file;
  6. private InputStream inputStream;
  7. /**
  8. * 如果string类型 必须指定转换器,string默认转换成string
  9. */
  10. @ExcelProperty(converter = StringImageConverter.class)
  11. private String string;
  12. private byte[] byteArray;
  13. /**
  14. * 根据url导出
  15. *
  16. * @since 2.1.1
  17. */
  18. private URL url;
  19. }

代码
  1. /**
  2. * 图片导出
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link ImageData}
  5. * <p>
  6. * 2. 直接写即可
  7. */
  8. @Test
  9. public void imageWrite() throws Exception {
  10. String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx";
  11. // 如果使用流 记得关闭
  12. InputStream inputStream = null;
  13. try {
  14. List<ImageData> list = new ArrayList<ImageData>();
  15. ImageData imageData = new ImageData();
  16. list.add(imageData);
  17. String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg";
  18. // 放入五种类型的图片 实际使用只要选一种即可
  19. imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));
  20. imageData.setFile(new File(imagePath));
  21. imageData.setString(imagePath);
  22. inputStream = FileUtils.openInputStream(new File(imagePath));
  23. imageData.setInputStream(inputStream);
  24. imageData.setUrl(new URL(
  25. "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg"));
  26. EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list);
  27. } finally {
  28. if (inputStream != null) {
  29. inputStream.close();
  30. }
  31. }
  32. }

根据模板写入

模板excel示例

写 - 图8

excel示例

写 - 图9

对象

参照:对象

代码
  1. /**
  2. * 根据模板写入
  3. * <p>1. 创建excel对应的实体对象 参照{@link IndexData}
  4. * <p>2. 使用{@link ExcelProperty}注解指定写入的列
  5. * <p>3. 使用withTemplate 写取模板
  6. * <p>4. 直接写即可
  7. */
  8. @Test
  9. public void templateWrite() {
  10. String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
  11. String fileName = TestFileUtil.getPath() + "templateWrite" + System.currentTimeMillis() + ".xlsx";
  12. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  13. EasyExcel.write(fileName, DemoData.class).withTemplate(templateFileName).sheet().doWrite(data());
  14. }

列宽、行高

excel示例

写 - 图10

对象
  1. @Data
  2. @ContentRowHeight(10)
  3. @HeadRowHeight(20)
  4. @ColumnWidth(25)
  5. public class WidthAndHeightData {
  6. @ExcelProperty("字符串标题")
  7. private String string;
  8. @ExcelProperty("日期标题")
  9. private Date date;
  10. /**
  11. * 宽度为50
  12. */
  13. @ColumnWidth(50)
  14. @ExcelProperty("数字标题")
  15. private Double doubleData;
  16. }

代码
  1. /**
  2. * 列宽、行高
  3. * <p>1. 创建excel对应的实体对象 参照{@link WidthAndHeightData}
  4. * <p>2. 使用注解{@link ColumnWidth}、{@link HeadRowHeight}、{@link ContentRowHeight}指定宽度或高度
  5. * <p>3. 直接写即可
  6. */
  7. @Test
  8. public void widthAndHeightWrite() {
  9. String fileName = TestFileUtil.getPath() + "widthAndHeightWrite" + System.currentTimeMillis() + ".xlsx";
  10. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  11. EasyExcel.write(fileName, WidthAndHeightData.class).sheet("模板").doWrite(data());
  12. }

注解形式自定义样式

since

2.2.0-beta1

excel示例

image.png

对象
  1. /**
  2. * 样式的数据类
  3. *
  4. * @author Jiaju Zhuang
  5. **/
  6. @Data
  7. // 头背景设置成红色 IndexedColors.RED.getIndex()
  8. @HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 10)
  9. // 头字体设置成20
  10. @HeadFontStyle(fontHeightInPoints = 20)
  11. // 内容的背景设置成绿色 IndexedColors.GREEN.getIndex()
  12. @ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 17)
  13. // 内容字体设置成20
  14. @ContentFontStyle(fontHeightInPoints = 20)
  15. public class DemoStyleData {
  16. // 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()
  17. @HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 14)
  18. // 字符串的头字体设置成20
  19. @HeadFontStyle(fontHeightInPoints = 30)
  20. // 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()
  21. @ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 40)
  22. // 字符串的内容字体设置成20
  23. @ContentFontStyle(fontHeightInPoints = 30)
  24. @ExcelProperty("字符串标题")
  25. private String string;
  26. @ExcelProperty("日期标题")
  27. private Date date;
  28. @ExcelProperty("数字标题")
  29. private Double doubleData;
  30. }

代码
  1. /**
  2. * 注解形式自定义样式
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link DemoStyleData}
  5. * <p>
  6. * 3. 直接写即可
  7. *
  8. * @since 2.2.0-beta1
  9. */
  10. @Test
  11. public void annotationStyleWrite() {
  12. String fileName = TestFileUtil.getPath() + "annotationStyleWrite" + System.currentTimeMillis() + ".xlsx";
  13. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  14. EasyExcel.write(fileName, DemoStyleData.class).sheet("模板").doWrite(data());
  15. }

自定义样式

excel示例

写 - 图12

对象

参照:对象

代码
  1. /**
  2. * 自定义样式
  3. * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
  4. * <p>2. 创建一个style策略 并注册
  5. * <p>3. 直接写即可
  6. */
  7. @Test
  8. public void styleWrite() {
  9. String fileName = TestFileUtil.getPath() + "styleWrite" + System.currentTimeMillis() + ".xlsx";
  10. // 头的策略
  11. WriteCellStyle headWriteCellStyle = new WriteCellStyle();
  12. // 背景设置为红色
  13. headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
  14. WriteFont headWriteFont = new WriteFont();
  15. headWriteFont.setFontHeightInPoints((short)20);
  16. headWriteCellStyle.setWriteFont(headWriteFont);
  17. // 内容的策略
  18. WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
  19. // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
  20. contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
  21. // 背景绿色
  22. contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
  23. WriteFont contentWriteFont = new WriteFont();
  24. // 字体大小
  25. contentWriteFont.setFontHeightInPoints((short)20);
  26. contentWriteCellStyle.setWriteFont(contentWriteFont);
  27. // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
  28. HorizontalCellStyleStrategy horizontalCellStyleStrategy =
  29. new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
  30. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  31. EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
  32. .doWrite(data());
  33. }

合并单元格

since

2.2.0-beta1

excel示例

写 - 图13

对象

方法1

  1. /**
  2. * 样式的数据类
  3. *
  4. * @author Jiaju Zhuang
  5. **/
  6. @Data
  7. // 将第6-7行的2-3列合并成一个单元格
  8. // @OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
  9. public class DemoMergeData {
  10. // 这一列 每隔2行 合并单元格
  11. @ContentLoopMerge(eachRow = 2)
  12. @ExcelProperty("字符串标题")
  13. private String string;
  14. @ExcelProperty("日期标题")
  15. private Date date;
  16. @ExcelProperty("数字标题")
  17. private Double doubleData;
  18. }

方法2参照:对象

代码
  1. /**
  2. * 合并单元格
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link DemoData} {@link DemoMergeData}
  5. * <p>
  6. * 2. 创建一个merge策略 并注册
  7. * <p>
  8. * 3. 直接写即可
  9. *
  10. * @since 2.2.0-beta1
  11. */
  12. @Test
  13. public void mergeWrite() {
  14. // 方法1 注解
  15. String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
  16. // 在DemoStyleData里面加上ContentLoopMerge注解
  17. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  18. EasyExcel.write(fileName, DemoMergeData.class).sheet("模板").doWrite(data());
  19. // 方法2 自定义合并单元格策略
  20. fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
  21. // 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写
  22. LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);
  23. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  24. EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板").doWrite(data());
  25. }

使用table去写入

excel示例

写 - 图14

对象

参照:对象

代码
  1. /**
  2. * 使用table去写入
  3. * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
  4. * <p>2. 然后写入table即可
  5. */
  6. @Test
  7. public void tableWrite() {
  8. String fileName = TestFileUtil.getPath() + "tableWrite" + System.currentTimeMillis() + ".xlsx";
  9. // 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例
  10. // 这里 需要指定写用哪个class去写
  11. ExcelWriter excelWriter = null;
  12. try {
  13. excelWriter = EasyExcel.write(fileName, DemoData.class).build();
  14. // 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
  15. WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();
  16. // 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
  17. WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.TRUE).build();
  18. WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();
  19. // 第一次写入会创建头
  20. excelWriter.write(data(), writeSheet, writeTable0);
  21. // 第二次写如也会创建头,然后在第一次的后面写入数据
  22. excelWriter.write(data(), writeSheet, writeTable1);
  23. } finally {
  24. // 千万别忘记finish 会帮忙关闭流
  25. if (excelWriter != null) {
  26. excelWriter.finish();
  27. }
  28. }
  29. }

动态头,实时生成头写入

excel示例

写 - 图15

对象

参照:对象

代码
  1. /**
  2. * 动态头,实时生成头写入
  3. * <p>
  4. * 思路是这样子的,先创建List<String>头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据
  5. *
  6. * <p>
  7. * 1. 创建excel对应的实体对象 参照{@link DemoData}
  8. * <p>
  9. * 2. 然后写入table即可
  10. */
  11. @Test
  12. public void dynamicHeadWrite() {
  13. String fileName = TestFileUtil.getPath() + "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx";
  14. EasyExcel.write(fileName)
  15. // 这里放入动态头
  16. .head(head()).sheet("模板")
  17. // 当然这里数据也可以用 List<List<String>> 去传入
  18. .doWrite(data());
  19. }
  20. private List<List<String>> head() {
  21. List<List<String>> list = new ArrayList<List<String>>();
  22. List<String> head0 = new ArrayList<String>();
  23. head0.add("字符串" + System.currentTimeMillis());
  24. List<String> head1 = new ArrayList<String>();
  25. head1.add("数字" + System.currentTimeMillis());
  26. List<String> head2 = new ArrayList<String>();
  27. head2.add("日期" + System.currentTimeMillis());
  28. list.add(head0);
  29. list.add(head1);
  30. list.add(head2);
  31. return list;
  32. }

自动列宽(不太精确)

excel示例

写 - 图16

对象
  1. @Data
  2. public class LongestMatchColumnWidthData {
  3. @ExcelProperty("字符串标题")
  4. private String string;
  5. @ExcelProperty("日期标题很长日期标题很长日期标题很长很长")
  6. private Date date;
  7. @ExcelProperty("数字")
  8. private Double doubleData;
  9. }

代码
  1. /**
  2. * 自动列宽(不太精确)
  3. * <p>
  4. * 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照
  5. * {@link LongestMatchColumnWidthStyleStrategy}重新实现.
  6. * <p>
  7. * poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。
  8. *
  9. * <p>
  10. * 1. 创建excel对应的实体对象 参照{@link LongestMatchColumnWidthData}
  11. * <p>
  12. * 2. 注册策略{@link LongestMatchColumnWidthStyleStrategy}
  13. * <p>
  14. * 3. 直接写即可
  15. */
  16. @Test
  17. public void longestMatchColumnWidthWrite() {
  18. String fileName =
  19. TestFileUtil.getPath() + "longestMatchColumnWidthWrite" + System.currentTimeMillis() + ".xlsx";
  20. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  21. EasyExcel.write(fileName, LongestMatchColumnWidthData.class)
  22. .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("模板").doWrite(dataLong());
  23. }
  24. private List<LongestMatchColumnWidthData> dataLong() {
  25. List<LongestMatchColumnWidthData> list = new ArrayList<LongestMatchColumnWidthData>();
  26. for (int i = 0; i < 10; i++) {
  27. LongestMatchColumnWidthData data = new LongestMatchColumnWidthData();
  28. data.setString("测试很长的字符串测试很长的字符串测试很长的字符串" + i);
  29. data.setDate(new Date());
  30. data.setDoubleData(1000000000000.0);
  31. list.add(data);
  32. }
  33. return list;
  34. }

自定义拦截器(上面几点都不符合但是要对单元格进行操作的参照这个)

excel示例

写 - 图17

对象

参照:对象

定义拦截器
  1. /**
  2. * 自定义拦截器。对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel
  3. *
  4. * @author Jiaju Zhuang
  5. */
  6. public class CustomCellWriteHandler implements CellWriteHandler {
  7. private static final Logger LOGGER = LoggerFactory.getLogger(CustomCellWriteHandler.class);
  8. @Override
  9. public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
  10. Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
  11. }
  12. @Override
  13. public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
  14. Head head, Integer relativeRowIndex, Boolean isHead) {
  15. }
  16. @Override
  17. public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
  18. List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
  19. // 这里可以对cell进行任何操作
  20. LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
  21. if (isHead && cell.getColumnIndex() == 0) {
  22. CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
  23. Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);
  24. hyperlink.setAddress("https://github.com/alibaba/easyexcel");
  25. cell.setHyperlink(hyperlink);
  26. }
  27. }
  28. }
  1. /**
  2. * 自定义拦截器.对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2
  3. *
  4. * @author Jiaju Zhuang
  5. */
  6. public class CustomSheetWriteHandler implements SheetWriteHandler {
  7. private static final Logger LOGGER = LoggerFactory.getLogger(CustomSheetWriteHandler.class);
  8. @Override
  9. public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
  10. }
  11. @Override
  12. public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
  13. LOGGER.info("第{}个Sheet写入成功。", writeSheetHolder.getSheetNo());
  14. // 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
  15. CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);
  16. DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper();
  17. DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"});
  18. DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
  19. writeSheetHolder.getSheet().addValidationData(dataValidation);
  20. }
  21. }

代码
  1. /**
  2. * 下拉,超链接等自定义拦截器(上面几点都不符合但是要对单元格进行操作的参照这个)
  3. * <p>
  4. * demo这里实现2点。1. 对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel 2. 对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2
  5. * <p>
  6. * 1. 创建excel对应的实体对象 参照{@link DemoData}
  7. * <p>
  8. * 2. 注册拦截器 {@link CustomCellWriteHandler} {@link CustomSheetWriteHandler}
  9. * <p>
  10. * 2. 直接写即可
  11. */
  12. @Test
  13. public void customHandlerWrite() {
  14. String fileName = TestFileUtil.getPath() + "customHandlerWrite" + System.currentTimeMillis() + ".xlsx";
  15. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  16. EasyExcel.write(fileName, DemoData.class).registerWriteHandler(new CustomSheetWriteHandler())
  17. .registerWriteHandler(new CustomCellWriteHandler()).sheet("模板").doWrite(data());
  18. }

插入批注

excel示例

image.png

对象

参照:对象

定义拦截器
  1. /**
  2. * 自定义拦截器.新增注释,第一行头加批注
  3. *
  4. * @author Jiaju Zhuang
  5. */
  6. public class CommentWriteHandler extends AbstractRowWriteHandler {
  7. @Override
  8. public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
  9. Integer relativeRowIndex, Boolean isHead) {
  10. if (isHead) {
  11. Sheet sheet = writeSheetHolder.getSheet();
  12. Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
  13. // 在第一行 第二列创建一个批注
  14. Comment comment =
  15. drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short)1, 0, (short)2, 1));
  16. // 输入批注信息
  17. comment.setString(new XSSFRichTextString("创建批注!"));
  18. // 将批注添加到单元格对象中
  19. sheet.getRow(0).getCell(1).setCellComment(comment);
  20. }
  21. }
  22. }

代码
  1. /**
  2. * 插入批注
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link DemoData}
  5. * <p>
  6. * 2. 注册拦截器 {@link CommentWriteHandler}
  7. * <p>
  8. * 2. 直接写即可
  9. */
  10. @Test
  11. public void commentWrite() {
  12. String fileName = TestFileUtil.getPath() + "commentWrite" + System.currentTimeMillis() + ".xlsx";
  13. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  14. // 这里要注意inMemory 要设置为true,才能支持批注。目前没有好的办法解决 不在内存处理批注。这个需要自己选择。
  15. EasyExcel.write(fileName, DemoData.class).inMemory(Boolean.TRUE).registerWriteHandler(new CommentWriteHandler())
  16. .sheet("模板").doWrite(data());
  17. }

不创建对象

不创建对象的写

excel示例

写 - 图19

代码
  1. /**
  2. * 不创建对象的写
  3. */
  4. @Test
  5. public void noModelWrite() {
  6. // 写法1
  7. String fileName = TestFileUtil.getPath() + "noModelWrite" + System.currentTimeMillis() + ".xlsx";
  8. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  9. EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList());
  10. }
  11. private List<List<String>> head() {
  12. List<List<String>> list = new ArrayList<List<String>>();
  13. List<String> head0 = new ArrayList<String>();
  14. head0.add("字符串" + System.currentTimeMillis());
  15. List<String> head1 = new ArrayList<String>();
  16. head1.add("数字" + System.currentTimeMillis());
  17. List<String> head2 = new ArrayList<String>();
  18. head2.add("日期" + System.currentTimeMillis());
  19. list.add(head0);
  20. list.add(head1);
  21. list.add(head2);
  22. return list;
  23. }
  24. private List<List<Object>> dataList() {
  25. List<List<Object>> list = new ArrayList<List<Object>>();
  26. for (int i = 0; i < 10; i++) {
  27. List<Object> data = new ArrayList<Object>();
  28. data.add("字符串" + i);
  29. data.add(new Date());
  30. data.add(0.56);
  31. list.add(data);
  32. }
  33. return list;
  34. }

web中的写

示例代码

DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java

对象

参照:对象 就是名称变了下

代码
  1. /**
  2. * 文件下载(失败了会返回一个有部分数据的Excel)
  3. * <p>
  4. * 1. 创建excel对应的实体对象 参照{@link DownloadData}
  5. * <p>
  6. * 2. 设置返回的 参数
  7. * <p>
  8. * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
  9. */
  10. @GetMapping("download")
  11. public void download(HttpServletResponse response) throws IOException {
  12. // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
  13. response.setContentType("application/vnd.ms-excel");
  14. response.setCharacterEncoding("utf-8");
  15. // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
  16. String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
  17. response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
  18. EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
  19. }

web中的写并且失败的时候返回json

since

2.1.1

对象

参照:对象 就是名称变了下

代码
  1. /**
  2. * 文件下载并且失败的时候返回json(默认失败了会返回一个有部分数据的Excel)
  3. *
  4. * @since 2.1.1
  5. */
  6. @GetMapping("downloadFailedUsingJson")
  7. public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
  8. // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
  9. try {
  10. response.setContentType("application/vnd.ms-excel");
  11. response.setCharacterEncoding("utf-8");
  12. // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
  13. String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
  14. response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
  15. // 这里需要设置不关闭流
  16. EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板")
  17. .doWrite(data());
  18. } catch (Exception e) {
  19. // 重置response
  20. response.reset();
  21. response.setContentType("application/json");
  22. response.setCharacterEncoding("utf-8");
  23. Map<String, String> map = new HashMap<String, String>();
  24. map.put("status", "failure");
  25. map.put("message", "下载文件失败" + e.getMessage());
  26. response.getWriter().println(JSON.toJSONString(map));
  27. }
  28. }