本文使用基于阿里的easyexcel编写的工具类对xls后缀的Excel文件(即03版)读取并写成xlsx后缀的Excel文件(即07版),中间转换过程使用String二维数组和对象列表两种形式.

easyexcel 项目git地址为: https://github.com/alibaba/easyexcel
官方使用指南见: https://github.com/alibaba/easyexcel/blob/master/quickstart.md

文章目录

一 工具类

/**
 * @version V1.0
 * @author: lin_shen
 * @date: 2018/9/26
 * @Description: TODO
 */
public class EasyExcelUtil {

    /**
     * StringList 解析监听器
     */
    private static class StringExcelListener extends AnalysisEventListener {
        /**
         * 自定义用于暂时存储data
         * 可以通过实例获取该值
         */
        private List<List<String>> datas = new ArrayList<>();

        /**
         * 每解析一行都会回调invoke()方法
         * @param object
         * @param context
         */
        @Override
        public void invoke(Object object, AnalysisContext context) {
            List<String> stringList= (List<String>) object;
            //数据存储到list,供批量处理,或后续自己业务逻辑处理。
            datas.add(stringList);
            //根据自己业务做处理
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            //解析结束销毁不用的资源
            //注意不要调用datas.clear(),否则getDatas为null
        }

        public List<List<String>> getDatas() {
            return datas;
        }
        public void setDatas(List<List<String>> datas) {
            this.datas = datas;
        }
    }

    /**
     * 使用 StringList 来读取Excel
     * @param inputStream Excel的输入流
     * @param excelTypeEnum Excel的格式(XLS或XLSX)
     * @return 返回 StringList 的列表
     */
    public static List<List<String>> readExcelWithStringList(InputStream inputStream,ExcelTypeEnum excelTypeEnum) {
        StringExcelListener listener = new StringExcelListener();
        ExcelReader excelReader = new ExcelReader(inputStream, excelTypeEnum, null, listener);
        excelReader.read();
        return  listener.getDatas();
    }

    /**
     * 使用 StringList 来写入Excel
     * @param outputStream Excel的输出流
     * @param data 要写入的以StringList为单位的数据
     * @param table 配置Excel的表的属性
     * @param excelTypeEnum Excel的格式(XLS或XLSX)
     */
    public static void writeExcelWithStringList(OutputStream outputStream, List<List<String>> data, Table table,ExcelTypeEnum excelTypeEnum) {
        //这里指定不需要表头,因为String通常表头已被包含在data里
        ExcelWriter writer = new ExcelWriter(outputStream, excelTypeEnum,false);
        //写第一个sheet, sheet1  数据全是List<String> 无模型映射关系,无表头
        Sheet sheet1 = new Sheet(0, 0);
        writer.write0(data, sheet1,table);
        writer.finish();
    }

    /**
     * 模型 解析监听器
     */
    private static class ModelExcelListener extends AnalysisEventListener {

        private List<Object> datas = new ArrayList<>();
        @Override
        public void invoke(Object object, AnalysisContext context) {
            datas.add(object);
        }
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
        }
        public List<Object> getDatas() {
            return datas;
        }
        public void setDatas(List<Object> datas) {
            this.datas = datas;
        }
    }

    /**
     * 使用 模型 来读取Excel
     * @param inputStream Excel的输入流
     * @param clazz 模型的类
     * @param excelTypeEnum Excel的格式(XLS或XLSX)
     * @return 返回 模型 的列表(为object列表,需强转)
     */
    public static List<Object> readExcelWithModel(InputStream inputStream, Class<? extends BaseRowModel> clazz,ExcelTypeEnum excelTypeEnum) {

        // 解析每行结果在listener中处理
        ModelExcelListener listener = new ModelExcelListener();
        ExcelReader excelReader = new ExcelReader(inputStream, excelTypeEnum, null, listener);
        //默认只有一列表头
        excelReader.read(new Sheet(1,1,clazz));
        return  listener.getDatas();

    }

    /**
     * 使用 模型 来写入Excel
     * @param outputStream Excel的输出流
     * @param data 要写入的以 模型 为单位的数据
     * @param table 配置Excel的表的属性
     * @param clazz 模型的类
     * @param excelTypeEnum Excel的格式(XLS或XLSX)
     */
    public static void writeExcelWithModel(OutputStream outputStream, List<? extends BaseRowModel> data, Table table,Class<? extends BaseRowModel> clazz,ExcelTypeEnum excelTypeEnum)  {
        //这里指定需要表头,因为model通常包含表头信息
        ExcelWriter writer = new ExcelWriter(outputStream, excelTypeEnum,true);
        //写第一个sheet, sheet1  数据全是List<String> 无模型映射关系
        Sheet sheet1 = new Sheet(1,0, clazz);
        writer.write(data, sheet1,table);
        writer.finish();
    }

}

