zoukankan      html  css  js  c++  java
  • 阿里巴巴EasyExcel使用(1)-简单写数据

    一、说明

    最近公司开发一个财务使用的系统,报表比较多。 以前用过POI,JXL,也遇到过OOM问题, 所以学习一下阿里的Excel工具:https://github.com/alibaba/easyexcel

    开发中主要用到:

    ① 简单数据导出,也就是查询实体导出(这里一般会自定义导出某些字段)

    ②自定义单元格样式,比如高亮显示"小计","总计"行等

    ③合并单元格

    那就先来试试简单数据导出吧

    、pom引入

    从官方文档上,目前版本2.2.0-beta1,那我们随便选一个2.X的版本,网上资料一般是1.1.1版本的,1.X和2.X版本个人感觉差别是有点大的~~

     <!-- 阿里开源EXCEL -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <!-- <version>1.1.1</version>-->
                <version>2.1.6</version>
            </dependency>
    

    三、准备工作

    这里准备两个实体,一个是官方文档的实体 DemoData类(带注解),一个是自定义的User类

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

    准备模拟数据

    /**
         * 模拟实体数据
         *
         * @return
         */
        private List<DemoData> getDemoDataList() {
            List<DemoData> list = new ArrayList<DemoData>();
            for (int i = 0; i < 10; i++) {
                DemoData data = new DemoData();
                data.setString("字符串" + i);
                //data.setDate(new Date());
                //设置属性一部分为空值
                if (i % 2 == 0) {
                    data.setDoubleData(null);
                } else {
                    data.setDate(new Date());
                }
                data.setDoubleData(0.56);
                list.add(data);
            }
            return list;
        }
    
    
        /**
         * 模拟实体数据
         *
         * @return
         */
        private List<User> getUserList() {
            List<User> list = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                User user = new User();
                user.setUid("识别码" + i);
                user.setAge(i * 10);
                //设置属性一部分为空值
                if (i % 2 == 0) {
                    user.setBirthday(new Date());
                } else {
                    user.setBirthday(null);
                }
                user.setName("用户名" + i);
                list.add(user);
            }
            return list;
        }

     在盘符准备2个Excel文件用于导入数据,我用的是 I:\temp\writeDemo1.xlsx 和 I:\temp\writeDemo2.xlsx

     设置表头和内容的策略,这个是官方文档复制过来的。

    /**
         * 获取策略,这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
         *
         * @return
         */
        private HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {
            // 头的策略
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            // 背景设置为红色
            headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
    
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short) 10);
    
            headWriteCellStyle.setWriteFont(headWriteFont);
            // 内容的策略
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
            //contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            // 背景绿色
            //contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
            //WriteFont contentWriteFont = new WriteFont();
            // 字体大小
            //contentWriteFont.setFontHeightInPoints((short)20);
            //contentWriteCellStyle.setWriteFont(contentWriteFont);
            // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
            HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                    new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    
            return horizontalCellStyleStrategy;
        }

    四、设置列宽

    1.X的版本是通过生成sheet,使用sheet设置宽度,2.X版本后大部分方法已经过期,不推荐使用了,而大部分都是使用EasyExcel类直接构造并实现大部分功能;

    根据官方文档的提示只需要注册写入处理器就可以了(WriteHandler),我这里直接复制一份过来修修改改~红色代码部分主要是关键部分

    /**
     * 自定义拦截器
     *
     * @author
     */
    public class CustomSheetWriteHandler implements SheetWriteHandler {
        //列宽集合
        private List<Integer> columnWidths;
        //构造
        public CustomSheetWriteHandler(List<Integer> columnWidths) {
            this.columnWidths = columnWidths;
        }
    
        private static final Logger LOGGER = LoggerFactory.getLogger(CustomSheetWriteHandler.class);
    
        @Override
        public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
    
        }
    
        @Override
        public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
            LOGGER.info("第{}个Sheet写入成功。", writeSheetHolder.getSheetNo());
    
            // 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
           /* CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);
            DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper();
            DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"});
            DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
            writeSheetHolder.getSheet().addValidationData(dataValidation);*/
            LOGGER.info("普通策略设置setColumnWidth开始~");
            if(CollectionUtils.isNotEmpty(columnWidths)){
                for (int i = 0; i < columnWidths.size(); i++) {
                    writeSheetHolder.getSheet().setColumnWidth(i, columnWidths.get(i));
                }
            }
            LOGGER.info("普通策略设置setColumnWidth结束~");
        }
    }

    五、根据注解导出数据到Excel文件中

       /**
         * 写入到固定文件中
         *
         * @throws IOException
         */
        @Test
        public void writeToExcelFile() {
            //写入的文excel文件
            String fileName = "I:\temp\writeDemo1.xlsx";
            //获取头和内容的策略
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = getHorizontalCellStyleStrategy();
    
            //列宽的策略,宽度是小单位
            Integer columnWidthArr[] = {3000, 6000};
            List<Integer> columnWidths = Arrays.asList(columnWidthArr);
            CustomSheetWriteHandler customSheetWriteHandler = new CustomSheetWriteHandler(columnWidths);
    
            // 根据用户传入字段 假设我们只要导出 string date
            String[] filds = {"string", "date"};
    
            //获取模拟的实体数据集合
            List<DemoData> demoDataList = getDemoDataList();
    
            //这里需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
            EasyExcel.write(fileName, DemoData.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .registerWriteHandler(customSheetWriteHandler)
                    //这个是导出需要展示的列
                    .includeColumnFiledNames(Arrays.asList(filds))
                    .sheet("模板")
                    .doWrite(demoDataList);
        }

    效果:

    六、自定义导出数据到Excel文件中

        /**
         * 写入到固定文件中,这里不使用注解的方式写入列和对应的属性
         *
         * @throws IOException
         */
        @Test
        public void writeToExcelFile2() {
            //写入的文excel文件
            String fileName = "I:\temp\writeDemo2.xlsx";
            //获取头和内容的策略
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = getHorizontalCellStyleStrategy();
    
            //列宽的策略,宽度是小单位
            Integer columnWidthArr[] = {3000, 3000, 2000, 6000};
            List<Integer> columnWidths = Arrays.asList(columnWidthArr);
            CustomSheetWriteHandler customSheetWriteHandler = new CustomSheetWriteHandler(columnWidths);
    
            // 根据用户传入字段 假设我们只要导出 string date
            String[] filds = {"uid", "name", "age", "birthday"};
    
            String[] headers = {"唯一识别码", "姓名", "年龄", "生日"};
    
            List head = getHeadByFilds(headers);
    
            //获取模拟的实体数据集合
            List<User> userList = getUserList();
    
            //这里指定头的名字去写入,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
            EasyExcel.write(fileName)
                    .head(head)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .registerWriteHandler(customSheetWriteHandler)
                    .includeColumnFiledNames(Arrays.asList(filds))
                    .sheet("模板")
                    .doWrite(userList);
        }

    效果:

    六、总结 

    后面继续实现合并单元格、自定义单元格、web导出和导入等功能~

  • 相关阅读:
    架构设计-业务逻辑层简述
    大牛的法宝
    架构设计中服务层的简单理解
    架构师都要懂哪些知识
    python 面向对象
    Ubuntu学习
    装饰器
    Py之基础数据类型
    Py之模块
    浏览器环境变量
  • 原文地址:https://www.cnblogs.com/coloz/p/12502564.html
Copyright © 2011-2022 走看看