C#将DataTable导出为Excel的两种主流方法

许南星
许南星
发布时间:2026-10-16 | 5人浏览过
原创

在C#开发中,将内存中的DataTable数据持久化为Excel文件是常见的业务需求。根据项目对格式定制程度、性能以及是否依赖第三方商业库的不同,通常有两种主流的解决思路:一是使用功能强大的Aspose.Cells组件直接生成文件,二是利用开源的NPOI库配合HSSF接口处理数据流。本文将分别解析这两种方法的实现逻辑与代码细节。

结果与目标

核心目标是获取一个包含完整表头和数据行的Excel文件(.xlsx或.xls格式),确保数据结构正确映射,并根据需求应用基本样式(如居中、字体、边框)。对于大数据量场景,还需考虑单文件行数限制的分 Sheet 策略。

准备条件

在使用以下代码前,请确保项目中已引入相应的引用:

  • 方法一 (Aspose):需添加 Aspose.Cells 的 DLL 引用。该方法不依赖系统安装的Office环境,但涉及商业授权。
  • 方法二 (NPOI):需通过 NuGet 安装 NPOI 包。该方法完全免费且开源,生成的 .xls 文件兼容 Office 97-2003 版本。

真实操作顺序

第1步:使用Aspose.Cells直接生成并保存Excel

目的:快速将DataTable转化为格式美观的Excel文件,支持丰富的样式控制。

入口:定义静态方法 DataTableExport(DataTable data, string filepath)。

动作与参数:

  1. 初始化对象:创建 Workbook 实例作为工作簿,获取第一张工作表 Worksheet 及其 Cells 集合。
  2. 配置样式:从 Styles 中添加新样式,设置边框(LineStyle = Thin)、水平对齐(Center)、字体(宋体)及大小(11)。需注意样式对象的引用有效性。
  3. 写入表头:遍历 data.Columns.Count,调用 cells[0, i].PutValue() 填入列名,并应用上述样式。
  4. 填充数据:双层循环遍历 data.Rows。内层将单元格内容转为字符串后写入;若需计算,可使用 Formula 属性(例如:"=B2+C2")。
  5. 自适应与保存:调用 sheet.AutoFitColumns() 调整列宽,最后执行 book.Save(filepath)。

/// <summary>
/// DataTable数据导出Excel - Aspose方案
/// </summary>
public static void DataTableExport(DataTable data, string filepath)
{
    try
    {
        // 创建工作簿和工作表
        Workbook book = new Workbook(); 
        Worksheet sheet = book.Worksheets[0]; 
        Cells cells = sheet.Cells;

        // 创建样式对象
        Aspose.Cells.Style style = book.Styles[book.Styles.Add()];
        // 设置边框线
        style.Borders[Aspose.Cells.BorderType.LeftBorder].LineStyle = Aspose.Cells.CellBorderType.Thin;
        style.Borders[Aspose.Cells.BorderType.RightBorder].LineStyle = Aspose.Cells.CellBorderType.Thin;
        style.Borders[Aspose.Cells.BorderType.TopBorder].LineStyle = Aspose.Cells.CellBorderType.Thin;
        style.Borders[Aspose.Cells.BorderType.BottomBorder].LineStyle = Aspose.Cells.CellBorderType.Thin;
        
        // 设置内容与字体
        style.HorizontalAlignment = TextAlignmentType.Center;
        style.Font.Name = "宋体";
        style.Font.IsBold = true;
        style.Font.Size = 11;
        
        // int Colnum = data.Columns.Count;
        // int Rownum = data.Rows.Count;
        
        // 生成表头行
        for (int i = 0; i < data.Columns.Count; i++)
        {
            cells[0, i].PutValue(data.Columns[i].ColumnName);
            cells[0, i].SetStyle(style);
        }

        // 生成数据行
        for (int i = 0; i < data.Rows.Count; i++)
        {
            for (int k = 0; k < data.Columns.Count; k++)
            {
                // 注意:实际生产中需处理 DBNull
                cells[1 + i, k].PutValue(data.Rows[i][k].ToString()); 
                cells[1 + i, k].SetStyle(style);
            }
            // 示例公式:假设E列计算B+C列之和
            // cells[1 + i, 4].Formula = "=B" + (2 + i) + "+C" + (2 + i);
        }

        sheet.AutoFitColumns(); // 自适应列宽
        book.Save(filepath); // 保存文件
        GC.Collect(); // 强制垃圾回收释放资源
    }
    catch (Exception e)
    {
        // logger.Error("生成excel出错:" + e.Message);
        throw new Exception("生成excel出错: " + e.Message);
    }
}

