Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Как записать диапазон в массив - Мир MS Excel

Старая форма входа
  • Страница 1 из 1
  • 1
Модератор форума: китин, _Boroda_  
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Как записать диапазон в массив (Макросы/Sub)
Как записать диапазон в массив
Serg5876 Дата: Суббота, 27.01.2024, 23:36 | Сообщение № 1
Группа: Пользователи
Ранг: Новичок
Сообщений: 11
Репутация: 0 ±
Замечаний: 0% ±

2007
Доброго времени суток ! Почему-то не создается массив из диапазона((
Делаю данную операцию первый раз, поэтому скорее всего ошибка в синтаксисе. Но не могу найти !
Помогите, пожалуйста !
Текст макроса прикреплен, а также приведен ниже:

[vba]
Код
Option Explicit
Public OstFile As Workbook, gFirma$, gAdr As String, ID As Integer
Private Dinamyc As Workbook, DinamycFileName$, PatternRecFileName As String, Lr1&, Lr2&, Lr3 As Long, _
PatternRecom As Workbook, i&, j As Long
Dim NameOfEGAIS() As Variant, NameOfPattern() As Variant, ProdName As String

Sub AnalisOst()
Set OstFile = ThisWorkbook
'UserForm1.Show 'форма. Работает
ID = 30
OstFile.Worksheets(1).Activate
Lr1 = OstFile.Worksheets(1).Cells(Rows.Count, "B").End(xlUp).Row
DinamycFileName = OstFile.Path & "\dinamika_prodazh" & ID & ".xls"
Set Dinamyc = Workbooks.Open(DinamycFileName)
Lr2 = Dinamyc.Worksheets(1).Cells(Rows.Count, "C").End(xlUp).Row [color=blue]'в Debug Lr2=5, все верно[/color]

'перенос наименований товара и заполнение массива из ЕГАИС
NameOfEGAIS = Dinamyc.Worksheets(1).Range(Cells(2, 3), Cells(Lr2, 3)).Value[b] [color=red]' в массив ничего не записывается !!![/b][/color]
Debug.Print LBound(NameOfEGAIS), NameOfEGAIS(0) [b][color=red]' тут выдает ошибку Subscript out of range и LBound=1[/color][/b]

[b] [color=blue]'проверка: диапазон корректно копируется и вставляется[/color][/b]
Dinamyc.Worksheets(1).Range(Cells(2, 3), Cells(Lr2, 3)).Copy
OstFile.Worksheets(1).Activate
Range(Cells(3, 2), Cells(Lr2, 2)).PasteSpecial Paste:=xlPasteAllExceptBorders

Terminate_Sub:
Dinamyc.Close SaveChanges:=False
Application.CutCopyMode = False
Cells(3, 3).Select
End Sub
[/vba]
К сообщению приложен файл: 9698312.xlsm (28.5 Kb) · dinamika_prodazh30.xls (51.5 Kb)


Сергей

Сообщение отредактировал Serg5876 - Суббота, 27.01.2024, 23:38
 
Ответить
СообщениеДоброго времени суток ! Почему-то не создается массив из диапазона((
Делаю данную операцию первый раз, поэтому скорее всего ошибка в синтаксисе. Но не могу найти !
Помогите, пожалуйста !
Текст макроса прикреплен, а также приведен ниже:

[vba]
Код
Option Explicit
Public OstFile As Workbook, gFirma$, gAdr As String, ID As Integer
Private Dinamyc As Workbook, DinamycFileName$, PatternRecFileName As String, Lr1&, Lr2&, Lr3 As Long, _
PatternRecom As Workbook, i&, j As Long
Dim NameOfEGAIS() As Variant, NameOfPattern() As Variant, ProdName As String

Sub AnalisOst()
Set OstFile = ThisWorkbook
'UserForm1.Show 'форма. Работает
ID = 30
OstFile.Worksheets(1).Activate
Lr1 = OstFile.Worksheets(1).Cells(Rows.Count, "B").End(xlUp).Row
DinamycFileName = OstFile.Path & "\dinamika_prodazh" & ID & ".xls"
Set Dinamyc = Workbooks.Open(DinamycFileName)
Lr2 = Dinamyc.Worksheets(1).Cells(Rows.Count, "C").End(xlUp).Row [color=blue]'в Debug Lr2=5, все верно[/color]

'перенос наименований товара и заполнение массива из ЕГАИС
NameOfEGAIS = Dinamyc.Worksheets(1).Range(Cells(2, 3), Cells(Lr2, 3)).Value[b] [color=red]' в массив ничего не записывается !!![/b][/color]
Debug.Print LBound(NameOfEGAIS), NameOfEGAIS(0) [b][color=red]' тут выдает ошибку Subscript out of range и LBound=1[/color][/b]

[b] [color=blue]'проверка: диапазон корректно копируется и вставляется[/color][/b]
Dinamyc.Worksheets(1).Range(Cells(2, 3), Cells(Lr2, 3)).Copy
OstFile.Worksheets(1).Activate
Range(Cells(3, 2), Cells(Lr2, 2)).PasteSpecial Paste:=xlPasteAllExceptBorders

Terminate_Sub:
Dinamyc.Close SaveChanges:=False
Application.CutCopyMode = False
Cells(3, 3).Select
End Sub
[/vba]

Автор - Serg5876
Дата добавления - 27.01.2024 в 23:36
Gustav Дата: Воскресенье, 28.01.2024, 01:26 | Сообщение № 2
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2748
Репутация: 1137 ±
Замечаний: 0% ±

начинал с Excel 4.0, видел 2.1
Полностью задачу пока не очень понимаю, поэтому начнём с малого - с красного текста.
в массив ничего не записывается !!!
Откуда такой вывод? Всё записывается - четыре элемента в столбик. Включите перед выполнением наблюдение за переменной NameOfEGAIS - по верхнему меню редактора VBA командой Debug \ Add Watch. Поставьте точку останова на следующую строку за чтением массива и всё увидите в Окне наблюдения (Watches).

выдает ошибку Subscript out of range и LBound=1
LBound=1 - всё правильно, это же нижняя граница. Чтобы верхнюю получить надо функцию UBound использовать. Вы случайно не на этом основании делаете вывод о пустоте массива? Ошибка же "за пределами массива" возникает из-за обращения к несуществующему элементу массива NameOfEGAIS(0). Дело в том, что массивы, считанные из диапазона рабочего листа, всегда двумерные и нумерация их строк и столбцов всегда начинается с 1 (даже если в программе явно установлено Option Base 0). И адресация к элементу такого массива тоже всегда двумерная: даже если массив состоит только из одной ячейки, то адрес ее в массиве будет NameOfEGAIS(1, 1).


МОИ: Ник, Tip box: 41001663842605

Сообщение отредактировал Gustav - Воскресенье, 28.01.2024, 01:29
 
Ответить
СообщениеПолностью задачу пока не очень понимаю, поэтому начнём с малого - с красного текста.
в массив ничего не записывается !!!
Откуда такой вывод? Всё записывается - четыре элемента в столбик. Включите перед выполнением наблюдение за переменной NameOfEGAIS - по верхнему меню редактора VBA командой Debug \ Add Watch. Поставьте точку останова на следующую строку за чтением массива и всё увидите в Окне наблюдения (Watches).

выдает ошибку Subscript out of range и LBound=1
LBound=1 - всё правильно, это же нижняя граница. Чтобы верхнюю получить надо функцию UBound использовать. Вы случайно не на этом основании делаете вывод о пустоте массива? Ошибка же "за пределами массива" возникает из-за обращения к несуществующему элементу массива NameOfEGAIS(0). Дело в том, что массивы, считанные из диапазона рабочего листа, всегда двумерные и нумерация их строк и столбцов всегда начинается с 1 (даже если в программе явно установлено Option Base 0). И адресация к элементу такого массива тоже всегда двумерная: даже если массив состоит только из одной ячейки, то адрес ее в массиве будет NameOfEGAIS(1, 1).

Автор - Gustav
Дата добавления - 28.01.2024 в 01:26
Serg5876 Дата: Воскресенье, 28.01.2024, 12:06 | Сообщение № 3
Группа: Пользователи
Ранг: Новичок
Сообщений: 11
Репутация: 0 ±
Замечаний: 0% ±

2007
Gustav, вы мне просто пелену с глаз убрали !))) Я вчера поздно ночью уже впал в ступор))). Конечно, вы правы. Все заработало ! Насчет LBound - это конечно я ошибся, по аналогии с переменной Lr (Last Row) буква L у меня ассоциировалась с концом списка B) ). Окном Add Watch активно пользуюсь, но почему то решил, что массив оно вывести не в состоянии, и даже не попробовал)). Насчет двумерной нумерации не знал, так что тут для меня открылась новая информация, благодаря вам ! А полностью задачу не поняли, потому что я поудалял лишний код, чтоб не морочить вам голову, а оставил только тот фрагмент, который выдавал ошибку. Спасибо вам большое !

