[英]How do I insert Excel cells without creating a corrupt file?
I'm using the OpenXML SDK to update the contents of an Excel spreadsheet. 我正在使用OpenXML SDK更新Excel电子表格的内容。 When inserting cells into an Excel row they must be inserted in the correct order or the file will not open properly in Excel.
将单元格插入Excel行时,必须按正确的顺序插入它们,否则文件将无法在Excel中正确打开。 I'm using the following code to find the first cell that will be after the cell I am inserting.
我正在使用以下代码查找要插入的单元格之后的第一个单元格。 This code comes almost directly from the OpenXML SDK documentation
这段代码几乎直接来自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;
}
When I edit files with this code and then open them in Excel, Excel reports that the file is corrupted. 当我使用此代码编辑文件,然后在Excel中打开文件时,Excel报告文件已损坏。 Excel is able to repair the file, but most of the data is removed from the workbook.
Excel能够修复该文件,但是大多数数据已从工作簿中删除。 Why does this result in file corruption?
为什么这会导致文件损坏?
Side note: I tried two different .NET Excel libraries before turning to the painfully low-level OpenXML SDK. 旁注:在尝试使用痛苦的低级OpenXML SDK之前,我尝试了两种不同的.NET Excel库。 NPOI created spreadsheets with corruption and EPPlus threw an exception whenever I tried to save.
NPOI创建的电子表格存在损坏,每当我尝试保存时,EPPlus都会引发异常。 I was using the most recent version of each.
我正在使用每个的最新版本。
The code you are using is seriously flawed. 您使用的代码存在严重缺陷。 This is very unfortunate, seeing as it comes from the documentation.
看到它来自文档,这是非常不幸的。 It may work acceptably for spreadsheets that only use the first 26 columns but will fail miserably when confronted with "wider" spreadsheets.
对于仅使用前26列的电子表格来说,它可能可以接受,但是当遇到“更宽”的电子表格时,它会惨败。 The first 26 columns are named alphabetically, AZ.
前26列按字母顺序命名为AZ。 Columns 27-52 are named AA-AZ.
第27-52列称为AA-AZ。 Column 53-78 are named BA-BZ.
列53-78命名为BA-BZ。 (You should notice the pattern.)
(您应该注意该模式。)
Cell "AA1" should come after all cells with a single character column name (ie "A1" - "Z1"). 单元格“ AA1”应排在所有具有单个字符列名称(即“ A1”-“ Z1”)的单元格之后。 Let's examine the current code comparing cell "AA1" with cell "B1".
让我们检查一下当前代码,将单元格“ AA1”与单元格“ B1”进行比较。
string.Compare("B1", "AA1", true)
returns the value 1 string.Compare("B1", "AA1", true)
返回值1 At this point the cells will be out of order and the Excel file is corrupted. 此时,单元格将出现故障,Excel文件已损坏。 Clearly,
string.Compare
by itself is not a sufficient test to determine the proper order of cells in a row. 显然,
string.Compare
本身不足以确定行中单元格的正确顺序。 A more sophisticated comparison is required. 需要更复杂的比较。
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;
}
If you wanted to place a new cell in column "BC" and you were comparing to cell "D5" you would use IsCellAfterColumn("D5", "BC5")
. 如果要在“ BC”列中放置一个新单元格,并且要与“ D5”单元格进行比较,则可以使用
IsCellAfterColumn("D5", "BC5")
。 Substituting the new comparison function into the original code and simplifying with LINQ: 将新的比较功能替换为原始代码,并使用LINQ进行简化:
public static Cell GetFirstFollowingCell(Row row, string newCellReference)
{
var rowCells = row.Elements<Cell>();
return rowCells.FirstOrDefault(c => IsNewCellAfterCurrentCell(c.CellReference.Value, newCellReference));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.