从基础到进阶:打造通用 Excel 导出工具的完整指南

从基础到进阶:打造通用Excel导出工具的完整指南

在后端开发中,Excel导出是一项几乎每个系统都必备的功能。无论是数据报表、信息归档还是统计分析,都需要将系统中的数据以直观的Excel格式呈现给用户。本文将详细介绍如何基于Apache POI实现一个通用的Excel导出工具,并通过样式优化提升导出文件的专业性,让你无需重复开发即可满足各类导出需求。

一、为什么需要通用Excel导出工具?

在传统开发模式中,为每个业务模块编写Excel导出代码会导致以下问题:

  • 重复劳动:创建工作簿、构建表头、填充数据等逻辑在不同模块反复编写
  • 维护困难:当需要调整格式时,需修改多处代码,易遗漏且效率低下
  • 风格混乱:不同开发者实现的导出功能样式不一,影响用户体验

通用Excel导出工具的核心价值在于:通过反射机制实现任意实体类的一键导出,一次开发,全项目复用,同时支持灵活的样式定制,兼顾功能性与美观度。

二、基础版实现:快速搭建导出功能

基础版工具类专注于实现核心导出逻辑,通过反射自动识别实体类字段,生成表头和数据行,满足最基本的导出需求。

1. 核心代码实现

import io.swagger.annotations.ApiModelProperty;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ExcelExportUtil {
   
   

    /**
     * 基础版Excel导出
     * @param entityList 待导出的数据集合
     * @param clazz 实体类字节码(用于反射获取字段信息)
     * @return 导出的Excel字节数组
     */
    public static <T> byte[] outputExcel(List<T> entityList, Class<T> clazz) {
   
   
        try {
   
   
            if (entityList == null || entityList.isEmpty()) return null;

            // 1. 创建工作簿和工作表
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("Sheet1");

            // 2. 获取字段与表头的映射关系(从Swagger注解提取)
            Map<Field, String> fieldTitleMap = getFieldTitleMap(clazz.getDeclaredFields());

            // 3. 创建表头行
            Row titleRow = sheet.createRow(0);
            titleRow.createCell(0).setCellValue("序号"); // 固定序号列
            int cellIndex = 1;
            for (Field field : fieldTitleMap.keySet()) {
   
   
                titleRow.createCell(cellIndex).setCellValue(fieldTitleMap.get(field));
                cellIndex++;
            }

            // 4. 填充数据行
            for (int i = 0; i < entityList.size(); i++) {
   
   
                T entity = entityList.get(i);
                processDataRow(sheet, fieldTitleMap, i + 1, entity);
            }

            // 5. 转换为字节数组返回
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            workbook.write(byteArrayOutputStream);
            byte[] buffer = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();

            return buffer;
        } catch (Exception e) {
   
   
            throw new RuntimeException("导出Excel失败:" + e);
        }
    }

    /**
     * 从实体类字段的@ApiModelProperty注解中提取表头名称
     */
    private static <T> Map<Field, String> getFieldTitleMap(Field[] fieldList) {
   
   
        Map<Field, String> fieldTitleMap = new LinkedHashMap<>(); // 保持字段声明顺序
        for (Field field : fieldList) {
   
   
            ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
            if (apiModelProperty != null) {
   
   
                fieldTitleMap.put(field, apiModelProperty.value());
            }
        }
        return fieldTitleMap;
    }

    /**
     * 处理单条数据,填充到Excel行
     */
    private static <T> void processDataRow(Sheet sheet, Map<Field, String> fieldTitleMap, int rowIndex, T entity) {
   
   
        try {
   
   
            Row dataRow = sheet.createRow(rowIndex);
            dataRow.createCell(0).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值