По дальнейшей цели создания этих массивов: есть два списка наименований (примерно по 1т в каждом, но не одинаковое кол-во), нужно сравнить все элементы 1го списка со вторым и несовпадающие добавить в конец 2го списка (поэтому 2й список при запуске программы явно может быть больше). Я после выгрузки этих списков в массивы дальше перебираю их циклом For Next, сравнивая каждый элемент 1го списка с каждым элементом 2го. Не очень оптимально, но зато все ясно и прозрачно. Но долго. Есть ли какой-то более продвинутый функционал для решения этой задачи ? Может, надо не в массивы загрузить списки, а в словари и потом использовать функцию Filter (ни разу еще это не делал) ? Читал, что в словарях какой-то алгоритм бинарного поиска очень шустрый.. Или использовать функцию WorksheetFunction.Match ? В каком направлении двигаться ?


Сергей

Сообщение отредактировал Serg5876 - Воскресенье, 28.01.2024, 12:08
 
Ответить
СообщениеGustav, вы мне просто пелену с глаз убрали !))) Я вчера поздно ночью уже впал в ступор))). Конечно, вы правы. Все заработало ! Насчет LBound - это конечно я ошибся, по аналогии с переменной Lr (Last Row) буква L у меня ассоциировалась с концом списка B) ). Окном Add Watch активно пользуюсь, но почему то решил, что массив оно вывести не в состоянии, и даже не попробовал)). Насчет двумерной нумерации не знал, так что тут для меня открылась новая информация, благодаря вам ! А полностью задачу не поняли, потому что я поудалял лишний код, чтоб не морочить вам голову, а оставил только тот фрагмент, который выдавал ошибку. Спасибо вам большое !

