NPOI自适应宽度不支持中文解决方案

本文介绍使用NPOI组件解决Excel导出时的速度问题及中文列宽自适应的方法。通过对比Excel COM组件,NPOI提高了导出效率,并针对中文支持不足进行了改进。

       最近一个项目中涉及报表导出为excel功能需求。我最开始使用微软自身的excel COM组件调用的方式进行导出,发现当需要导出的内容增大到一定程度时,速度十分缓慢,而且调用COM组件需要在服务器端安装excel客户端,添加服务器对COM组件的调用权限,比较繁琐,后来在网上找了下相关信息,发现一个基于excel的操作组件NPOI,试了一下,导出速度比较理想,缩短1/5左右。

       不过在处理中文时,需要表格列宽自动调整宽度时遇到问题,NPOI的自带函数AutoSizeColumn(int 列号)只能支持英文和数字,好吧,吐槽下,身为国人,中文确实给我带来很大困扰,为什么计算机不是中国人发明的:) 吐槽完问题还是需要解决,分析下主要的问题是不支持中文,英文和数字没有问题,那就先用AutoSizeColumn(int 列号)处理一下,然后单独解决中文,NPOI自身自带为列宽指定宽度函数SetColumnWidth(int 列号,int宽度),只需要遍历一下每一列的文字,求出文字的宽度,算出这一列的最大值,重新设置本列的宽度即可。

       下面是具体代码:

//列宽自适应,只对英文和数字有效
for (int i = 0; i <= maxColumn; i++)
{
    sheet.AutoSizeColumn(i);
}
//获取当前列的宽度,然后对比本列的长度,取最大值
for (int columnNum = 0; columnNum <= maxColumn; columnNum++)
{
    int columnWidth = sheet.GetColumnWidth(columnNum) / 256;
    for (int rowNum = 1; rowNum <= sheet.LastRowNum; rowNum++)
    {
        IRow currentRow;
        //当前行未被使用过
        if (sheet.GetRow(rowNum) == null)
        {
            currentRow = sheet.CreateRow(rowNum);
        }
        else 
        {
            currentRow = sheet.GetRow(rowNum);
        }
                            
        if(currentRow.GetCell(columnNum) != null)
        {
            ICell currentCell = currentRow.GetCell(columnNum);
            int length = Encoding.Default.GetBytes(currentCell.ToString()).Length;
            if (columnWidth < length)
            {
                columnWidth = length;
            }
        }
    }
    sheet.SetColumnWidth(columnNum, columnWidth * 256);
}

       需要注意的是列的宽度为 列宽*256,所以获得的宽度需要处以256得到真实的宽度,同样再设置的时候需要再乘上256才能得到正确的值。

       我用的NPOI的版本是1.2.4,中文官方网站地址:http://tonyqus.sinaapp.com/

### C# 使用 NPOI 实现 Excel 表格列宽自适应及设置表头 以下是基于提供的引用内容和专业知识编写的代码示例,展示如何使用 C# 和 NPOI 库来实现 Excel 表格中的列宽自适应以及设置表头。 #### 列宽自适应与表头设置方法 通过 `sheet.AutoSizeColumn` 方法可以实现列宽的自动调整,而表头可以通过创建第一行并填充数据的方式完成。需要注意的是,在调用 `AutoSizeColumn` 前,必须先向单元格写入数据[^1]。 ```csharp using System; using System.Data; using NPOI.SS.UserModel; public class ExcelHelper { public void CreateExcelWithHeaderAndAutoFit(DataTable dataTable, string[] headers, IWorkbook workbook) { // 创建工作表 ISheet sheet = workbook.CreateSheet("Data"); // 定义字体样式用于表头 IFont headerFont = workbook.CreateFont(); headerFont.Boldweight = (short)FontBoldWeight.BOLD; ICellStyle headerStyle = workbook.CreateCellStyle(); headerStyle.SetFont(headerFont); // 添加表头 IRow headerRow = sheet.CreateRow(0); for (int colIndex = 0; colIndex < headers.Length; colIndex++) { ICell cell = headerRow.CreateCell(colIndex); cell.SetCellValue(headers[colIndex]); cell.CellStyle = headerStyle; } // 将 DataTable 数据填入表格 for (int rowIndex = 0; rowIndex < dataTable.Rows.Count; rowIndex++) { IRow dataRow = sheet.CreateRow(rowIndex + 1); // 跳过第0行(表头) for (int colIndex = 0; colIndex < dataTable.Columns.Count; colIndex++) { ICell cell = dataRow.CreateCell(colIndex); object value = dataTable.Rows[rowIndex][colIndex]; if (value != DBNull.Value && value != null) cell.SetCellValue(value.ToString()); } } // 自动调整列宽 for (int columnIndex = 0; columnIndex < headers.Length; columnIndex++) { sheet.AutoSizeColumn(columnIndex); // 自动生成适合宽度 int columnWidth = sheet.GetColumnWidth(columnIndex) / 256; if (columnWidth < 25) // 如果默认宽度不足,则手动扩展至最小值 sheet.SetColumnWidth(columnIndex, 25 * 256); } } } ``` 此代码实现了以下功能: 1. **表头定义**:通过数组参数传递表头名称,并应用加粗样式的字体。 2. **数据导入**:将 `DataTable` 中的数据逐行列出到 Excel 工作表中。 3. **列宽自适应**:利用 `sheet.AutoSizeColumn` 动态计算每列的最佳宽度,并提供了一个最低宽度限制以防止某些列因内容较少显得过于狭窄[^2]。 --- ### 注意事项 - 在实际开发过程中,如果发现 `AutoSizeColumn` 的效果不理想,可能是因为部分字符(如中文或其他特殊符号)未能正确影响列宽计算逻辑。这种情况下可考虑手动设定固定宽度作为补充措施。 - 当前代码假设输入的 `headers` 数组长度等于 `dataTable.Columns.Count`,否则可能导致索引越界异常。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值