ОК, я заканчиваю проект надстройки для устаревшего приложения Excel-VBA, и я еще раз столкнулся с загадкой таинственного диапазона. Rows (?) и workheet.Rows.
Кто-нибудь знает, что эти свойства действительно делают и что они должны предоставить мне? (примечание: все это, вероятно, относится также к соответствующим *. Свойствам столбцов.)
То, что я действительно хотел бы использовать для этого, это вернуть ряд строк, например:
SET rng = wks.Rows(iStartRow, iEndRow)
Но я никогда не мог заставить это сделать, хотя Intellisense показывает два аргумента. Вместо этого я должен использовать одну из двух или трех других (очень глупых) методик.
Помощь очень бесполезна (как правило, для Office VBA), а поиск в Google для строк не очень полезен, независимо от того, сколько других терминов я добавляю к нему.
Единственными вещами, которые я смог использовать для этого, являются: 1) возвращает одну строку в виде диапазона (rng.Rows(i)) и 2) возвращает количество строк в диапазон ( rng.Rows.Count). Это оно? Нет ли в этом ничего хорошего?
Уточнение: Я знаю, что он возвращает диапазон и что есть другие способы получить ряд строк. То, что я прошу, - это то, что мы получаем от .Rows(), которые мы еще не получаем из .Cells() и .Range()? Две вещи, которые я знаю, - это 1) более простой способ вернуть диапазон одной строки и 2) способ подсчета количества строк в диапазоне.
Есть ли что-нибудь еще?
Range.Rows
и Range.Columns
возвращают по существу тот же диапазон, за исключением того факта, что новый Range имеет флаг, который указывает, что он представляет строки или столбцы. Это необходимо для некоторых свойств Excel, таких как Range.Count и Range.Hidden, а также для некоторых методов, таких как Range.AutoFit()
:
Range.Rows.Count
возвращает количество строк в диапазоне.Range.Columns.Count
возвращает количество столбцов в диапазоне.Range.Rows.AutoFit()
autofits строки в Range.Range.Columns.AutoFit()
автоподтверждает столбцы в Range.Вы можете обнаружить, что Range.EntireRow
и Range.EntireColumn
полезны, хотя они все еще не совсем то, что вы ищете. Они возвращают все возможные столбцы для EntireRow
и всех возможных строк для EntireColumn
для представленного диапазона.
Я знаю это, потому что SpreadsheetGear для .NET поставляется с .NET API, которые очень похожи на API Excel. API SpreadsheetGear поставляется с несколькими сильно типизированными перегрузками для индексатора IRange, включая тот, который вы, вероятно, пожелаете Excel:
IRange this[int row1, int column1, int row2, int column2];
Отказ от ответственности: у меня есть SpreadsheetGear LLC
essentially the same Range...
пропускает ценную часть этих свойств, которая заключается в том, что они предоставляют новый итератор для циклов For Each
который проходит через Range
ряд за строкой или столбец за столбцом. Смотрите ответ Нила для справки. Это очень эффективно в сочетании со специальными SpecialCells
или другими прерывистыми диапазонами (например, из AutoFilter
). Конкретный пример: быстрое применение раскрашенной строки для видимых данных после AutoFilter
когда у вас нет Table
.
Range.Rows, Range.Columns и Range.Cells - это объекты Excel.Range, в соответствии с функциями VBA Type():
? TypeName (Selection.rows) АссортиментОднако это не вся история: те возвращенные объекты являются расширенными типами, которые наследуют каждое свойство и метод из Excel:: Range - но .Columns и .Rows имеют специальное значение для... Каждый итератор и специальное свойство .Count, которое aren 't совершенно так же, как итератор родительского объекта Range и count.
Итак. Cells повторяется и учитывается как набор диапазонов с одной ячейкой, как и итератор по умолчанию родительского диапазона.
Но. Колонки повторяются и подсчитываются как набор вертикальных поддиапазонов, каждый из которых имеет ширину в один столбец;
... И .Rows повторяется и подсчитывается как набор горизонтальных поддиапазонов, каждый из которых имеет высоту в одну строку.
Самый простой способ понять это - пройти этот код и посмотреть, что выбрали:
Открытый Sub Test()Наслаждаться. И попробуйте с помощью пары объединенных ячеек, чтобы увидеть, как могут быть нечетные объединенные диапазоны.
Для каждого поддиапазона в ParentRange.Rows SubRange.Select Следующий
Для каждого поддиапазона в ParentRange.Columns SubRange.Select Следующий
Для каждого поддиапазона в ParentRange SubRange.Select Следующий
End Sub
Rows
и Columns
являются одинаковыми , за исключением Count
». Возможность перебирать строки и столбцы диапазона без учета того, как был создан Range
, очень мощная. Он обеспечивает очень чистый способ итерации ячеек, который избегает логики типа Cells(i,j)
внутри циклов. Это также хорошо работает с прерывистыми диапазонами, которые могут возникнуть в определенных сценариях.
Ваши два примера - это единственные вещи, которые я когда-либо использовал для свойств Rows
и Columns
, но в теории вы могли бы сделать с ними что-нибудь, что можно сделать с помощью объекта Range
.
Возвращаемый тип этих свойств сам является Range
, поэтому вы можете делать такие вещи, как:
Dim myRange as Range
Set myRange = Sheet1.Range(Cells(2,2),Cells(8,8))
myRange.Rows(3).Select
который выберет третью строку в myRange
(ячейки B4: H4 в Sheet1).
update: Чтобы сделать то, что вы хотите сделать, вы можете использовать:
Dim interestingRows as Range
Set interestingRows = Sheet1.Range(startRow & ":" & endRow)
update # 2: Или, чтобы получить подмножество строк из другого диапазона:
Dim someRange As Range
Dim interestingRows As Range
Set myRange = Sheet1.Range(Cells(2, 2), Cells(8, 8))
startRow = 3
endRow = 6
Set interestingRows = Range(myRange.Rows(startRow), myRange.Rows(endRow))
Поскольку результат .Rows помечен как состоящий из строк, вы можете "Для каждого" его обрабатывать каждую строку отдельно, например:
Function Attendance(rng As Range) As Long
Attendance = 0
For Each rRow In rng.Rows
If WorksheetFunction.Sum(rRow) > 0 Then
Attendance = Attendance + 1
End If
Next
End Function
Я использую это для проверки посещаемости в любой из нескольких категорий (разные столбцы) для списка людей (разные строки).
(И, конечно же, вы можете использовать .Columns для выполнения "Для каждого" по столбцам в диапазоне.)
Я обнаружил, что использую range.Rows для его эффектов в методе Copy. Он копирует высоту строк из начала координат в пункт назначения, что является поведением, которое я хочу.
rngLastRecord.Rows.Copy Destination:=Sheets("Availability").Range("a" & insertRow)
Если бы я использовал rngLastRecord.Copy вместо rngLastRecord.Rows.Copy, высота строк была бы тем, что было там до копии.
Я не уверен, но я думаю, что вторым параметром является красная селедка.
Оба .Rows и .Columns берут два необязательных параметра: RowIndex и ColumnIndex. Попробуйте использовать ColumnIndex, например. Rows(ColumnIndex:=2)
генерирует ошибку для обоих .Rows и .Columns.
Мое ощущение, что оно унаследовано в некотором смысле от свойства Cells(RowIndex,ColumnIndex)
, но подходит только первый параметр.
Я нашел, что это работает:
Rows(CStr(iVar1) & ":" & CStr(iVar2)).Select
.Cells
тоже.
Rows(Cstr(iVar1) & ":" & CStr(iVar2))
безусловно, не совпадает с Cells(Cstr(iVar1) & ":" & CStr(iVar2))
. Последнее приводит к ошибке несоответствия типов.
Возможно, это битка, но следующий код делает то, что вы, похоже, хотите сделать:
Set rng = wks.Range(wks.Rows(iStartRow), wks.Rows(iEndRow)).Rows
Есть другой способ: возьмите это как пример
Dim sr As String
sr = "6:10"
Rows(sr).Select
Все, что вам нужно сделать, это преобразовать переменные iStartRow
, iEndRow
в строку.