You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenXML SDK将DataSet导出为Excel时遇数据填充难题

问题解决:用OpenXML SDK将DataSet导出为多工作表Excel

先理清Sheet与Worksheet的核心区别

  • Sheet:属于工作簿级别的元数据条目,仅用于声明工作表的名称、唯一标识(SheetId)以及指向实际内容的关联ID(Id),本身不存储任何单元格数据。
  • WorksheetPart:是存储工作表实际内容的部件,包含SheetData(行、单元格集合)、格式设置等核心数据。每个Sheet必须关联一个独立的WorksheetPart,你之前的错误是所有Sheet都指向同一个WorksheetPart,导致文件结构异常。

修正后的完整代码

private byte[] DataSetToXlsx(DataSet ds)
{
    using var stream = new MemoryStream();
    using var spreadsheet = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook);

    // 创建工作簿部件
    var workbookPart = spreadsheet.AddWorkbookPart();
    workbookPart.Workbook = new Workbook();

    var sheets = workbookPart.Workbook.AppendChild(new Sheets());

    foreach (DataTable dt in ds.Tables)
    {
        // 为每个DataTable创建独立的WorksheetPart
        var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
        var sheetData = new SheetData();
        worksheetPart.Worksheet = new Worksheet(sheetData);

        // 1. 写入表头行
        var headerRow = new Row();
        foreach (DataColumn col in dt.Columns)
        {
            headerRow.AppendChild(CreateCell(col.ColumnName, CellValues.String));
        }
        sheetData.AppendChild(headerRow);

        // 2. 写入数据行
        foreach (DataRow row in dt.Rows)
        {
            var dataRow = new Row();
            foreach (var item in row.ItemArray)
            {
                var cellValue = item == DBNull.Value ? string.Empty : item.ToString();
                // 根据数据类型设置单元格类型,可按需扩展更多类型判断
                var cellType = item is int || item is double || item is decimal ? CellValues.Number : CellValues.String;
                dataRow.AppendChild(CreateCell(cellValue, cellType));
            }
            sheetData.AppendChild(dataRow);
        }

        // 创建Sheet元数据,关联当前WorksheetPart
        var sheetName = string.IsNullOrWhiteSpace(dt.TableName) ? $"Sheet {sheets.Count() + 1}" : dt.TableName;
        var sheet = new Sheet
        {
            Id = workbookPart.GetIdOfPart(worksheetPart),
            SheetId = (uint)(sheets.Count() + 1),
            Name = sheetName
        };
        sheets.Append(sheet);
    }

    workbookPart.Workbook.Save();
    stream.Seek(0, SeekOrigin.Begin);
    return stream.ToArray();
}

// 辅助方法:创建带值和类型的单元格
private Cell CreateCell(string cellValue, CellValues cellType)
{
    return new Cell
    {
        CellValue = new CellValue(cellValue),
        DataType = new EnumValue<CellValues>(cellType)
    };
}

关键修正点说明

  1. 每个DataTable对应独立WorksheetPart:循环内每次创建新的WorksheetPart,确保每个工作表拥有独立的内容容器,避免所有Sheet共享同一内容导致的结构错误。
  2. 填充SheetData内容:通过SheetData对象依次添加表头行和数据行,为每个单元格明确设置值和数据类型,确保Excel能正常解析文件。
  3. 正确绑定Sheet与WorksheetPart:每个Sheet的Id属性指向当前循环生成的WorksheetPart的唯一ID,完成元数据与实际内容的关联。

内容的提问来源于stack exchange,提问作者Stephan G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:52:42