简体   繁体   English

筛选后如何获取正确的行范围导致excel互操作

[英]How to get correct range of rows after filtering results in excel interop

This is an extension of How do I access a cell in Excel Interop when using filtered ranges? 这是使用过滤范围时如何访问Excel Interop中的单元格的扩展

Why does the first segment of code iterate through the correct number of rows, but the second segment continue beyond the range of rows? 为什么第一段代码迭代正确的行数,但是第二段继续超出行范围? To recap: 回顾一下:

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

Iterates through the correct number of rows but does not take into account filtered rows. 遍历正确的行数,但不考虑过滤的行。

   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;
            }
    }

Takes into account filtered rows but the inner loop continues beyond the rage of rows per area. 考虑到已过滤的行,但内部循环继续超出每个区域行数的范围。

The outer loop across areas seems redundant. 跨区域的外部循环似乎是多余的。 You could try removing it and changing the inner loop to 您可以尝试将其删除并将内部循环更改为

foreach (Excel.Range row in range.Rows)

Furthermore, Range.UsedRange is known to sometimes return unexpected results. 此外,已知Range.UsedRange有时会返回意外结果。 See http://www.vbaexpress.com/kb/getarticle.php?kb_id=82 参见http://www.vbaexpress.com/kb/getarticle.php?kb_id=82

There are several alternatives:- 有几种选择:

  1. range = ((Excel.Range)ws.Cells[1, 1]).CurrentRegion - if your range has at least one column which has continuous values (no gaps) then this should work well. range = ((Excel.Range)ws.Cells[1, 1]).CurrentRegion如果您的范围中至少有一列具有连续值(无间隔),则此方法应该可以正常工作。

  2. Name the range explicitly, so that you can just do range = ws.Range("MyRange") 明确命名范围,以便您可以执行range = ws.Range("MyRange")

  3. Find the last row of your range and construct the target range using the first row and last row, eg range = ws.Range(ws.Cells[1, 1], ((Excel.Range)ws.Cells[1048576,1]).End(xlUp)).EntireRow (note that 1048576 is the highest row index in Excel 2007 and Excel 2010 and 65536 is the highest row index in earlier versions). 找到范围的最后一行,并使用第一行和最后一行来构建目标范围,例如range = ws.Range(ws.Cells[1, 1], ((Excel.Range)ws.Cells[1048576,1]).End(xlUp)).EntireRow (请注意,1048576是Excel 2007和Excel 2010中的最高行索引,而65536是早期版本中的最高行索引)。 Here I am using the first column of the range to determine the last row of the range by calling End(xlUp) on the cell at the bottom of the worksheet in that first column. 在这里,我使用范围的第一列来确定范围的最后一行,方法是在工作表底部第一列的单元格上调用End(xlUp) This requires that the column does not contain any empty values within the data. 这要求该列在数据中不包含任何空值。 If the first column can contain empty values, then you should use another column, which is guaranteed to have a value in your data. 如果第一列可以包含空值,则应使用另一列,该列保证在您的数据中包含一个值。

Also, to preserve your skipping of the first two rows, you could try:- 另外,要保留对前两行的跳过,可以尝试:

using System.Linq;

foreach (Excel.Range row in range.Rows.Skip(2))

(Obviously if you used alternative method 3 to determine your target range then you could set the first row to be row 3 instead of row 1 by using ws.Cells[3, 1] as the top bound of the range, so you would not have to call Skip() in this manner). (显然,如果您使用替代方法3确定目标范围,则可以使用ws.Cells[3, 1]作为范围的上限,将第一行设置为第3行而不是第1行,因此您不必必须以这种方式调用Skip() )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM