Range в массив

Программирование на Visual Basic for Applications
Calvin
Постоялец
Постоялец
 
Сообщения: 409
Зарегистрирован: 21.01.2003 (Вт) 12:13
Откуда: Sebastopol

Range в массив

Сообщение Calvin » 29.06.2007 (Пт) 18:33

Подскажите плиз, как значения в диапазоне А1:А100 быстрым способом представить в виде массива?
-Whose the motocycle, is this? -It`s a chopper, baby! -Whose chopper is this? -Zed`s! -Who is Zed? -Zed`s dead, baby, Zed`s dead! :-D

Pavel55
Обычный пользователь
Обычный пользователь
 
Сообщения: 90
Зарегистрирован: 27.10.2006 (Пт) 20:11

Сообщение Pavel55 » 29.06.2007 (Пт) 19:29

Наверное так

Код: Выделить всё
Sub Макрос1()
Dim myArray()  As Long 'в зависимости от значений
ReDim myArray(1 To 100)
Dim i&
    For i = 1 To 100
        myArray(i) = Cells(i, 1)
    Next i
End Sub
Последний раз редактировалось Pavel55 29.06.2007 (Пт) 19:33, всего редактировалось 1 раз.

Gloom
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 200
Зарегистрирован: 23.11.2004 (Вт) 15:57
Откуда: СПб

Сообщение Gloom » 29.06.2007 (Пт) 19:30

Код: Выделить всё
Dim arr() As Variant
   
arr = Application.WorksheetFunction.Transpose(Range("A1:A100").Value)

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 29.06.2007 (Пт) 19:32

Это довольно сложно.

dim v as variant
v=range("a1:a100").value

Примерно так.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 01.07.2007 (Вс) 12:45

еще варианты:

Код: Выделить всё
Sub test()
    Dim x1, x2, x3, y1, y2, y3, z1, z2, z3
    x1 = Range("A1:A100")
    x2 = Range("INDEX((A1:A100,B1:B100,C1:C100),,,2)")
    x3 = Range("OFFSET(A1:A100,2,1)")
    y1 = Evaluate("A1:A100")
    y2 = Evaluate("INDEX((A1:A100,B1:B100,C1:C100),,,2)")
    y3 = Evaluate("OFFSET(A1:A100,2,1)")
    z1 = [A1:A100]
    z2 = [INDEX((A1:A100,B1:B100,C1:C100),,,2)]
    z3 = [OFFSET(A1:A100,2,1)]
End Sub
Привет,
KL

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 23.07.2007 (Пн) 12:20

Эти все варианты закидывают диапазон в двуменрный массив. А как без цикла получить из этого одномерный массив ?

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 23.07.2007 (Пн) 12:25

Пропатчить SAFEARRAY ;-)
Изображение

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 23.07.2007 (Пн) 13:29

@Nik писал(а):Эти все варианты закидывают диапазон в двуменрный массив. А как без цикла получить из этого одномерный массив ?


- Если диапазон двухмерный, то никак :-(
если конечно речь не идет о простом отрубании второго измерения: x=Application.Index([A1:B100],,1)

- Если диапазон одномерный, то незачем ;-)
Привет,
KL

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 13.08.2007 (Пн) 18:26

Хочу ещё раз акцентировать внимание на один нюанс:
все вышеперечисленные варианты загоняют диапазон в ДВУМЕРНЫЙ массив, у которого длина второго измерения = 1, но обращаться к полученному массиву надо всё равно как к двумерному....! Х1(1,1); Х1(1,2) и т.д. При этом не получается воспользоваться, скажем, функцией Join() :-( Мой вопрос касается именно функции Join() - каким синтаксисом можно сделать так, чтобы она восприняла полученный массив. Естесственно, вариант, когда в цикле пересылаются значения из двумерного массива в одномерный не допускается...
Другими словами мне надо любым возможным (но быстрым способом) сцепить значения диапазона

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 13.08.2007 (Пн) 19:27

Gloom уже некоторым образом дал решение, отвечая на вопрос Calvin.
Код: Выделить всё
Sub test()
    MsgBox Join(Application.Transpose(Range("A1:A10")), "")
    MsgBox Join(Application.Transpose(Application.Transpose(Range("A1:J1"))), "")
End Sub

Только учитывай три вещи:

1) для гориз. диапазонов транспонировать надо дважды

