Страницы: 1
RSS
VBA: Поиск ID в списке и заполнение данных из найденной строки
 
Здравствуйте. Я только начинаю осваивать VBA, так что за ламерские вопросы, если что, сильно не ругайте.  
 
Данные хранятся на одном листе (Dox). В первом столбце приведён идентификационный номер, по которому и проходит поиск. Эти ID будут упорядочиваться по возрастанию. Интерфейс осуществляется при помощи UserForm. Значения списков для ComboBox берутся с другого листа (DB).  
 
Как можно наиболее оптимально сделать поиск ID с последующим внесением данных и этой строки в соответствующие пункты UserForm, а также запись значений из формы таким образом, чтобы при изменении/добавлении данных ID по-прежнему оставались по возрастанию.  
 
Поиск ID в списке и внесение данных в форму будут осуществляться с помощью функции FillByID(). Добавление/изменение записи будет осуществляться при нажатии соответствующей кнопки UserForm.  
Надеюсь, всё понятно описал.  
 
P.S. Я не прошу делать за меня всю работу, мне куда важнее научиться. В первую очередь интересуют алгоритмы и методы их реализации.
 
Не вполне понял (в деталях) задачу. Поясните чуть подробнее.  
Зато заметил в коде интересный синтаксис (ранее не встречал) - надо взять на вооружение:  
 
[DB!L1].Value = "test"
 
Я иногда так пишу:  
 Лист3.[L1].Value = "test"
Но почему-то DB.[L1].Value = "test" не работает...
 
DB.[L1].Value и не должно - это ведь не кодовое имя листа... Семён Семёныч!... :)
 
У меня всегда в подобных ситуациях алгоритм такой:  
При загрузке формы считываем данные в  публичный массив, затем массив индексируем  словарем(тоже публичным), так как ID является уникальным значением.  
Затем при нужном событиии получаем значение из словаря(номер строки массива), и уже зная номер строки извлекаем из массива необходимые данные.  
Иногда вместо массива я использую ListBox , или ComboBox
Спасибо
 
может find поможет  
 
Dim rgResult As Range  
Dim rng As Range  
 
last = Range("A65536").End(xlUp).Row 'последняя строка  
set rng = Rang("A1") 'начинать поиск с ячейки А1  
's = Userform1.Combobox1.value 'что искать  
s = "С-1-1-01"  
Set rgResult = Range("A1:A" & last & "").Find(s, rng, xlValues, , xlByColumns)  
'rgResult.address - адрес искомой ячейки  
 
typ = rgResult.offset(0,1)  
nomer = rgResult.offset(0,2)  
'и так далее
 
{quote}{login=Hugo}{date=17.02.2012 04:10}{thema=}{post}Не вполне понял (в деталях) задачу. Поясните чуть подробнее.{/post}{/quote}  
Тут, по сути 2 случая.  
В первом случае, надо в первом столбце листа Dox просто найти значение, совпадающее с TestBox3.Value, а затем, если совпадение найдено, внести значения из найденной строки в соответствующие поля формы.  
Во втором случае посложнее. Сначала то же самое нахождение, что и в первом случае. Если совпадений нет, на листе Dox вставляется новая строчка, соответствующая новому ID. И выбирается такое место в таблице, чтобы все ID по-прежнему шли по возрастанию. Строчка заполняется значениями, введёнными пользователем в различных полях формы. Если же совпадение ID есть, то значения в таблице просто заменяются на новые из формы.  
Надеюсь, теперь понятнее.  
 
Честно говоря, не понял к чему это, да и следующее сообщение - тоже.
 
{quote}{login=R Dmitry}{date=17.02.2012 04:19}{thema=}{post}У меня всегда в подобных ситуациях алгоритм такой:  
При загрузке формы считываем данные в  публичный массив, затем массив индексируем  словарем(тоже публичным), так как ID является уникальным значением.  
Затем при нужном событиии получаем значение из словаря(номер строки массива), и уже зная номер строки извлекаем из массива необходимые данные.  
Иногда вместо массива я использую ListBox , или ComboBox{/post}{/quote}  
Если с массивом более-менее понятно (хотя, разве при большой базе данных разве макрос не будет жрать кучу оперативки, ведь по сути, будут единовременно практически дублироваться данные из экселя?), то можно поподробнее написать, что значит "индексировать словарем"?  
 
