阿里easyExcel小记

文章目录

  • 前言
  • 一、初识
  • 二、读excel
    • 1.日期、数字或者自定义格式转换
  • 三、写excel
    • 1.图片导出
    • 2.根据模板写入
    • 3.合并单元格
  • 四、填充excel
    • 1.多列表组合填充
  • 总结


前言

之前我们操作excel大多都是用的Apache POI或者JXL,遇到了很多的问题,大多数公司也都自己对其进行封装。easyExcel是阿里开源的项目,将excel的内存占用控制在KB级别,而且绝对不会内存溢出。项目gitHub地址:https://github.com/alibaba/easyexcel


一、初识

比较:
阿里easyExcel小记_第1张图片

  • POI: 当利用POI去读取Excel时,首先会将数据全部加载到内存中,然后返回给调用者,当数据量比较大时,及其容易发生OOM
  • EasyExcel: 与POI 不用的是,EasyExcel主要是采用sax模式一行一行解析,并将一行的解析结果以观察者的模式通知处理,即使数据量较大时也不会发生OOM,以下是其读取数据原理图:
    阿里easyExcel小记_第2张图片

快速使用:引入依赖(这里使用的是2.2.7 ):

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.7</version>
        </dependency>

二、读excel

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

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

三、写excel

1.图片导出

<font color=#999AAA >代码如下(示例):

   /**
     * 图片导出
     * 

* 1. 创建excel对应的实体对象 参照{@link ImageDemoData} *

* 2. 直接写即可 */ @Test public void imageWrite() throws Exception { String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx"; 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://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg")); // 这里演示 // 需要额外放入文字 // 而且需要放入2个图片 // 第一个图片靠左 // 第二个靠右 而且要额外的占用他后面的单元格 WriteCellData<Void> writeCellData = new WriteCellData<>(); imageDemoData.setWriteCellDataFile(writeCellData); // 这里可以设置为 EMPTY 则代表不需要其他数据了 writeCellData.setType(CellDataTypeEnum.STRING); writeCellData.setStringValue("额外的放一些文字"); // 可以放入多个图片 List<ImageData> imageDataList = new ArrayList<>(); ImageData imageData = new ImageData(); imageDataList.add(imageData); writeCellData.setImageDataList(imageDataList); // 放入2进制图片 imageData.setImage(FileUtils.readFileToByteArray(new File(imagePath))); // 图片类型 imageData.setImageType(ImageType.PICTURE_TYPE_PNG); // 上 右 下 左 需要留空 // 这个类似于 css 的 margin // 这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。 imageData.setTop(5); imageData.setRight(40); imageData.setBottom(5); imageData.setLeft(5); // 放入第二个图片 imageData = new ImageData(); imageDataList.add(imageData); writeCellData.setImageDataList(imageDataList); imageData.setImage(FileUtils.readFileToByteArray(new File(imagePath))); imageData.setImageType(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); // 写入数据 EasyExcel.write(fileName, ImageDemoData.class).sheet().doWrite(list); } }

2.根据模板写入

代码如下(示例):

  /**
     * 根据模板写入
     * 

1. 创建excel对应的实体对象 参照{@link IndexData} *

2. 使用{@link ExcelProperty}注解指定写入的列 *

3. 使用withTemplate 写取模板 *

4. 直接写即可 */ @Test public void templateWrite() { String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; String fileName = TestFileUtil.getPath() + "templateWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).withTemplate(templateFileName).sheet().doWrite(data()); }

3.合并单元格

  /**
     * 合并单元格
     * 

* 1. 创建excel对应的实体对象 参照{@link DemoData} {@link DemoMergeData} *

* 2. 创建一个merge策略 并注册 *

* 3. 直接写即可 * * @since 2.2.0-beta1 */ @Test public void mergeWrite() { // 方法1 注解 String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx"; // 在DemoStyleData里面加上ContentLoopMerge注解 // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 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()); }

四、填充excel

1.多列表组合填充

 /**
     * 多列表组合填充填充
     *
     * @since 2.2.0-beta1
     */
    @Test
    public void compositeFill() {
        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        // {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list
        String templateFileName =
            TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "composite.xlsx";

        String fileName = TestFileUtil.getPath() + "compositeFill" + System.currentTimeMillis() + ".xlsx";
        ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
        // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹
        excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
        excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
        excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
        excelWriter.fill(new FillWrapper("data3", data()), writeSheet);

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("date", "2019年10月9日13:28:28");
        excelWriter.fill(map, writeSheet);

        // 别忘记关闭流
        excelWriter.finish();
    }

总结

文章代码参照:
https://www.yuque.com/easyexcel,点击查看更多最佳实践。excel操作在工作中用到的很多,也可以去学习下excel的许多公式应用。我是油条~下期见

你可能感兴趣的:(java,后端)