package com.cxkh.aqjk.util;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.utils.DateUtils;
import org.apache.poi.ss.usermodel.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EnhancedExcelUtil<T> {
public void exportExcel(HttpServletResponse response, List<T> list, String title, Class<T> clazz) throws IOException {
Workbook workbook = WorkbookFactory.create(true);
Sheet sheet = workbook.createSheet(title);
// 设置默认列宽
sheet.setDefaultColumnWidth(40);
// 获取表头信息(通过 @Excel 注解)
List<ExcelColumn> excelColumns = getExcelColumns(clazz);
int columnCount = excelColumns.size();
// 创建表头行
Row headerRow = sheet.createRow(0);
for (int i = 0; i < columnCount; i++) {
ExcelColumn column = excelColumns.get(i);
Cell cell = headerRow.createCell(i);
cell.setCellValue(column.getName());
// 设置表头样式(可根据需求自定义,这里简单示例)
CellStyle headerStyle = workbook.createCellStyle();
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
headerStyle.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerStyle.setFont(headerFont);
cell.setCellStyle(headerStyle);
}
CellStyle wrapCellStyle = workbook.createCellStyle();
wrapCellStyle.setWrapText(true); // 关键:启用自动换行
wrapCellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
wrapCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
// 填充数据行
for (int i = 0; i < list.size(); i++) {
T entity = list.get(i);
Row dataRow = sheet.createRow(i + 1);
// 初始行高设为默认值(可选)
dataRow.setHeight((short) -1); // 使用默认高度
for (int j = 0; j < columnCount; j++) {
ExcelColumn column = excelColumns.get(j);
Cell cell = dataRow.createCell(j);
Object value = getFieldValue(entity, column.getField());
// 设置单元格值
setCellValue(cell, value, column);
// 应用自动换行样式
cell.setCellStyle(wrapCellStyle);
}
// 关键:自动调整行高
adjustRowHeight(dataRow, sheet);
}
// 导出设置
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(title + ".xlsx", "UTF-8"));
OutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
outputStream.close();
workbook.close();
}
// 自动调整行高的辅助方法
private void adjustRowHeight(Row row, Sheet sheet) {
for (Cell cell : row) {
if (cell.getCellType() == CellType.STRING) {
String text = cell.getStringCellValue();
if (text != null && !text.isEmpty()) {
// 计算文本所需高度
int lines = calculateLineCount(text, sheet.getColumnWidth(cell.getColumnIndex()));
if (lines > 1) {
// 设置行高(每行高度约20点)
row.setHeightInPoints(lines * 50);
}
}
}
}
}
// 计算文本在单元格中的行数
private int calculateLineCount(String text, int columnWidth) {
// 列宽单位转换(POI单位 → 字符宽度)
double charWidth = 256; // 每个字符的标准宽度
double maxChars = columnWidth / charWidth * 1.5; // 估算每行字符数
// 简单换行计算(实际应用需考虑单词边界)
int lineCount = 1;
if (text.length() > maxChars) {
lineCount = (int) Math.ceil(text.length() / maxChars);
}
return Math.max(lineCount, 1); // 至少1行
}
private List<ExcelColumn> getExcelColumns(Class<T> clazz) {
List<ExcelColumn> columns = new ArrayList<>();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
Excel excel = field.getAnnotation(Excel.class);
if (excel != null) {
ExcelColumn column = new ExcelColumn();
column.setName(excel.name());
column.setField(field);
columns.add(column);
}
}
return columns;
}
private Object getFieldValue(T entity, Field field) {
try {
field.setAccessible(true);
return field.get(entity);
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
private void setCellValue(Cell cell, Object value, ExcelColumn column) {
if (value == null) {
cell.setCellValue("");
return;
}
if (value instanceof Date) {
cell.setCellValue(DateUtils.dateTime(value.toString(), "yyyy-MM-dd"));
} else if (value instanceof String) {
cell.setCellValue((String) value);
} else {
cell.setCellValue(value.toString());
}
}
private static class ExcelColumn {
private String name; // 列名(@Excel.name)
private Field field; // 对应的实体类字段
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Field getField() {
return field;
}
public void setField(Field field) {
this.field = field;
}
}
}
java若依 excel 导出高度自适应
只有干货2025-06-11 15:43
相关推荐
bxlj_jcj1 小时前
深入剖析Debezium:CDC领域的“数据魔法棒”叶 落1 小时前
ubuntu 安装 JDK8爱学习的白杨树1 小时前
Sentinel介绍XW1 小时前
java mcp client调用 (modelcontextprotocol)保持学习ing2 小时前
SpringBoot前后台交互 -- 登录功能实现(拦截器+异常捕获器)gadiaola2 小时前
【JVM面试篇】高频八股汇总——类加载和类加载器七七&5563 小时前
【Java开发日记】基于 Spring Cloud 的微服务架构分析小猫咪怎么会有坏心思呢3 小时前
华为OD机考-数字游戏-逻辑分析(JAVA 2025B卷)Aesopcmc3 小时前
idea 启动jar程序并调试南极Ou3 小时前
Mybatis逆向工程详解(附源码文件)动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件