Для того, чтобы добавить строку "(Все)" в список разработчиками MSA в solutions.mdb (решения.mdb) из инсталляции MSA97, а также в Neat Codes 97 предлагается использовать функцию AddAllToList, в первой базе - в модуле modSolutionUtilities, во втором - в модуле формы frmFormTopics. Эта функция заносится в RowSourceType списка, а в RowSource - запрос. Сам список свободный, предназначен для установки фильтра и не обновляется в процессе работы с формой. При использовании такой функции выявляются недостатки: - громоздкость функции,
-
после выбора пункта "(Все)" текстовое поле списка останется разумеется пустым, -
сложность добавления нескольких таких строк, -
требование на уникальность вызова функции, иначе будет вам "Object is invalid or no longer valid" (т.е. если вы захотите создать еще один список с добавленной строкой, который может быть открыт одновременно с предыдущим, нужно будет писать аналогичную новую функцию). -
эта функция вызывается большое количество раз, зависящее от количества столбцов и строк в списке. Она открывает Recordset, выдает все параметры списка, вычисляет значения всех клеток списка, закрывает Recordset. Кроме того, пользоваться такой функцией при разработке не очень удобно. Конструктор в строке RowSource отсутствует. А если запрос в RowSource зависит от элементов формы, тогда его приходится либо целиком переносить в тело функции, либо использовать запрос с параметрами и всё равно модифицировать функцию. Конечно, можно обойтись и без добавленной строки, обрабатывая например группу переключателей, один из которых "включал" бы список, а другой позволял бы выбирать дополнительную строку. Однако существует простой способ добавть любое количество строчек в список, элементарным образом изменив сам запрос следующим образом: если запрос в RowSource имеет вид SELECT Table1.Table1ID, Table1.NameField, ... FROM Table1 то к нему следует добавить UNION SELECT 0, "(Все)", "" или Null FROM Table1 Если Table1ID - счетчик, то вместо 0 можно выбрать любое число <=0, IMHO лучше выбрать 0 или -1 (последнее - если у вас в исходном запросе может быть Table1ID=0). На самом деле добавленный "запрос" конечно не нуждается в источнике :), но предложение "FROM" обязательно по правилам синтаксиса [А почему бы в очередной версии MS Jet SQL не ввести запрос SELECT без всякого источника?]. В добавленном запросе источником записей может служить любая таблица или информационный запрос (хоть перекрестный), но так как этот источник будет открываться, лучше оставлять ту же таблицу, что и в исходном, либо использовать любую маленькую табличку, для ускорения быстродействия. При этом обработка выбора изменится так: для AddAllToList (пример из solutions.mdb): RowSourceType = AddAllToList RowSource = SELECT Customers.CompanyName, Customers.CustomerID FROM Customers ORDER BY Customers.CompanyName; Private Sub SelectCustomer_AfterUpdate() ' Return record(s) that match value selected in SelectCustomer combo box. If Len(Me!SelectCustomer.Column(1)) = 0 Then DoCmd.ShowAllRecords Else DoCmd.ApplyFilter , "CustomerID = Forms!AddAllToList!SelectCustomer" End If End Sub для запроса с UNION: RowSourceType = Таблица или запрос RowSource = SELECT Customers.CompanyName, Customers.CustomerID FROM Customers UNION SELECT "(Все)", 0 FROM Customers ORDER BY Customers.CompanyName; Private Sub SelectCustomer_AfterUpdate() If Me!SelectCustomer = 0 Then DoCmd.ShowAllRecords Else DoCmd.ApplyFilter , "CustomerID = '" & Me!SelectCustomer & "'" 'CustomerID - 5-символьный уникальный код (не число) End If End Sub Еще одно заметное отличие - при использовании функции AddAllToList сначала показывается рамка списка, клетки которой потом постепенно заполняются последовательными вызовами функции, а при использовании запроса на основе UNION список открывается уже заполненный. Принцип тот же, что и в формах - данные в форме, полученные из источника данных в RecordSource, показываются сразу, а вычисленные как результат функции, например DLookUp - по мере вычисления. Проблема возникнет, если вы захотите отсортировать список по результату функции, т.е. например, "SELECT Customers.CompanyName, Customers.CustomerID FROM Customers UNION SELECT "Все", 0 FROM Customers ORDER BY CompanyName DESC;" - корректно, сортировка - обратная по названию фирмы, со строкой "Все" сверху (обратите внимание, что "Все" здесь без круглых скобок, т.к. "("<"A"<"Z"<"А кириллица"), а "SELECT Customers.CompanyName, Customers.CustomerID FROM Customers UNION SELECT "(Все)", 0 FROM Customers ORDER BY anyfunc(CompanyName);" - ошибка "В выражение ORDER BY anyfunc(CompanyName) включены поля, не выбранные в запросе. Допускается включение в выражение ORDER BY только полей, затребованных в первом запросе." [Кстати описание этой ошибки в справке слово в слово повторяет само сообщение об ошибке! Только "anyfunc(CompanyName)" заменено на "запроса на объединение"]. В исходный запрос придется добавить поле для сортировки: SELECT Customers.CompanyName, Customers.CustomerID, anyfunc(CompanyName) as OrderByField FROM Customers UNION SELECT "(Все)", 0, " " FROM Customers ORDER BY OrderByField; Вообще конечно, с помощью функции AddAllToList не составит особого труда вставить любое количество строчек в любое место списка. Конструирование UNION - намного более хлопотное дело, но для подавляющего большинства задач и не требуются сколь либо сложные списки (для поля со списком). Можно таким образом добавлять несколько строчек, добавляя UNIONы, или даже организовать какую-нибудь таблицу DEFAULT с записанными значениями для добавки. Тогда запрос примет вид SELECT Table1.Table1ID, Table1.NameField, ... FROM Table1 UNION SELECT Default.ID, Default.AddName, ... FROM Default Учитывая, что практически не бывает списка, в который бы не хотелось добавить какую-нибудь строчку (типа "Все", "Отсутствует", "Текущий документ" и т.п.) такой прием будет весьма полезен. Просмотров: 10770
Ваш коментарий будет первым | | |