Что на самом деле делает свойство Excel range.Rows?

Хорошо, я заканчиваю надстройку для устаревшего приложения Excel-VBA, и я снова столкнулся с загадкой загадочных свойств range.Rows (?) И worksheet.Rows.

Кто-нибудь знает, что на самом деле делают эти свойства и что они должны мне дать? (Примечание: все это, вероятно, относится и к соответствующим свойствам *.Columns).

На самом деле мне хотелось бы иметь возможность использовать его для возврата диапазона строк, например:

   SET rng = wks.Rows(iStartRow, iEndRow)

Но мне никогда не удавалось заставить его сделать это, хотя Intellisense показывает два аргумента в пользу этого. Вместо этого я должен использовать одну из двух или трех других (очень неуклюжих) техник.

Помощь очень бесполезна (как правило, для Office VBA), а поиск в Google «Строки» не очень полезен, независимо от того, сколько других терминов я добавляю к нему.

Единственное, для чего мне удалось его использовать: 1) вернуть одну строку как диапазон (rng.Rows(i)) и 2) вернуть количество строк в диапазоне (rng.Rows.Count). Это оно? Неужели нет ничего другого, для чего он нужен?

Уточнение: я знаю, что он возвращает диапазон и что есть другие способы получить диапазон строк. Я прошу конкретно о том, что мы получаем от .Rows(), чего мы еще не получили от .Cells() и .Range()? Я знаю две вещи: 1) более простой способ вернуть диапазон из одной строки и 2) способ подсчета количества строк в диапазоне.

Есть ли еще что-нибудь?


person RBarryYoung    schedule 24.06.2009    source источник
comment
RBY - Думаю, это все. Это удобный способ манипулировать целой строкой листа / фрагментом диапазона (очень полезно!) С помощью Count для загрузки. Наиболее полезно для циклов, когда вы просматриваете несколько строк (или столбцов, если на то пошло).   -  person Joel Goodwin    schedule 24.06.2009
comment
Отличный вопрос ... кроме .Count, я задавался вопросом, для какого *** они были.   -  person Mark Nold    schedule 27.08.2009
comment
Интересно, почему этот вопрос, по-видимому, вызвал у всех желание публиковать ответы, которые являются простыми предположениями или даже не касаются вопроса! -1 ВСЕМ !! (Эта последняя часть была шуткой. В основном.)   -  person Jean-François Corbett    schedule 29.06.2011
comment
Да, это странно. Еще более странно то, что, несмотря на то, что у меня более 6000 баллов, почти все заработанные за ответы на вопрос по SQL Server, мой единственный золотой значок - это почти 25000 просмотров этого вопроса, которые на самом деле были просто праздным любопытством с моей стороны. И все же интерес к нему в 10 раз больше, чем ко всему, что я делал здесь. Не совсем строитель эго.   -  person RBarryYoung    schedule 30.06.2011
comment
+1 интересный вопрос.   -  person brettdj    schedule 08.12.2013
comment
@RBarryYoung Это потому, что Excel гораздо более распространен, чем SQL Server, поэтому количество людей, интересующихся этими вещами, соответственно, больше. Вы помогли многим людям задать этот вопрос. Наслаждайтесь своей заслуженной кармой.   -  person Carlos A. Ibarra    schedule 19.03.2017


Ответы (9)


Range.Rows и Range.Columns возвращают по существу один и тот же диапазон, за исключением того факта, что новый диапазон имеет флаг, который указывает, что он представляет строки или столбцы. Это необходимо для некоторых свойств Excel, таких как Range.Count и Range.Hidden, а также для некоторых методов, таких как Range.AutoFit():

  • Range.Rows.Count возвращает количество строк в диапазоне.
  • Range.Columns.Count возвращает количество столбцов в диапазоне.
  • Range.Rows.AutoFit() автоматически заполняет строки в диапазоне.
  • Range.Columns.AutoFit() автоматически заполняет столбцы в диапазоне.

Вы можете обнаружить, что Range.EntireRow и Range.EntireColumn полезны, хотя они все еще не совсем то, что вы ищете. Они возвращают все возможные столбцы для EntireRow и все возможные строки для EntireColumn для представленного диапазона.

Я знаю это, потому что SpreadsheetGear для .NET поставляется с .NET API, которые очень похожи на API Excel. SpreadsheetGear API поставляется с несколькими строго типизированными перегрузками для индексатора IRange, включая ту, которую вы, вероятно, хотели бы иметь в Excel:

  • IRange this[int row1, int column1, int row2, int column2];

Отказ от ответственности: я владею SpreadsheetGear LLC

