Страницы: 1 2 След.
RSS
Фильтр по данным в Listbox
 
Доброго времени суток уважаемые жители планеты!
Есть две формы. В первую выгружаются данные с которыми далее работаю ( в оригинале данные берутся из БД Acces но для примера беру их с листа). Подскажите пожалуйста, как отобрать только те строки в ListBox, которые подходят по условию отбора? Заранее спасибо всем!
 
Циклом по диапазону и проверять соответствие условиям: если да, то Additem
 
Доброе время суток
Ronin751, а каков критерий отбора записей во 2-ую форму? Не понятно.
Цитата
Юрий М написал:
Циклом по диапазону и проверять соответствие условиям: если да, то Additem
Из базы данных можно грузить и без AddItem.
Код
ListBox.Column = Recordset.GetRows
 
Андрей, не дружу с Access, потом и вариант по примеру ))
 
Юрий, так у ТС таблица как раз в имеет типичную структуру баз данных, вполне можно и ADO-style загрузки данных в combox и listbox применить и запросами подгружать выборку. Только определить надо от куда берутся данные для 2-ой формы и на основании какого критерия.
 
Цитата
Андрей VG написал:
от куда берутся данные для 2-ой формы и на основании какого критерия.
Жмём кнопку "Выполнить отбор" - там видим критерии ))
 
Юрий, да я как бы щёлкнул, только увидел
Цитата
   UserForm2.Show
 
Юрий.М.! Спасибо Вам, что обратили внимание на тему. Сделал так:
Код
With Me.ListBox1
        X = 0
        For i = 0 To UserForm1.ListBox1.ListCount - 1
            If UserForm1.ListBox1.List(i, 2) Like Me.TextBox3 & "*" Then
                .AddItem ""
                .List(X, 0) = i
                .List(X, 1) = UserForm1.ListBox1.List(i, 1)
                .List(X, 2) = UserForm1.ListBox1.List(i, 2)
                .List(X, 3) = UserForm1.ListBox1.List(i, 3)
                X = X + 1
            End If
        Next
    End With
Но в оригинале столбцов в ListBox более 25. Может более простой вариант есть? Думал Взять всё в массив, типа:
Код
AllRows = UserForm1.ListBox1.List
но что с этим потом делать ни как не скумекаю.

Андрей VG, здравствуйте! Спасибо, что ответили. К слову сказать, пользуясь случаем, постоянно читаю Ваши ответы в теме JeyCi. Благодарю Вас за столь подробное и в основном доходчивое объяснение премудростей отношений Аксес и Эксель!

Цитата
Ronin751, а каков критерий отбора записей во 2-ую форму? Не понятно.
1)Отобрать данные которые входят в диапазон дат
2)Отбор значений которые содержат - TextBox3.Text
3)Отбор значений которые содержат - TextBox4.Text
Цитата
ListBox.Column = Recordset.GetRows
Тут немного не понял, что имелось ввиду. ((
Изменено: Ronin751 - 07.09.2015 21:31:44
 
Цитата
Ronin751 написал:
в оригинале столбцов в ListBox более 25
Тогда такой метод не подойдёт: можно не более 10.
Вариант: циклом по условию (условиям) отбираем в промежуточный массив и уже его в List.
 
Цитата
Андрей VG написал:
Юрий, да я как бы щёлкнул, только увидел
Странно... Вот, что вижу я
 
Изменил #8. Простите!
Код
If UserForm1.ListBox1.List(i, 2) Like Me.TextBox3 & "*" Then
Изменено: Ronin751 - 07.09.2015 21:38:08
 
Ronin751, пример для 1-ой формы. Так как у вас 4 столбца, пришлось добавить в таблицу поле, видимо для Access вы предполагаете в этом поле хранить первичный ключ таблицы. Может и ошибаюсь
Цитата
Юрий М написал: Странно... Вот, что вижу я
так я тоже вижу, что бы на 1-ой не выбрал - одно и тоже. А на каком основании.
Изменено: Андрей VG - 08.09.2015 01:32:02
 
Ronin751, извиняюсь, пропустил. про отбор между заданными датами. Тогда не совсем понятно, а зачем на 1-ой форме отображается вся таблица?
Может тогда на первой диапазон дат, а на второй отображать записи между этими датами?
 
Цитата
видимо для Access вы предполагаете в этом поле хранить первичный ключ таблицы.
Так и есть.
Из Аксес данные беру:
Код
    Dim cnt     As New ADODB.Connection
    Dim rst     As New ADODB.Recordset
    Dim rcArray As Variant
    Dim sSQL    As String
    Dim sdbPath, sConnect
    sdbPath = ThisWorkbook.Path & "\Закрытые.mdb": sConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sdbPath & ";"
    sSQL = "SELECT * FROM Выполненные  ORDER BY iD;": cnt.Open sConnect: rst.Open sSQL, cnt
    With Me.ListBox1
        .Clear: .ColumnCount = 29: .Column = rst.GetRows: .ListIndex = -1
    End With
    rst.Close: cnt.Close
    Set rst = Nothing
    Set cnt = Nothing
 
Цитата
а зачем на 1-ой форме отображается вся таблица?
Тут суть какая? Это, своего рода, журнал. Для упрощения визуального восприятия ( не показывать же все, допустим, 1млн строк ), все данные из Аксес выгружаются в невидимый ListBox. А вот уж из него необходимо вытянуть только необходимые, подходящие по условиям. И уже их и отобразить.
 
Цитата
Ronin751 написал:
все данные из Аксес выгружаются в невидимый ListBox
Список в ЛистБоксе - это уже массив, зачем ЛистБокс тогда? Выбирайте из массива. Странная реализация ))
 
