Пример установки свойств элемента ADO Data из кода
На рис. 16.42 представлена форма с элементами управления для просмотра накладных файла фирма.mdb, а некоторые свойства элементов управления, помещенных на форму, приведены в следующей за рисунком таблице. Рис. 16.42 Диалоговое окно для примера формирования свойств элемента ADO Data из кода
Для кнопки CmdHelp мы, конечно, не будем писать процедуру обработки события Click (здесь кнопка просто является напоминанием разработчику о необходимости поддерживать диалоговые формы справочной системой), а для кнопки CmdExit — напишем, поскольку кнопка закрытия формы убрана с формы: Private Sub CmdExit_Click() Unload Me End Sub Прежде чем написать код событийных процедур для остальных управляющих элементов, опишем сценарий работы пользователя с данной формой (рис. 16.41). Как только диалоговое окно появляется на экране, в списке Подразделения (Combo1) должно отображаться первое (по алфавиту) наименование списка подразделений (хранимых в таблице Подразделения базы данных фирма.mdb),коды которых имеются в заголовках накладных; в списке Даты (Combo2) для первого подразделения должна появиться первая дата из заголовков накладных; в списке Накладная (Combo2) — первая накладная, соответствующая первой дате в списке Даты, и, наконец, элемент DataGrid1 должен отобразить спецификацию этой накладной. Если накладных в базе данных не окажется на момент загрузки диалогового окна, следует об этом сообщить при помощи, например, функции MsgBox. Причем это должно быть известно при формировании списка Подразделения: нет накладных — нет и списка с подразделениями. Рис. 16.43 Сценарий загрузки диалогового окна После загрузки формы алгоритм работы приложения зависит от действий пользователя, но в любом случае будет повторяться тот же сценарий, только начинаться он будет либо «дальше» от загрузки элемента DataGrid1, либо — «ближе». Например, если пользователь выбрал накладную (номер) в списке Накладные, то сценарий работы диалогового окна будет соответствовать рис. 16.44. Рис. 16.44 Сценарий загрузки диалогового окна, если пользователь выбрал накладную (номер) в списке Накладные Если пользователь выбрал дату в списке Даты, сценарий будет «длиннее» (рис. 16.45). Рис. 16.45 Сценарий загрузки диалогового окна, если пользователь выбрал дату в списке Даты Если пользователь выбрал подразделение в списке Подразделения, сценарий будет на один «блок» меньше, чем сценарий загрузки формы (рис. 16.46). Рис. 16.46 Сценарий загрузки диалогового окна, если пользователь выбрал подразделение в списке Подразделения На самом деле, на рис. 16.44–16.46 представлены алгоритмы процедур обработки событий, связанных с выбором в элементах Combo1, Combo2 и Combo3. Заметьте, что каждый следующий (в порядке рассмотрения) алгоритм содержит предыдущие. Такой анализ сценария позволяет написать код, в котором ни одна строка не повторяется ни в какой процедуре (листинг 16.1). Листинг 16.1 Код модуля формы Просмотр накладных (FrmNacl) 1: Dim КодПодраз As String 'текущее подразделение 2: Dim ДатаНакл As String 'текущая дата 3: Dim НомерНакл As Integer 'номер текущей накладной 4: 5: 6: Private Sub Form_Load() 7: ' процедура загрузки формы 8: 9: Dim file_name As String 'имя mdb-файла 10: 11: ' полное имя mdb-файла: 12: file_name = App.Path & "\фирма.mdb" 13: 14: 'строка подключения: 15: Adodc1.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ 16: "Data Source=" & _ 17: file_name & _ 18: ";Persist Security Info=False" 19: 20: 'запрос только тех подразделений, для которых 21: 'имеются накладные (запрос хранится в mdb-файле): 22: Adodc1.RecordSource = "Запрос21" 23: Adodc1.Refresh 24: 25: If Adodc1.Recordset.RecordCount > 0 Then 26: 'если имеются записи, 27: 'сформировать список Combo1 и List1: 28: Adodc1.Recordset.MoveFirst 29: Combo1.Text = Adodc1.Recordset.Fields(1) 30: Do While Not Adodc1.Recordset.EOF 31: Combo1.AddItem Adodc1.Recordset.Fields(1) 32: List1.AddItem Adodc1.Recordset.Fields(0) 33: Adodc1.Recordset.MoveNext 34: Loop 35: 36: 'вызвать Combo1_Click для первого элемента Combo1-списка: 37: Combo1_Click 38: Else 39: MsgBox "Нет подразделений с накладными!" 40: End If 41: 42: End Sub 43: 44: 45: Private Sub Combo1_Click() 46: 'пользователь выбрал подразделение 47: 48: 'код подразделения в List1: 49: If Not Combo1.ListIndex = -1 Then 50: 'выбор пользователя: 51: КодПодраз = List1.List(Combo1.ListIndex) 52: Else 53: 'первый элемент в списке: 54: КодПодраз = List1.List(0) 55: End If 56: 57: Combo2.Clear 58: 59: 'сформировать список Combo2 для КодПодраз: 60: Adodc1.RecordSource = _ 61: "SELECT DISTINCT Дата FROM НаклЗаголовки " & _ 62: " WHERE КодПодразделения ='" & КодПодраз & "'" 63: 64: Adodc1.Refresh 65: 66: Adodc1.Recordset.MoveFirst 67: Combo2.Text = Adodc1.Recordset.Fields(0) 68: Do While Not Adodc1.Recordset.EOF 69: Combo2.AddItem Adodc1.Recordset.Fields(0) 70: Adodc1.Recordset.MoveNext 71: Loop 72: 73: 'вызвать процедуру обработки события для Combo2: 74: Combo2_Click 75: 76: End Sub 77: 78: 79: 80: Private Sub Combo2_Click() 81: 'пользователь выбрал дату 82: 83: 'дата: 84: ДатаНакл = Combo2.Text 85: 86: Combo3.Clear 87: List3.Clear 88: 89: 'сформировать список Combo3 для ДатаНакл и КодПодраз: 90: Adodc1.RecordSource = _ 91: "SELECT a.Номер, b.НаимКАгента, c.НаимТипа " & _ 92: "FROM НаклЗаголовки a, КонтрАгенты b, ТипыНакладных c " & _ 93: "WHERE a.КодКАгента = b.КодКАгента " & _ 94: " AND a.КодПодразделения ='" & КодПодраз & "'" & _ 95: " AND a.ТипНакладной=c.ТипНакладной" & _ 96: " AND a.Дата = CDate('" & ДатаНакл & "') ORDER BY a.Номер" 97: 98: Adodc1.Refresh 99: 100: Adodc1.Recordset.MoveFirst 101: Combo3.Text = Adodc1.Recordset.Fields(0) & " " & _ 102: Adodc1.Recordset.Fields(1) & " " & _ 103: Adodc1.Recordset.Fields(2) 104: Do While Not Adodc1.Recordset.EOF 105: Combo3.AddItem Adodc1.Recordset.Fields(0) & " " & _ 106: Adodc1.Recordset.Fields(1) & " " & _ 107: Adodc1.Recordset.Fields(2) 108: List3.AddItem Adodc1.Recordset.Fields(0) 109: Adodc1.Recordset.MoveNext 110: Loop 111: 112: 'вызвать процедуру обработки события для Combo3: 113: Combo3_Click 114: 115: End Sub 116: 117: Private Sub Combo3_Click() 118: 'пользователь выбрал номер накладной 119: 120: 'номер соответствующей накладной в List3: 121: If Not Combo3.ListIndex = -1 Then 122: 'выбор пользователя: 123: НомерНакл = List3.List(Combo3.ListIndex) 124: Else 125: 'первый элемент в списке: 126: НомерНакл = List3.List(0) 127: End If 128: 129: 'сформировать запрос для спецификации накладной: 130: 131: Adodc1.RecordSource = _ 132: "SELECT b.НаимТовара as [Наименование], " & _ 133: "a.Количество, a.ЦенаОперации as [Цена] " & _ 134: "FROM НаклСпецификации a, Товары b " & _ 135: "WHERE a.КодТовара=b.КодТовара " & _ 136: " AND a.КодПодразделения='" & КодПодраз & "'" & _ 137: " AND a.Дата=CDate('" & ДатаНакл & "') " & _ 138: " AND Номер =" & Str(НомерНакл) & " ORDER BY b.НаимТовара " 139: 140: 141: Adodc1.Refresh 142: 143: End Sub 144: 145: 146: Private Sub CmdExit_Click() 147: Unload Me 148: End Sub Рассмотрим листинг 16.1. В первых трех строках описаны переменные, которые являются общими для всех процедур модуля формы. В строках 6–42 определена процедура загрузки формы Form_Load, которая формирует списки Combo1 и List1. В строке 12 формируется полное имя файла с использованием App.Path (возвращает путь текущего приложения) и строки "\фирма.mdb". Код строк 15–18 формирует строку для подключения и присваивает ее свойству ConnectionString объекта Adodc1. В строке 22 свойству RecordSource объекта Adodc1 присвается строка "Запрос21". В главе «Основы языка баз данных SQL» этот запрос был создан для формирования списка подразделений, накладные которых имеются в таблице НаклЗаголовки: SELECT DISTINCT b.КодПодразделения, a.НаимПодразделения FROM Подразделения a, НаклЗаголовки b WHERE a.КодПодразделения =b.КодПодразделения В результате этого запроса получается таблица наименований и кодов подразделений. Наименованиями следует заполнить окно комбинированного списка (Combo1) для отображения в диалоговом окне (строки 29, 31). Коды необходимо записать в список (List1) (строка 32), не отображаемый в окне, но синхронизированный с видимым комбинированным списком. После выбора пользователем необходимого подразделения из окна комбинированного списка можно узнать код этого подразделения посредством неотображаемого списка. После формирования списков Combo1 и List1 в строке 37 вызывается событийная процедура[3] Combo1_Click, описанная в строках 45–76. В строках 49–55 определяется переменная КодПодраз — код подразделения из списка List1. Если пользователь еще не выбирал подразделение из Combo1 (при загрузке формы), то код выбирается из первого элемента списка List1 (стоки 54). Если выбор был сделан (в нормальном режиме работы с диалоговой формой), то номер элемента в списке List1 определяется как Combo1.ListIndex (строка 51). Если основной функцией процедуры Form_Load является формирование списков для элементов Combo1 и List1 и вызов событийной процедуры Combo1_Click, то основной функцией процедуры является формирование списка Combo2 и вызов событийной процедуры Combo2_Click. В строках 61–62 формируется SQL-запрос в качестве строки подключения элемента Adodc1. Отличие от SQL-запросов, которые использовались в главе «Основы языка баз данных SQL», здесь до запуска программы код в SQL-предложении WHERE неизвестен, поэтому вместо, например, строки: "SELECT DISTINCT Дата FROM НаклЗаголовки " & _ " WHERE КодПодразделения ='0429'" мы используем строку: "SELECT DISTINCT Дата FROM НаклЗаголовки " & _ " WHERE КодПодразделения ='" & КодПодраз & "'" В строках 67–71 заполняется список Combo2 (предварительно он очищается в строке 57). Здесь не используется вспомогательный элемент типа List, поскольку одни и те же данные используются и в элементе отображения, и в коде для формирования запроса. После формирования списка Combo2 вызывается событийная процедура Combo2_Click. Процедура Combo2_Click, как Combo1_Click выполняет простую функцию — определяет выбранный элемент (в данном случае — ДатаНакл) в строке 84, формирует списки Combo3 и List3 (строки 101–110) и вызывает событийную процедуру Combo3_Click (строка 113). В строках 90–96 определяется свойство RecordSource объекта Adodc1. Здесь формируется SQL-запрос с использованием значений переменных КодПодраз и ДатаНакл, которые определены в процедурах Combo1_Click и Combo2_Click, соответственно: 90: Adodc1.RecordSource = _ 91: "SELECT a.Номер, b.НаимКАгента, c.НаимТипа " & _ 92: "FROM НаклЗаголовки a, КонтрАгенты b, ТипыНакладных c " & _ 93: "WHERE a.КодКАгента = b.КодКАгента " & _ 94: " AND a.КодПодразделения ='" & КодПодраз & "'" & _ 95: " AND a.ТипНакладной=c.ТипНакладной" & _ 96: " AND a.Дата = CDate('" & ДатаНакл & "') ORDER BY a.Номер" Код в строках 101–103 назначает свойству Text элемента Combo3 (текстовое окно комбинированного списка) строку, состоящую из значений всех трех полей (разделенных двумя пробелами) набора — номера накладной, наименования контрагента и наименования типа накладной: 101: Combo3.Text = Adodc1.Recordset.Fields(0) & " " & _ 102: Adodc1.Recordset.Fields(1) & " " & _ 103: Adodc1.Recordset.Fields(2) Код в строках 105–107 добавляет подобные строки к списку элемента Combo3. Код строки 108 добавляет к списку только значение первого поля набора (номер накладной): 108: List3.AddItem Adodc1.Recordset.Fields(0) Процедура Combo3_Click (строки 117–143) устанавливает значение переменной НомерНакл (в строках 121–127): 120: 'номер соответствующей накладной в List3: 121: If Not Combo3.ListIndex = -1 Then 122: 'выбор пользователя: 123: НомерНакл = List3.List(Combo3.ListIndex) 124: Else 125: 'первый элемент в списке: 126: НомерНакл = List3.List(0) 127: End If Если пользователь не выбирал номер накладной (например, выполняется загрузка формы, или если пользователь выбрал подразделение и/или дату), то номер накладной задается оператором в строке 126. Иначе — в строке 123. В строках 131–138 формируется SQL-запрос для определения таблицы, отражающей спецификацию накладной: 131: Adodc1.RecordSource = _ 132: "SELECT b.НаимТовара as [Наименование], " & _ 133: "a.Количество, a.ЦенаОперации as [Цена] " & _ 134: "FROM НаклСпецификации a, Товары b " & _ 135: "WHERE a.КодТовара=b.КодТовара " & _ 136: " AND a.КодПодразделения='" & КодПодраз & "'" & _ 137: " AND a.Дата=CDate('" & ДатаНакл & "') " & _ 138: " AND Номер =" & Str(НомерНакл) & " ORDER BY b.НаимТовара "
В строке запроса используются все три переменные: КодПодраз, ДатаНакл и НомерНакл, определенные в разных событийных процедурах. На рис. 16.47 приведено диалоговое окно, полученное в результате работы процедуры загрузки формы. Несмотря на то, что пользователь не производил никакого выбора, все элементы управления отображают информацию. Рис. 16.47 Результат загрузки формы (пользователь еще ничего не выбирал) На рис. 16.48 приведено диалоговое окно в результате выбора пользователем даты и номера накладной. Рис. 16.48 Пользователь выбрал дату и номер накладной Остается надеяться, что рассмотренный пример отчетливо показал пользу установки свойств элемента ADO Data из кода. Замечание Элемент управления ComboBox позволяет не только выбирать данные из списка, но и вводить информацию в текстовое окно. Этот режим работы здесь не рассматривается, и программа не будет работать, если пользователь введет в текстовое окно комбинированного списка данные, отсутствующие в его списке.
|