person Joe Erickson    schedule 24.06.2009
comment
essentially the same Range... упускает ценную часть этих свойств, а именно то, что они предоставляют новый итератор для For Each циклов, который проходит Range строка за строкой или столбец за столбцом. Для справки см. ответ Нила. Это очень эффективно в сочетании с SpecialCells или другими прерывистыми диапазонами (например, от AutoFilter). Конкретный пример: быстрое применение окраски полосатых строк к видимым данным после AutoFilter, когда у вас нет Table на месте. - person Byron Wall; 01.06.2015
comment
@ByronWall благодарим вас за этот комментарий, поскольку я обнаружил, что на этой странице ищу конкретную информацию об использовании свойства range.rows для этой цели. Я очень ценю ваш указатель на этот вариант использования. - person Alex M; 09.11.2019

Range.Rows, Range.Columns and Range.Cells are Excel.Range objects, according to the VBA Type() functions:

?TypeName(Selection.rows)
Range
However, that's not the whole story: those returned objects are extended types that inherit every property and method from Excel::Range - but .Columns and .Rows have a special For... Each iterator, and a special .Count property that aren't quite the same as the parent Range object's iterator and count.

Таким образом, .Cells повторяется и считается набором диапазонов с одной ячейкой, как итератор по умолчанию для родительского диапазона.

Но .Columns повторяется и считается набором вертикальных поддиапазонов, каждый из которых имеет ширину в один столбец;

... И .Rows повторяется и считается набором горизонтальных поддиапазонов, каждый из которых является одной строкой в ​​высоту.

The easiest way to understand this is to step through this code and watch what's selected:

Public Sub Test() 
Dim SubRange As Range Dim ParentRange As Range
Set ParentRange = ActiveSheet.Range("B2:E5")

For Each SubRange In ParentRange.Cells SubRange.Select Next
For Each SubRange In ParentRange.Rows SubRange.Select Next
For Each SubRange In ParentRange.Columns SubRange.Select Next
For Each SubRange In ParentRange SubRange.Select Next
End Sub
Enjoy. And try it with a couple of merged cells in there, just to see how odd merged ranges can be.

person Nigel Heffernan    schedule 30.04.2014
comment
ЭТО - недостающий элемент во всех ответах, в которых говорится, что Rows и Columns одинаковы, за исключением Count. Возможность перебирать строки и столбцы диапазона независимо от того, как был создан Range, очень эффективна. Он обеспечивает очень чистый способ перебора ячеек, избегающий логики типа Cells(i,j) внутри циклов. Он также хорошо работает с прерывистыми диапазонами, которые могут возникать в определенных сценариях. - person Byron Wall; 01.06.2015

Два ваших примера - единственное, для чего я когда-либо использовал свойства 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)

обновление №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))
person e.James    schedule 24.06.2009
comment
Я знал, что он вернул диапазон (упомянул об этом в моем исходном сообщении) и что есть другие способы получить диапазон строк (также упомянутые). Я прошу конкретно о том, что мы получаем от .Rows (), чего мы еще не получили от .Cells () и .Range ()? Уточню это в своем вопросе ... - person RBarryYoung; 24.06.2009
comment
Боюсь, что это все. Свойства Rows и Columns - это просто быстрый доступ к объектам Range, которые удобно настроены так, чтобы содержать отдельные строки (или отдельные столбцы) вашего начального диапазона. В этом нет большего волшебства. - person e.James; 24.06.2009
comment
Я чувствую себя идиотом из-за того, что не подумал о Set ИнтересRows = Sheet1.Range (startRow &: & endRow). (Некоторые согласились бы со мной, даже если бы я подумал об этом.) ‹8 ^ |. Это простейшая форма, не нужно даже преобразовывать длинные строки в строки, и она работает. - person riderBill; 05.12.2015
comment
'Как выяснилось, Интересные строки = Sheet1.Range (startRow &: & endRow) не работал все-таки. Он не разбился, но какой бы диапазон я ни выбрал, я не хотел. testStr = 65 &: & 5 оценивается как 65: 5, но я не уверен, к какому диапазону это привело. Досадно, что MS не считает нужным предоставлять полезные функции для такого рода вещей. . AFAIK (хотя в VBA это не так уж и далеко) нет конструктора, подобного диапазону, который принимает индексы строк и столбцов или пары ячеек, если на то пошло. Потребность возникает достаточно часто. - person riderBill; 07.12.2015
comment
СИ поместил мой старый утомительный метод получения ссылки на поддиапазон большего диапазона в функции показано здесь. У меня есть решение - создать строку стиля A4: G7 и передать ее конструктору диапазона следующим образом: rangeStr = Chr (AM1 + iCol1) & CStr (iRow1) &: & Chr (AM1 + iCol2) & CStr (iRow2); _ Установить getSubRange = sourceRange.Range (rangeStr) _. Но, конечно же, есть более прямой метод, использующий напрямую индексы, не так ли? - person riderBill; 07.12.2015
comment
Истекло время редактирования. AM1 = (значение ASCII 'A') минус 1, т.е. 65-1 = 64. Я полагаю, что в наши дни мне следует называть его значением UNICODE или UTF-8, но это то же самое число. - person riderBill; 07.12.2015

