java若依 excel 导出高度自适应

复制代码
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;
        }
    }
}
相关推荐
小咕聊编程13 分钟前
【含文档+PPT+源码】基于spring boot的固定资产管理系统
java·spring boot·后端
roykingw13 分钟前
【终极面试集锦】如何设计微服务熔断体系?
java·微服务·面试
我命由我1234514 分钟前
Spring Cloud - Spring Cloud 微服务概述 (微服务的产生与特点、微服务的优缺点、微服务设计原则、微服务架构的核心组件)
java·运维·spring·spring cloud·微服务·架构·java-ee
それども17 分钟前
忽略Lombok构建警告
java·开发语言·jvm
用户685453759776924 分钟前
🎮 Java设计模式:从青铜到王者的代码修炼手册
java·后端
马尚道39 分钟前
Java高手速成--吃透源码+手写组件+定制开发教程
java
我命由我1234544 分钟前
Spring Cloud - Spring Cloud 注册中心与服务提供者(Spring Cloud Eureka 概述、微服务快速入门、微服务应用实例)
java·spring boot·spring·spring cloud·微服务·eureka·java-ee
MetaverseMan1 小时前
Java Spring 框架的`@Autowired` 注解 以及依赖注入分析
java·开发语言·spring
一吃就胖的1 小时前
【给服务器安装服务器安装nacos】
java·运维·服务器
码住懒羊羊1 小时前
【C++】stack|queue|deque
java·开发语言·c++