java实现动态列excel导出

915 阅读2分钟

在业务开发中,有大量的excel下载导出的场景,有时候需要excel的列可以支持动态的扩展,没有固定的表头。下面Util可实现excel表头的动态扩展并支持多sheet页下载

/**
 * 动态导出工具
 */
@Slf4j
public class DynamicEasyExcelExportUtils {

    private static final String DEFAULT_SHEET_NAME = "自定义sheet1";


    /**
     * 动态导出文件。具体使用查看本类的单元测试方法
     * @param headColumnMap  有序列头部
     * 按顺序,key=列的code标识,value=第一行,第二行,……
     * 如果下面的列不写,自动以上面列填充,并合并单元格。
     * 如果不同的列的同一行的名字相同,自动合并单元格
     * @param dataList       数据体
     * @return
     */
    public static byte[] exportExcelFile(LinkedHashMap<String, String> headColumnMap, List<Map<String, Object>> dataList){
        //获取列名称
        List<List<String>> excelHead = new ArrayList<>();
        if(MapUtils.isNotEmpty(headColumnMap)){
            //key为匹配符,value为列名,如果多级列名用逗号隔开
            headColumnMap.entrySet().forEach(entry -> {
                excelHead.add(Lists.newArrayList(entry.getValue().split(",")));
            });
        }
        List<List<Object>> excelRows = new ArrayList<>();
        if(MapUtils.isNotEmpty(headColumnMap) && CollectionUtils.isNotEmpty(dataList)){
            for (Map<String, Object> dataMap : dataList) {
                List<Object> rows = new ArrayList<>();
                headColumnMap.entrySet().forEach(headColumnEntry -> {
                    if(dataMap.containsKey(headColumnEntry.getKey())){
                        Object data = dataMap.get(headColumnEntry.getKey());
                        rows.add(data);
                    } else {
                        rows.add(null);
                    }
                });
                excelRows.add(rows);
            }
        }
        byte[] stream = createExcelFile(excelHead, excelRows);
        return stream;
    }

    /**
     * 生成文件
     * @param excelHead
     * @param excelRows
     * @return
     */
    private static byte[] createExcelFile(List<List<String>> excelHead, List<List<Object>> excelRows){
        try {
            if(CollectionUtils.isNotEmpty(excelHead)){
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                EasyExcel.write(outputStream).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                        .head(excelHead)
                        .sheet(DEFAULT_SHEET_NAME)
                        .doWrite(excelRows);
                return outputStream.toByteArray();
            }
        } catch (Exception e) {
            log.error("动态生成excel文件失败,headColumns:" + JSON.toJSONString(excelHead) + ",excelRows:" + JSON.toJSONString(excelRows), e);
        }
        return null;
    }

    /**
     * 动态导出文件
     * @param headColumnMap  有序列头部
     * @param dataList       数据体
     * @return
     */
    public static byte[] exportExcelFileSheets(List<SheetObject> sheetObjects){
        Assert.isTrue(!CollectionUtils.isEmpty(sheetObjects),"sheetObjects不可为空");

        List<SheetObjectDetail> sheetObjectDetails = new ArrayList<>();
        for(SheetObject sheetObject : sheetObjects){
            LinkedHashMap<String, String> headColumnMap = sheetObject.getHeadColumnMap();
            List<Map<String, Object>> dataList = sheetObject.getDataList();
            //获取列名称
            List<List<String>> excelHead = new ArrayList<>();
            if(MapUtils.isNotEmpty(headColumnMap)){
                //key为匹配符,value为列名,如果多级列名用逗号隔开
                headColumnMap.entrySet().forEach(entry -> {
                    excelHead.add(Lists.newArrayList(entry.getValue().split(",")));
                });
            }
            List<List<Object>> excelRows = new ArrayList<>();
            if(MapUtils.isNotEmpty(headColumnMap) && CollectionUtils.isNotEmpty(dataList)){
                for(Map<String, Object> dataMap : dataList){
                    List<Object> rows = new ArrayList<>();
                    headColumnMap.entrySet().forEach(headColumnEntry -> {
                        if(dataMap.containsKey(headColumnEntry.getKey())){
                            Object data = dataMap.get(headColumnEntry.getKey());
                            rows.add(data);
                        }else{
                            rows.add("/");
                        }
                    });
                    excelRows.add(rows);
                }
            }
            SheetObjectDetail sheetObjectDetail = new SheetObjectDetail(sheetObject.getSheetName(),excelHead,excelRows);

            sheetObjectDetails.add(sheetObjectDetail);
        }
        byte[] stream = createExcelFileSheets(sheetObjectDetails);
        return stream;
    }

