【问题标题】:How to make a foreach loop with 3 or more excel ranges using C#如何使用 C# 制作具有 3 个或更多 excel 范围的 foreach 循环
【发布时间】:2017-02-07 05:54:35
【问题描述】:

在搜索了很多但无法找到我可以适应我需要的东西之后,我想我会尝试询问。 基本上我需要的是一个循环,它将贯穿我的整个范围(usedRange) 并验证是否在同一行中,3 列或更多列的单元格为空(例如 A10、B10、C10),则应删除整行。

我的一个尝试如下:

xl.Range emptyCellsDel = MySheet.UsedRange.SpecialCells(xl.XlCellType.xlCellTypeBlanks);
        xl.Range myRange = emptyCellsDel.Range["A:C"];
        const int aCol = 1; const int bCol = 2; const int cCol = 3;
        for (int i = 1; i < MySheet.UsedRange.Rows.Count; i++)
        {
            if ((MySheet.Cells[i, aCol].Value ?? "").ToString() == "" &&
                (MySheet.Cells[i, bCol].Value ?? "").ToString() == "" &&
                (MySheet.Cells[i, cCol].Value ?? "").ToString() == "")
            {
                myRange.EntireRow.Delete();
            }
        }

任何形式的想法/建议都会很棒,非常感谢。 提前谢谢你!

【问题讨论】:

    标签: c# for-loop foreach interop excel-interop


    【解决方案1】:

    正如 SmStroble 的回答所表明的那样,我之前已经提到过。如果您从 excel 文件的顶部开始并删除空行,当您删除一行并将其他行向上移动时,您将遇到索引问题,循环中的行索引将被抛出。在您发布的for 循环代码中,该变量将是i。使用这种方法会遗漏空行并可能删除非空行。

    SmStroble 的答案是解决此问题的正确方法,但存在一些问题。首先,正如评论所言,我们想从下往上删除行,因此 SmStroble 的解决方案是遍历行以查找空行的行索引并将它们放在 List&lt;int&gt; 中。这里唯一的问题是,当您在这里使用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 多行的测试表,UsedRangefor 循环中花费了 2447 毫秒,而当 usedRangefor 循环之外时花费了 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 列表。

    【讨论】:

    • 我也试过这样,但我似乎无法让它工作。我确定我在这里做错了什么,但我打算摆弄它,直到我可以让它工作。它通常处理的 excel 文件大约有 20.000-30.000 行。到目前为止,我设法完成这项工作的方式(但我试图让它更花哨)是通过在我的第一列中过滤,然后知道有时我的第二和第三列可能有空白,我将它们过滤掉,从而获得空白行并将其删除。但我想对它做一些“更大更好”的事情。我会尽快发布更新。谢谢!
    【解决方案2】:

    您需要记下要删除的行并将它们移出 for 循环,这样您就不会修改 for 循环访问的范围。

    此外,如果您要向上移动行,您还需要先删除最后一行,以免行索引混乱。在下面的示例中,我通过反转 for 循环的顺序并将行号存储在将强制排序的列表中来完成此操作。

    xl.Range myRange = emptyCellsDel.Range["A:C"];
    const int aCol = 1; const int bCol = 2; const int cCol = 3;
    List<int> rowsToDelete = new List<int>();
    int rowCount = MySheet.UsedRange.Rows.Count
    for (int i = rowCount; i >= 1; i--)
    {
        if ((MySheet.Cells[i, aCol].Value2 ?? "").ToString() == "" &&
            (MySheet.Cells[i, bCol].Value2 ?? "").ToString() == "" &&
            (MySheet.Cells[i, cCol].Value2 ?? "").ToString() == "")
        {
            rowsToDelete.Add(i);
        }
    }
    foreach (int row in rowsToDelete) { ((Range)(MySheet.Rows[row])).Delete(XlDirection.xlUp); }
    

    【讨论】:

    • 我试过了,但由于某种原因,它不会删除任何空行。
    • 尝试将 .Value 切换为 .Value2 单元格可能有一些格式(如日期/时间),它返回具有非空白默认值的类型。
    • @JohnG 废话。我发誓我做了那个改变,我想它没有成为我的答案。固定。
    猜你喜欢
    • 2020-02-23
    • 2023-03-28
    • 1970-01-01
    • 2016-11-24
    • 1970-01-01
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多