По дальнейшей цели создания этих массивов: есть два списка наименований (примерно по 1т в каждом, но не одинаковое кол-во), нужно сравнить все элементы 1го списка со вторым и несовпадающие добавить в конец 2го списка (поэтому 2й список при запуске программы явно может быть больше). Я после выгрузки этих списков в массивы дальше перебираю их циклом For Next, сравнивая каждый элемент 1го списка с каждым элементом 2го. Не очень оптимально, но зато все ясно и прозрачно. Но долго. Есть ли какой-то более продвинутый функционал для решения этой задачи ? Может, надо не в массивы загрузить списки, а в словари и потом использовать функцию Filter (ни разу еще это не делал) ? Читал, что в словарях какой-то алгоритм бинарного поиска очень шустрый.. Или использовать функцию WorksheetFunction.Match ? В каком направлении двигаться ?

Автор - Serg5876
Дата добавления - 28.01.2024 в 12:06
Gustav Дата: Воскресенье, 28.01.2024, 16:18 | Сообщение № 4
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2748
Репутация: 1137 ±
Замечаний: 0% ±

начинал с Excel 4.0, видел 2.1
Читал, что в словарях какой-то алгоритм бинарного поиска очень шустрый.. Или использовать функцию WorksheetFunction.Match ? В каком направлении двигаться ?

Да, наверное, эффективнее всего для решения поставленной задачи здесь использовать объект "Словарь" (Scripting.Dictionary). Без всяких утомительных попарных сравнений элементов двух массивов. Сначала записываете в словарь элементы массива 2 (циклом по этому массиву). А затем, тоже циклом, добавляете в словарь элементы массива 1. При этом, если очередного элемента массива 1 еще нет в словаре, он добавляется в конец словаря, иначе - просто игнорируется. По окончании процесса имеете словарь, содержащий все уникальные элементы обоих массивов.

Теоретически хорошо бы еще и сортировку по алфавиту к элементам словаря применить, чтобы получился классический отсортированный "справочник" уникальных элементов. Но если сортировка нужна только для ускорения доступа к элементам (как это было бы уместно для списка на рабочем листе), то для этого в словаре существует механизм доступа по ключам, а также быстрая проверка наличия того или иного значения. Поэтому фактическая последовательность элементов внутри словаря не столь уж и важна, и, соответственно, необходимость сортировки - не столь уж актуальна.


МОИ: Ник, Tip box: 41001663842605
 
Ответить
Сообщение
Читал, что в словарях какой-то алгоритм бинарного поиска очень шустрый.. Или использовать функцию WorksheetFunction.Match ? В каком направлении двигаться ?

