Уже два дня бьюсь над этим, и литературу прочел, и на сайте много топиков просмотрел, но ни как не могу вникнуть в тему массивов и их применения... Объявил массив. [vba]
Код
Sub Учусь() Dim x() As String End Sub
[/vba] Как в него залить столбец А с текстовыми данными? Вот пример, выложенный пользователем nilem(считывание диапазона в массив): [vba]
Код
Sub example_2() 'одномерный массив (на выбор) Dim x With Range("A1", Cells(Rows.Count, 1).End(xlUp)) 'из столбца x = WorksheetFunction.Transpose(.Value) End With
[/vba] Непонятки: 1) Разве не нужно после объявления массива ставить две скобки, независимо от того определено число элементов или нет? 2) Вроде бы сделал все тоже самое, но выдает type missmatch... 3) Есть ячейка С1 с текстовым значением, как найти это значение в массиве и вернуть ячейку в которой оно находится? Быть может есть более простой, менее продвинутый, но более понятный путь для добавления элементов в массив??
Добрый вечер.
Уже два дня бьюсь над этим, и литературу прочел, и на сайте много топиков просмотрел, но ни как не могу вникнуть в тему массивов и их применения... Объявил массив. [vba]
Код
Sub Учусь() Dim x() As String End Sub
[/vba] Как в него залить столбец А с текстовыми данными? Вот пример, выложенный пользователем nilem(считывание диапазона в массив): [vba]
Код
Sub example_2() 'одномерный массив (на выбор) Dim x With Range("A1", Cells(Rows.Count, 1).End(xlUp)) 'из столбца x = WorksheetFunction.Transpose(.Value) End With
[/vba] Непонятки: 1) Разве не нужно после объявления массива ставить две скобки, независимо от того определено число элементов или нет? 2) Вроде бы сделал все тоже самое, но выдает type missmatch... 3) Есть ячейка С1 с текстовым значением, как найти это значение в массиве и вернуть ячейку в которой оно находится? Быть может есть более простой, менее продвинутый, но более понятный путь для добавления элементов в массив??Railord
На данном примере хотелось бы понять и научиться применять массив... Хотя я и циклы пока не освоил...
Я никогда не пользовался массивами. А циклы бывают необходимы. ИМХО, лучше начать с циклов. Есть же довольно простые ситуации, можно начать с цикла For-Next с известным количеством элементов.
На данном примере хотелось бы понять и научиться применять массив... Хотя я и циклы пока не освоил...
Я никогда не пользовался массивами. А циклы бывают необходимы. ИМХО, лучше начать с циклов. Есть же довольно простые ситуации, можно начать с цикла For-Next с известным количеством элементов.alex1248
Скобки ставить желательно, но необязательно. Определять типизированный массив для закачки данных с листа - нежелательно, мало ли что там будет на листе. Транспонировать тоже необязательно - вы просто должны понимать, как происходит копирование диапазона в массив (и обратно) [vba]
Код
Dim m()
' Определяем диапазон A1:A25, массив будет содержать 25 элементов With Range("A1", Cells(Rows.Count, 1).End(xlUp)) m = .Value End With
' Переопределяем диапазон на A7:A25, массив будет содержать 19 элементов Dim oRng As Range Set oRng = Range([a1].End(xlDown), Cells(Rows.Count, 1).End(xlUp)) m = oRng.Value
[/vba]При чтении диапазона, размер массива будет динамически переопределен. При этом создается двумерный массив, нумерация индексов начинается с единицы, аналогично такому: ReDim m(1 To oRng.Rows.Count, 1 To oRng.Columns.Count). Далее, зная это, вы просто можете работать с этим массивом через циклы. Попробуем найти первое совпадение с C1: [vba]
Код
Dim i, cToFind cToFind = UCase(Trim([c1])) For i = 1 To UBound(m, 1) If InStr(1, UCase(m(i, 1)), cToFind) Then 'If UCase(m(i, 1)) Like "*" & cToFind & "*" Then MsgBox "Найдено: M(" & i & ") = " & m(i, 1) Exit For End If Next If i > UBound(m, 1) Then MsgBox "Не найдено"
[/vba]Получаем ответ - M(14). Обратите внимание, что мы искали не просто совпадение, а вхождение одной строки в другую, при этом без учета регистра (кстати, символьное сравнение можно было бы провести не поиском подстроки, а через Like). Ну и можно было искать не первое совпадение, а любое (или все) - достаточно не прерывать цикл. С другой стороны, мы находим значения - но не ячейки на листе. Поэтому и ответ - "14-й элемент массива", а не "ячейка A20". Хотя, зная то, как мы считывали массив - получить адрес ячейки (или её значение) тоже можно - это будет [a1].End(xlDown).Offset(i - 1).Value. Ну и если бы нужно было просто найти совпадения в массиве строк, то можно было бы воспользоваться функцией Filter. Нужно только учитывать, что параметр этой функции - одномерный массив, так что наш массив пришлось бы преобразовать: [vba]
Код
ReDim a(1 To UBound(m, 1)) As String Dim f For i = 1 To UBound(m, 1) a(i) = m(i, 1) Next f = Filter(a, [c1]) If UBound(f) >= 0 Then MsgBox f(0)
[/vba]
А в целом, нужно понимать, что сами по себе ячейки (листы, книги) - это уже коллекции объектов, т.е. перечислимые множества. Т.е. с ними можно напрямую работать как с массивами. Кроме того, для ваших задач, сразу можно задействовать как имеющиеся свойства и методы модели, так и функции листа. Например, в нашем случае можно было бы просто найти нужную ячейку: [vba]
Код
Dim oCell As Range Set oCell = oRng.Find([c1], , , xlPart) If oCell Is Nothing Then MsgBox "Не найдено" Else MsgBox oCell.Value
[/vba]
Скобки ставить желательно, но необязательно. Определять типизированный массив для закачки данных с листа - нежелательно, мало ли что там будет на листе. Транспонировать тоже необязательно - вы просто должны понимать, как происходит копирование диапазона в массив (и обратно) [vba]
Код
Dim m()
' Определяем диапазон A1:A25, массив будет содержать 25 элементов With Range("A1", Cells(Rows.Count, 1).End(xlUp)) m = .Value End With
' Переопределяем диапазон на A7:A25, массив будет содержать 19 элементов Dim oRng As Range Set oRng = Range([a1].End(xlDown), Cells(Rows.Count, 1).End(xlUp)) m = oRng.Value
[/vba]При чтении диапазона, размер массива будет динамически переопределен. При этом создается двумерный массив, нумерация индексов начинается с единицы, аналогично такому: ReDim m(1 To oRng.Rows.Count, 1 To oRng.Columns.Count). Далее, зная это, вы просто можете работать с этим массивом через циклы. Попробуем найти первое совпадение с C1: [vba]
Код
Dim i, cToFind cToFind = UCase(Trim([c1])) For i = 1 To UBound(m, 1) If InStr(1, UCase(m(i, 1)), cToFind) Then 'If UCase(m(i, 1)) Like "*" & cToFind & "*" Then MsgBox "Найдено: M(" & i & ") = " & m(i, 1) Exit For End If Next If i > UBound(m, 1) Then MsgBox "Не найдено"
[/vba]Получаем ответ - M(14). Обратите внимание, что мы искали не просто совпадение, а вхождение одной строки в другую, при этом без учета регистра (кстати, символьное сравнение можно было бы провести не поиском подстроки, а через Like). Ну и можно было искать не первое совпадение, а любое (или все) - достаточно не прерывать цикл. С другой стороны, мы находим значения - но не ячейки на листе. Поэтому и ответ - "14-й элемент массива", а не "ячейка A20". Хотя, зная то, как мы считывали массив - получить адрес ячейки (или её значение) тоже можно - это будет [a1].End(xlDown).Offset(i - 1).Value. Ну и если бы нужно было просто найти совпадения в массиве строк, то можно было бы воспользоваться функцией Filter. Нужно только учитывать, что параметр этой функции - одномерный массив, так что наш массив пришлось бы преобразовать: [vba]
Код
ReDim a(1 To UBound(m, 1)) As String Dim f For i = 1 To UBound(m, 1) a(i) = m(i, 1) Next f = Filter(a, [c1]) If UBound(f) >= 0 Then MsgBox f(0)
[/vba]
А в целом, нужно понимать, что сами по себе ячейки (листы, книги) - это уже коллекции объектов, т.е. перечислимые множества. Т.е. с ними можно напрямую работать как с массивами. Кроме того, для ваших задач, сразу можно задействовать как имеющиеся свойства и методы модели, так и функции листа. Например, в нашем случае можно было бы просто найти нужную ячейку: [vba]
Код
Dim oCell As Range Set oCell = oRng.Find([c1], , , xlPart) If oCell Is Nothing Then MsgBox "Не найдено" Else MsgBox oCell.Value
AndreTM, большое спасибо за то что откликнулись, и дали такой развернутый ответ.
Цитата
Скобки ставить желательно, но необязательно.
А я, видя написания кодов участниками форума, не понимал, как простая переменная становится массивом. Думал, чтобы переменная стала массивом - надо поставить скобки обязательно. Хотя массив - это получается группа переменных... Ясно.
Цитата
вы просто должны понимать, как происходит копирование диапазона в массив (и обратно)
Для понимания кода я стараюсь проговаривать все действия, которые будет совершать программа. Непонятки Код1:
где m = .Value. Что значит .Value? Присваивает, определенный ранее диапазон значений, переменной m? Почему мы не можем [vba]
[/vba]написать сразу после WIth вначале кода, и определить диапазон с A7-A25 сразу? Не делая массив двумерным? Код2:
[vba]
Код
MsgBox "Найдено: M(" & i & ") = " & m(i, 1)
[/vba] - что значит конкатенация m(i, 1) в этом выражении и что значат i и 1 в скобках? [vba]
Код
If i > UBound(m, 1) Then MsgBox "Не найдено"
[/vba] - это строка означает, что если счетчик i превысил нижний индекс массива m, то выводится месседж "Не найдено"?
[a1].End(xlDown).Offset(i - 1).Value. - чтобы возвращало "ячейка А20"это надо поставить после MsgBox "Найдено:?
AndreTM, большое спасибо за то что откликнулись, и дали такой развернутый ответ.
Цитата
Скобки ставить желательно, но необязательно.
А я, видя написания кодов участниками форума, не понимал, как простая переменная становится массивом. Думал, чтобы переменная стала массивом - надо поставить скобки обязательно. Хотя массив - это получается группа переменных... Ясно.
Цитата
вы просто должны понимать, как происходит копирование диапазона в массив (и обратно)
Для понимания кода я стараюсь проговаривать все действия, которые будет совершать программа. Непонятки Код1:
где m = .Value. Что значит .Value? Присваивает, определенный ранее диапазон значений, переменной m? Почему мы не можем [vba]
Вы забываете, что этот код находится внутри With ... End With. Соответственно, обращение .Value (именно точка) - это обращение к свойствам/методам вышестоящего объекта (который определяется With). Т.е. это есть Range("A1", Cells(Rows.Count, 1).End(xlUp)).Value. То же самое мы наблюдаем при перечислении For Each ... Next. Что касается "почему мы не можем написать код..." - это же пример на динамическое переопределение массива самим Excel'ем. Т.е. два первоначальных определения - это аналоги, показывающие, что вы должны определить диапазон для считывания... они независимы друг от друга, это "параллельный код" При этом я вам же указал - при "прямом чтении/записи" лист<->массив всегда используется двумерная адресация, это аксиома.
что значит конкатенация m(i, 1) в этом выражении и что значат i и 1 в скобках?
Это странный вопрос... Именно то и значат, что вы написали - конкатенацию (как строки, по определению конкатенации) значения i-го элемента массива (Excel его преобразует в строку автоматом). Единица там - это "первый столбец" - ведь, невзирая на то, что мы прочитали "всего лишь" как бы одномерный массив - динамически он был определен двумерным: ReDim m(1 To 19, 1 To 1), поэтому мы и вынуждены указывать второй индекс.
Да, именно это. Здесь использовано то, что при "стандартном" выходе из цикла (по достижению предела индекса) - переменная-счетчик содержит следующее значение. Ведь в большинстве ЯП цикл FOR, как ни странно, реализуется средствами ассемблера - и условный переход по J*** оставляет в регистре новое значение счетчика...
Вы забываете, что этот код находится внутри With ... End With. Соответственно, обращение .Value (именно точка) - это обращение к свойствам/методам вышестоящего объекта (который определяется With). Т.е. это есть Range("A1", Cells(Rows.Count, 1).End(xlUp)).Value. То же самое мы наблюдаем при перечислении For Each ... Next. Что касается "почему мы не можем написать код..." - это же пример на динамическое переопределение массива самим Excel'ем. Т.е. два первоначальных определения - это аналоги, показывающие, что вы должны определить диапазон для считывания... они независимы друг от друга, это "параллельный код" При этом я вам же указал - при "прямом чтении/записи" лист<->массив всегда используется двумерная адресация, это аксиома.
что значит конкатенация m(i, 1) в этом выражении и что значат i и 1 в скобках?
Это странный вопрос... Именно то и значат, что вы написали - конкатенацию (как строки, по определению конкатенации) значения i-го элемента массива (Excel его преобразует в строку автоматом). Единица там - это "первый столбец" - ведь, невзирая на то, что мы прочитали "всего лишь" как бы одномерный массив - динамически он был определен двумерным: ReDim m(1 To 19, 1 To 1), поэтому мы и вынуждены указывать второй индекс.
Да, именно это. Здесь использовано то, что при "стандартном" выходе из цикла (по достижению предела индекса) - переменная-счетчик содержит следующее значение. Ведь в большинстве ЯП цикл FOR, как ни странно, реализуется средствами ассемблера - и условный переход по J*** оставляет в регистре новое значение счетчика...
Голова кругом идет - чтобы понять массивы, по моему нужно сделать шаг назад и перечитать книгу заново и в частности изучить объектную модель - читать читал, раздел объекты и коллекции... За словарь вообще молчу Информации реально очень много - открыто 15 вкладок в опере, 2 книги, справка.... Вообщем... Как ни странно - кратчайший путь оказался самым эффективным, без массива без цикла, зато работает - попробовал и даже мне понятно !!! [vba]
Код
Dim oCell As Range Set oCell = oRng.Find([c1], , , xlPart) If oCell Is Nothing Then MsgBox "Не найдено" Else MsgBox oCell.Value
[/vba]
Только, на что нужно поменять xlpart, чтобы сравнивать полностью - совпадение должно быть абсолютно точным, т.е. чтобы было так: "пикник<> пикник большой"??
P.S. Как открыть эту справку в эксель 2010? - где расписаны все параметры типо xl... vb... и что они означают там написано. Через F1 - открывается какая-то неинформативная справка...
Голова кругом идет - чтобы понять массивы, по моему нужно сделать шаг назад и перечитать книгу заново и в частности изучить объектную модель - читать читал, раздел объекты и коллекции... За словарь вообще молчу Информации реально очень много - открыто 15 вкладок в опере, 2 книги, справка.... Вообщем... Как ни странно - кратчайший путь оказался самым эффективным, без массива без цикла, зато работает - попробовал и даже мне понятно !!! [vba]
Код
Dim oCell As Range Set oCell = oRng.Find([c1], , , xlPart) If oCell Is Nothing Then MsgBox "Не найдено" Else MsgBox oCell.Value
[/vba]
Только, на что нужно поменять xlpart, чтобы сравнивать полностью - совпадение должно быть абсолютно точным, т.е. чтобы было так: "пикник<> пикник большой"??
P.S. Как открыть эту справку в эксель 2010? - где расписаны все параметры типо xl... vb... и что они означают там написано. Через F1 - открывается какая-то неинформативная справка...Railord
Nil novi sub luna, так что - век живи, век учись!)
Сообщение отредактировал Railord - Воскресенье, 28.09.2014, 23:00
Как открыть эту справку в эксель 2010? - где расписаны все параметры типо xl... vb... и что они означают
Конечно. можно посоветовать поставить ОфисXP/2k/2003... но зачем? Разве запрос в инет, типа http://yandex.ru/yandsearch?clid=9582&text=excel%20vba%20range%20find выдаёт настолько много неверных ссылок? Ну и значения констант VB/VBA можно просто изучить через Immediate... а также есть обсервер (жмакните F2 в IDE(VBE), чтобы посмотреть на текущие объекты текущей модели).
Как открыть эту справку в эксель 2010? - где расписаны все параметры типо xl... vb... и что они означают
Конечно. можно посоветовать поставить ОфисXP/2k/2003... но зачем? Разве запрос в инет, типа http://yandex.ru/yandsearch?clid=9582&text=excel%20vba%20range%20find выдаёт настолько много неверных ссылок? Ну и значения констант VB/VBA можно просто изучить через Immediate... а также есть обсервер (жмакните F2 в IDE(VBE), чтобы посмотреть на текущие объекты текущей модели).AndreTM
Skype: andre.tm.007 Donate: Qiwi: 9517375010
Сообщение отредактировал AndreTM - Воскресенье, 28.09.2014, 23:11
- Сработало. Благодарю. Допишу небольшую облегчалку жизни в ексель для брата. Затем вернусь к основам, и не зря же вы такие здоровые посты строчили - очень надеюсь, что я стану понимать массивы и научусь их применять. Пусть не сейчас, но я уверен, что это пригодится мне в будущем.
Цитата
а также есть обсервер (жмакните F2 в IDE(VBE), чтобы посмотреть на текущие объекты текущей модели).
- вот это я и искал, только видимо не там... Благодарю за ссылку - буду пользоваться msdn ской справкой... Завтра продолжу! - Буду учить пока не пойму. Спасибо за поддержку.
Цитата
xlWhole?
- Сработало. Благодарю. Допишу небольшую облегчалку жизни в ексель для брата. Затем вернусь к основам, и не зря же вы такие здоровые посты строчили - очень надеюсь, что я стану понимать массивы и научусь их применять. Пусть не сейчас, но я уверен, что это пригодится мне в будущем.
Цитата
а также есть обсервер (жмакните F2 в IDE(VBE), чтобы посмотреть на текущие объекты текущей модели).
- вот это я и искал, только видимо не там... Благодарю за ссылку - буду пользоваться msdn ской справкой... Завтра продолжу! - Буду учить пока не пойму. Спасибо за поддержку.Railord
Nil novi sub luna, так что - век живи, век учись!)
- речь шла о том, чтобы получить адрес ячейки, имея номер элемента массива. Просьба приблизить к пониманию, почему в скобках указано (i -1) - зачем отнимать единицу от найденного элемента массива??
Ап! Возрождаем тему! Добрый вечер всем! Пост №5
Цитата
[a1].End(xlDown).Offset(i - 1).Value.
- речь шла о том, чтобы получить адрес ячейки, имея номер элемента массива. Просьба приблизить к пониманию, почему в скобках указано (i -1) - зачем отнимать единицу от найденного элемента массива??Railord
Nil novi sub luna, так что - век живи, век учись!)
Когда проверяете код в VBE (например, остановив его исполнение на ошибке, по брейкпойнту, по Stop...) - смотрИте не только на код. Есть окно Locals, где вы можете оперативно наблюдать состояние переменных проекта, есть окно Immediate, где вы можете проверить любой кусочек кода, есть окно Watch, где вы можете отслеживать выражения... Вообще, Locals и Immediate при работе с проектом лучше вообще не закрывать, пусть они в VBE висят всё время...
Когда проверяете код в VBE (например, остановив его исполнение на ошибке, по брейкпойнту, по Stop...) - смотрИте не только на код. Есть окно Locals, где вы можете оперативно наблюдать состояние переменных проекта, есть окно Immediate, где вы можете проверить любой кусочек кода, есть окно Watch, где вы можете отслеживать выражения... Вообще, Locals и Immediate при работе с проектом лучше вообще не закрывать, пусть они в VBE висят всё время... AndreTM
Ветераны - благодарю за поддержку! AndreTM, - не поверите, хотя нет - поверите... Ничем из того, что вы перечислили я не пользовался - надо исправляться... Rioran, - тема к месту - однозначно поможет в изучении!
Ветераны - благодарю за поддержку! AndreTM, - не поверите, хотя нет - поверите... Ничем из того, что вы перечислили я не пользовался - надо исправляться... Rioran, - тема к месту - однозначно поможет в изучении!Railord
Nil novi sub luna, так что - век живи, век учись!)
Сообщение отредактировал Railord - Понедельник, 27.10.2014, 21:44