第2步:使用NPOI (HSSF) 处理大容量数据导出

目的:在不引入商业库的前提下,处理可能超过65536行限制的数据,并输出标准 .xls 格式。

入口:实例化方法 ToExcel(DataTable dt)。

动作与参数:

  1. 计算Sheet数量:HSSF (.xls) 每个 Sheet 最大容纳 65,536 行。根据总行数动态计算需要创建的 Sheet 个数。
  2. 循环创建Sheet:外层循环按容量切割数据,内层 CreateSheet("Sheet" + i)。
  3. 写入标题:在每个 Sheet 的第一行(Index 0)遍历列名,使用 CreateCell().SetCellValue()。
  4. 分批写入数据:使用 count 变量追踪已写入的行数。内层循环判断当前批次剩余行数是否溢出阈值,逐个创建 Row 和 Cell。
  5. 输出文件:创建文件流 File.Create(),调用 workbook.Write(sw) 写入二进制数据,并关闭流。随后可通过 ExcelConverter 或 HTTP 响应将文件返回给前端。

public void ToExcel(DataTable dt)
{
    string FilePath = @"D:\ToExcel\"; // 产生Excel文件路径
    // DeleteFile(FilePath); // 建议增加目录存在性检查与清理逻辑

    // HSSFWorkbook 对应 .xls 格式,单Sheet上限65536行
    var workbook = new HSSFWorkbook(); 
    var count = 0;
    
    // 计算需要的Sheet数量
    double totalSheets = Math.Ceiling((double)dt.Rows.Count / 65534.0);

    for (int i = 0; i < totalSheets; i++)
    {
        var row_index = 0;
        // 创建新的Sheet
        var sheet = workbook.CreateSheet("Sheet" + i);
        IRow headerRow;
        
        // 1. 写入标题行
        headerRow = sheet.CreateRow(row_index);
        for (int j = 0; j < dt.Columns.Count; j++)
        {
            headerRow.CreateCell(j).SetCellValue(dt.Columns[j].Caption.ToString());
        }
        row_index++;

        // 2. 写入数据行
        int batchSize = (dt.Rows.Count - count > 65534) ? 65534 : (dt.Rows.Count - count);
        
        for (int j = 0; j < batchSize; j++)
        {
            var r = dt.Rows[count + j];
            var dataRow = sheet.CreateRow(row_index++);
            
            for (int k = 0; k < dt.Columns.Count; k++)
            {
                // 保持简单的字符串转换,生产环境建议按需转换为 Double/Int
                dataRow.CreateCell(k).SetCellValue(r[k].ToString());
            }
        }
        count += batchSize;
    }

    // 保存文件
    var FileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls";
    var sw = File.Create(FilePath + FileName);
    workbook.Write(sw);
    sw.Close();
    
    // 示例:Web环境下打开文件(需结合具体Web框架)
    // var EC = new ExcelConverter();
    // EC.WebopenExcel(Response, FilePath + FileName);
}

完成判断

  • 样式验证:打开生成的Excel文件,确认单元格边框清晰、文字居中且字体符合预设。
  • 数据完整性:对比源DataTable的行数与Excel中的实际行数,确保无截断或遗漏。
  • 格式兼容性:Aspose生成的 .xlsx 可被所有现代Office版本打开;NPOI生成的 .xls 确保在低版本环境中可用。

简要总结

如果项目预算允许且追求极致的格式控制与开发效率,Aspose.Cells 是首选;若需严格控制成本且只需处理基础表格,NPOI (HSSF) 则提供了可靠的开源替代方案。在实际应用中,请务必注意处理 `DBNull` 值以防止 ToString() 抛出异常,并对大文件进行必要的磁盘空间预留。

以上就是C#把DataTable导出为Excel文件的详细内容,更多关于C# Excel导出资料的关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表