Да, наверное, эффективнее всего для решения поставленной задачи здесь использовать объект "Словарь" (Scripting.Dictionary). Без всяких утомительных попарных сравнений элементов двух массивов. Сначала записываете в словарь элементы массива 2 (циклом по этому массиву). А затем, тоже циклом, добавляете в словарь элементы массива 1. При этом, если очередного элемента массива 1 еще нет в словаре, он добавляется в конец словаря, иначе - просто игнорируется. По окончании процесса имеете словарь, содержащий все уникальные элементы обоих массивов.

Теоретически хорошо бы еще и сортировку по алфавиту к элементам словаря применить, чтобы получился классический отсортированный "справочник" уникальных элементов. Но если сортировка нужна только для ускорения доступа к элементам (как это было бы уместно для списка на рабочем листе), то для этого в словаре существует механизм доступа по ключам, а также быстрая проверка наличия того или иного значения. Поэтому фактическая последовательность элементов внутри словаря не столь уж и важна, и, соответственно, необходимость сортировки - не столь уж актуальна.

Автор - Gustav
Дата добавления - 28.01.2024 в 16:18
Serg5876 Дата: Воскресенье, 28.01.2024, 16:24 | Сообщение № 5
Группа: Пользователи
Ранг: Новичок
Сообщений: 11
Репутация: 0 ±
Замечаний: 0% ±

2007
Да, наверное, эффективнее всего для решения поставленной задачи здесь использовать объект "Словарь" (Scripting.Dictionary).

Спасибо, Gustav, за совет !
Буду пробовать в этом направлении ...


Сергей
 
Ответить
Сообщение
Да, наверное, эффективнее всего для решения поставленной задачи здесь использовать объект "Словарь" (Scripting.Dictionary).

Спасибо, Gustav, за совет !
Буду пробовать в этом направлении ...

Автор - Serg5876
Дата добавления - 28.01.2024 в 16:24
Serg5876 Дата: Понедельник, 18.03.2024, 17:43 | Сообщение № 6
Группа: Пользователи
Ранг: Новичок
Сообщений: 11
Репутация: 0 ±
Замечаний: 0% ±

2007
Доброго дня всем ! Особенно Gustavu) С вашей помощью моя программа-макрос прекрасно работала... до тех пор, пока не возник частный случай: при записи диапазона в массив размер диапазона - одна ячейка. И все рухнуло !
Размер диапазона - это список адресов торговых точек из листа Excel, которые пользователь выбирает из выпадающего списка ComboBox. Так вот, в одном случае торговая точка всего одна оказалась.. Макрос выдает ошибку на этапе формирования списка для ComboBox (скрин прикреплен).
Ошибка происходит вот в этой форме:

[vba]
Код
Private Sub ComboBox1_Change()
Dim AdrMarket() As Variant

Firma = Me.ComboBox1.Text
Me.Label1.Caption = lbl1captionBegin & Firma

FirmCol = AdrPoint.Cells.Find(Firma).Column
LastRow = AdrPoint.Cells(Rows.Count, FirmCol).End(xlUp).Row
AdrPoint.Activate
AdrMarket = Range(Cells(3, FirmCol), Cells(LastRow, FirmCol)).Value ' [color=red]вот здесь, при записи диапазона в динамический массив. При длине диапазона =1 происходит ошибка.[/color]
Me.ComboBox2.List = AdrMarket
End Sub
[/vba]

Вопрос: Бывает ли диапазон Range из одного элемента ? Можно ли свойством List заполнить список из одного элемента ?
Или надо в таком случае добавлять специальный признак конца списка (2ю строчку) и потом отлавливать, чтоб его пользователь не выбирал ?
К сообщению приложен файл: 3728828.png (177.1 Kb) · 9131244.png (35.4 Kb) · 2117294.png (173.1 Kb) · 9773227.png (37.0 Kb) · 4756424.png (166.1 Kb)


Сергей
 
Ответить
СообщениеДоброго дня всем ! Особенно Gustavu) С вашей помощью моя программа-макрос прекрасно работала... до тех пор, пока не возник частный случай: при записи диапазона в массив размер диапазона - одна ячейка. И все рухнуло !
Размер диапазона - это список адресов торговых точек из листа Excel, которые пользователь выбирает из выпадающего списка ComboBox. Так вот, в одном случае торговая точка всего одна оказалась.. Макрос выдает ошибку на этапе формирования списка для ComboBox (скрин прикреплен).
Ошибка происходит вот в этой форме:

