这是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;
}
}
考虑过滤后的行,但内部循环继续超出每个区域的行范围。
答案 0 :(得分:1)
跨区域的外环似乎是多余的。您可以尝试删除它并将内循环更改为
foreach (Excel.Range row in range.Rows)
此外,已知Range.UsedRange
有时会返回意外结果。见http://www.vbaexpress.com/kb/getarticle.php?kb_id=82
有几种选择: -
range = ((Excel.Range)ws.Cells[1, 1]).CurrentRegion
- 如果您的范围至少有一列具有连续值(无间隙),那么这应该可以正常工作。
明确命名范围,以便您可以range = ws.Range("MyRange")
找到范围的最后一行,并使用第一行和最后一行构建目标范围,例如: range = ws.Range(ws.Cells[1, 1], ((Excel.Range)ws.Cells[1048576,1]).End(xlUp)).EntireRow
(请注意,1048576是Excel 2007和Excel 2010中的最高行索引,而65536是早期版本中的最高行索引)。在这里,我使用范围的第一列通过调用第一列工作表底部单元格上的End(xlUp)
来确定范围的最后一行。这要求列不包含数据中的任何空值。如果第一列可以包含空值,那么您应该使用另一列,该列保证在您的数据中具有值。
另外,为了保留跳过前两行,您可以尝试: -
using System.Linq;
foreach (Excel.Range row in range.Rows.Skip(2))
(显然,如果您使用替代方法3来确定目标范围,那么您可以使用ws.Cells[3, 1]
作为范围的上限,将第一行设置为第3行而不是第1行,这样您就不会必须以这种方式致电Skip()
。