1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

2021.05.08 easyExcel简单读写

前言

web开发中,我们经常会遇到数据导入或者导出excel的需求,如果用原生的poi(阿帕奇的顶级项目,项目地址:https://poi.apache.org/),虽然能够满足我们的需求,但是原生的接口用起来很不方便,数据格式都需要我们设定,而且它又是基于单元格的操作,在多个数据导出导入的场景下,每个场景都需要定制化的导出入方法,很不方便。

那有没有一个组件,能够根据我们的Vo导出excel,导出的时候,每行一条数据,传入一个lsit就可以实现所有数据的导出;导入的时候,指定vo,然后就可以把excel转成一个volist,方便我们的操作?

easyExcel是什么

有呀,当然有呀,easyExcel就是这样的一个组件,它是由阿里巴巴开发的一个基于Java的简单、省内存的读写Excel的开源组件,在尽可能节约内存的情况下支持读写百MExcel

github地址:https://github.com/alibaba/easyexcel

根据官方文档,该组件有着较好的性能:

接下来,我们就来看下如何在我们自己的项目中快速地使用它。

简单应用

添加依赖

首先需要先引入easyExcel的依赖,目前最新的发布版本是2.2.6

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

创建数据对应的VO

这里用到了lombox,所有就不需要自己创建gettersetter方法,如果你不想用lombox,可以手动创建getter/setter方法。

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

/**
 * @program: example-2021.05.08
 * @description: demoData
 * @author: syske
 * @date: 2021-05-08 18:12
 */
@Data
public class DemoData {
    @ExcelProperty("名称")
    private String name;

    @ExcelProperty("标题")
    private String title;

    @ExcelProperty("描述")
    private String description;
}

核心的点就一个,@ExcelProperty其实就是指定数据的表头,当然也可以通过注解的方式,直接指定表头样式

简单写excel

 public static String writeExcel() {
        String fileName = UUID.randomUUID().toString() + ".xlsx";
     	// 创建ExcelWriterBuilder
        ExcelWriterBuilder write = EasyExcel.write(fileName, DemoData.class);
        // 创建sheet
        ExcelWriterSheetBuilder sheet = write.sheet("模板");
       // 构建数据
        DemoData demoData = new DemoData();
        demoData.setDescription("描述信息");
        demoData.setName("名称");
        demoData.setTitle("标题");
        List<DemoData> dataList = Lists.newArrayList(demoData);
        // 写入数据
        sheet.doWrite(dataList);
        return fileName;
    }

注释已经够详细了,这里再简单解释下,我们先要创建ExcelWriterBuilder,这里要指定生成的excel的完整文件名(包括保存路径)和excel对应的VO;

然后再创建sheet,如果经常用excel的小伙伴应该知道,一个excel可以创建多个sheet,而且sheet的名字必须唯一,这里我们指定的sheet名称是“模板”;

再接着,我们要创建我们要写入的数据,也就是前面VO对应的List

最后,将List的数据写入。

跑一下上面的代码,会生成这样的excel

我们并没有指定表头,但是发现生成的excel是有表头的,而且就是我们前面创建VO指定的ExcelProperty,这也印证了我们前面的说法,当然它也支持自定义表头,我们稍后再看

简单读excel

自定义解析事件监听

相比写,读稍微复杂一点,需要我们自定义一个EventListener,继承AnalysisEventListener就可以了:

public class DemoDataListener extends AnalysisEventListener<DemoData> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    List<DemoData> list = Lists.newArrayList();

    public DemoDataListener() {}


    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
        System.out.println("解析数据:" + JSON.toJSONString(data));
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        LOGGER.info("{}条数据,开始存储数据库!", list.size());
        LOGGER.info("存储数据库成功!");
    }
}

这里其实就相当于excel的解析器,我们只需要重写相应的方法即可。 invoke(DemoData data, AnalysisContext context)方法是每解析一行数据,就会被调用,在这里你可以做数据的校验和转换操作;doAfterAllAnalysed(AnalysisContext context)是所有数据解析完成后进行的操作,类似回调函数,你可以根据自己的业务需求进行修改。

开始读

然后读取的话,就很简单了:

public static void readExcel(String filePath) {
        EasyExcel.read(filePath, DemoData.class, new DemoDataListener()).sheet().doRead();
    }

默认情况下,数据是从第二行开始读取的,第一行默认为表头,当然你也可以通过headRowNumber(Integer headRowNumber)指定从第几行开始读取:

EasyExcel.read(filePath, DemoData.class, new DemoDataListener()).sheet().headRowNumber(0).doRead();

另外,有一点需要注意,就是读取的时候,excel的字段顺序要和VO的字段顺序保持一致,否则会出现串行的问题,当然你也可以通过指定字段顺序的方式解决这个问题,索引顺序从0开始,当然这个index也会影响导出的excel里面的字段顺序。

设定写的样式

设定样式有两种方式,一种是通过代码的方式设定,另一种就是通过注解的方式实现,我们先看第一种方式。

代码设定样式
public static String writeExcel() {
        String fileName = UUID.randomUUID().toString() + ".xlsx";
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为红色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 20);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 设定bord
        headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        headWriteCellStyle.setBorderTop(BorderStyle.THIN);
        headWriteCellStyle.setBorderRight(BorderStyle.THIN);
        headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
        contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        // 背景绿色
        contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
         // 设定边框样式
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 20);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
		// 设定样式
        ExcelWriterBuilder write = EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy);
        ExcelWriterSheetBuilder sheet = write.sheet("模板");
        DemoData demoData = new DemoData();
        demoData.setDescription("描述信息");
        demoData.setName("名称");
        demoData.setTitle("标题");
        List<DemoData> dataList = Lists.newArrayList(demoData);
        sheet.doWrite(dataList);
        return fileName;
    }

代码和上面写的代码一样,只是增加了样式的设定,就是在创建ExcelWriterBuilder的时候,指定样式registerWriteHandler(horizontalCellStyleStrategy)

setFillForegroundColor设定背景颜色,也就是填充颜色;

setFontHeightInPoints设定字体大小;

setWriteFont是设定字体样式;

setBorder是设定边框样式;

然后我们再来看下生成的效果:

但是我发现,这里的样式没法指定列宽,下面我们看下注解的样式是不是可以指定。

注解设定样式

首先我们看下列宽度如何设定,设置方式很简单,只需要在对应的字段上加上ColumnWidth注解即可:

之后的效果如下

然后,我们在通过注解设定其他样式,我在名称上面添加如下注解:

然后生成的效果变成这样了:

代码里面的样式设定也没有删除,说明启用注解之后,代码里面设定的样式就失效了。其中,HeadStyle是设定标题栏样式,HeadFontStyle是设定标题字体字体样式,ContentStyle是设定内容的样式,ContentFontStyle是设置内容的字体样式,样式的内容可以根据自己的需求进行调整,这里就不作过多的说明了。

总结

easyExcel对于列表式的数据导入导出,是特别友好的,而且用起来也特别方便,但是对于不规律的表格(比如票据)poi可能是更好的选择,当然easyExcel本身也是基于poi实现的,只是前者对用户更友好。

简单总结下,今天我们通过几个简单的示例,演示了如何用easyExcel实现数据的导入导出,展示了设置样式的两种方式,可以说上面的这些内容基本上可以满足我们大部分的应用场景,但如果你还有很多其他的业务需求,建议你再去研究下官方文档,更高级的用法还有很多,今天我们算是抛砖引玉了,有兴趣的小伙伴自己去看吧!

好了,今天是母亲节,让我们一起祝所有的母亲节日快乐,当然更重要的是别忘了给自己的妈妈打个电话,给一句问候,一句关心……

项目路径:

https://github.com/Syske/example-everyday

本项目会每日更新,让我们一起学习,一起进步,遇见更好的自己,加油呀

posted @ 2021-05-09 15:36  云中志  阅读(447)  评论(0编辑  收藏  举报