jxls-poi 以导入的思路做Excel导出

一、分析

        原生的poi导出,最麻烦的就是导出excel样式的设置,十分麻烦。于是有一种想法,就是以导入的思路做导出,就像我们知道的那样,导入excel进内存也必然对象化了,那么我们只要替换对应的业务数据不就可以了吗?

        正如所想的那样,可以实现的,只是有人做到了,也就是有现成的工具类可以使用,说道本文的主角,那就是jxls-poi.看名字也知道必然依赖poi,没错必须依赖poi,只是poi的很多版本存在兼容的问题,略微有点坑。

        jxls是一个简单的、轻量级的excel导出库,使用特定的标记在excel模板文件中来定义输出格式和布局,底层应该是利用反射做的映射,这里本文不针对jxls的具体实现原理做探究,本文重点在于记录一下jxls的使用。(有空再做研究,有空的话或者需要的话)。

        jxls-poi的使用相对来说,是比较简单的,但是其功能是比较强大的。最关键的是对jxls的标记语言的熟悉与使用,当然不熟悉也没关系,因为我也不是很熟悉的。本文记录的使用案例是基本对导出excel来说是通用的,多sheet页,当然还没用多行遍历集合数据。重在在使用中进行摸索,不采坑不进步~

二、导出模板

批注的使用

//指定模板的范围

jx:area(lastCell="L56") 

//items对导出数据进行遍历,var遍历出的每一项数据,lastCell指定模板的范围,multisheet多sheet的对应sheet名称集合

jx:each(items="aiFormulaResultData", var="data", lastCell="L56" multisheet="aiFormulaResultDataSheetNames")

导出模板.xlsx
指定模板的范围

三、业务代码

@RequestMapping("/downloadExcel.action")

public void downloadExcel(HttpServletRequest request, HttpServletResponse response)throws IOException {

    List data =dataService.getData();

    List dataSheetNames =new ArrayList<>(data .size());

    //sheetName

    String templateSheetName1 = ConstVar.SHEET_DATA1;

    String templateSheetName2 = ConstVar.SHEET_DATA2;

    for (int i =0; i < data.size(); i++) {

        dataSheetNames.add((String)data.get(i).get("code"));

    }

    Map bindDataMap =new HashMap<>();

    bindDataMap.put("aiChemicalDataSheetNames", aiChemicalDataSheetNames);

    bindDataMap.put("aiChemicalDataList", chemicalData);

    //获取获取模板  国际化

    String templateFileName = RequestContextUtils.getLocale(request).equals(Locale.SIMPLIFIED_CHINESE) ? ConstVar.AI_EXCEL_CHINESE_NAME : ConstVar.AI_EXCEL_ENGLISH_NAME;

    File tempTargetFile =new File(CommonUtil.getGuid() +".xlsx");

    InputStream inputStreamClassPath =null;

    InputStream inputStream =null;

try {

    inputStreamClassPath =new ClassPathResource("downloadTemplateExcel/" + templateFileName).getInputStream();

    //读取模板-写入数据-删除模板sheet

    JxlsExportTemplateExcelUtils.exportExcelAndDeleteTemplateSheet(inputStreamClassPath, tempTargetFile, bindDataMap, templateSheetName1, templateSheetName2);

    inputStream =new FileInputStream(tempTargetFile);

    //设置response头信息

    response.reset();

    String title = CommonUtil.encodingFileName(I18nUtils.getMessage("chemical.pdfTitleName"));

    response.setContentType("application/octet-stream");

    response.setHeader("Content-Length", String.valueOf(inputStream.available()));

    response.setHeader("Content-Disposition","attachment;filename=" + title + CommonUtil.getCurrentDate() +".xlsx");

    OutputStream out = response.getOutputStream();

    //创建缓冲区

    FileCopyUtils.copy(new BufferedInputStream(inputStream),new BufferedOutputStream(out));

}catch (Exception e) {

    logger.error("下载EXCEL出现异常 " + CommonUtil.getExceptionDetail(e));

}finally {

    if (inputStream !=null) {

        inputStream.close();

    }

    if (inputStreamClassPath !=null) {

        inputStreamClassPath.close();

    }

    if (tempTargetFile !=null && tempTargetFile.exists()) {

        tempTargetFile.delete();

    }

}

}

四、工具类

JxlsExportTemplateExcelUtils

//对外提供

public static void exportExcelAndDeleteTemplateSheet(InputStream templateFileInputStreamn, File tempTargetFile, Map bindDataMap, String... templateSheetNames)throws FileNotFoundException, IOException {

exportExcel(templateFileInputStreamn, tempTargetFile, bindDataMap, templateSheetNames);

}

//多种重载

private static void exportExcel(InputStream is, File out, Map model, String... sheetNames)throws IOException {

    OutputStream os =new FileOutputStream(out);

Context context = PoiTransformer.createInitialContext();

if (model !=null) {

for (Map.Entry entry : model.entrySet()) {

context.putVar(entry.getKey(), entry.getValue());

}

}

JxlsHelper jxlsHelper = JxlsHelper.getInstance();


//必须要这个,否者表格函数统计会错乱

   jxlsHelper.getInstance().setUseFastFormulaProcessor(false).processTemplate(context, jxlsHelper.createTransformer(is, os));

//删除对应的模板sheet页

    deleteSheet(out, sheetNames);

}

//删除对应的模板sheet页

public static void deleteSheet(File file, String... sheetNames) {

try {

FileInputStream fis =new FileInputStream(file);

XSSFWorkbook wb =new XSSFWorkbook(fis);

fileWrite(file, wb);

//删除Sheet

        for (String sheetName : sheetNames) {

wb.removeSheetAt(wb.getSheetIndex(sheetName));

}

fileWrite(file, wb);

fis.close();

}catch (Exception e) {

//e.printStackTrace();

    }

}

五、maven依赖

org.jxls

jxls-poi

1.1.0

org.apache.poi

poi

org.apache.poi

poi-ooxml

org.apache.poi

poi

3.17

org.apache.poi

poi-ooxml

3.17

六、总结

整体来说,是相对简单的,思路与想法很重要,只要你能想到的,一般就已经有人做到了,而且做得还不错。但是需要在实践中发现问题,解决问题。

你可能感兴趣的:(jxls-poi 以导入的思路做Excel导出)