JXLS (Excel导入、导出工具使用)

jxls是一个简单的、轻量级的excel导出库,使用特定的标记在excel模板文件中来定义输出格式和布局。java中成熟的excel导出工具备pol、jxl,但他们都是使用java代码的方式来导出excel,编码效率很低且不方便维护。maven

还可使用一些工具很轻松的实现模板导出。这些工具如今还在维护,并且作得比较好的国内的有easyPOI,国外的就是这个JXLS了。

比较:

项目中有不少复杂的报表(大量单元格合并和单元格样式),easyPOI处理合并单元格时候容易出现残损的状况,poi代码维护成本高。

效果图

根据模板样式进行填充数据

依赖包

<dependency><groupId>org.jxls</groupId><artifactId>jxls</artifactId><version>2.4.6</version>
</dependency>
<dependency><groupId>org.jxls</groupId><artifactId>jxls-poi</artifactId><version>1.0.15</version>
</dependency>
<dependency><groupId>org.jxls</groupId><artifactId>jxls-jexcel</artifactId><version>1.0.7</version>
</dependency>
<dependency><groupId>net.sf.jxls</groupId><artifactId>jxls-core</artifactId><version>1.0.5</version>
</dependency>

工具类

import org.apache.commons.collections4.*;
import org.jxls.builder.xls.*;
import org.jxls.common.*;
import org.jxls.transform.Transformer;
import org.jxls.transform.jexcel.*;
import org.jxls.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Objects;/*** @Author: qinqc* @Date: 2019/9/30 11:25* @Desc: Jxls excel*/
public class JxlsUtil {private static Logger log = LoggerFactory.getLogger(JxlsUtil.class);private static final String CONTENT_TYPE = "application/vnd.ms-excel";static {XlsCommentAreaBuilder.addCommandMapping("merge", MergeCommand.class);}/*** 导出Excel** @param templatePath   模板路径* @param exportFile* Name 导出的文件名* @param data           数据集合* @param response* @throws IOException*/public static void exportExcel(String templatePath, String exportFileName, Map<String, Object> data, HttpServletResponse response) {try {exportFileName = URLEncoder.encode(exportFileName, "UTF-8");response.setContentType(CONTENT_TYPE);response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + exportFileName + ".xls");response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");Context context = new Context(data);ServletOutputStream os = response.getOutputStream();InputStream is = new FileInputStream(templatePath);JxlsHelper.getInstance().processTemplate(is, os, context);is.close();} catch (Exception e) {log.error("excel导出异常", e);}}/*** 导出Excel** @param sheetNameList   需要删除的sheet* @param templatePath   模板路径* @param exportFileName 导出的文件名* @param data           数据集合* @param response* @throws IOException*/public static void exportExcel(List<String> sheetNameList, String templatePath, String exportFileName, Map<String, Object> data, HttpServletResponse response) {try {exportFileName = URLEncoder.encode(exportFileName, "UTF-8");response.setContentType(CONTENT_TYPE);response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + exportFileName + ".xls");response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");Context context = new Context(data);ServletOutputStream os = response.getOutputStream();InputStream is = new FileInputStream(templatePath);JxlsHelper jxlsHelper = JxlsHelper.getInstance();Transformer transformer = jxlsHelper.createTransformer(is, os);if (CollectionUtils.isNotEmpty(sheetNameList)){sheetNameList.forEach(transformer::deleteSheet);}
//            jxlsHelper.processTemplate(is, os, context);jxlsHelper.setUseFastFormulaProcessor(false).processTemplate(context, transformer);is.close();} catch (Exception e) {log.error("excel导出异常", e);}}/*** 导出Excel** @param templatePath 模板路径* @param data         数据集合* @throws IOException*/public static InputStream exportExcel(String templatePath, Map<String, Object> data) {InputStream excelStream = null;try {ByteArrayOutputStream os = new ByteArrayOutputStream();JexcelContext context = new JexcelContext(data);InputStream is = new FileInputStream(templatePath);JxlsHelper.getInstance().processTemplate(is, os, context);is.close();excelStream = new ByteArrayInputStream(os.toByteArray());os.close();} catch (Exception e) {log.error("excel导出异常", e);}return excelStream;}public static void closedInputStream(InputStream inputStream) {try {if (Objects.nonNull(inputStream)) {inputStream.close();}} catch (IOException e) {e.printStackTrace();log.error("关闭流管道异常");}}public static void closedOutputStream(OutputStream outputStream) {try {if (Objects.nonNull(outputStream)) {outputStream.close();}} catch (IOException e) {e.printStackTrace();log.error("关闭流管道异常");}}/*** 将InputStream写入本地文件* @param destination 写入本地目录* @param input    输入流* @throws IOException*/private static void writeToLocal(String destination, InputStream input)throws IOException {int index;byte[] bytes = new byte[1024];FileOutputStream downloadFile = new FileOutputStream(destination);while ((index = input.read(bytes)) != -1) {downloadFile.write(bytes, 0, index);downloadFile.flush();}downloadFile.close();input.close();}
}

合并单元格所需要的类

