top
本文目录
1. 基本导出
2. 指定字段排序和导出内容
3. 设置复杂头
4. 分页查询数据写入
5. 写入不同sheet
6. 格式转换
7. 写入图片
8. 导出并合并
9. 自定义样式
10. 其他

Java 使用 EasyExcel 导出基本使用方法


共计 7390 个字符,预计需要花费 19 分钟才能阅读完成。

工作中要说用到 excel 的情况说多也不多,说少也不少,但是很多次遇到似乎都要去查一遍 EasyExcel 的用法,所以这里把经常用到的注解记录一下。

1. 基本导出

1.1 指定标题

常规导出情况下,只需要指定单元格头部标题,和忽略部分字段即可。

public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

1.2 指定行高和列宽

行高和列宽可以先对所有字段统一设置,再根据每个字段具体调整。

// 指定头部行高、内容行高和宽度
@HeadRowHeight(20)
@ContentRowHeight(10)
@ColumnWidth(25)
public class WidthAndHeightData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    /**
     * 宽度为50
     */
    @ColumnWidth(50)
    @ExcelProperty("数字标题")
    private Double doubleData;
}

2. 指定字段排序和导出内容

2.1 指定字段排序

可以设置 index 或者 order 来指定字段所在的列。

@ExcelProperty(value = "字符串标题", index = 0)
private String string;
// 使用 order 的好处是,当排除字段时不会出现空行
@ExcelProperty(value = "字符串标题", order = 0)
private String string;

2.2 指定导出字段

// 根据用户传入字段 假设我们只要导出 date
Set<String> includeColumnFieldNames = new HashSet<>();
includeColumnFieldNames.add("date");
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).includeColumnFieldNames(includeColumnFieldNames).sheet("模板")
    .doWrite(data());

2.3 指定排除字段

// 根据用户传入字段 假设我们要忽略 date
Set<String> excludeColumnFieldNames = new HashSet<>();
excludeColumnFieldNames.add("date");
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).excludeColumnFieldNames(excludeColumnFieldNames).sheet("模板")
    .doWrite(data());

3. 设置复杂头

通过对单元格头部设置多个标题来实现复杂头。

@ExcelProperty({"主标题", "字符串标题"})
private String string;
@ExcelProperty({"主标题", "日期标题"})
private Date date;
@ExcelProperty({"主标题", "数字标题"})
private Double doubleData;

通过对所有字段设置相同的标题可以将单元格合并,如果想要设置更复杂的头部,参考示例:

@ExcelProperty({"顶格", "顶格", "两格"})
private String string0;
@ExcelProperty({"顶格", "顶格", "两格"})
private String string1;
@ExcelProperty({"顶格", "四联", "四联"})
private String string2;
@ExcelProperty({"顶格", "四联", "四联"})
private String string3;
@ExcelProperty({"顶格"})

结果如下:

Java 使用 EasyExcel 导出基本使用方法

/>

4. 分页查询数据写入

数据量太大的情况下,可以考虑分页查询数据,然后再多次写入。

try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
    // 这里注意 如果同一个sheet只要创建一次
    WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
    // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
    for (int i = 0; i < 5; i++) {
        // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
        List<DemoData> data = data();
        excelWriter.write(data, writeSheet);
    }
}

5. 写入不同sheet

写入不同 sheet 也是一个很常见的功能需求,比如导出员工数据时根据部分进行划分 sheet。

5.1 写入相同的对象


try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
    // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
    for (int i = 0; i < 5; i++) {
        // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
        WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
        // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
        List<DemoData> data = data();
        excelWriter.write(data, writeSheet);
    }
}

5.2 写入不同的对象

try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {
    // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
    for (int i = 0; i < 5; i++) {
        // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class
        // 实际上可以一直变
        WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();
        // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
        List<DemoData> data = data();
        excelWriter.write(data, writeSheet);
    }
}

6. 格式转换

EasyExcel 提供对常用的日期、数字转换的注解,同时也提供了自定义格式转换器。

public class ConverterData {
    /**
     * 我自定义 转换器,不管数据库传过来什么 。我给他加上“自定义:”
     */
    @ExcelProperty(converter = CustomStringStringConverter.class)
    private String string;
    /**
     * 这里用string 去接日期才能格式化。我想接收年月日格式
     */
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    private String date;
    /**
     * 我想接收百分比的数字
     */
    @NumberFormat("#.##%")
    private String doubleData;
}

其实大部分情况下还是需要格式转换器来转换,比如员工性别,数据库的数据是 0 和 1,需要将其转换问男和女。

下面是 EasyExcel 提供的一个示例:

public class CustomStringStringConverter implements Converter<String> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * 这里读的时候会调用
     *
     * @param context
     * @return
     */
    @Override
    public String convertToJavaData(ReadConverterContext<?> context) {
        return "自定义:" + context.getReadCellData().getStringValue();
    }

    /**
     * 这里是写的时候会调用 不用管
     *
     * @return
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
        return new WriteCellData<>(context.getValue());
    }
}

7. 写入图片

可以通过多种方式写入图片,比如 url,file 对象,Stream 流。

String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg";
try (InputStream inputStream = FileUtils.openInputStream(new File(imagePath))) {
    List<ImageDemoData> list = ListUtils.newArrayList();
    ImageDemoData imageDemoData = new ImageDemoData();
    list.add(imageDemoData);
    // 放入五种类型的图片 实际使用只要选一种即可
    imageDemoData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));
    imageDemoData.setFile(new File(imagePath));
    imageDemoData.setString(imagePath);
    imageDemoData.setInputStream(inputStream);
    imageDemoData.setUrl(new URL(
        "https://www.qcyqq.com/wp-content/uploads/2023/04/f09d57b823cf06b3d50fba052e21baf.png"));
    // 写入数据
    EasyExcel.write(fileName, ImageDemoData.class).sheet().doWrite(list);
}

其中 ImageDemoData.java 类如下:

@Getter
@Setter
@EqualsAndHashCode
@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;
}

可以看见 string 使用了 StringImageConverter 转换器,这个转换器将给定的路径读取文件,然后再进行写入。

public class StringImageConverter implements Converter<String> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public WriteCellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) throws IOException {
        return new WriteCellData<>(FileUtils.readFileToByteArray(new File(value)));
    }
}

8. 导出并合并

可能会遇到这种情况,某些字段导出的内容也需要进行合并。

public void mergeWrite() {
    // 方法1 注解
    String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
    // 在DemoStyleData里面加上ContentLoopMerge注解
    EasyExcel.write(fileName, DemoMergeData.class).sheet("模板").doWrite(data());

    // 方法2 自定义合并单元格策略
    fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
    // 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写
    LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板").doWrite(data());
}

其中 DemoMergeData 类如下:

public class DemoMergeData {
    // 这一列 每隔2行 合并单元格
    @ContentLoopMerge(eachRow = 2)
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
}

9. 自定义样式

自定义样式可以自定义单元格的背景,单元格的文字大小等等。

// 头背景设置成红色 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;
}

10. 其他

其他比如生成动态头部、插入超链接、拦截器形式自定义样式等等,更多内容参考:https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write

提醒:本文发布于514天前,文中所关联的信息可能已发生改变,请知悉!

Tips:清朝云网络工作室

阅读剩余
THE END
icon
0
icon
分享
icon
二维码
icon
海报
发表评论
评论列表

赶快来坐沙发

您好,今天过得怎么样?