Массив из диапазона в Excel VBA

Что ж, я боролся с небольшим количеством кода и, похоже, не могу его обойти... Я пытаюсь получить массив из диапазона ячеек, однако массив отображается шириной в 1 элемент.
Вот код:

Dim item As Variant
MsgBox Range("D19:H19").Count    
item = Range("D19:H19").Value
MsgBox LBound(item) & " " & UBound(item)   

насколько я понимаю, элемент должен содержать 2D-массив... однако я получаю следующий результат: 1-й MsgBox печатает 5 2-й MsgBox печатает 1 1

Что происходит не так?


person Kevin Boyd    schedule 10.10.2009    source источник
comment
Я не эксперт по vba, но использование значения диапазона (или массива) кажется странным. Возвращает ли он первое значение диапазона?   -  person dave    schedule 11.10.2009
comment
Как правило, VBA возвращает 2D-массив со значениями строки, являющимися 1-м измерением, и значениями столбца, являющимися 2-м измерением, однако здесь я ищу диапазон, который имеет 5 ячеек в одной строке, поэтому я не совсем уверен, является ли 1d или 2d массив будет возвращен...   -  person Kevin Boyd    schedule 11.10.2009
comment
@dave: и да, он возвращает только первое значение диапазона... есть идеи, почему он так делает?!   -  person Kevin Boyd    schedule 11.10.2009
comment
На самом деле он не возвращает первое значение диапазона. Выберите 2D-диапазон ячеек и несколько раз нажмите Tab. Вы увидите выбранную ячейку, которая будет выделена. Это ячейка Value возвращает содержимое.   -  person Atmocreations    schedule 11.10.2009


Ответы (5)


Проблема в LBound и UBound

jtolle был прав насчет LBound и UBound.

LBound(item, 2)

UBound(item, 2)

Однако элемент не должен быть затемнен как массив (вы получите сообщение об ошибке).

Я думаю, это то, что вам нужно

Dim item As Variant
MsgBox Range("D19:H19").Count
item = Range("D19:H19").Value

MsgBox LBound(item, 2) & " " & UBound(item, 2)

For i = LBound(item, 2) To UBound(item, 2)
  MsgBox item(1, i)
Next
person Community    schedule 11.10.2009
comment
Это правильно. Мое редактирование предназначалось для описания формы массива, возвращаемого путем получения свойства Value объекта Range и помещения его в элемент. Я не собирался предлагать, чтобы элемент был объявлен как массив, только то, что после назначения он будет выглядеть так же, как переменная, объявленная как таковая. - person jtolle; 11.10.2009
comment
@imfrancisd: Работает как шарм! Я до сих пор не понял, что я делаю неправильно, я, кажется, не понимаю концепции массива в VBA. - person Kevin Boyd; 12.10.2009

Ваш элемент должен содержать двумерный массив, как и ожидалось. Если вы установите точку останова в своем коде и посмотрите на маленькое окно "Локальные" в редакторе VBA, вы должны это увидеть. Ваши вызовы LBound и UBound получают границы в первом измерении. Если вы вызовете Lbound(item,2) и UBound(item,2), вы должны получить 1 и 5, как и ожидалось.

РЕДАКТИРОВАТЬ: То есть после того, как вы сделали назначение, элемент будет выглядеть так, как вы могли бы объявить как таковой:

Тусклый элемент (от 1 до 1, от 1 до 5)

Одним из недостатков программирования на VBA является то, что массивы могут иметь произвольные нижние границы. Поэтому весь ваш код должен знать об этом.

person jtolle    schedule 11.10.2009

Это правильно как есть. Даже если вы выберете массив ячеек, у вас все равно есть возможность выбрать одну ячейку из массива (и, например, перейти с помощью табуляции по элементам этого массива)

.Value

получает только содержимое текущей выбранной ячейки.

если вы хотите перечислить массив, вы можете вызвать .Cells()-метод Range-объекта

Предполагая, что D19 до H19 содержат от «a» до «e» соответственно, вызов

Range("D19:H19").Cells(2)

возвращает вам "b". Обратите внимание, что это одномерный массив, который может быть двумерным. Cells() принимает не более 2 параметров для указания внутреннего смещения от начала выделения.

надеюсь, что это проясняет... привет

person Atmocreations    schedule 10.10.2009
comment
Фрагмент кода здесь support.microsoft.com/kb/213798 в разделе Чтобы получить значения из рабочий лист и заполнение раздела массива показывает аналогичный код, поэтому мне интересно, почему мой код не работает! - person Kevin Boyd; 11.10.2009
comment
Ну, я проверил это на Excel 2k3. Возможно, это связано с тем, что значение может быть двумерным... lbound принимает второй параметр, который выражает то, что мы называем измерением. Я больше не уверен, какой параметр соответствует какому значению. Что возвращает VarType(Range("D19:H19").Value)? Должно быть vbArray... Попробуйте Ubound(item,1) вместо Ubound(1) - person Atmocreations; 11.10.2009
comment
хорошо, я пробовал Ubound(item, 1), но безрезультатно.. Я все еще получаю 1 1 из 2-го вывода MsgBox.. И что (Range(D19:H19).Value) должен возвращаться... я думаю, что я' я не совсем уверен.. Я просто работаю над примерами кода.. - person Kevin Boyd; 11.10.2009
comment
хм странно тогда... ну в статье речь идет обо всех версиях до 2007, а не о самой 2007. Поэтому возможно, что сейчас это работает по-другому. Как насчет решения с .Cells(number)? ... Еще один момент: попробуйте объявить элемент с item() вместо item - person Atmocreations; 11.10.2009
comment
Используя .Cells(number), мне придется перебирать все ячейки в диапазоне в цикле for-next, верно?... хорошо, если нет другого выбора, я не против пойти на это решение... как пока стабильно работает... - person Kevin Boyd; 11.10.2009
comment
да придется, к сожалению. если Range(D19:H19).Value = yourArray не работает, другого решения я не вижу. В конце концов, Excel не делает ничего, кроме того, что работает намного быстрее, потому что он скомпилирован в основные функции Excel. - person Atmocreations; 11.10.2009

Попробуй это:

Dim item As Variant
MsgBox Range("D19:H19").Count
item = Application.Transpose(Range("D19:H19").Value)
MsgBox LBound(item) & " " & UBound(item)
person JimmyPena    schedule 15.10.2009
comment
Я думал, что транспонирование предназначено для столбцов... но я все равно это проверю... - person Kevin Boyd; 16.10.2009
comment
К вашему сведению, транспонирование недоступно в Excel 2003. - person ErikE; 18.02.2010

если вам нужен массив 1D, чтобы присоединиться к нему, например, для предложения IN, вы должны транспонировать свой диапазон. Я обнаружил, что вам нужно транспонировать дважды для строки, один раз для столбца данных, подобных этому:

Dim rngRow As Range, rngColumn As Range

Set rngRow = Sheets(1).Range("A1", "Z1")
Set rngColumn = Sheets(1).Range("A1", "A20")

Dim arrRowValues, arrColValues
arrRowValues = WorksheetFunction.Transpose(WorksheetFunction.Transpose(rngRow))
arrColValues = WorksheetFunction.Transpose(rngColumn)

Dim numList As String, stringList As String
numList = Join(arrRowValues, ",")
stringList = "'" & Join(arrColValues, "','") & "'"

стоит поиграть.

person Nick    schedule 14.10.2009