import jxl.write.WriteException;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.jxls.area.Area;
import org.jxls.command.AbstractCommand;
import org.jxls.command.Command;
import org.jxls.common.CellRef;
import org.jxls.common.Context;
import org.jxls.common.Size;
import org.jxls.transform.Transformer;
import org.jxls.transform.jexcel.JexcelTransformer;
import org.jxls.transform.poi.PoiTransformer;/*** @Date: 2020/10/28 0020 15:04* 合并单元格命令*/
@Data
public class MergeCommand extends AbstractCommand {/*** 合并的列数*/private String cols;/*** 合并的行数*/private String rows;private Area area;/*** 单元格的样式*/private CellStyle cellStyle;@Overridepublic String getName() {return "merge";}@Overridepublic Command addArea(Area area) {if (super.getAreaList().size() >= 1) {throw new IllegalArgumentException("You can add only a single area to 'merge' command");}this.area = area;return super.addArea(area);}@Overridepublic Size applyAt(CellRef cellRef, Context context) {int rows = 1, cols = 1;if (StringUtils.isNotBlank(this.rows)) {Object rowsObj = getTransformationConfig().getExpressionEvaluator().evaluate(this.rows, context.toMap());if (rowsObj != null && NumberUtils.isDigits(rowsObj.toString())) {rows = NumberUtils.toInt(rowsObj.toString());}}if (StringUtils.isNotBlank(this.cols)) {Object colsObj = getTransformationConfig().getExpressionEvaluator().evaluate(this.cols, context.toMap());if (colsObj != null && NumberUtils.isDigits(colsObj.toString())) {cols = NumberUtils.toInt(colsObj.toString());}}if (rows > 1 || cols > 1) {Transformer transformer = this.getTransformer();if (transformer instanceof PoiTransformer) {return poiMerge(cellRef, context, (PoiTransformer) transformer, rows, cols);} else if (transformer instanceof JexcelTransformer) {return jexcelMerge(cellRef, context, (JexcelTransformer) transformer, rows, cols);}}area.applyAt(cellRef, context);return new Size(1, 1);}protected Size poiMerge(CellRef cellRef, Context context, PoiTransformer transformer, int rows, int cols) {Sheet sheet = transformer.getWorkbook().getSheet(cellRef.getSheetName());CellRangeAddress region = new CellRangeAddress(cellRef.getRow(),cellRef.getRow() + rows - 1,cellRef.getCol(),cellRef.getCol() + cols - 1);sheet.addMergedRegion(region);area.applyAt(cellRef, context);setRegionStyle(cellStyle, region, sheet);return new Size(cols, rows);}protected Size jexcelMerge(CellRef cellRef, Context context, JexcelTransformer transformer, int rows, int cols) {try {transformer.getWritableWorkbook().getSheet(cellRef.getSheetName()).mergeCells(cellRef.getRow(),cellRef.getCol(),cellRef.getRow() + rows - 1,cellRef.getCol() + cols - 1);area.applyAt(cellRef, context);} catch (WriteException e) {throw new IllegalArgumentException("合并单元格失败");}return new Size(cols, rows);}public static void setRegionStyle(CellStyle cs, CellRangeAddress region, Sheet sheet) {for (int i = region.getFirstRow(); i <= region.getLastRow(); i++) {Row row = sheet.getRow(i);if (row == null) {row = sheet.createRow(i);}for (int j = region.getFirstColumn(); j <= region.getLastColumn(); j++) {Cell cell = row.getCell(j);if (cell == null) {cell = row.createCell(j);}if (cs == null) {setPoiCellStyle(cell);}}}}/*** 设置单元格格式* 根据自己需求修改** @param cell* @return*/private static void setPoiCellStyle(Cell cell) {CellStyle cellStyle = cell.getCellStyle();if (cellStyle != null) {cellStyle.setBorderRight(BorderStyle.THIN);cellStyle.setBorderRight(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);}}}

参考接口

