POI 通用导出Excel(.xls,.xlsx)

POI操作EXCEL对象
HSSF:操作Excel 97(.xls)格式
XSSF:操作Excel 2007 OOXML (.xlsx)格式,操作EXCEL内存占用高于HSSF
SXSSF:从POI3.8 beta3开始支持,基于XSSF,低内存占用。

使用POI的HSSF对象,生成Excel 97(.xls)格式,生成的EXCEL不经过压缩直接导出。
线上问题:负载服务器转发请求到应用服务器阻塞,以及内存溢出 。
如果系统存在大数据量报表导出,则考虑使用POI的SXSSF进行EXCEL操作。

HSSF生成的Excel 97(.xls)格式本身就有每个sheet页不能超过65536条的限制。
XSSF生成Excel 2007 OOXML (.xlsx)格式,条数增加了,但是导出过程中,内存占用率却高于HSSF.
SXSSF是自3.8-beta3版本后,基于XSSF提供的低内存占用的操作EXCEL对象。其原理是可以设置或者手动将内存中的EXCEL行写到硬盘中,这样内存中只保存了少量的EXCEL行进行操作。

EXCEL的压缩率特别高,能达到80%,12M的文件压缩后才2M左右。 如果未经过压缩、不仅会占用用户带宽,且会导致负载服务器(apache)和应用服务器之间,长时间占用连接(二进制流转发),导致负载服务器请求阻塞,不能提供服务。

  • 一定要注意文件流的关闭

  • 防止前台(页面)连续触发导出EXCEL

1.通用核心导出工具类 ExcelUtil.java
package sy.util;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFComment;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class ExcelUtil{
    public static String NO_DEFINE = "no_define";//未定义的字段
    public static String DEFAULT_DATE_PATTERN="yyyy年MM月dd日";//默认日期格式
    public static int DEFAULT_COLOUMN_WIDTH = 17;
    /**
     * 导出Excel 97(.xls)格式 ,少量数据
     * @param title 标题行 
     * @param headMap 属性-列名
     * @param jsonArray 数据集
     * @param datePattern 日期格式,null则用默认日期格式
     * @param colWidth 列宽 默认 至少17个字节
     * @param out 输出流
     */
   
在使用 Apache POI 导出 Excel `.xls` 文件时,可能会遇到设置列宽超过最大限制的问题。Excel `.xls` 格式(HSSF)对列宽有明确的限制,最大列宽为 **255 字符宽度单位**(1 个字符宽度单位约为 1/256 个字符宽度)[^2]。 ### 解决方案 1. **理解列宽限制** Excel 97(`.xls`)格式的列宽最大值为 255,因此尝试设置超过该值的列宽将不会生效。例如,若设置 `sheet.setColumnWidth(0, 300)`,实际列宽仍会被限制为 255[^2]。 2. **自动调整列宽** 如果需要根据内容自动调整列宽,可以使用 `sheet.autoSizeColumn()` 方法。该方法会根据当前列中最长的内容自动调整列宽,但需要注意的是,此方法在处理大量数据时可能影响性能。 ```java sheet.autoSizeColumn(0); // 自动调整第一列宽度 ``` 3. **使用 `.xlsx` 格式替代 `.xls`** 若需要更宽的列,建议使用 `.xlsx` 格式(XSSF)代替 `.xls` 格式。`.xlsx` 格式支持的最大列宽为 **255 字符**,与 `.xls` 相同,但 XSSF 提供了更好的结构支持和更高的灵活性。如果确实需要更宽的列,可考虑将内容换行或拆分到多个列中。 4. **优化数据展示方式** 如果列宽受限导致内容显示不全,可以考虑以下优化方式: - 使用换行符 `\n` 在单元格中换行显示内容。 - 将长字段拆分为多个字段,分别放在不同列中。 - 调整单元格的对齐方式以提高可读性。 ```java Cell cell = row.createCell(0); cell.setCellValue("第一行内容\n第二行内容"); ``` 5. **内存优化与大数据导出** 若导出的数据量较大,建议使用 `SXSSF`(基于 `.xlsx` 的内存优化模型),以避免内存溢出问题。虽然 SXSSF 主要用于 `.xlsx` 文件,但在大数据量场景下其性能优势明显[^2]。 ```java Workbook workbook = new SXSSFWorkbook(100); // 保留100行在内存中 Sheet sheet = workbook.createSheet("Sheet1"); ``` ### 总结 在使用 Apache POI 导出 `.xls` 文件时,列宽限制为 255 字符宽度单位是不可突破的限制。解决该问题的可行方法包括自动调整列宽、优化数据展示、使用 `.xlsx` 格式或采用 SXSSF 模型进行大数据导出。在实际开发中,应根据业务需求选择合适的格式和策略,以确保导出功能的稳定性和可扩展性。 ---
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值