[vba]
Код
Private Sub ComboBox1_Change()
Dim AdrMarket() As Variant

Firma = Me.ComboBox1.Text
Me.Label1.Caption = lbl1captionBegin & Firma

FirmCol = AdrPoint.Cells.Find(Firma).Column
LastRow = AdrPoint.Cells(Rows.Count, FirmCol).End(xlUp).Row
AdrPoint.Activate
AdrMarket = Range(Cells(3, FirmCol), Cells(LastRow, FirmCol)).Value ' [color=red]вот здесь, при записи диапазона в динамический массив. При длине диапазона =1 происходит ошибка.[/color]
Me.ComboBox2.List = AdrMarket
End Sub
[/vba]

Вопрос: Бывает ли диапазон Range из одного элемента ? Можно ли свойством List заполнить список из одного элемента ?
Или надо в таком случае добавлять специальный признак конца списка (2ю строчку) и потом отлавливать, чтоб его пользователь не выбирал ?

Автор - Serg5876
Дата добавления - 18.03.2024 в 17:43
Gustav Дата: Понедельник, 18.03.2024, 18:10 | Сообщение № 7
Группа: Друзья
Ранг: Участник клуба
Сообщений: 2748
Репутация: 1137 ±
Замечаний: 0% ±

начинал с Excel 4.0, видел 2.1
Dim AdrMarket() As Variant

Попробуйте скобки здесь убрать, т.е. вот так сделайте:
[vba]
Код
Dim AdrMarket As Variant
[/vba]
Выполняется ли при этом оператор присвоения диапазона переменной?
А следующий за ним оператор, т.е. вот этот:
[vba]
Код
Me.ComboBox2.List = AdrMarket
[/vba]
?

[p.s.]Скорее всего, ошибка будет, поэтому замените этот последний оператор на следующий фрагмент:[/p.s.]
[vba]
Код
    If IsArray(AdrMarket) Then
        Me.ComboBox2.List = AdrMarket
    Else
        Me.ComboBox2.AddItem AdrMarket
    End If
[/vba]
Теперь должно всё правильно отработать.


МОИ: Ник, Tip box: 41001663842605

Сообщение отредактировал Gustav - Понедельник, 18.03.2024, 18:36
 
Ответить
Сообщение
Dim AdrMarket() As Variant

Попробуйте скобки здесь убрать, т.е. вот так сделайте:
[vba]
Код
Dim AdrMarket As Variant
[/vba]
Выполняется ли при этом оператор присвоения диапазона переменной?
А следующий за ним оператор, т.е. вот этот:
[vba]
Код
Me.ComboBox2.List = AdrMarket
[/vba]
?

[p.s.]Скорее всего, ошибка будет, поэтому замените этот последний оператор на следующий фрагмент:[/p.s.]
[vba]
Код
    If IsArray(AdrMarket) Then
        Me.ComboBox2.List = AdrMarket
    Else
        Me.ComboBox2.AddItem AdrMarket
    End If
[/vba]
Теперь должно всё правильно отработать.

Автор - Gustav
Дата добавления - 18.03.2024 в 18:10
Serg5876 Дата: Понедельник, 18.03.2024, 18:56 | Сообщение № 8
Группа: Пользователи
Ранг: Новичок
Сообщений: 11
Репутация: 0 ±
Замечаний: 0% ±

2007
Gustav, спасибо, все заработало ! Range с одним элементом сработал. Ошибку выдавал List. Теперь я узнал, что свойством List нельзя заполнить 1 элемент)). А также познакомился с функцией IsArray, тоже до этого не приходилось использовать. А то я начал мудрить со специальным значением (признак конца списка), за которым бы потом пришлось следить, чтобы его не выбирали из списка))


Сергей

Сообщение отредактировал Serg5876 - Понедельник, 18.03.2024, 18:57
 
Ответить
СообщениеGustav, спасибо, все заработало ! Range с одним элементом сработал. Ошибку выдавал List. Теперь я узнал, что свойством List нельзя заполнить 1 элемент)). А также познакомился с функцией IsArray, тоже до этого не приходилось использовать. А то я начал мудрить со специальным значением (признак конца списка), за которым бы потом пришлось следить, чтобы его не выбирали из списка))

Автор - Serg5876
Дата добавления - 18.03.2024 в 18:56
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Как записать диапазон в массив (Макросы/Sub)
  • Страница 1 из 1
  • 1
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!