kcw-wx-java/youchain-system/src/main/java/com/youchain/utils/FastExcelUtil.java

294 lines
11 KiB
Java
Raw Normal View History

2025-07-25 11:22:48 +08:00
package com.youchain.utils;
2025-09-09 13:32:59 +08:00
import cn.idev.excel.ExcelReader;
2025-07-25 11:22:48 +08:00
import cn.idev.excel.ExcelWriter;
import cn.idev.excel.FastExcel;
2025-09-09 13:32:59 +08:00
import cn.idev.excel.read.metadata.ReadSheet;
2025-07-25 11:22:48 +08:00
import cn.idev.excel.write.metadata.WriteSheet;
import cn.idev.excel.write.metadata.style.WriteCellStyle;
import cn.idev.excel.write.metadata.style.WriteFont;
import cn.idev.excel.write.style.HorizontalCellStyleStrategy;
import com.youchain.exception.BadRequestException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
2025-07-25 11:22:48 +08:00
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
2025-09-09 13:32:59 +08:00
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
2025-07-25 11:22:48 +08:00
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.web.multipart.MultipartFile;
2025-07-25 11:22:48 +08:00
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
2025-07-25 11:22:48 +08:00
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
2025-07-25 11:22:48 +08:00
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.ToLongFunction;
import java.util.stream.Collectors;
import static cn.hutool.core.util.CharsetUtil.UTF_8;
/**
* excel
*/
@Slf4j
public class FastExcelUtil {
/**
*
*
* @param response
* @param fileName
* @param fileSize
*/
public static void setDownloadFileHeader(HttpServletResponse response, String fileName, Long fileSize) {
response.setCharacterEncoding(UTF_8);
if (fileSize != null) {
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileSize));
}
if (StringUtils.isNotEmpty(fileName)) {
response.setHeader(HttpHeaders.CONTENT_TYPE, MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM) + ";charset=utf-8");
try {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, UTF_8).replaceAll("\\+", "%20"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
}
}
/**
*
*
* @return horizontalCellStyleStrategy
*/
public static HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontName("宋体");
headWriteFont.setColor(IndexedColors.WHITE.getIndex());
headWriteCellStyle.setWriteFont(headWriteFont);
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setFillForegroundColor(IndexedColors.BLACK.getIndex());
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}
/**
* sheet
*/
public static void exportExcel(HttpServletResponse response, String fileName, String sheetName, Class head, Collection<?> data) throws IOException {
// 设置下载消息头
setDownloadFileHeader(response, fileName, null);
//样式
HorizontalCellStyleStrategy horizontalCellStyleStrategy = getHorizontalCellStyleStrategy();
// 下载
FastExcel.write(response.getOutputStream(), head)
.autoCloseStream(Boolean.FALSE)
.sheet(sheetName)
.registerWriteHandler(horizontalCellStyleStrategy)
.doWrite(data);
}
/**
*
*
* @param response
* @param fileName
* @param sheetName sheet
* @param head
2025-07-25 11:22:48 +08:00
* @param pageQueryFunction
* @param convertFunction
* @param idExtractor id
* @param pageSize
* @param <T>
* @param <E>
2025-07-25 11:22:48 +08:00
*/
public static <T, E> void batchExportExcel(HttpServletResponse response, String fileName, String sheetName, Class head, BiFunction<Long, Integer, List<T>> pageQueryFunction, Function<T, E> convertFunction, ToLongFunction<T> idExtractor, int pageSize) {
long startTime = System.currentTimeMillis();
// 设置下载消息头
setDownloadFileHeader(response, fileName, null);
HorizontalCellStyleStrategy horizontalCellStyleStrategy = getHorizontalCellStyleStrategy();
try (ExcelWriter excelWriter = FastExcel.write(response.getOutputStream(), head).registerWriteHandler(horizontalCellStyleStrategy).build()) {
WriteSheet writeSheet = FastExcel.writerSheet(sheetName).build();
long lastId = 0;//最后一个id
while (true) {
List<T> batch = pageQueryFunction.apply(lastId, pageSize);
if (batch.isEmpty()) {
break;
}
List<E> excelData = batch.stream()
.map(convertFunction)
.collect(Collectors.toList());
excelWriter.write(excelData, writeSheet);
lastId = batch.stream()
.mapToLong(idExtractor)
.max()
.orElse(lastId);
}
excelWriter.finish();
log.info("导出总耗时: {}ms", System.currentTimeMillis() - startTime);
} catch (Exception e) {
throw new BadRequestException("导出失败");
}
}
/**
* Excel
*
* @param file Excel
* @param clazz Template1.class
* @param <T>
* @return
*/
public static <T> List<T> readExcelData(MultipartFile file, Class<T> clazz, int sheetNo, int headRowNumber) {
List<T> dataList;
try {
dataList = FastExcel.read(file.getInputStream()).head(clazz)
.sheet(sheetNo)
.headRowNumber(headRowNumber)
.doReadSync();
} catch (IOException e) {
throw new BadRequestException("数据格式存在问题,无法读取");
}
if (CollectionUtils.isEmpty(dataList)) {
throw new BadRequestException("数据为空");
}
return dataList;
}
2025-08-20 14:35:05 +08:00
2025-09-09 13:32:59 +08:00
public static List<Map<Integer, Object>> readExcelData2(MultipartFile file, int headRowNumber) {
2025-08-20 14:35:05 +08:00
try {
return FastExcel.read(file.getInputStream())
2025-08-29 18:01:11 +08:00
.sheet()
.headRowNumber(headRowNumber)
2025-08-20 14:35:05 +08:00
.doReadSync();
} catch (IOException e) {
throw new BadRequestException("数据格式存在问题,无法读取");
}
}
/**
* Excel
*
* @param file Excel
* @param reader
*/
2025-09-09 13:32:59 +08:00
public static Map<String, String> readExcelCellValues(MultipartFile file, FastExcelCellListener reader, int sheetNo) {
try {
FastExcel.read(file.getInputStream(), reader)
2025-09-09 13:32:59 +08:00
.sheet(sheetNo)
.doReadSync();
} catch (IOException e) {
throw new BadRequestException("数据格式存在问题,无法读取");
}
return reader.getAllCellValues();
}
/**
* Excel
*
* @param inputStream Excel
* @return
*/
public static List<String> readHeadContent(InputStream inputStream, int sheetNo, int headRowNumber) {
List<Object> data = FastExcel.read(inputStream)
.sheet(sheetNo)
.headRowNumber(headRowNumber)
.doReadSync();
// 检查是否有数据
if (data.isEmpty()) {
throw new BadRequestException("导入模板不正确,请确认模板信息");
}
Object firstRow = data.get(0);
// 将头部内容转换为字符串列表
if (firstRow instanceof Map) {
Map<?, ?> rowMap = (Map<?, ?>) firstRow;
return rowMap.values().stream()
.map(value -> value == null ? "" : value.toString())
.collect(Collectors.toList());
} else {
throw new BadRequestException("读取Excel头部内容格式异常");
}
}
/**
* Excel
*
* @return true
*/
2025-09-09 13:32:59 +08:00
public static List<String> readHeadContent(MultipartFile file, int sheetNo, int headRowNumber) {
try {
//判断头部内容是否包含所有必填列
2025-10-21 18:29:09 +08:00
log.info(file.getInputStream()+"");
return readHeadContent(file.getInputStream(), sheetNo, headRowNumber);
} catch (IOException e) {
throw new BadRequestException("数据格式存在问题,无法读取");
}
}
2025-09-09 13:32:59 +08:00
public static List<ReadSheet> readSheets(MultipartFile file) {
try (ExcelReader excelReader = FastExcel.read(file.getInputStream()).build()) {
// 获取所有Sheet
List<ReadSheet> allSheets = excelReader.excelExecutor().sheetList();
// 使用 POI 检测隐的sheet
Set<String> hiddenSheetNames = getHiddenSheetNames(file);
//过滤隐藏的sheet
return allSheets.stream()
.filter(sheet -> !hiddenSheetNames.contains(sheet.getSheetName()))
.collect(Collectors.toList());
} catch (IOException e) {
log.error("读取Excel Sheet信息失败", e);
throw new BadRequestException("读取Excel Sheet信息失败");
}
}
/**
* Sheet
*
* @param file
*/
private static Set<String> getHiddenSheetNames(MultipartFile file) {
Set<String> hiddenSheets = new HashSet<>();
try (InputStream inputStream = file.getInputStream();
Workbook workbook = WorkbookFactory.create(inputStream)) {
int numberOfSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
if (workbook.isSheetHidden(i) || workbook.isSheetVeryHidden(i)) {
String sheetName = workbook.getSheetName(i);
hiddenSheets.add(sheetName);
}
}
} catch (Exception e) {
throw new BadRequestException("获取隐藏的Sheet名称失败");
}
return hiddenSheets;
}
2025-07-25 11:22:48 +08:00
}