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

使用DocumentFormat.OpenXml拼接Excel单元格字符串遇格式问题求助

解决DocumentFormat.OpenXml Excel字符串拼接问题

问题根源

Excel的OpenXml格式中,字符串类型单元格默认会把文本存入共享字符串表(SharedStringTable),Cell.Value存储的是该文本在表中的整数索引,而非实际显示的字符串:

  • 直接拼接Cell.Value会因类型不匹配(整数和字符串/数值拼接)报错;
  • 强行设置单元格类型为String后,会把索引数字当成文本拼接,导致得到数字组合而非预期的显示文本。

解决方案

核心是先获取单元格的实际显示文本,再将拼接结果按规范写入Excel。

1. 编写工具方法获取单元格实际文本

private static string GetCellText(Cell cell, SharedStringTablePart sharedStringPart)
{
    if (cell == null || cell.CellValue == null)
        return string.Empty;

    string rawValue = cell.CellValue.Text;
    // 处理共享字符串类型的单元格
    if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
    {
        return sharedStringPart.SharedStringTable.ElementAt(int.Parse(rawValue)).InnerText;
    }
    // 处理数字、布尔等其他类型,直接转字符串
    return rawValue;
}

2. 编写工具方法将文本存入共享字符串表

(符合Excel存储规范,避免重复文本占用空间)

private static int AddSharedString(string text, SharedStringTablePart sharedStringPart)
{
    if (sharedStringPart.SharedStringTable == null)
    {
        sharedStringPart.SharedStringTable = new SharedStringTable();
    }

    // 检查文本是否已存在,复用已有索引
    foreach (SharedStringItem item in sharedStringPart.SharedStringTable.Elements<SharedStringItem>())
    {
        if (item.InnerText == text)
        {
            return sharedStringPart.SharedStringTable.Elements<SharedStringItem>().ToList().IndexOf(item);
        }
    }

    // 添加新文本并返回索引
    sharedStringPart.SharedStringTable.AppendChild(new SharedStringItem(new Text(text)));
    sharedStringPart.SharedStringTable.Save();
    return sharedStringPart.SharedStringTable.Elements<SharedStringItem>().Count() - 1;
}

3. 完整遍历拼接代码示例

using (SpreadsheetDocument doc = SpreadsheetDocument.Open("your-file.xlsx", true))
{
    WorkbookPart workbookPart = doc.WorkbookPart;
    WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
    // 确保共享字符串表存在
    SharedStringTablePart sharedStringPart = workbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault() 
        ?? workbookPart.AddNewPart<SharedStringTablePart>();

    SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

    // 遍历行(跳过表头,从第2行开始,根据实际需求调整)
    foreach (Row row in sheetData.Elements<Row>().Skip(1))
    {
        Cell cellA = row.Elements<Cell>().FirstOrDefault(c => c.CellReference.Value.StartsWith("A"));
        Cell cellB = row.Elements<Cell>().FirstOrDefault(c => c.CellReference.Value.StartsWith("B"));

        if (cellA == null || cellB == null)
            continue;

        // 获取A、B列的实际显示文本
        string textA = GetCellText(cellA, sharedStringPart);
        string textB = GetCellText(cellB, sharedStringPart);

        // 执行拼接
        string combinedText = $"{textA}{textB}";

        // 将拼接结果写入A列
        int stringIndex = AddSharedString(combinedText, sharedStringPart);
        cellA.CellValue = new CellValue(stringIndex.ToString());
        cellA.DataType = new EnumValue<CellValues>(CellValues.SharedString);
    }

    worksheetPart.Worksheet.Save();
}

补充:内联字符串写法(适合少量修改)

如果不需要复用共享字符串,也可以直接使用内联字符串写入,省去操作共享字符串表的步骤:

// 拼接完成后直接写入内联字符串
cellA.DataType = CellValues.String;
cellA.InlineString = new InlineString(new Text(combinedText));
cellA.CellValue = null; // 清除原有CellValue避免冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:12:17