使用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
相关产品推荐
相关产品推荐