    /**
     * 生成文件
     * @param excelHead
     * @param excelRows
     * @return
     */
    private static byte[] createExcelFileSheets(List<SheetObjectDetail> sheetObjectDetails){
        Assert.isTrue(!CollectionUtils.isEmpty(sheetObjectDetails),"sheetObjectDetails 不可为空");
        log.info("createExcelFileSheets sheetObjectDetails " + JSON.toJSONString(sheetObjectDetails));
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ExcelWriter excelWriter = EasyExcel.write(outputStream).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();

            for(SheetObjectDetail sheetObjectDetail : sheetObjectDetails){
                WriteSheet sheet = EasyExcel.writerSheet(sheetObjectDetail.getSheetName()).head(sheetObjectDetail.getExcelHead()).build();
                log.info("createExcelFileSheets sheet" + JSON.toJSONString(sheet));
                excelWriter.write(sheetObjectDetail.getExcelRows(),sheet);
            }
            excelWriter.finish();
            return outputStream.toByteArray();
        } catch (Exception e) {
            log.error("动态生成excel文件失败,sheetObjects:" + JSON.toJSONString(sheetObjectDetails), e);
            throw new RuntimeException("动态生成excel文件失败",e);
        }
    }
}

一、动态excel表头

private static void testCase1() throws IOException{
    //导出包含数据内容的文件
    LinkedHashMap<String, String> headColumnMap = Maps.newLinkedHashMap();
    headColumnMap.put("className","班级");
    headColumnMap.put("name","学生信息,名称");
    headColumnMap.put("sex","学生信息,性别");
    headColumnMap.put("age","学生信息,年龄");
    List<Map<String, Object>> dataList = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        Map<String, Object> dataMap = Maps.newHashMap();
        dataMap.put("className", "一年级");
        dataMap.put("name", "张三" + i);
        dataMap.put("sex", "男");
        dataMap.put("age", i+20);
        dataList.add(dataMap);
    }
    byte[] stream = exportExcelFile(headColumnMap, dataList);
    List<byte[]> list=new ArrayList();
    InputStream input=new ByteArrayInputStream(exportExcelFile(headColumnMap, dataList));
    list.add(exportExcelFile(headColumnMap, dataList));
    list.add(exportExcelFile(headColumnMap, dataList));

    FileOutputStream outputStream = new FileOutputStream(new File("/Users/eric/Documents/easyexcel-export-user5.xlsx"));
    outputStream.write(stream);
    outputStream.close();
}

二、多sheet页

private static void testCase2() throws IOException{
    List<SheetObject> sheetObjects = new ArrayList<>();

    //导出包含数据内容的文件
    LinkedHashMap<String, String> headColumnMap1 = Maps.newLinkedHashMap();
    headColumnMap1.put("className","班级");
    headColumnMap1.put("name","学生信息");
    headColumnMap1.put("sex","学生信息,性别");
    List<Map<String, Object>> dataList1 = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        Map<String, Object> dataMap = Maps.newHashMap();
        dataMap.put("className", "一年级");
        dataMap.put("name", "张三" + i);
        dataMap.put("sex", "男");
        dataList1.add(dataMap);
    }
    sheetObjects.add(new SheetObject("sheet1",headColumnMap1,dataList1));

    LinkedHashMap<String, String> headColumnMap2 = Maps.newLinkedHashMap();
    headColumnMap2.put("className","班级");
    headColumnMap2.put("name","学生信息");
    headColumnMap2.put("sex","学生信息,性别");
    headColumnMap2.put("age","学生信息,年龄");
    List<Map<String, Object>> dataList2 = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        Map<String, Object> dataMap = Maps.newHashMap();
        dataMap.put("className", "一年级");
        dataMap.put("name", "张三" + i);
        dataMap.put("sex", "男");
        dataMap.put("age", i+20);
        dataList2.add(dataMap);
    }
    sheetObjects.add(new SheetObject("sheet2",headColumnMap2,dataList2));

    byte[] stream = exportExcelFileSheets(sheetObjects);
    FileOutputStream outputStream = new FileOutputStream(new File("/Users/eric/Documents/easyexcel-export-user6.xlsx"));
    outputStream.write(stream);
    outputStream.close();
}