POI下载excel通用方法

POI下载excel通用方法

最近遇到一个业务是需要下载excel,使用POI,这里记录一下实现过程

1、导包

  <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.9</version></dependency>

2.公共方法的编写

package com.pingan.esbx.cassandra.util;import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.util.CollectionUtils;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;public class ExcelDonload {/*** 26个英文字母表**/public static final String[] letters = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};/*** 创建excel的行数(随描述 标题等的增加而增加)**/public static int rowNum = NumberUtils.INTEGER_ZERO;/*** 指定时间格式*/public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");/*** 下载* ①tableTitles 与 titlesInfoKey 个数要一致,不能为空* ②fileName、title、subtitle、desc均可不传或者传null* ③titlesInfoKey 是与tableTitles对应的字段,需与实体类一致** @param title         标题* @param resultList    数据* @param fileName      文件名* @param tableTitles   表头* @param titlesInfoKey 表头对应的字段* @param subtitle      副标题* @param desc          描述* @param response*/public static <T> void donloadExcel(String title,List<T> resultList,String fileName,String[] tableTitles,String[] titlesInfoKey,String subtitle,String[] desc,HttpServletResponse response) {//1.参数校验if (CollectionUtils.isEmpty(resultList)|| tableTitles.length <= NumberUtils.INTEGER_ZERO) {throw new RuntimeException("请求参数不正确!");}if (resultList.size() > 60000) {throw new RuntimeException("到处数据超过6w,不能导出!");}//2.创建Excel工作簿HSSFWorkbook workbook = new HSSFWorkbook();HSSFSheet sheet = workbook.createSheet();//3.设置excel的 描述、标题、副标题、表头setExcelTitle(workbook, sheet, title, tableTitles, subtitle, desc);//4.写入数据HSSFCellStyle dataStyle = workbook.createCellStyle();dataStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);dataStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);for (int i = 0; i < resultList.size(); i++) {T clazz = resultList.get(i);insertDataToCell(sheet, clazz, titlesInfoKey, dataStyle);}//5.返回数据量File file = returnExcelDataStream(fileName, workbook);//6.导出buildResponseExcelFile(file, response);}/*** 下载文件流** @param file* @param response*/private static void buildResponseExcelFile(File file, HttpServletResponse response) {InputStream in = null;OutputStream out = null;try {in = new FileInputStream(file.getPath());response.reset();response.setHeader("Content-disposition", "attachment;filename=" + new String(file.getName().getBytes(), "iso-8859-1"));response.setContentType("application/octet-stream");response.addHeader("Context-Length", "" + file.length());response.setCharacterEncoding("utf-8");out = response.getOutputStream();int b;while ((b = in.read()) != -1) {out.write(b);}} catch (Exception e) {e.printStackTrace();} finally {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}if (out != null) {try {out.close();} catch (IOException e) {e.printStackTrace();}}}file.delete();}/*** 返回文件流** @param fileName* @param workbook* @return*/private static File returnExcelDataStream(String fileName, HSSFWorkbook workbook) {File file = null;try {String tempExcelPath = null;if (StringUtils.isNotBlank(fileName)) {tempExcelPath = File.separator + fileName + ".xls";} else {tempExcelPath = File.separator + "report.xls";}file = new File(tempExcelPath);file.deleteOnExit();file.createNewFile();FileOutputStream fileOutputStream = FileUtils.openOutputStream(file);workbook.write(fileOutputStream);fileOutputStream.close();} catch (Exception e) {e.printStackTrace();}return file;}/*** 通过反射获取字段值** @param sheet* @param clazz* @param titlesInfoKey* @param <T>*/private static <T> void insertDataToCell(HSSFSheet sheet, T clazz, String[] titlesInfoKey, HSSFCellStyle dataStyle) {HSSFRow row = sheet.createRow(rowNum);row.setHeight((short) (15 * 20));for (int j = 0; j < titlesInfoKey.length; j++) {HSSFCell cell = row.createCell(j);cell.setCellStyle(dataStyle);//反射获取对象的值Object fieldValue = getValueByReflect(titlesInfoKey[j], clazz);String cellResult = null;//时间类型 Date 转换为字符串if (fieldValue instanceof Date) {cellResult = getStringTime((Date) fieldValue);} else {cellResult = Objects.isNull(fieldValue) ? "" : String.valueOf(fieldValue);}cell.setCellValue(cellResult);}rowNum += NumberUtils.INTEGER_ONE;}/*** 设置excel的 描述、标题、副标题、表头** @param workbook* @param sheet* @param title* @param tableTitles* @param subtitle* @param desc*/private static void setExcelTitle(HSSFWorkbook workbook,HSSFSheet sheet,String title,String[] tableTitles,String subtitle,String[] desc) {//合并单元格的行数 desc描述的数组项数+(beginTime && endTime)+title标题//$A$1:$I$1" 的含义是 第1行的A列到第1行的I列合并//计算要合并的行数int cellMergedRegionNm = NumberUtils.INTEGER_ZERO;//描述的长度int descLength = NumberUtils.INTEGER_ZERO;//当前要创建的excel的行数rowNum = NumberUtils.INTEGER_ZERO;if (desc != null) {descLength = desc.length;cellMergedRegionNm += descLength;rowNum += descLength;}//统计时间栏if (StringUtils.isNotBlank(subtitle)) {cellMergedRegionNm += NumberUtils.INTEGER_ONE;}//标题栏if (StringUtils.isNotBlank(title)) {cellMergedRegionNm += NumberUtils.INTEGER_ONE;}//获取表头的数量(他决定了合并单元格的列数)int tableTitleLength = tableTitles.length;//获取表头的长度对应的字母String letter = getLetterByNum(tableTitleLength);//设置需合并的行数与列数(循环次数是行数 ,$A$1:$I$1中的A代表第一列,I代表列的最后一列)for (int i = 0; i < cellMergedRegionNm; i++) {sheet.addMergedRegion(CellRangeAddress.valueOf("$A$" + (i + 1) + ":$" + letter + "$" + (i + 1)));}//设置颜色HSSFPalette palette = workbook.getCustomPalette();palette.setColorAtIndex((short) 9, (byte) 240, (byte) 240, (byte) 240);palette.setColorAtIndex((short) 10, (byte) 255, (byte) 153, (byte) 102);palette.setColorAtIndex((short) 11, (byte) 100, (byte) 149, (byte) 137);palette.setColorAtIndex((short) 12, (byte) 176, (byte) 196, (byte) 222);//字体HSSFFont workbookFont = workbook.createFont();workbookFont.setFontName("仿宋");workbookFont.setFontHeightInPoints((short) 14);//字体HSSFFont titleFont = workbook.createFont();titleFont.setFontName("黑体");titleFont.setFontHeightInPoints((short) 18);titleFont.setColor(IndexedColors.WHITE.index);//单元格的风格1HSSFCellStyle descStyleLong = workbook.createCellStyle();descStyleLong.setFont(workbookFont);descStyleLong.setFillForegroundColor((short) 9);descStyleLong.setFillPattern(CellStyle.SOLID_FOREGROUND);//单元格的风格2HSSFCellStyle descStyleShort = workbook.createCellStyle();descStyleShort.setFont(workbookFont);descStyleShort.setFillForegroundColor((short) 10);descStyleShort.setFillPattern(CellStyle.SOLID_FOREGROUND);//单元格的风格3HSSFCellStyle titleStyle = workbook.createCellStyle();titleStyle.setFont(titleFont);titleStyle.setFillForegroundColor((short) 11);titleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//描述:设置描述,没有就不传HSSFRow row = null;HSSFCell cell = null;if (descLength > 0) {for (int i = 0; i < descLength; i++) {row = sheet.createRow(i);row.setHeight((short) (23 * 20));cell = row.createCell(0);cell.setCellValue(desc[i]);if (i >= 4) {row.setHeight((short) (40 * 20));cell.setCellStyle(descStyleShort);} else {cell.setCellStyle(descStyleLong);}}}//设置标题:没有就不传if (StringUtils.isNoneBlank(title)) {row = sheet.createRow(rowNum);row.setHeight((short) (60 * 20));cell = row.createCell(0);cell.setCellValue(title);cell.setCellStyle(titleStyle);rowNum += NumberUtils.INTEGER_ONE;}HSSFCellStyle styleTimeRange = workbook.createCellStyle();styleTimeRange.setFont(titleFont);styleTimeRange.setFillForegroundColor((short) 11);styleTimeRange.setFillPattern(CellStyle.FINE_DOTS);styleTimeRange.setAlignment(HSSFCellStyle.ALIGN_CENTER);styleTimeRange.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//设置时间范围if (StringUtils.isNotBlank(subtitle)) {row = sheet.createRow(rowNum);row.setHeight((short) (30 * 20));cell = row.createCell(0);cell.setCellValue(subtitle);cell.setCellStyle(styleTimeRange);rowNum += NumberUtils.INTEGER_ONE;}//设置表头字体HSSFFont tableTitleFont = workbook.createFont();tableTitleFont.setFontName("仿宋");tableTitleFont.setFontHeightInPoints((short) 14);tableTitleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//表头风格HSSFCellStyle tableTitleStyle = workbook.createCellStyle();tableTitleStyle.setFont(tableTitleFont);tableTitleStyle.setFillForegroundColor((short) 12);tableTitleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);tableTitleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);tableTitleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);tableTitleStyle.setLeftBorderColor(IndexedColors.WHITE.index);tableTitleStyle.setRightBorderColor(IndexedColors.WHITE.index);tableTitleStyle.setTopBorderColor(IndexedColors.WHITE.index);tableTitleStyle.setBottomBorderColor(IndexedColors.WHITE.index);tableTitleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);tableTitleStyle.setBorderTop(HSSFCellStyle.BORDER_THICK);tableTitleStyle.setBorderRight(HSSFCellStyle.BORDER_THICK);tableTitleStyle.setBorderBottom(HSSFCellStyle.BORDER_THICK);if (tableTitles != null && tableTitles.length > 0) {row = sheet.createRow(rowNum);row.setHeight((short) (41.2 * 20));for (int i = 0; i < tableTitles.length; i++) {cell = row.createCell(i);String tableTitle = tableTitles[i];cell.setCellValue(tableTitle);cell.setCellStyle(tableTitleStyle);//根据标题长短设置单元格的宽窄sheet.setColumnWidth(i, (tableTitle.length() * 5) * 256);}rowNum += NumberUtils.INTEGER_ONE;}}private static String getLetterByNum(int tableTitleLength) {return letters[tableTitleLength - NumberUtils.INTEGER_ONE];}/*** 返回指定时间的指定字符串格式 yyyy-MM-dd HH:mm:ss* SimpleDateFormat 线程不安全 所以枷锁*/public synchronized static String getStringTime(Date date) {String format = dateFormat.format(date);return format;}/*** 通过反射获取字段值(通过get方法)** @param fieldName* @param t* @param <T>* @return*/public static <T> Object getValueByReflect(String fieldName, T t) {String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);try {Method method = t.getClass().getMethod(methodName);Object fieldValue = method.invoke(t);return fieldValue;} catch (Exception e) {return null;}}
}

3.调用示例

@RestController
@RequestMapping("/excel")
public class ExcelController {private static final String[] TITLES_NONEXP_INFO_KEY = {"time","consumerCompany","consumerSystem","consumerCode","providerCompany","providerSystem","providerCode","failCount","failRatio","totalCount"};private static final String[] TITLES_NONEXP_INFO = {"时  间", "消费方公司", "消费方系统","消费方编码", "服务方公司","服务方系统", "服务方编码", "失败次数", "失败率", "总数"};@GetMapping("/exportExcel")public void exportExcel(HttpServletRequest request, HttpServletResponse response) {String title = "INVALID 月报表";List<ReportDTO> list = new ArrayList<>();String inputParams = "111111";ReportDTO reportDTO = new ReportDTO();reportDTO.setTime(new Date());reportDTO.setConsumerCompany("集团总部");reportDTO.setConsumerSystem("文件处理系统");reportDTO.setConsumerCode("EIP_DPS");reportDTO.setProviderCompany("中国科技");reportDTO.setProviderSystem("中国智者统一搜索平台");reportDTO.setProviderCode("PA011-ZHIZHE-USP-SE_PZHIZHE_ESG");reportDTO.setFailCount(100);reportDTO.setFailRatio(0.34);reportDTO.setTotalCount(340);list.add(reportDTO);String fileName = "我的测试";String[] desc = {"报表中数据排序方法:","1.选中待排序的数据区域","2.excel菜单栏:【开始】->【格式】->【设置单元格】->【对齐】->【文本控制】:取消\"合并单元格\"选项\"","3.excel菜单栏:【开始】->【排序和筛选】->【自定义排序】","查询条件:",JSON.toJSONString("这里可以写自己的查询条件")};String beginTime = "2023-7-6";String endTime = "2023-7-7";String subtitle = "统计时间范围【" + beginTime + "," + endTime + "】";ExcelDonload.donloadExcel(title,list,fileName,TITLES_NONEXP_INFO,TITLES_NONEXP_INFO_KEY,subtitle,desc,response);}
}

