正如 SmStroble 的回答所表明的那样,我之前已经提到过。如果您从 excel 文件的顶部开始并删除空行,当您删除一行并将其他行向上移动时,您将遇到索引问题,循环中的行索引将被抛出。在您发布的for 循环代码中,该变量将是i。使用这种方法会遗漏空行并可能删除非空行。
SmStroble 的答案是解决此问题的正确方法,但存在一些问题。首先,正如评论所言,我们想从下往上删除行,因此 SmStroble 的解决方案是遍历行以查找空行的行索引并将它们放在 List<int> 中。这里唯一的问题是,当您在这里使用foreach 循环时,它将从列表中的第一项开始,而不是最后一项。
您可能遇到的第二个问题是执行时间。循环遍历 Excel 行可能会很昂贵。当您在 for 循环中使用以下 MySheet.UsedRange 行时:
for (int i = 1; i < MySheet.UsedRange.Rows.Count; i++) {…
这条线很贵。如果工作表中有很多行,这可能会花费大量时间。还有其他解决方案,但是一个简单的解决方案是简单地创建一个int 变量来保存行数并在for 循环中使用它,如下所示:
int totalRows = MySheet.UsedRange.Rows.Count;
for (int i = 1; i < totalRows; i++) {
这个小改动将显着加快执行速度,具体取决于电子表格中的行数。使用包含 730 多行的测试表,UsedRange 在 for 循环中花费了 2447 毫秒,而当 usedRange 在 for 循环之外时花费了 1118 毫秒。希望这会有所帮助。
string filePath = @"C:\YourPathToExcelFile\YourExcelFile.xls";
Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();
ExcelApp.Visible = true;
Workbooks wbs = ExcelApp.Workbooks;
Workbook xlWorkbook = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Excel._Worksheet MySheet = xlWorkbook.Sheets[1];
const int aCol = 1;
const int bCol = 2;
const int cCol = 3;
List<int> rowsToDelete = new List<int>();
int totalRows = MySheet.UsedRange.Rows.Count;
for (int i = totalRows; i > 0; i--) {
if ((MySheet.Cells[i, aCol].Value ?? "").ToString() == "" &&
(MySheet.Cells[i, bCol].Value ?? "").ToString() == "" &&
(MySheet.Cells[i, cCol].Value ?? "").ToString() == "") {
rowsToDelete.Add(i);
}
}
foreach (int row in rowsToDelete) {
((Range)(MySheet.Rows[row])).Delete(XlDirection.xlUp);
}
xlWorkbook.Save();
xlWorkbook.Close();
ExcelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(ExcelApp);
Console.WriteLine("Fished processing! Press any key to exit");
Console.ReadKey();
编辑: 将上面的代码更改为从 excel 文件的底部循环到顶部。这避免了必须反转 rowsToDelete 列表。