我使用OpenXML SDK更新Excel电子表格的内容。将单元格插入Excel行时,必须以正确的顺序插入,否则文件将无法在Excel中正确打开。我使用以下代码查找将插入单元格后面的第一个单元格。此代码几乎直接来自OpenXML SDK documentation
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创建了腐败的电子表格,每当我试图保存时,EPPlus都会抛出异常。我正在使用每个版本的最新版本。
答案 0 :(得分:1)
您使用的代码存在严重缺陷。这非常不幸,因为它来自文档。对于仅使用前26列的电子表格,它可能会令人满意,但在面对更宽的&#34;时会失败。电子表格。前26列按字母顺序命名,A-Z。第27-52列命名为AA-AZ。第53-78栏命名为BA-BZ。 (你应该注意到这种模式。)
Cell&#34; AA1&#34; 之后 所有具有单个字符列名称的单元格(即&#34; A1&#34; - &#34; Z1&#34;)。让我们检查比较单元格的当前代码&#34; AA1&#34;与细胞&#34; B1&#34;。
string.Compare("B1", "AA1", true)
返回值1 此时单元格将出现故障,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;
}
如果您想在列中放置一个新单元格&#34; BC&#34;你正在与细胞进行比较&#34; D5&#34;你会使用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));
}