4.实体类

@Data
public class ReportDTO implements Serializable {private Date time;private String consumerCompany;private String consumerSystem;private String consumerCode;private String providerCompany;private String providerSystem;private String providerCode;private Integer failCount;private Double failRatio;private Integer totalCount;
}

5.下载效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/21193.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python实现将pdf,docx,xls,doc,wps链接下载并将文件保存到本地

前言 本文是该专栏的第31篇,后面会持续分享python的各种干货知识,值得关注。 在工作上,尤其是在处理爬虫项目中,会遇到这样的需求。访问某个网页或者在采集某个页面的时候,正文部分含有docx,或pdf,或xls,或doc,或wps等链接。需要你使用python自动将页面上含有的这些信…

什么是RPC并实现一个简单的RPC

1. 基本的RPC模型 主要介绍RPC是什么&#xff0c;基本的RPC代码&#xff0c;RPC与REST的区别&#xff0c;gRPC的使用 1.1 基本概念 RPC&#xff08;Remote Procedure Call&#xff09;远程过程调用&#xff0c;简单的理解是一个节点请求另一个节点提供的服务本地过程调用&am…

C++STL:顺序容器之vector

文章目录 1. 概述2. 成员函数3. 创建 vector 容器的几种方式4. 迭代器vector容器迭代器的基本用法vector容器迭代器的独特之处 5. 访问元素5.1 访问vector容器中单个元素5.2 访问vector容器中多个元素 6. 添加元素6.1 push_back()6.2 emplace_back()6.3 emplace_back()和push_b…

【Java/大数据】Kafka简介

Kafka简介 Kafka概念关键功能应用场景 Kafka的原理Kafka 的消息模型早期的队列模型发布-订阅模型Producer、Consumer、Broker、Topic、PartitionPartitionoffsetISR Consumer Groupleader选举Controller leaderPartition leader producer 的写入流程 多副本机制replicas的同步时…

SOKIT软件的使用

1.模拟客户端向服务器发送报文 客户端---->TCP连接---->填写数据----->点击“发送” 2.模拟服务器接受报文 服务器---->设置IP地址与端口---->点击TCP侦听 就可以往该地址发送报文信息了

回归预测 | MATLAB实现WOA-CNN-LSTM鲸鱼算法优化卷积长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现WOA-CNN-LSTM鲸鱼算法优化卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现WOA-CNN-LSTM鲸鱼算法优化卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计学习总结参考资料 预测效果 基本介绍 回归预测 …

机器学习(13)--支持向量机

目录 一、支持向量机概述 二、Sklearn中的SVM概述 三、线性SVM损失函数 四、sklearn中进行可视化 1、导入模块 2、实例化数据集&#xff0c;可视化 3、网格点制作 4、建立模型并绘制决策边界和超平面 5、常用接口 6、如果数据是环形呢&#xff1f; 五、核函数 1、…

mysql什么情况下行锁(表锁)(锁的概念)

1&#xff1a;数据表aa的设计结构 2&#xff1a; 使用navicat编写手动控制事务 3&#xff1a;先选择开启事务和执行更新操作&#xff0c;where b1&#xff08;表锁&#xff09;是不带索引&#xff0c;不提交事务&#xff0c;&#xff08;如果where b1&#xff0c;b是索引就行锁…

Spring MVC 系列2 -- 创建连接、获取与输出

上个系列总结了关于Spring MVC 项目的一些基础 ,Spring MVC就是在Spring Boot的基础上引入了Spring Web依赖.接下来就进行总结一下Spring MVC项目的创建,连接,获取参数,输出响应. 目录 1. Spring MVC 创建和连接 1.1 创建Spring MVC 项目实现与浏览器互通 1.2 RequestMapping…

DEVICENET转ETHERNET/IP网关devicenet怎么读

远创智控YC-EIP-DNT&#xff0c;你听说过吗&#xff1f;这是一款自主研发的ETHERNET/IP从站功能的通讯网关&#xff0c;它能够连接DEVICENET总线和ETHERNET/IP网络&#xff0c;从而解决生产管理系统中协议不同造成的数据交换互通问题。 这款产品在工业自动化领域可谓是一大利…

【Linux】Linux工具

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 一、Linux安装软件&#xff1a; 1.yum安装 2.Linux和Windows文件互传 问题: 3.yum卸载软件 二、vim编辑器 1.命令模式 2.vim配置项说明 3.vim操作总结 一、Linux安装软件&#…

flask计算pin码

目录 Flask计算pin码 <1> 概念 什么是pin码&#xff1f; pin码生成条件&#xff1f; 读取相关文件绕过过滤 <2> 源码分析 werkzeug 1.0.x版本 计算PIN的源码 werkzeug 2.0.x版本 计算PIN的源码 <3> 计算生成pin的脚本 CTF中 flask-pin的应用 <1…