2) в некоторых версиях (по-моему 2000 и ранее) функция Transpose транспонирует не более 5461 элементов за раз.

3) функция Join() доступна, начиная с версии Excel2000
Привет,
KL

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 14.08.2007 (Вт) 10:44

Класс !!! Оригинальное решение.... :thumright: Но это ещё не всё :-) А как быть, если сцепляемые элементы лежат в формуле массива в одной ячейке ? :-)

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 15.08.2007 (Ср) 8:48

У меня возник ещё один интересный вопрос.... Можно сказать обратная задача - массив в range.
Например есть формула:
{=если(A1:A10=55;A1:A10)}
Можно ли как-то сделать, чтобы возвращались ссылки а не значения ячеек ? Тогда, например, если этой формуле присвоить имя и обратиться к этому имени из ВБА, то получить сами ячейки из диапазона А1:А10 (объект Range).

dormouse
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 140
Зарегистрирован: 10.01.2007 (Ср) 21:58
Откуда: Волжский

Сообщение dormouse » 15.08.2007 (Ср) 16:18

ещёб понять, что эта формула делает...

это имелось в виду?
ActiveCell.FormulaArray
или
ActiveCell.Formula

или чтоб программа читала формулу?
целый синтаксический анализатор надо писать :)
VBA, MSA97

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 15.08.2007 (Ср) 16:26

Она выбирает цифры "55" из диапазона А1:А10, если они там есть. Но мне надо получить не сами значения, а ячейки, где они лежат....

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 15.08.2007 (Ср) 17:33

@Nik писал(а):Она выбирает цифры "55" из диапазона А1:А10, если они там есть. Но мне надо получить не сами значения, а ячейки, где они лежат....


не знаю, то ли это, но...