Цитата
Ronin751 написал:
А вот уж из него необходимо вытянуть только необходимые, подходящие по условиям. И уже их и отобразить.
Так а смысл в таких "костылях"? Тянуть фильтрами можно сразу из Access. Пример для второй формы.
 
Если же вы однократно хотите загрузить всё (допустим, чтоб сеть только раз нагрузить), то точно также можно загрузить всё в Recordset, а потом использовать метод Filter для отбора требуемых записей в ListBox (не забывайте после этой фильтрации Recordset.MoveFirst выполнить перед GetRows).
Плюс для этого случая нужно вынести переменные для Connection, Recordset на уровень формы и закрывать подключения при закрытии формы.
Изменено: Андрей VG - 07.09.2015 22:30:33
 
Андрей VG! Спасибо Вам за совет и помощь. Обязательно поищу в нэте. А то пока немного тяжело понять. Буду грызть.
 
Ronin751, вариант для 2-ой формы с Recordset, в который загружены все данные, а выборка из него по значениям Textbox в Combobox осуществляется Recordset.Filter (отличия есть - не пугайтесь).
Изменено: Андрей VG - 07.09.2015 23:33:25
 
Андрей, спасибо Вам, что уделили столько времени и внимания этой теме! Буду стараться, на досуге вникнуть по-более. Спасибо Вам!
Пытаюсь всё же идти по такому пути:
Код
Dim AllRows As Variant
    Dim i As Long
    Dim Name As String          'Фамилия
    Dim Street As String          'Улица
    Dim DateSt As Date, DateEnd As Date     'Диапазон дат
    
    'Данные ListBox в массив
    AllRows = UserForm1.ListBox1.List
    
    Street = Me.TextBox2 & "*"                
    Name = Me.TextBox4                  
    DateSt = DateValue(Me.TextBox1.Value)    
    DateEnd = DateValue(Me.TextBox2.Value)  
    
    'Прохожу по всем строкам ListBox
    For i = 1 To UBound(AllRows)
        'Проверка: соответствует ли дата условию
        If AllRows(i, 1) >= DateSt And AllRows(i, 1) <= DateEnd Then
            'Наличие улицы
            If InStr(1, AllRows(i, 3), Street) <> 0 Then
                'Наличие имени
                If InStr(1, AllRows(i, 4), Name) <> 0 Then
                    '?????????????????????????????????????
                End If
            End If
        End If
    Next i
По идее логика должна быть правильной ( по крайней мере я на это надеюсь ).
Не могу понять, как отобразить подходящие по условию стоки, в ListBox на второй форме? :cry:
Изменено: Ronin751 - 08.09.2015 01:15:45
 
Как я понимаю, далее необходимо схожие условию строки UserForm1.ListBox1 вставить в новый массив. И как итог, UserForm2.ListBox1.List = новый массив. Подскажите пожалуйста, как это сделать и вообще, правильным ли путем я иду? Спасибо!
 
Доброе время суток
Код
        'Проверка: соответствует ли дата условию
        If AllRows(i, 1) >= DateSt And AllRows(i, 1) <= DateEnd Then

вот это не будет работать DateSt, DateEnd у вас дата, а в AllRows - текст. Нужно тогда использовать CDate(AllRows(i,1))
Следующее, вы же не знаете заранее - сколько реально строк попадёт в массив. Лучше уж тогда сразу писать данные, удовлетворяющие условию в ListBox через AddItem и последовательное указание номера столбца. По идее массив вообще не нужен.
И, честно говоря, так и не понял - почему не используете код с Recordset? Там всего лишь нужно поменять строку подключения (её формирование у вас есть в #14. Переписать из таблицы Выполненные Access правильные наименования столбцов в SQL запрос и фильтр Where (если они у вас назывались точно также как и в примере таблицы на Лист1, то ничего менять не нужно). Плюс заменить [Лист1$] в предложении From на имя таблицы Выполненные. Плюс добавить обработку ошибок, если дата в полях ввода формы будет введена не в верном формате. Вот собственно и все различия между обращениями к  таблице Access и таблице Excel.
Изменено: Андрей VG - 08.09.2015 08:42:30
 
Всем доброго времени суток! Прошу прощения за столь долгое молчание. Работа гнусно мешает, внося свои коррективы.
Цитата
так и не понял - почему не используете код с Recordset
При Recordset, во время каждого поиска нужно будет подключатся к Аксес. Мне кажется из ListBox будет быстрее (ИМХО). Или нет?
Откровенно говоря, мне теперь для себя (на будущее) охота знать как сделать отбор по ListBox. ))

