Featured image of post 【合集】EasyExcel-写出excel

【合集】EasyExcel-写出excel

相关文章

EasyExcel官网

【合集】EasyExcel-读取excel

【合集】EasyPOI-写出excel

【合集】EasyPOI-读取excel

依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>4.0.1</version>
</dependency>

Spring-Web写

常规写出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.util.MapUtils;

/**
 ** easyExcel框架导出excel
 */
@SneakyThrows
private void easyExcelExportExcel(HttpServletResponse response, List<DemoVO> demoVoList) {
    // 构建excel对象数据
    List<WriteVo> excelList = Optional.ofNullable(demoVoList).orElse(new ArrayList<>())
            .stream()
            .map(s -> {
                WriteVo excel = new WriteVo();
                BeanUtils.copyProperties(s, excel);
                return excel;
            })
            .collect(Collectors.toList());
    // 构建response
    response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode("fileName", StandardCharsets.UTF_8)
            .replaceAll("\\+", "%20")
            .replaceAll("%2F", "/")

            + ".xlsx");
    response.setContentType("application/vnd.ms-excel"); // application/json application/pdf
    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
    // 构建head
    List<List<String>> head = new ArrayList<>();
    List<String> headRow1 = new ArrayList<>();
    headRow1.add("姓名");
    headRow1.add("年龄");
    headRow1.add("性别");
    head.add(headRow1);
    // 写数据
    EasyExcel.write(response.getOutputStream(), User.class)
            .sheet("sheetName")
            .head(head)
            .doWrite(excelList);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@ContentRowHeight(10)
@HeadRowHeight(20)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WriteVo {

    @ExcelProperty(value = "主键")
    @ColumnWidth(20)
    private Long id;

    @ExcelProperty(value = "开始日")
    @ColumnWidth(20)
    @DateTimeFormat("yyyy-MM-dd")
    private LocalDate startDate;

    @ExcelProperty(value = "开始时间")
    @ColumnWidth(20)
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private LocalDateTime startTime;

    @ExcelProperty(value = "换电模式*")
    @ColumnWidth(20)
    private String swapMode;

}

写出-如果失败返回json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.util.MapUtils;

/**
 * easyExcel框架导出excel, 如果失败了,返回json格式的错误信息
 */
@SneakyThrows
private void easyExcelExportExcelIfErrorReturnJson(HttpServletResponse response, List<DemoVO> demoVoList) {
    // 构建excel对象数据
    List<WriteVo> excelList2 = Optional.ofNullable(demoVoList).orElse(new ArrayList<>())
            .stream()
            .map(s -> {
                WriteVo excel = new WriteVo();
                BeanUtils.copyProperties(s, excel);
                return excel;
            })
            .collect(Collectors.toList());
    try {
        // 构建response
        response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode("fileName",
                        StandardCharsets.UTF_8)
                .replaceAll("\\+", "%20")
                .replaceAll("%2F", "/")
                + ".xlsx");
        response.setContentType("application/vnd.ms-excel"); // application/json application/pdf
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        // 构建head
        List<List<String>> head = new ArrayList<>();
        List<String> headRow1 = new ArrayList<>();
        headRow1.add("姓名");
        headRow1.add("年龄");
        headRow1.add("性别");
        head.add(headRow1);
        // 写数据
        EasyExcel.write(response.getOutputStream(), WriteVo.class)
                .autoCloseStream(Boolean.FALSE) // 这里需要设置不关闭流
                .sheet("sheetName")
                .head(head)
                .doWrite(excelList2);
    } catch (Exception e) {
        response.reset(); // 重置response
        response.setContentType("application/json");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        Map<String, String> map = MapUtils.newHashMap();
        map.put("status", "failure");
        map.put("message", "下载文件失败" + e.getMessage());
        response.getWriter().println(new ObjectMapper().writeValueAsString(map));
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@ContentRowHeight(10)
@HeadRowHeight(20)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WriteVo {

    @ExcelProperty(value = "主键")
    @ColumnWidth(20)
    private Long id;

    @ExcelProperty(value = "开始日")
    @ColumnWidth(20)
    @DateTimeFormat("yyyy-MM-dd")
    private LocalDate startDate;

    @ExcelProperty(value = "开始时间")
    @ColumnWidth(20)
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private LocalDateTime startTime;

    @ExcelProperty(value = "换电模式*")
    @ColumnWidth(20)
    private String swapMode;

}

本文excel文件生成路径

img.png

简单写

效果:

img_1.png

1
2
3
4
5
6
7
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 简单写出
// 5000以内使用,量大参考重复多次写入
EasyExcel.write(out, DemoData.class)
        .sheet("sheet名称")
        .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;

    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList {
    List<DemoData> list = ListUtils.newArrayList();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setName("字符串" + i);
        data.setStartDateTime(new Date());
        data.setScore(0.56);
        list.add(data);
    }
    return list;
}

