Внешний цикл по областям кажется избыточным. Вы можете попробовать удалить его и изменить внутренний цикл на
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 для определения целевого диапазона, то вы могли бы установить первую строку равной строке 3 вместо строки 1, используя ws.Cells[3, 1]
в качестве верхней границы диапазона, поэтому вам не придется звоните Skip()
таким образом).