java动态导出excel头

java动态导出excel头

    • java根据动态头导出excel文件
    • 一、需求背景
      • 1、调用接口将表头传给给后端
      • 2、请求结果展示
      • 3、核心代码
        • 1、工具类,注意异常抛出类如报错,需自定义异常类
        • 2、标题设置类
        • 3、单元各简单设置类
        • 4、controller接收参数

java根据动态头导出excel文件

一、需求背景

用户可选择列表中列展示,当选择好之后点击导出,excel中只导出用户选择列的数据

1、调用接口将表头传给给后端

在这里插入图片描述

2、请求结果展示

在这里插入图片描述

3、核心代码

pom包
在这里插入图片描述

1、工具类,注意异常抛出类如报错,需自定义异常类

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;import cn.hutool.core.util.ReflectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.mbcloud.cloud.commons.exception.ApiException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;@Component
@Slf4j
public class ExcelUtil {/*** 从 sheet 中获取指定行列的单元格值** @param sheet        表单* @param rowNumber    行号* @param columnNumber 列号* @return 统一返回字符串类型,null 表示找不到*/public static String getCellValue(Sheet sheet, int rowNumber, int columnNumber) {Row row = sheet.getRow(rowNumber);if (null == row) {return null;}Cell cell = row.getCell(columnNumber);if (null == cell) {return null;}// 只处理数字、文本、公式结果为数字、文本的,其余认为错误switch (cell.getCellTypeEnum()) {case NUMERIC:// 保留两位小数,并处理科学计数法DecimalFormat df = new DecimalFormat("0.00");return df.format(cell.getNumericCellValue());case STRING:return cell.getStringCellValue();case FORMULA:switch (cell.getCachedFormulaResultTypeEnum()) {case STRING:return cell.getStringCellValue();case NUMERIC:NumberFormat nf = NumberFormat.getInstance();nf.setGroupingUsed(false);return String.valueOf(nf.format(cell.getNumericCellValue()));default:return null;}default:return null;}}/*** 根据模板导出数据 单个sheet** @param response     返回对象* @param dataList     导出的数据集合* @param object       填充对象* @param fileName     文件名称* @param templateName 模板名称* @throws Exception*/public void exportTemplateExcel(HttpServletResponse response, List<?> dataList, Object object,String fileName, String templateName) throws Exception {InputStream inputStream = this.getClass().getResourceAsStream(templateName);FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();ExcelWriter excelWriter = EasyExcelFactory.write(getOutputStream(fileName, response)).withTemplate(inputStream).build();WriteSheet writeSheet0 = EasyExcelFactory.writerSheet(0).build();excelWriter.fill(object, fillConfig, writeSheet0);excelWriter.fill(dataList, fillConfig, writeSheet0);excelWriter.finish();}/*** 构建输出流** @param fileName 文件名称* @param response 输出流* @return* @throws Exception*/private OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding(StandardCharsets.UTF_8.name());response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");return response.getOutputStream();}/*** 文件格式校验** @param file 文件*/public  void checkFile(MultipartFile file) throws ApiException{if (file == null) {throw new ApiException("500", "文件不能为空");}String filename = file.getOriginalFilename();if (StringUtils.isEmpty(filename)) {throw new ApiException("500", "文件不能为空");}if (!filename.endsWith(".xls") && !filename.endsWith(".xlsx")) {throw new ApiException("500", "请上传.xls文件或者.xlsx文件");}}/*** 动态表头生成excel* @param headers 要生成的表头* @param dataList 数据* @param response* @param fileName 文件名称* @param titleName title名称* @param <T>*/public static <T> void dynamicExportExcel(List<ExcelHeader> headers, List<T> dataList, HttpServletResponse response, String fileName, String titleName) {long startTime = System.currentTimeMillis();List<List<T>> allList = new ArrayList<>();for (T detail : dataList) {allList.addAll(dataList(headers, detail));}try (ServletOutputStream outputStream = response.getOutputStream()) {String name = com.sun.deploy.net.URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + name + ".xlsx");//设置响应头response.setHeader("mime","application/vnd.ms-excel");EasyExcel.write(outputStream).head(headers(headers))//表格标题占位.relativeHeadRowIndex(1)//文件样式.registerWriteHandler(new CustomTitleWriteHandler(headers.size(),titleName)).registerWriteHandler(new CellStyle()).sheet(fileName).doWrite(allList);} catch (IOException e) {log.error("生成动态EXL失败,字段", e);}long endTime = System.currentTimeMillis();log.info("动态导出耗时:{}", endTime - startTime);}//excel表头public static List<List<String>> headers(List<ExcelHeader> excelHeaders) {List<List<String>> headers = new ArrayList<>();for (ExcelHeader header : excelHeaders) {List<String> head = new ArrayList<>();head.add(header.getHeadName());headers.add(head);}return headers;}/*** 要导出的字段** @param exportFields 表头集合* @param obj          数据对象* @return 集合*/@SneakyThrowspublic static <T> List<List<T>> dataList(List<ExcelHeader> exportFields, T obj) {List<List<T>> list = new ArrayList<>();List<T> data = new ArrayList<>();List<String> propList = exportFields.stream().map(ExcelHeader::getFieldName).collect(Collectors.toList());//先根据反射获取实体类的class对象Class<?> objClass = obj.getClass();//设置实体类属性的集合Field[] fields = ReflectUtil.getFields(objClass);for (String prop : propList) {//循环实体类对象集合for (Field field : fields) {field.setAccessible(true);//判断实体类属性跟特定字段集合名是否一样if (field.getName().equals(prop)) {T object = (T) field.get(obj);//获取属性对应的值if(null == object){object = (T) "--";}else{if(object instanceof LocalDate){object = (T) DateUtil.localDateToString((LocalDate)object);}if(object instanceof LocalDateTime){object = (T) DateUtil.localDateTimeToString((LocalDateTime)object);}}data.add(object);}}}list.add(data);return list;}}

2、标题设置类

import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;public class CustomTitleWriteHandler implements SheetWriteHandler {/*** 标题*/private final String fileName;/*** 字段个数*/private final Integer count;public CustomTitleWriteHandler(Integer count,String fileName) {this.fileName = fileName;this.count = count;}@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 获取clazz所有的属性Workbook workbook = writeWorkbookHolder.getWorkbook();Sheet sheet = workbook.getSheetAt(0);Row row1 = sheet.createRow(0);row1.setHeight((short) 800);Cell cell = row1.createCell(0);//设置标题cell.setCellValue(fileName);CellStyle cellStyle = workbook.createCellStyle();cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);cellStyle.setAlignment(HorizontalAlignment.CENTER);Font font = workbook.createFont();font.setBold(true);font.setFontHeight((short) 400);font.setFontName("宋体");cellStyle.setFont(font);cell.setCellStyle(cellStyle);sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 0, 0, count-1));}
}

3、单元各简单设置类

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;import java.util.List;public class CellStyle extends AbstractColumnWidthStyleStrategy {@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head,Integer relativeRowIndex, Boolean isHead) {// 简单设置Sheet sheet = writeSheetHolder.getSheet();sheet.setColumnWidth(cell.getColumnIndex(), 5000);}}

4、controller接收参数

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ExcelHeader {/*** 要导出的字段名称英文*/private String fieldName;/*** 要导出的表头名称中文*/private String headName;/*** 排序*/private Integer order;/*** 是否展示*/private Boolean display;}

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

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

相关文章

LeetCode 203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 &#xff08;1&#xff09;直接使用原来的链表来进行移除节点操作&#xff1a; //不带头结点删除元素节点 class Solution { public:Lis…

ssh配置多账号(Mac)

一. 应用场景 当存在同时需要git在GitHub、gitee、gitlab等多个不同git托管平台进行ssh代码操作的时候。 二. 具体操作 默认 ssh-keygen -t rsa -C "你的邮箱"之后一直回车就可以&#xff0c;会默认在~/.ssh目录下生成id_rsa、id_rsa.pub 指定文件 ssh-keygen …

Git Commit的规范及高级使用方法

git commit是日常工作中使用率极高的一个命令&#xff0c;但是根据我从业5年的经验来看&#xff0c;大多数人在用git commit命令时都很粗糙&#xff0c;比如git commit -m 后跟的message是五花八门&#xff0c;有用中文的&#xff0c;有用英文的&#xff0c;甚至还有直接跟111的…

Codeforces Round 882 (Div. 2)(视频讲解A——D)

[TOC](Codeforces Round 882 (Div. 2)&#xff08;视频讲解A——D&#xff09;) 讲解在B站&#xff1a;Codeforces Round 882 (Div. 2)&#xff08;视频讲解A——D&#xff09; A The Man who became a God #include<bits/stdc.h> #define endl \n #define INF 0x3f3…

【分布式应用】zookeeper集群

目录 一、zookeeper概述1.1zookeeper工作机制1.2Zookeeper 数据结构1.3Zookeeper 应用场景1.4Zookeeper 选举机制第一次启动选举机制**非第一次启动选举机制 二、部署 Zookeeper 集群2.1环境配置2.2安装 Zookeeper 一、zookeeper概述 Zookeeper是一个开源的分布式的&#xff0c…

机械臂与RealSense相机手眼标定

环境&#xff1a; 本文主要使用kinova mico机械臂 RealSense D435i深度相机进行了eye to hand的手眼标定。 系统环境&#xff1a;Ubuntu18.04&#xff0c;ROS Melodic 硬件&#xff1a;Kinova mico&#xff0c;RealSense D435i 特别注意&#xff1a;经测试&#xff0c;本方法…

【Python】Python实现串口通信(Python+Stm32)

&#x1f389;欢迎来到Python专栏~Python实现串口通信 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望…

Js语法学习实战 -数据类型

Js语法学习实战 -数据类型 1. undefined2. null3. Boolean4. Number5. String5.1 常用方法5.2 字符串迭代遍历方法5.3 字符串替换 6. Symbol类型7. Object7.1 基本使用7.2 对象遍历7.3 复制对象方法 8. 数组 - Array8.1 数组的常用方法8.2 数组遍历 9. Function JS语法学习实战…

18.JavaWeb-JWT(登录、鉴权)

1.CSRF跨站请求伪造 跨站请求伪造&#xff08;英语&#xff1a;Cross-site request forgery&#xff09;&#xff0c;也被称为 one-click attack 或者 session riding&#xff0c;通常缩写为 CSRF 或者 XSRF&#xff0c; 是一种挟制用户在当前已登录的Web应用程序上执行非本意的…

postman测试传参格式

postman测试传参格式 创建User实体 import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;Data NoArgsConstructor AllArgsConstructor public class User {private Integer id;private String name; }接口参数是集合 PostMapping("…

第50步 深度学习图像识别:Data-efficient Image Transformers建模(Pytorch)

基于WIN10的64位系统演示 一、写在前面 &#xff08;1&#xff09;Data-efficient Image Transformers Data-efficient Image Transformers (DeiT)是一种用于图像分类的新型模型&#xff0c;由Facebook AI在2020年底提出。这种方法基于视觉Transformer&#xff0c;通过训练策…

LoRA指令微调——源码解析

目录 1. lit-llama工程2. LoRA部分3. 代码部分4. LoRA模型文件 &#xff08;本次博文的LoRA代码主要基于lit-llama工程&#xff09; 1. lit-llama工程 lit-llama是一个大语言模型的工程&#xff0c;可用于语言模型的训练、测试等优点&#xff1a;很简洁&#xff0c;代码也很容…