EasyExcel——写文件

easyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。
64M内存1分钟内读取75M(46W行25列)的Excel(当然还有急速模式能更快,但是内存占用会在100M多一点)
可有效避免OOM。
致敬阿里:

---参照官方文档进行编辑,主要记录了工作中用到的,用的少的就没有记录
---官方文档 : https://www.yuque.com/easyexcel
---官方github : https://github.com/alibaba/easyexcel

写入数据实体类

@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String stringData;
    @ExcelProperty("整型标题")
    private Integer  integerData;
    @ExcelProperty("日期标题")
    private Date  dateData;
    @NumberFormat("#.##%")
    private Double  dounleData;
}
  • @ExcelProperty("***") 标题行名称

构造数据的方法

    private List<DemoData> data() {
        List<DemoData> list = new ArrayList<DemoData>();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setStringData("字符串" + i);
            data.setIntegerData(i);
            data.setDateData(new Date());
            data.setDounleData(0.56);
            list.add(data);
        }

        return list;
    }

创建对象的写

简单写入

        //写法一
        String fileName = "c://Users//****";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
        
        //写法二
        String fileName = "c://Users//****";
        // 这里 需要指定写用哪个class去写
        ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
        WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
        excelWriter.write(data(), writeSheet);
        // 千万别忘记finish 会帮忙关闭流
        excelWriter.finish();

根据参数只导出指定列


  String fileName = "c://Users//****";
  
  
  //排除掉不想输出的列 假设我们要忽略 stringData
  Set<String> excludeColumnFiledNames = new HashSet<String>();
  excludeColumnFiledNames.add("stringData");
  EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板").doWrite(data());
  
  
  
  //只输出实体类我们想要的字段  假设我们只要导出 stringData
  Set<String> includeColumnFiledNames = new HashSet<String>();
  includeColumnFiledNames.add("stringData");
  EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板").doWrite(data());

指定写入的列

修改实体类注解即可

    @ExcelProperty(value = "数字标题", index =5)
    private Integer  integerData;

复杂头写入

修改实体类注解即可

@ExcelProperty({"主标题", "字符串标题"})
@ExcelProperty({"主标题", "日期标题"})
@ExcelProperty({"主标题", "数字标题"})

重复多次写入(写到单个或者多个Sheet)

同一个sheet多次写

String fileName = "c://Users//****";
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);
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();

写到不同的sheet 同一个对象

String fileName = "c://Users//****";
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);
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();

写到不同的sheet 不同的对象

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

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

修改实体类注解即可

日期、数字

    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date  dateData;
    @NumberFormat("#.##%")
    @ExcelProperty("浮点型标题")
    private Double   dounleData;

自定义格式转换

@ExcelProperty(converter = CustomStringStringConverter.class)
private String stringData;
public class CustomStringStringConverter  implements Converter<String> {
    @Override
    public Class supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
    /**
     * 这里读的时候会调用
     */
    @Override
    public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return "自定义:" + cellData.getStringValue();
    }

    /**
     * 这里是写的时候会调用
     */
    @Override
    public CellData convertToExcelData(String value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new CellData(value);
    }
}

指定列宽、行高

@Data
@ContentRowHeight(10)
@HeadRowHeight(20)
@ColumnWidth(25)
public class DemoData {
    @ColumnWidth(50)
    @ExcelProperty("字符串标题")
    //@ExcelProperty(converter = CustomStringStringConverter.class)
    private String stringData;
    @ExcelProperty(value = "数字标题")
    private Integer  integerData;
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date  dateData;
    @NumberFormat("#.##%")
    @ExcelProperty("浮点型标题")
    private Double   dounleData;
}

注解形式自定义样式

@Data
// 头背景设置成红色 IndexedColors.RED.getIndex()
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 10)
// 头字体设置成20
@HeadFontStyle(fontHeightInPoints = 20)
// 内容的背景设置成绿色 IndexedColors.GREEN.getIndex()
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 17)
// 内容字体设置成20
@ContentFontStyle(fontHeightInPoints = 20)
public class DemoData {
    @ColumnWidth(50)
    @ExcelProperty("字符串标题")
    // 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()
    @HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 14)
    private String stringData;
    // 字符串的头字体设置成20
    @HeadFontStyle(fontHeightInPoints = 30)
    @ExcelProperty(value = "数字标题")
    private Integer  integerData;
    // 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()
    @ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 40)
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date  dateData;
    // 字符串的内容字体设置成20
    @ContentFontStyle(fontHeightInPoints = 30)
    @NumberFormat("#.##%")
    @ExcelProperty("浮点型标题")
    private Double   dounleData;
}

自定义样式

        String fileName = "c://Users//****";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为红色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short)20);
        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);

        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
                .doWrite(data());

合并单元格

@Data
// 将第6-7行的2-3列合并成一个单元格
//@OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
public class DemoData {
    // 这一列 每隔2行 合并单元格
    @ContentLoopMerge(eachRow = 2)
    @ExcelProperty("字符串标题")
    private String stringData;
    @ExcelProperty(value = "数字标题")
    private Integer  integerData;
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date  dateData;
    @NumberFormat("#.##%")
    @ExcelProperty("浮点型标题")
    private Double   dounleData;
}

自动列宽(不太精确)

        EasyExcel.write(fileName, DemoData.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("模板")
                .doWrite(data());

不创建对象的写



    String fileName = "c://Users//****";
    EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList());
    
    -------------------------------------------------------------------------
    
    
    private List<List<String>> head() {
        List<List<String>> list = new ArrayList<List<String>>();
        List<String> head0 = new ArrayList<String>();
        head0.add("字符串" + System.currentTimeMillis());
        List<String> head1 = new ArrayList<String>();
        head1.add("数字" + System.currentTimeMillis());
        List<String> head2 = new ArrayList<String>();
        head2.add("日期" + System.currentTimeMillis());
        list.add(head0);
        list.add(head1);
        list.add(head2);
        return list;
    }
    
    
    private List<List<Object>> dataList() {
        List<List<Object>> list = new ArrayList<List<Object>>();
        for (int i = 0; i < 10; i++) {
            List<Object> data = new ArrayList<Object>();
            data.add("字符串" + i);
            data.add(new Date());
            data.add(0.56);
            list.add(data);
        }
        return list;
    }
    

web的写(文件下载)

    /**
     * 文件下载(失败了会返回一个有部分数据的Excel)
     */
    @GetMapping("download")
    public void download(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
    }

web中的写并且失败的时候返回json

    @GetMapping("downloadFailedUsingJson")
    public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 和easyexcel没有关系
            String fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), DownloadData.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                .doWrite(data());
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }
    
    
     private List<DownloadData> data() {
        List<DownloadData> list = new ArrayList<DownloadData>();
        for (int i = 0; i < 10; i++) {
            DownloadData data = new DownloadData();
            data.setStringData("字符串" + i);
            data.setIntegerData(i);
            data.setDateData(new Date());
            data.setDounleData(0.56);
            list.add(data);
        }
        return list;
    }
posted @ 2020-04-13 18:30  6。  阅读(2856)  评论(0编辑  收藏  举报