如何插入Excel单元格而不创build损坏的文件?

我正在使用OpenXML SDK来更新Excel电子表格的内容。 将单元格插入Excel行时,必须按照正确的顺序插入,否则文件将无法在Excel中正确打开。 我正在使用下面的代码来find将插入单元格后的第一个单元格。 这段代码几乎直接来自OpenXML SDK文档

public static Cell GetFirstFollowingCell(Row row, string newCellReference) { Cell refCell = null; foreach (Cell cell in row.Elements<Cell>()) { if (string.Compare(cell.CellReference.Value, newCellReference, true) > 0) { refCell = cell; break; } } return refCell; } 

当我用此代码编辑文件,然后在Excel中打开它们时,Excel报告文件已损坏。 Excel能够修复该文件,但大部分数据已从工作簿中删除。 为什么这会导致文件损坏?

注意:在转向痛苦的底层OpenXML SDK之前,我尝试了两个不同的.NET Excel库。 NPOI创build了包含损坏的电子表格,并且每当我尝试保存时,EPPlus都会抛出exception。 我正在使用每个版本的最新版本。

你使用的代码是严重的缺陷。 这是非常不幸的,因为它来自文件。 对于仅使用前26列的电子表格而言,它可能是可以接受的,但在面对“更宽”的电子表格时将会惨遭失败。 前26列按字母顺序排列,AZ。 第27-52列被命名为AA-AZ。 列53-78被命名为BA-BZ。 (你应该注意到这个模式。)

单元格“AA1”应该单个字符列名(即“A1” – “Z1”)的所有单元格之后 。 我们来看一下比较单元格“AA1”和单元格“B1”的当前代码。

  1. string.Compare("B1", "AA1", true)返回值1
  2. 代码解释这意味着“AA1”应放在单元格“B1” 之前
  3. 调用代码将在XML中的“B1” 之前插入“AA1”。

在这一点上,单元格将失序,Excel文件已损坏。 显然, string.Compare是不足以确定一行中单元格的正确顺序的。 需要更复杂的比较。

 public static bool IsNewCellAfterCurrentCell(string currentCellReference, string newCellReference) { var columnNameRegex = new Regex("[A-Za-z]+"); var currentCellColumn = columnNameRegex.Match(currentCellReference).Value; var newCellColumn = columnNameRegex.Match(newCellReference).Value; var currentCellColumnLength = currentCellColumn.Length; var newCellColumnLength = newCellColumn.Length; if (currentCellColumnLength == newCellColumnLength) { var comparisonValue = string.Compare(currentCellColumn, newCellColumn, StringComparison.OrdinalIgnoreCase); return comparisonValue > 0; } return currentCellColumnLength < newCellColumnLength; } 

如果您想在“BC”列中放置一个新的单元格,并且您正在比较单元格“D5”,则可以使用IsCellAfterColumn("D5", "BC5") 。 将新的比较函数代入原始代码并用LINQ进行简化:

 public static Cell GetFirstFollowingCell(Row row, string newCellReference) { var rowCells = row.Elements<Cell>(); return rowCells.FirstOrDefault(c => IsNewCellAfterCurrentCell(c.CellReference.Value, newCellReference)); }