Коль уж об Аксес заговорили, то уж лучше на примерах.
Цитата
Переписать из таблицы Выполненные Access правильные наименования столбцов в SQL запрос и фильтр Where
Код
    Dim cnt     As New ADODB.Connection
    Dim rst     As New ADODB.Recordset
    Dim rcArray As Variant
    Dim sSQL    As String
    Dim sdbPath, sConnect
    sdbPath = ThisWorkbook.Path & "\Закрытые.mdb": sConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sdbPath & ";"
    If Me.TextBox3 > "" Then
    sSQL = "SELECT * FROM Выполненные  Where Адрес = TextBox3;"
    End If
    cnt.Open sConnect: rst.Open sSQL, cnt
    With Me.ListBox1
    .Clear: .ColumnCount = 5: .Column = rst.GetRows: .ListIndex = -1
    For i = 0 To Me.ListBox1.ListCount - 1
      .List(i, 1) = Format(.List(i, 1), "dd.mm.yyyy")
    Next
    End With
    
    rst.Close: cnt.Close
    Set rst = Nothing
    Set cnt = Nothing
Ругается. На sSQL = "SELECT * FROM Выполненные  Where Дата = TextBox3;"  Я так понимаю, что в запросе нужно условие отбора устанавливать как то иначе. ??? А касательно промежутка по датам, так тут вообще не догадываюсь.
Изменено: Ronin751 - 09.09.2015 19:30:53
 
Цитата
Ronin751 написал: Ругается. На sSQL = "SELECT * FROM Выполненные  Where Дата = TextBox3;"  
TextBox3 у вас Адрес, не Дата...
и брать надо в формате Access...
как-то так
Код
sSQL = "SELECT * FROM Выполненные  Where Дата = " & Format$(TextBox1.Text, "mm\/dd\/yyyy") & ";"
... только запрос какой-то др должен быть - с BETWEEN, видимо, если вы хотите между двух дат...
я ещё с ходу не напишу (только учусь  :))...
но там потом др ошибка выскакивает...  
Изменено: JeyCi - 09.09.2015 19:25:56
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Здравствуйте JeyCi! Уже изменил #24. Спасибо Вам, за подсказку. Я, откровенно говоря, и не думал, что так не просто будет фильтровать данные. Уже весь нэт перерыл, а подобного не нашел. ((
 
Доброе время суток
Ronin751, я же в #24 в коде отобразил, как формируется запрос на интервал дат. Можно же просмотреть, что получается в переменной sSQL при открытии Recordset?
Код
Дата Between #mm/dd/yyyy# And #mm/dd/yyyy#
, где mm - месяц, dd - день, yyyy год
И замечания.
Лучше не писать Select *, а перечислять список требуемых полей. У вас названия полей таблицы в Access сильно отличаются от вашего примера в Excel?
Не надо очищать ListBox.Clear перед заливкой данных из Recordset - лишний код. ListBox.Column = Recordset.GetRows - заменяет данные, а не добавляет.

Цитата
При Recordset, во время каждого поиска нужно будет подключатся к Аксес. Мне кажется из ListBox будет быстрее (ИМХО).
Если у вас настроено индексирования для полей, по которым вы применяете фильтр в SQL-запросе, то Recordset будет быстрее, если нет, то разница будет не особенно существенной и в какую сторону однозначно без теста не скажешь. Учитывая, что Access может неявно и сам создавать индексы, при достаточно большом объёме исходных данных Recordset всё равно будет быстрее. Хотя, конечно, и придётся держать открытым соединение с базой данных. Только это соединение чем-то вам мешает?
 
Цитата
Только это соединение чем-то вам мешает
Как таковой, не мешает конечно. Тем более, что я наполняю базу так же через эксель. Просто вопрос скорости волнует?! Андрей, а как создать запрос если нужно искать по данным во всех 4х TextBox? Спасибо!
 
Цитата
Ronin751 написал:
а как создать запрос если нужно искать по данным во всех 4х TextBox?
Вы не внимательны, в приведённом коде всё это есть. Выкладываю код обработчика нажатия кнопки CommandButton1 в форме 2 с комментариями.
Скрытый текст

Успехов
 
Для меня (ввиду незнания Access) было бы проще перебрать массив (ListBox)  :)
Только нет ясности, что делать, если один из критериев не заполнен?
Страницы: 1 2 След.
Наверх