ListBox или ComboBox, насколько я понял, для нахождения индекса при совпадении?
 
sub test()  
a=array("a","b","c")  
set dict=createobject("Scripting.Dictionary")  
for i=0 to ubound(a)  
dict.add a(i),i  
next  
msgbox dict.item("b")  
end sub  
 
Вот вам простейший пример
Спасибо
 
<<ListBox или ComboBox, насколько я понял, для нахождения индекса при совпадении?>>  
 
В вашем случае я бы выбрал именно этот вариант, без использования массива.  
В случае отсутствия данных доступен метод add как в словаре так и элементе формы,  
а синхронизацию проводил бы, после всех операций.  
==============  
по поводу памяти у вас, что нынче 128 кб оперативы?  
или мега база данных(если так тогда переходите на СУБД типа клиент-сервер)
Спасибо
 
{quote}{login=R Dmitry}{date=17.02.2012 07:37}{thema=}{post}sub test()  
a=array("a","b","c")  
set dict=createobject("Scripting.Dictionary")  
for i=0 to ubound(a)  
dict.add a(i),i  
next  
msgbox dict.item("b")  
end sub  
 
Вот вам простейший пример{/post}{/quote}  
Команды по отдельности вроде понятны, а как работает всё вместе - никак не пойму. >_<
 
Это был я, авторизация сбилась.  
{quote}{login=R Dmitry}{date=17.02.2012 07:48}{thema=}{post}<<ListBox или ComboBox, насколько я понял, для нахождения индекса при совпадении?>>  
 
В вашем случае я бы выбрал именно этот вариант, без использования массива.{/post}{/quote}  
А как это делается на практике? Куда ставится сам ComboBox? Его, как я понял, видно не должно быть, просто забираем результат? Как проводится сравнение при поиске? Как лучше полученный индекс использовать для подстановки значений из той же строки?
 
{quote}{login=}{date=17.02.2012 04:27}{thema=}{post}может find поможет  
 
Dim rgResult As Range  
Dim rng As Range  
 
last = Range("A65536").End(xlUp).Row 'последняя строка  
set rng = Rang("A1") 'начинать поиск с ячейки А1  
's = Userform1.Combobox1.value 'что искать  
s = "С-1-1-01"  
Set rgResult = Range("A1:A" & last & "").Find(s, rng, xlValues, , xlByColumns)  
'rgResult.address - адрес искомой ячейки  
 
typ = rgResult.offset(0,1)  
nomer = rgResult.offset(0,2)  
'и так далее{/post}{/quote}  
На основе этого попытался сделать код такого вида:  
 
Private Function FillByID()  
' Заполнение всех полей данными для этого ID, введённого в TextBox3,  
' если только данные для документа с этим ID уже внесены на лист Dox  
   Dim IDRange As Range  
   Dim rgResult As Range  
   Set IDRange = Range("Dox!A:A")  
   Set IDRange = Range(IDRange.Columns.End(xlUp).Address, IDRange.Columns.End(xlDown).Address)  
   s = TextBox3.Value  
   Set rgResult = IDRange.Find(s, Range("Dox!A2"), xlValues, , xlByColumns)  
   ComboBox2.Value = rgResult.Offset(0, 1)  
End Function  
 
Однако, оно почему-то не работает. Видимо, где-то напутал с типами данных. :(
 
{quote}{login=Arex}{date=17.02.2012 08:39}{thema=Re: }{post}Однако, оно почему-то не работает. Видимо, где-то напутал с типами данных. :({/post}{/quote}  
В смысле, при запуске выдаёт ошибку.
 
Вот Вам учебное пособие.
Спасибо
 
Маленькая поправочка  
 
Dict.Add CLng(Me.TextBox1), c + 1
Спасибо
 
{quote}{login=R Dmitry}{date=17.02.2012 09:31}{thema=Простейший пример без отслеживания ИД}{post}Вот Вам учебное пособие.{/post}{/quote}  
Спасибо большое. Буду разбираться.
Страницы: 1
Читают тему
Наверх