@GetMapping("/excel-maternal-health-management-ones")@PreAuthorize("hasAnyRole(\"" + AuthoritiesConstants.ADMIN + "\",\""+AuthoritiesConstants.ALL_MATERNALHEALTHMANAGEMENTONE + "\",\""+AuthoritiesConstants.SELECT_MATERNALHEALTHMANAGEMENTONE+"\")")public void excelMaternalHealthManagementOnes(MaternalHealthManagementOneCriteria criteria, HttpServletResponse response, Pageable pageable) throws Exception {/*  String fileName = "xxx";String url = maternalHealthManagementOneService.excelMaternalHealthManagementOne(criteria);EasyPoiUtil.fileStream(fileName,url,response);*/String fileName ="54641";Map<String, Object> data = maternalHealthManagementOneService.getMaternalHealthManagementOneMap(criteria);String property = System.getProperty("user.dir");String templateFileName = property + "/wordtemplate/maternalHealthManagementOne/maternalHealthManagementOne.xlsx";JxlsUtil.exportExcel(templateFileName,fileName,data,response);//完成导出

注意点1

注释中的遍历表达式“data”需与map中的key一致且key对应的值应为List<>类型

注意点2

lastCell=‘’‘P5’‘需一致(与注解点1中的lastCell),一个前注释,一个后注释“P5”代表的是需要执行遍历的区域

Excel注释语法

jx:merge(
lastCell =“合并单元格范围”
[,cols =“合并的列数”]
[,rows =“合并的行数”]
[,minCols =“要合并的最小列数”]
[,minRows = “要合并的最小行数”]
)

附链接

https://www.shangmayuan.com/a/d98c48f2194d425481057984.html

JXLS (Excel 导出工具使用)相关推荐

  1. Excel导出工具类

    前言 相信不少同学在开发中都会遇到导出excel这种需求,今天将Excel的导出工具和大家进行一个分享,如有错误还请大佬们批评指正.该工具类可以实现自定义列宽,自定义表头样式,实现了多sheet页合并 ...

  2. Java之Excel导出工具类使用教程

    前言: 本工具类经过PostMan和web页面严格测试可用,经过了多个版本迭代优化,可以直接使用,也方便大家根据自己的业务需求,修改定制自己的导出工具. 市面上有很多封装好的导出工具(如:阿里的eas ...

  3. 自己写的java excel导出工具类

    最近项目要用到excel导出功能,之前也写过类似的代码.因为这次项目中多次用到excel导出.这次长了记性整理了一下 分享给大伙 欢迎一起讨论 生成excel的主工具类: public class E ...

  4. java Excel导出工具类

    Excel工具类 一.开发原因 最近工作的时候,正在写关于Excel导出功能,由于当前使用的工具类不太灵活和不易看懂,自己从头写又很浪费时间等原因,我决定自己写一款很简单的Excel导出的工具类,仅仅 ...

  5. 游戏开发 excel导出工具

    今天做excel生成工具的时候遇到 .net core以上版本使用exceldatareader包出现错误System.NotSupportedException: No data is availa ...

  6. 我把这个贼好用的Excel导出工具开源了!!

    写在前面 不管是传统软件企业还是互联网企业,不管是管理软件还是面向C端的互联网应用.都不可避免的会涉及到报表操作,而对于报表业务来说,一个很重要的功能就是将数据导出到Excel.如果我们在业务代码中, ...

  7. 「starter推荐」简单高效 Excel 导出工具

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:牛人 20000 字的 Spring Cloud 总结,太硬核了~ 作者:冷冷gg 链接:https://jue ...

  8. easyexcel 导出 代码翻译converter_啥?这么简单高效的Excel 导出工具都不知道? 还不快来看!

    EasyExcel EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项目.在尽可能节约内存的情况下支持读写百M的Excel. 64M内存1分钟内读取75M(46W行25列)的E ...

  9. Poi excel 导出 工具类参考

    public void poiCreateExcel(HttpServletResponse response, Map<String, Object> map) {// 下载文件信息St ...

  10. 【工具】vue excel导出

    本文中的excel导出工具取自花裤衩的https://gitee.com/panjiachen/vue-element-admin 环境: vue@2.6.12 element-ui@2.15.5 f ...

最新文章

  1. oracle数据库数据导入导出步骤(入门)
  2. 操作系统(三十四)覆盖和交换
  3. [转]ASP.NET会话(Session)保存模式
  4. 不属于前后端分离的Vue+Django的例子
  5. 高扫后督解决方案 力助银行内部核查
  6. 彻底解决zend studio 下 assignment in condition警告
  7. java 短信验证码===随机数
  8. 简单聊一聊PRINCE2与PMP的区别
  9. MySQL数据库InnoDB存储引擎底层原理详解
  10. rs232接口_USB转RS232接口9针串口线,工控数据转接线驱动安装方法
  11. 晶晨线刷工具_Amlogic_USB_Burning_Tool _刷机工具分享
  12. android中pdf转换成图片格式,Android-PDF转图片
  13. Vins-Mono系列代码和理论解读<五>.位姿图Pose_graph理论和代码实现细节
  14. 用python的tkinter做游戏(八)—— 实现图片在tkinter中自适应大小(自动匹配窗口)
  15. 如何有效提高生产车间的生产效率呢?
  16. python如何读取log文件_怎么解决Python读取log文件时报错
  17. uni-app app上实现截屏保存图片到本地
  18. 网络天气预报项目笔记(Qt)
  19. 什么是电压跟随器?电压跟随器计算方法讲解
  20. Java~通讯录系统

热门文章

  1. 【色空win7动漫美女诱惑主题】
  2. 河北师范大学计算机专业保研率,12所师范大学2018-2020年保研率对比!附9所师范大学2021保研率...
  3. Rime中州韵导入QQ五笔词库
  4. 电商后台管理系统——JavaWeb项目 毕业设计论文
  5. matlab simulink 单气室油气弹簧阻尼特性分析
  6. 浏览器UserAgent发展历史
  7. 从零学Java目录导航
  8. 计算机科学的endnote格式,基于国家标准的 EndNote 输出样式模板
  9. jdk32位安装包下载_天正T20V5.0软件安装包下载(建筑,给排水,结构,电气,暖通)+安装教程...
  10. java实习计划_JAVA实习计划及指导书.pdf