Код: Выделить всё
Sub test()
    Dim strAddr As String
    Dim arrRef() As Variant
    Dim strRng As String
   
    strAddr = ActiveSheet.Range("A1:A10").Address(, , , True)
   
    arrRef = Application.Transpose(Evaluate("IF(" & strAddr & "=55,ADDRESS(ROW(" & strAddr & "),COLUMN(" & strAddr & ")),"""")"))
    'arrRef = Application.Transpose([IF(A1:A10=55,ADDRESS(ROW(A1:A10),COLUMN(A1:A10)),"")])
   
    strRng = Replace(Application.Trim(Join(arrRef, " ")), " ", ",")
   
    ActiveSheet.Range(strRng).Select
End Sub


(!!!) Если не ошибаюсь макс. длина текстовой строки интерпретируемой пропертью Range - 255 знаков.

P.S. Формула типа =IF(...,...,...) может возвращать ссылку только если условие проверяется для всего диапазона сразу:
=IF(A1=55,A1:A10) <- работает
=IF(A1:A10=55,A1:A10) <- не работает
Думаю, логика проста:
в первом случае результат либо диапазон (тип Range) либо логическое значение FALSE (тип Boolean)
во втором - результат cостоит из множества результатов и может содержать более одного типа одновременно, а значит автоматически массив (Array) типа Variant
Привет,
KL

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 15.08.2007 (Ср) 17:37

@Nik писал(а):А как быть, если сцепляемые элементы лежат в формуле массива в одной ячейке ? :-)


Думаю, что в этом случае единственный способ это брать из ячейки формулу и интерпретировать ее из-под VBA с пом. функции Evaluate().
Привет,
KL

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 16.08.2007 (Чт) 10:31

Большое спасибо.... Ты как всегда раскрываешь глаза на широчайшие возможности ВБА :-)
А я, вот, ещё попробовал так: задал имя формуле:
=ДВССЫЛ(ЕСЛИ(Лист1!$A$1:$A$10=55;АДРЕС(СТРОКА(Лист1!$A$1:$A$10);СТОЛБЕЦ(Лист1!$A$1:$A$10));"A1"))
Если ввести формулу в ячейку - вроде как работает.... даже можно поверху сделать СМЕЩ(....). Но если ввести в область имён - выдаёт только ссылку на первую ячейку :-(

А вообще задача была такая: есть числовой столбец, есть поле для фильтра по этому столбцу, т.е. вводимые в поле цифры должны искаться внутри значений столбца (типа подстроки). Так вот, обычным автофильтром воспользоваться нельзя (подстроку внутри числового столца он не ищет). Вышел из положения так: рядом сделал дополнительный столбец с формулой:
=ЕСЛИ(ЕОШ(ПОИСК(ИскомоеЗнач;L12&""));"";1), где "L" - исходный числовой столбец
а потом автофильтр с условием "=1" выдавал мне то, что надо :-)

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 17.08.2007 (Пт) 1:45

@Nik писал(а):Большое спасибо.... Ты как всегда раскрываешь глаза на широчайшие возможности ВБА :-)
А я, вот, ещё попробовал так: задал имя формуле:
=ДВССЫЛ(ЕСЛИ(Лист1!$A$1:$A$10=55;АДРЕС(СТРОКА(Лист1!$A$1:$A$10);СТОЛБЕЦ(Лист1!$A$1:$A$10));"A1"))
Если ввести формулу в ячейку - вроде как работает.... даже можно поверху сделать СМЕЩ(....). Но если ввести в область имён - выдаёт только ссылку на первую ячейку :-(


Функция ДВССЫЛ() действительно теряет способность работать с матрицами при использовании ее в именах или VBA. Однако на листе эта формула практически уникальна - она может возвращать массив значений несмежных ячеек(!!!) Такое еще возможно только с функцией СМЕЩ():
=ДВССЫЛ({"A4";"A7";"A10"})
=СМЕЩ(A1;{3;6;9};0)

Твою формулу можно еще усложнить, чтобы она возвращала массив значений только найденных ячеек:
{=ДВССЫЛ("A"&НАИМЕНЬШИЙ(ЕСЛИ($A$1:$A$10=55;СТРОКА($A$1:$A$10));СТРОКА(ДВССЫЛ("1:"&СЧЁТЕСЛИ($A$1:$A$10;55)))))}

Задачу твою я, если честно, не понял :-( Если не сложно, повесь файл с примером.
Привет,
KL

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 17.08.2007 (Пт) 9:18

Да, можно и так... мы уже тобой научены ;-)

А задачка вот:
Вложения
Фильтр_для_цифр.xls
(72.5 Кб) Скачиваний: 137

KL
Microsoft MVP
 
Сообщения: 483
Зарегистрирован: 30.10.2005 (Вс) 0:31
Откуда: Madrid

Сообщение KL » 17.08.2007 (Пт) 17:33

@Nik писал(а):А задачка вот:


Такой вариант без доп. столбца (вероятно будет несколько медленнее, чем с доп. столбцом)
Вложения
Book1.xls
(61 Кб) Скачиваний: 144
Привет,
KL

@Nik
Обычный пользователь
Обычный пользователь
 
Сообщения: 80
Зарегистрирован: 14.05.2007 (Пн) 12:11

Сообщение @Nik » 20.08.2007 (Пн) 10:21

Мдя.... мне ещё учиться и учиться..... :-) Отличное решение :thumright: И не надо заботиться о распространении формулы при обновлении таблицы и изменении кол-ва строк


Вернуться в VBA

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex-бот и гости: 74

    TopList