二 编写excel对应Java对象

现有excel格式如下:
Excel解析easyexcel工具类-LMLPHP
故定义对应Java对象如下:
注意:@ExcelProperty注解的value值对应的是Excel表格的表头内容

@Data
public class ETUInfo extends BaseRowModel {
    @ExcelProperty(value ={"TxHash"},index = 0)
    private String txHash;

    @ExcelProperty(value ={"Date"},index =1)
    private String date;

    @ExcelProperty(value ={"From"},index = 2)
    private String from;

    @ExcelProperty(value ={"To"},index = 3)
    private String to;

    @ExcelProperty(value ={"Quantity"},index = 4)
    private String quantity;
}

三 使用两种方法测试

第一种使用了String列表对Excel属性进行解析,每一行对应一个List,这样灵活性高,注意表头也会被当成List。
第二种使用了Model对Excel属性进行解析,每一行对应一个 Model,也就是Java对象,这样可以直接将excel文件解析为对象列表,方便后续操作。
两种方法都是将xls格式读入再以xlsx格式写出。
注意还可以利用TableStyle设置Excel格式(主要是字体大小和颜色),默认是很丑的,而且目前最新版本EasyExcel还不能设置单元格内容居中和自动适应宽度

public class EasyExcelUtilTest {
    @Test
    public void testReadExcelWithStringList(){
        try(
                InputStream inputStream=new FileInputStream("C:\\Users\\Shinelon\\IdeaProjects\\webmagic\\webmagic\\src\\test\\java\\etherscan-page1-1000.xls");
                OutputStream outputStream=new FileOutputStream("C:\\Users\\Shinelon\\IdeaProjects\\webmagic\\webmagic\\src\\test\\java\\etherscan-page1-1000String.xlsx")
        ) {
            //读入文件,每一行对应一个List<String>
            List<List<String>> stringLists = EasyExcelUtil.readExcelWithStringList(inputStream, ExcelTypeEnum.XLS);

            //定义Excel正文背景颜色
            TableStyle tableStyle=new TableStyle();
            tableStyle.setTableContentBackGroundColor(IndexedColors.WHITE);

            //定义Excel正文字体大小
            Font font=new Font();
            font.setFontHeightInPoints((short) 10);

            tableStyle.setTableContentFont(font);

            Table table=new Table(0);
            table.setTableStyle(tableStyle);

            EasyExcelUtil.writeExcelWithStringList(outputStream,stringLists,table,ExcelTypeEnum.XLSX);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Test
    public void testReadExcelWithModel(){
        try (
                InputStream inputStream=new FileInputStream("C:\\Users\\Shinelon\\IdeaProjects\\webmagic\\webmagic\\src\\test\\java\\etherscan-page1-1000.xls");
                OutputStream outputStream=new FileOutputStream("C:\\Users\\Shinelon\\IdeaProjects\\webmagic\\webmagic\\src\\test\\java\\etherscan-page1-1000model.xlsx")
        ) {
            //读入文件,每一行对应一个 Model ,获取Model 列表
            List<Object> objectList = EasyExcelUtil.readExcelWithModel(inputStream,ETUInfo.class,ExcelTypeEnum.XLS);
            List<ETUInfo> etuInfoList=(List)objectList;
            //定义Excel正文背景颜色
            TableStyle tableStyle=new TableStyle();
            tableStyle.setTableContentBackGroundColor(IndexedColors.WHITE);

            //定义Excel正文字体大小
            Font font=new Font();
            font.setFontHeightInPoints((short) 10);
            tableStyle.setTableContentFont(font);

            Table table=new Table(0);
            table.setTableStyle(tableStyle);

            EasyExcelUtil.writeExcelWithModel(outputStream,etuInfoList,table,ETUInfo.class,ExcelTypeEnum.XLSX);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

四 查看输出结果

可以看到比较明显的区别是在表头部分,String并没有设置表头,对于EasyExcel来说第一行的数据和第二行没什么区别,需要的话得将第一行的数据去除,再单独设置表头。

1 String 输出格式如下

Excel解析easyexcel工具类-LMLPHP

2 Model 输出格式如下

Excel解析easyexcel工具类-LMLPHP

10-06 16:23