复杂头写入

效果:

img_2.png

1
2
3
4
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 复杂头写入
EasyExcel.write(out, WriteComplexHeadExcelBO.class).sheet("sheet名称").doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Data
public class WriteComplexHeadExcelBO {

    @ExcelProperty({"主标题", "字符串标题"})
    private String string;

    @ExcelProperty({"主标题", "日期标题"})
    private Date date;

    @ExcelProperty({"主标题", "数字标题"})
    private Double doubleData;

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<WriteComplexHeadExcelBO> dataList() {
    List<WriteComplexHeadExcelBO> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        WriteComplexHeadExcelBO data = new WriteComplexHeadExcelBO();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

日期转换、数字转换、自定义转换器

效果

img_3.png

1
2
3
4
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 日期、数字或者自定义格式转换
EasyExcel.write(out, ConverterData.class).sheet("sheet名称").doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Data
public class ConverterData {
    /**
     * CustomStringStringConverter转换器,在写入写出时转换
     */
    @ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class)
    private String string;

    /**
     * 我想写到excel 用年月日的格式
     */
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date date;

    /**
     * 我想写到excel 用百分比表示
     */
    @NumberFormat("#.##%")
    @ExcelProperty(value = "数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class CustomStringStringConverter implements Converter<String> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
    @Override
    public String convertToJavaData(ReadConverterContext<?> context) {
        return "从excel读取数据加前缀:" + context.getReadCellData().getStringValue();
    }
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
        return new WriteCellData<>("写出到excel加前缀:" + context.getValue());
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<ConverterData> dataList() {
    List<ConverterData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        ConverterData data = new ConverterData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

根据参数只导出指定列

效果

img_4.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 忽略部分字段
Set<String> exclude = new HashSet<>();
exclude.add("date");

// 只取部分字段
Set<String> include = new HashSet<>();
include.add("doubleData");

// 根据参数只导出指定列
EasyExcel.write(out, DemoData.class)
        .excludeColumnFieldNames(exclude) // 忽略部分字段
        .includeColumnFieldNames(include) // 只取部分字段
        .sheet("sheet名称")
        .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

指定写入的列

效果

img_5.png

1
2
3
4
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 指定写入的列
EasyExcel.write(out, IndexData.class).sheet("模板").doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Data
public class IndexData {
    @ExcelProperty(value = "字符串标题", index = 0)
    private String string;

    @ExcelProperty(value = "日期标题", index = 1)
    private Date date;

    /**
     * 这里设置3 会导致第二列空的
     */
    @ExcelProperty(value = "数字标题", index = 3)
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<IndexData> dataList() {
    List<IndexData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        IndexData data = new IndexData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

重复多次写入

方法1: 同一个sheet + 同一个对象

效果

img_6.png

1
2
3
4
5
6
7
8
9
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法1: 同一个sheet + 同一个对象
try (ExcelWriter excelWriter = EasyExcel.write(out, DemoData.class).build()) {
    WriteSheet writeSheet = EasyExcel.writerSheet("sheet名称").build();
    for (int i = 0; i < 5; i++) {
        excelWriter.write(dataList(), writeSheet);
   }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

方法2: 不同sheet + 同一个对象

效果

img_7.png

1
2
3
4
5
6
7
8
9
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法2: 不同sheet + 同一个对象
try (ExcelWriter excelWriter = EasyExcel.write(out, DemoData.class).build()) {
    for (int i = 0; i < 5; i++) {
        WriteSheet writeSheet = EasyExcel.writerSheet(i, "sheet名称" + i).build();
        excelWriter.write(dataList(), writeSheet);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

方法3 不同sheet + 不同对象(head控制对象)

效果

img_8.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法3 不同sheet + 不同对象 head控制对象
try (ExcelWriter excelWriter = EasyExcel.write(out, DemoData.class).build()) {
    for (int i = 0; i < 5; i++) {
        // DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class。
        WriteSheet writeSheet = EasyExcel.writerSheet(i, "sheet名称" + i)
                .head(DemoData.class).build();
        excelWriter.write(dataList(), writeSheet);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

注解形式设置每个单元格样式

效果

img_9.png

1
2
3
4
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 注解形式设置每个单元格样式
EasyExcel.write(out, DemoStyleDataBO.class).sheet("模板").doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * 样式的数据类 
 * 如果版本问题导致FillPatternTypeEnum不存在,则替换成FillPatternType
 **/
@Data
// 头背景设置成红色 IndexedColors.RED.getIndex()
@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 10)
// 头字体设置成20
@HeadFontStyle(fontHeightInPoints = 20)
// 内容的背景设置成绿色 IndexedColors.GREEN.getIndex()
@ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 17)
// 内容字体设置成20
@ContentFontStyle(fontHeightInPoints = 20)
public class DemoStyleData {
    // 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()
    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 14)
    // 字符串的头字体设置成20
    @HeadFontStyle(fontHeightInPoints = 30)
    // 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()
    @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    // 字符串的内容字体设置成20
    @ContentFontStyle(fontHeightInPoints = 30)
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoStyleData> dataList() {
    List<DemoStyleData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoStyleData data = new DemoStyleData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

代码设置单个单元格样式:超链接、备注、公式

效果

img_10.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 代码设置单个单元格样式:超链接、备注、公式
WriteCellDemoData cellExcel = new WriteCellDemoData();

// 1. 设置超链接
WriteCellData<String> hyperlink = new WriteCellData<>("官方网站");
HyperlinkData hyperlinkData = new HyperlinkData();
hyperlinkData.setAddress("https://github.com/alibaba/easyexcel");
hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);
hyperlink.setHyperlinkData(hyperlinkData);
cellExcel.setHyperlink(hyperlink);

// 2. 设置批注
WriteCellData<String> comment = new WriteCellData<>("备注的单元格信息");
CommentData commentData = new CommentData();
commentData.setAuthor("Jiaju Zhuang");
commentData.setRichTextStringData(new RichTextStringData("这是一个备注"));
// 批注的默认单元格大小 这里想调整到4个单元格那么大 所以向后 向下 各额外占用了一个单元格
commentData.setRelativeLastColumnIndex(1);
commentData.setRelativeLastRowIndex(1);
comment.setCommentData(commentData);
cellExcel.setCommentData(comment);

// 3. 设置公式
WriteCellData<String> formula = new WriteCellData<>();
FormulaData formulaData = new FormulaData();
// 将 123456789 中的第一个数字替换成 2
// 这里只是例子 如果真的涉及到公式 能内存算好尽量内存算好 公式能不用尽量不用
formulaData.setFormulaValue("REPLACE(123456789,1,1,2)");
formula.setFormulaData(formulaData);
cellExcel.setFormulaData(formula);

// 4. 设置单个单元格的样式 当然样式 很多的话 也可以用注解等方式。
WriteCellData<String> writeCellStyle = new WriteCellData<>("单元格样式");
WriteCellStyle writeCellStyleData = new WriteCellStyle();
writeCellStyleData.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.
writeCellStyleData.setFillForegroundColor(IndexedColors.GREEN.getIndex()); // 背景绿色
writeCellStyle.setWriteCellStyle(writeCellStyleData);
writeCellStyle.setType(CellDataTypeEnum.STRING);
cellExcel.setWriteCellStyle(writeCellStyle);

// 5. 设置单个单元格多种样式 这里需要设置 inMomery=true 不然会导致无法展示单个单元格多种样式,所以慎用
WriteCellData<String> richTest = new WriteCellData<>();
RichTextStringData richTextStringData = new RichTextStringData();
richTextStringData.setTextString("红色绿色默认");
// 前2个字红色
WriteFont writeFont = new WriteFont();
writeFont.setColor(IndexedColors.RED.getIndex());
richTextStringData.applyFont(0, 2, writeFont);
// 接下来2个字绿色
writeFont = new WriteFont();
writeFont.setColor(IndexedColors.GREEN.getIndex());
richTextStringData.applyFont(2, 4, writeFont);
richTest.setRichTextStringDataValue(richTextStringData);
richTest.setType(CellDataTypeEnum.RICH_TEXT_STRING);
cellExcel.setRichText(richTest);
List<WriteCellDemoData> list = new ArrayList<>();
list.add(cellExcel);

EasyExcel.write(out, WriteCellDemoData.class).inMemory(true).sheet("模板").doWrite(list);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Data
public class WriteCellDemoData {

    /**
     * 超链接
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> hyperlink;

    /**
     * 备注
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> commentData;

    /**
     * 公式
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> formulaData;

    /**
     * 指定单元格的样式。当然样式 也可以用注解等方式。
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> writeCellStyle;

    /**
     * 指定一个单元格有多个样式
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> richText;
}

图片导出到excel

效果

img_11.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";
String urlStr = AllTest.class.getResource("/").getPath() + "easyExcel" + File.separator + "converter" + File.separator + "img.jpg";
File file = new File(urlStr);
URL url;
try {
    url = new URL("https://easyexcel.opensource.alibaba.com/img/logo.png");
} catch (MalformedURLException e) {
    log.error("图片地址异常", e);
    throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "图片地址异常", e);
}
byte[] byteArray;
try {
    byteArray = FileUtils.readFileToByteArray(file);
} catch (IOException e) {
    log.error("文件转字节数组异常", e);
    throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "文件转字节数组异常", e);
}

// 图片导出
// 这里注意下 所有的图片都会放到内存 暂时没有很好的解法,大量图片的情况下建议 2选1:
// 1. 将图片上传到oss 或者其他存储网站: https://www.aliyun.com/product/oss ,然后直接放链接
// 2. 使用: https://github.com/coobird/thumbnailator 或者其他工具压缩图片
try (InputStream inputStream = FileUtils.openInputStream(file)) {
    ImageDemoData imageDemoData = new ImageDemoData();
    // 放入五种类型的图片 实际使用只要选一种即可
    imageDemoData.setByteArray(byteArray);
    imageDemoData.setFile(file);
    imageDemoData.setString(urlStr);
    imageDemoData.setInputStream(inputStream);
    imageDemoData.setUrl(url);

    // 最后一个单元格放入:文字+2张图片
    // 1. 放入文字
    WriteCellData<Void> writeCellData = new WriteCellData<>();
    writeCellData.setType(CellDataTypeEnum.STRING); // 这里可以设置为 EMPTY 则代表不需要其他数据了
    writeCellData.setStringValue("额外的放一些文字");
    // 2. 放入多个图片
    List<ImageData> imageDataList = new ArrayList<>();
    // 2.1 第1张
    ImageData imageData = new ImageData();
    imageData.setImage(byteArray);  // 放入2进制图片
    imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG); // 图片类型
    imageData.setTop(5); // 图片上边距 这个类似于 css 的 margin 这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。
    imageData.setRight(40); //
    imageData.setBottom(5);
    imageData.setLeft(5);
    imageDataList.add(imageData);
    writeCellData.setImageDataList(imageDataList);
    // 2.2第2张
    imageData = new ImageData();
    imageData.setImage(byteArray);
    imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
    imageData.setTop(5);
    imageData.setRight(5);
    imageData.setBottom(5);
    imageData.setLeft(50);
    // 设置图片的位置 假设 现在目标 是 覆盖 当前单元格 和当前单元格右边的单元格
    // 起点相对于当前单元格为0 当然可以不写
    imageData.setRelativeFirstRowIndex(0);
    imageData.setRelativeFirstColumnIndex(0);
    imageData.setRelativeLastRowIndex(0);
    // 前面3个可以不写  下面这个需要写 也就是 结尾 需要相对当前单元格 往右移动一格
    // 也就是说 这个图片会覆盖当前单元格和 后面的那一格
    imageData.setRelativeLastColumnIndex(1);
    imageDataList.add(imageData);
    writeCellData.setImageDataList(imageDataList);
    imageDemoData.setWriteCellDataFile(writeCellData);

    List<ImageDemoData> imageExcels = new ArrayList<>();
    imageExcels.add(imageDemoData);
    EasyExcel.write(out, ImageDemoData.class)
              .sheet()
              .doWrite(imageExcels);
} catch (IOException e) {
    log.error("图片文档导出失败", e);
    throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "图片文档导出失败", e);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 * 图片导出类
 */
@Data
@ContentRowHeight(100)
@ColumnWidth(100 / 8)
public class ImageDemoData {

    private File file;

    private InputStream inputStream;

    /**
     * 如果string类型 必须指定转换器,string默认转换成string
     */
    @ExcelProperty(converter = StringImageConverter.class)
    private String string;

    private byte[] byteArray;

    /**
     * 根据url导出
     *
     * @since 2.1.1
     */
    private URL url;

    /**
     * 根据文件导出 并设置导出的位置。
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<Void> writeCellDataFile;
}

根据模板写入

模版

img_12.png

写出的文件

img_13.png

1
2
3
4
5
6
7
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";
String template = easyExcel_write.class.getResource("/").getPath() + "easyExcel" + File.separator + "demo.xlsx";

// 根据模板写入
// 模板文件会全量存内存里面,所以尽量不要用于追加文件,文件模板文件过大会OOM
// 如果要再文件中追加(无法在一个线程里面处理,可以在一个线程的建议参照多次写入的demo) 建议临时存储到数据库 或者 磁盘缓存(ehcache) 然后再一次性写入
EasyExcel.write(out, DemoData.class).withTemplate(template).sheet().doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

拦截器形式自定义样式

方法1 使用已有的策略 推荐

效果

img_14.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法1 使用已有的策略 推荐
// 头的策略
WriteCellStyle head = new WriteCellStyle();
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short) 20);
head.setWriteFont(headWriteFont);
head.setFillForegroundColor(IndexedColors.RED.getIndex()); // 背景设置为红色

// 内容的策略
WriteCellStyle content = new WriteCellStyle();
WriteFont writeFont1 = new WriteFont();
writeFont1.setFontHeightInPoints((short) 20); // 字体大小
content.setWriteFont(writeFont1);
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
content.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
content.setFillForegroundColor(IndexedColors.GREEN.getIndex()); // 背景绿色

// 两种策略
// 1. HorizontalCellStyleStrategy 每一行的样式都一样 或者隔行一样
// 2. AbstractVerticalCellStyleStrategy 每一列的样式都一样 需要自己回调每一页
HorizontalCellStyleStrategy strategy = new HorizontalCellStyleStrategy(head, content);

EasyExcel.write(out, DemoData.class)
        .registerWriteHandler(strategy)
        .sheet("sheet名称")
        .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

方法2: 使用easy excel的方式完全自己写 不太推荐 尽量使用已有策略

效果

img_15.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法2: 使用easyexcel的方式完全自己写 不太推荐 尽量使用已有策略
// @since 3.0.0-beta2
CellWriteHandler cellWriteHandler = new CellWriteHandler() {
    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        // 当前事件会在 数据设置到poi的cell里面才会回调
        // 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true
        if (BooleanUtils.isNotTrue(context.getHead())) {
            // 第一个单元格
            // 只要不是头 一定会有数据 当然fill的情况 可能要context.getCellDataList() ,这个需要看模板,因为一个单元格会有多个 WriteCellData
            WriteCellData<?> cellData = context.getFirstCellData();
            // 这里需要去cellData 获取样式
            // 很重要的一个原因是 WriteCellStyle 和 dataFormatData绑定的 简单的说 比如你加了 DateTimeFormat
            // ,已经将writeCellStyle里面的dataFormatData 改了 如果你自己new了一个WriteCellStyle,可能注解的样式就失效了
            // 然后 getOrCreateStyle 用于返回一个样式,如果为空,则创建一个后返回
            WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
            writeCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
            writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            // 这样样式就设置好了 后面有个FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到 cell里面去 所以可以不用管了
        }
    }
};
EasyExcel.write(out, ReadExcelBO.class)
        .registerWriteHandler(cellWriteHandler)
        .sheet("sheet名称").doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

方法3: 使用 poi的样式完全自己写 不推荐

效果

img_16.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法3: 使用poi的样式完全自己写 不推荐
// @since 3.0.0-beta2
// 坑1:style里面有dataformat 用来格式化数据的 所以自己设置可能导致格式化注解不生效
// 坑2:不要一直去创建style 记得缓存起来 最多创建6W个就挂了
CellWriteHandler cellWriteHandler = new CellWriteHandler() {
    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        // 当前事件会在 数据设置到poi的cell里面才会回调
        // 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true
        if (BooleanUtils.isNotTrue(context.getHead())) {
            Cell cell = context.getCell();
            // 拿到poi的workbook
            Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
            // 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式
            // 不同单元格尽量传同一个 cellStyle
            CellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            cell.setCellStyle(cellStyle);

            // 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确

            // 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到
            // cell里面去 会导致自己设置的不一样
            context.getFirstCellData().setWriteCellStyle(null);
        }
    }
};
EasyExcel.write(out, ReadExcelBO.class)
        .registerWriteHandler(cellWriteHandler)
      .sheet("sheet名称").doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

合并单元格

方法1:通过ContentLoopMerge注解

效果

img_17.png

1
2
3
4
5
6
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法1 注解
EasyExcel.write(out, DemoMergeData.class)
          .sheet("sheet名称")
          .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Data
// 将第6-7行的2-3列合并成一个单元格
// @OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
public class DemoMergeData {
    // 这一列 每隔2行 合并单元格
    @ContentLoopMerge(eachRow = 2)
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoMergeData> dataList() {
    List<DemoMergeData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoMergeData data = new DemoMergeData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

方法2:自定义合并单元格策略LoopMergeStrategy

效果

img_18.png

1
2
3
4
5
6
7
8
9
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 方法2 自定义合并单元格策略
// 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写
LoopMergeStrategy lms = new LoopMergeStrategy(2, 0);
EasyExcel.write(out, DemoData.class)
        .registerWriteHandler(lms)
        .sheet("sheet名称")
        .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoMergeData> dataList() {
    List<DemoMergeData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoMergeData data = new DemoMergeData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

使用table去写入(多个表数据在一个sheet内)

效果

img_19.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 使用table去写入
// 方法1 这里直接写多个table的案例了,如果只有一个,也可以直一行代码搞定,参照其他案例
try (ExcelWriter excelWriter = EasyExcel.write(out, DemoData.class).build()) {
    // 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
    WriteSheet writeSheet = EasyExcel.writerSheet("sheet名称").needHead(Boolean.FALSE).build();

    // 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
    WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.TRUE).build();
    WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();

    // 第一次写入会创建头
    excelWriter.write(dataList(), writeSheet, writeTable0);
    // 第二次写入也会创建头,然后在第一次的后面写入数据
    excelWriter.write(dataList(), writeSheet, writeTable1);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

动态头,实时生成头写入

效果

img_20.png

1
2
3
4
5
6
7
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

EasyExcel.write(out)
          // 这里放入动态头
          .head(headList())
          .sheet("sheet名称")
          .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
private static List<List<String>> headList() {
    List<List<String>> list = new ArrayList<>();

    List<String> head0 = new ArrayList<>();
    head0.add("字符串" + System.currentTimeMillis());

    List<String> head1 = new ArrayList<>();
    head1.add("数字" + System.currentTimeMillis());

    List<String> head2 = new ArrayList<>();
    head2.add("日期" + System.currentTimeMillis());

    list.add(head0);
    list.add(head1);
    list.add(head2);

    return list;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

自动列宽(不太精确)

效果

img_21.png

这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照 LongestMatchColumnWidthStyleStrategy 重新实现.

poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。

1
2
3
4
5
6
7
8
9
String out = AllTest.class.getResource("/").getPath() + "out" 
        + File.separator + System.currentTimeMillis() + ".xlsx";

LongestMatchColumnWidthStyleStrategy longestMatchColumnWidthStyleStrategy = 
        new LongestMatchColumnWidthStyleStrategy();
EasyExcel.write(out, LongestMatchColumnWidthData.class)
        .registerWriteHandler(longestMatchColumnWidthStyleStrategy)
        .sheet("sheet名称")
        .doWrite(dataLong());
1
2
3
4
5
6
7
8
9
@Data
public class LongestMatchColumnWidthData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题很长日期标题很长日期标题很长很长")
    private Date date;
    @ExcelProperty("数字")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<LongestMatchColumnWidthData> dataLong() {
    List<LongestMatchColumnWidthData> list = ListUtils.newArrayList();
    for (int i = 0; i < 10; i++) {
        LongestMatchColumnWidthData data = new LongestMatchColumnWidthData();
        data.setString("测试很长的字符串测试很长的字符串测试很长的字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(1000000000000.0);
        list.add(data);
    }
    return list;
}

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

demo这里实现2点

  1. 对第一行第一列的头超链接到:https://github.com/alibaba/easy excel

  2. 对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2

效果

img_22.png

img_23.png

1
2
3
4
5
6
7
8
String out = AllTest.class.getResource("/").getPath() + "out" 
        + File.separator + System.currentTimeMillis() + ".xlsx";

EasyExcel.write(out, DemoData.class)
          .registerWriteHandler(new CustomSheetWriteHandler())
          .registerWriteHandler(new CustomCellWriteHandler())
          .sheet("sheet名称")
          .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 自定义拦截器.对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2
 */
@Slf4j
public class CustomSheetWriteHandler implements SheetWriteHandler {

    @Override
    public void afterSheetCreate(SheetWriteHandlerContext context) {
        log.info("第{}个Sheet写入成功。", context.getWriteSheetHolder().getSheetNo());

        // 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
        CellRangeAddressList cellRangeAddressList = 
                new CellRangeAddressList(1, 2, 0, 0);
        DataValidationHelper helper = context.getWriteSheetHolder()
                .getSheet().getDataValidationHelper();
        DataValidationConstraint constraint = helper
                .createExplicitListConstraint(new String[]{"测试1", "测试2"});
        DataValidation dataValidation = helper
                .createValidation(constraint, cellRangeAddressList);
        context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);
    }

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * 自定义拦截器。对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel
 */
@Slf4j
public class CustomCellWriteHandler implements CellWriteHandler {

    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        Cell cell = context.getCell();
        // 这里可以对cell进行任何操作
        log.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
        if (BooleanUtils.isTrue(context.getHead()) && cell.getColumnIndex() == 0) {
            CreationHelper createHelper = context.getWriteSheetHolder()
                    .getSheet().getWorkbook().getCreationHelper();
            Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);
            hyperlink.setAddress("https://github.com/alibaba/easyexcel");
            cell.setHyperlink(hyperlink);
        }
    }

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

插入批注

效果

img_24.png

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 插入批注
// 这里要注意inMemory 要设置为true,才能支持批注。目前没有好的办法解决 不在内存处理批注。这个需要自己选择。
CommentWriteHandler commentWriteHandler = new CommentWriteHandler();
EasyExcel.write(out, DemoData.class)
        .inMemory(Boolean.TRUE)
        .registerWriteHandler(commentWriteHandler)
        .sheet("sheet名称")
        .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * 自定义拦截器.新增注释,第一行头加批注
 */
@Slf4j
public class CommentWriteHandler implements RowWriteHandler {

    @Override
    public void afterRowDispose(RowWriteHandlerContext context) {
        if (BooleanUtils.isTrue(context.getHead())) {
            Sheet sheet = context.getWriteSheetHolder().getSheet();
            Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
            // 在第一行 第二列创建一个批注
            Comment comment = drawingPatriarch
                    .createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) 1, 0, (short) 2, 1));
            // 输入批注信息
            comment.setString(new XSSFRichTextString("创建批注!"));
            // 将批注添加到单元格对象中
            sheet.getRow(0).getCell(1).setCellComment(comment);
        }
    }

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

可变标题处理(包括标题国际化等)

效果

img_25.png

1
2
3
4
5
6
7
8
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 可变标题处理(包括标题国际化等)
// 简单的说用List<List<String>>的标题 但是还支持注解
EasyExcel.write(out, DemoData.class)
        .head(variableTitleHead())
        .sheet("sheet名称")
        .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
private static List<List<String>> variableTitleHead() {
    List<List<String>> list = new ArrayList<>();

    List<String> head0 = new ArrayList<>();
    head0.add("string" + System.currentTimeMillis());

    List<String> head1 = new ArrayList<>();
    head1.add("number" + System.currentTimeMillis());

    List<String> head2 = new ArrayList<>();
    head2.add("date" + System.currentTimeMillis());

    list.add(head0);
    list.add(head1);
    list.add(head2);

    return list;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

不创建对象的写

效果

img_26.png

1
2
3
4
5
6
7
String out = AllTest.class.getResource("/").getPath() + "out" + File.separator + System.currentTimeMillis() + ".xlsx";

// 不创建对象的写
EasyExcel.write(out)
        .head(headList())
        .sheet("sheet名称")
        .doWrite(dataList());
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;

    @ExcelProperty("日期标题")
    private Date date;

    @ExcelProperty("数字标题")
    private Double doubleData;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
private static List<List<String>> headList() {
    List<List<String>> list = new ArrayList<>();

    List<String> head0 = new ArrayList<>();
    head0.add("字符串" + System.currentTimeMillis());

    List<String> head1 = new ArrayList<>();
    head1.add("数字" + System.currentTimeMillis());

    List<String> head2 = new ArrayList<>();
    head2.add("日期" + System.currentTimeMillis());

    list.add(head0);
    list.add(head1);
    list.add(head2);

    return list;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private static List<DemoData> dataList() {
    List<DemoData> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}
皖ICP备2024056275号-1
发表了78篇文章 · 总计148.99k字
本站已稳定运行