过滤后如何获得正确的行范围导致excel互操作

时间:2011-12-11 23:21:21

标签: c# visual-studio-2008 excel excel-interop

这是How do I access a cell in Excel Interop when using filtered ranges?

的扩展

为什么第一段代码会迭代正确的行数,但第二段继续超出行的范围?回顾一下:

   range = ws.UsedRange;
   for (int row = 3; row <= range.Rows.Count; row++)
    {
        Object nObj = ((Excel.Range)ws.Cells[row, "N"]).Text;
    }

迭代正确的行数,但不考虑过滤的行。

   range = ws.UsedRange.SpecialCells(Excel.XlCellType.xlCellTypeVisible, Type.Missing);
    foreach (Excel.Range area in range.Areas)
    {
        foreach (Excel.Range row in area.Rows)
            //for (int row = 3; row <= range.Rows.Count; row++)
            {
                Object nObj = ((Excel.Range)row.Cells[1, 14]).Text;
            }
    }

考虑过滤后的行,但内部循环继续超出每个区域的行范围。

1 个答案:

答案 0 :(得分:1)

跨区域的外环似乎是多余的。您可以尝试删除它并将内循环更改为

foreach (Excel.Range row in range.Rows)

此外,已知Range.UsedRange有时会返回意外结果。见http://www.vbaexpress.com/kb/getarticle.php?kb_id=82

有几种选择: -

  1. range = ((Excel.Range)ws.Cells[1, 1]).CurrentRegion - 如果您的范围至少有一列具有连续值(无间隙),那么这应该可以正常工作。

  2. 明确命名范围,以便您可以range = ws.Range("MyRange")

  3. 找到范围的最后一行,并使用第一行和最后一行构建目标范围,例如: range = ws.Range(ws.Cells[1, 1], ((Excel.Range)ws.Cells[1048576,1]).End(xlUp)).EntireRow(请注意,1048576是Excel 2007和Excel 2010中的最高行索引,而65536是早期版本中的最高行索引)。在这里,我使用范围的第一列通过调用第一列工作表底部单元格上的End(xlUp)来确定范围的最后一行。这要求列不包含数据中的任何空值。如果第一列可以包含空值,那么您应该使用另一列,该列保证在您的数据中具有值。

  4. 另外,为了保留跳过前两行,您可以尝试: -

    using System.Linq;
    
    foreach (Excel.Range row in range.Rows.Skip(2))
    

    (显然,如果您使用替代方法3来确定目标范围,那么您可以使用ws.Cells[3, 1]作为范围的上限,将第一行设置为第3行而不是第1行,这样您就不会必须以这种方式致电Skip()