Поскольку результат .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 для выполнения «Для каждого» столбцов в диапазоне.)

person mrento    schedule 06.03.2014
comment
Связанный: stackoverflow.com/questions/1463236/ - person cladelpino; 19.12.2017

Я не уверен, но думаю, что второй параметр - отвлекающий маневр.

И .Rows, и .Columns принимают два необязательных параметра: RowIndex и ColumnIndex. Попробуйте использовать ColumnIndex, например. Rows(ColumnIndex:=2), генерирует ошибку для обоих .Rows и .Columns.

Мне кажется, это в некотором смысле унаследовано от свойства Cells(RowIndex,ColumnIndex), но подходит только первый параметр.

person Joel Goodwin    schedule 24.06.2009
comment
Чувства, не более чем чувства -1 - person Jean-François Corbett; 29.06.2011
comment
@ Жан-Франсуа Корбетт - Иногда это единственные ответы, которые вы можете получить, и лучше узнать анекдоты людей, которые были в этой области, чем вообще ничего. Я бы, наверное, не стал публиковать что-то подобное в наши дни (ответ - 2 года назад !!) - это слишком неуклюже, и меня совершенно не беспокоит публикация чего-то, что имеет мало надежды на голоса. Вопросы VBA в целом не заслуживают особого внимания. Но я решительно возражаю против вашего предположения, что ответы, основанные на чувствах, неверны просто потому, что это закрывает дискуссию по вопросам, на которые нет очевидных или простых ответов. - person Joel Goodwin; 30.06.2011
comment
Я понимаю вашу точку зрения. Честно говоря, я не смотрел на дату и не понимал, что она такая старая. Тем не менее, я чувствую (sic), что на SO слишком много этих предположений-ответов, и что только крошечное меньшинство полезно, в то время как большинство квалифицируются как бесполезные, то есть законные кандидаты с понижением, и я поддерживаю свое предыдущее суждение по этому вопросу. . Другие, по-видимому, видят вещи по-другому, так как вы все еще получаете чистую поддержку за свой ответ / чувство. - person Jean-François Corbett; 30.06.2011

Я обнаружил, что использую range.Rows для его эффектов в методе Copy. Он копирует высоту строк от источника до места назначения, что мне и нужно.

rngLastRecord.Rows.Copy Destination:=Sheets("Availability").Range("a" & insertRow)

Если бы я использовал rngLastRecord.Copy вместо rngLastRecord.Rows.Copy, высота строки была бы такой, какая была до копирования.

person Nick Mellor    schedule 29.06.2011

Возможно, это немного похоже на кладж, но следующий код делает то, что вы, кажется, хотите делать:

Set rng = wks.Range(wks.Rows(iStartRow), wks.Rows(iEndRow)).Rows
person jswolf19    schedule 12.03.2010
comment
Да, я знаю. Не тот вопрос, который я задал. - person RBarryYoung; 12.03.2010
comment
Хотя это не вопрос, который задают, люди, которые приходят сюда, могут задавать вопрос (как и я), поэтому я подумал, что предоставлю его. - person jswolf19; 24.03.2010
comment
Может, уборщик использовать with wks ... end with? - person RubberDuck; 01.05.2014

Есть другой способ, возьмите это как пример

Dim sr As String    
sr = "6:10"
Rows(sr).Select

Все, что вам нужно сделать, это преобразовать ваши переменные iStartRow, iEndRow в строку.

person blash    schedule 23.12.2010

Я нашел такие работы:

Rows(CStr(iVar1) & ":" & CStr(iVar2)).Select
person Paolo Bortolini    schedule 16.09.2012
comment
@RBarryYoung Rows(Cstr(iVar1) & ":" & CStr(iVar2)) определенно не то же самое, что Cells(Cstr(iVar1) & ":" & CStr(iVar2)). Последнее приводит к ошибке несоответствия типов. - person Daniel; 18.09.2012