Обновление единиц наличного запаса
Благодаря очень толковой форме ShipOrders,которую вы видели в предыдущем разделе, коммерческая деятельность компании Boutique Fudge протекает гладко. Но в один прекрасный день сотрудники склада приходят в главное управление с жалобой. Несмотря на то, что заказы проходят без отклонений, товарные запасы не поддерживаются в должном порядке. Никто не удосужился исправить данные в поле UnitsInStock,поэтому они становятся все более бесполезными.
По настоящему автоматизированное решение должно было бы автоматически обновлять данные UnitsInStock,когда заказ отправлен. В конце концов, не для этого ли прежде всего разработана программа Access?
Эта задача полностью отличается от тех, которые вы решали до сих пор, поскольку вынуждает вносить изменения в совершенно другой набор записей — записи, которые не отображаются ни на одной из форм.
Вы уже знаете, что можно применять статистические функции по подмножеству для извлечения информации из других таблиц. Но, к сожалению, у программы Access нет похожего набора функций, которые позволяют вносить изменения. Вместо этого придется обратиться к совершенно новому набору объектов, названных объектами доступа к данным (или для краткости просто DAO).
Технология DAO позволяет выполнять любую обработку данных, независимо от ваших форм. Но это довольно сложная структура.
* DAO следует использовать очень специфическим образом. Если методы применяются в неверной последовательности или пропущен шаг, вы столкнетесь с ошибкой. Часто легче всего начать с работающего примера (как, например программный код, включенный в примеры к данной главе), скопировать его и затем переделать, как нужно.
■ Технология DAO не применяет объекты запросов. Вместо этого следует писать SQL-операторы (см. главу 6).
DAO включает два важных метода. Первый метод, CurrentDb. Execute, позволяет выполнять прямую SQL-команду, задавая ее в виде строки:
CurrentDb.Execute MyUpdateCommand
Этот метод — быстрый практический способ внесения в БД изменений, таких как операции очищающего обновления, удаления или вставки.
Второй важный метод предназначен для извлечения записей с помощью специализированного объекта Recordset. Для применения этого объекта вы должны начать с вызова метода CurrentDb. OpenRecordset и задать строку с SQL-командой выбора.
Dim Recordset
Set Recordset = CurrentDb.OpenRecordset(MySelectCommand)
Объект Recordset представляет группу записей, но доступ в каждый момент времени возможен только к одной из них. Для перехода от одной записи к другой применяется метод Recordset .MoveNext. Для проверки, достигнут ли конец набора, используется свойство Recordset .EOF, означающее конец файла (end-of-file). Если оно равно True, вы прошли последнюю запись.
Чаще всего объект Recordset применяется в цикле. Свойство Recordset .EOF можно использовать как условие цикла, так что цикл завершается, как только программа Access достигает конца набора Recordset. Внутри цикла можно извлекать значения полей текущей записи. В конце каждого прохода цикла следует вызывать метод MoveNext для перехода к следующей записи: Do While Recordset.EOF = False
' Отображается значение поля ProductName ■ MsgBox Recordset("ProductName")
' Переход к следующей записи Recordset.MoveNext
Loop
Держа в голове эти непременные условия, можно создать следующий код, корректирующий величину запасов товаров, основываясь на только что отправленном заказе. (Построчный анализ приведен после кода.)
1 Sub UpdateStock()
' Если возникает ошибка, переход в секцию DataAccessError
2 On Error GoTo DataAccessError
' Создание команды SELECT
3 Dim Query
4 Query = _
"SELECT ProductID, Quantity FROM OrderDetails WHERE OrderID=" & ID
' Получение набора записей с помощью этой команды
5 Dim Recordset
6 Set Recordset = CurrentDb.OpenRecordset(Query)
' Перебор набора записей с просмотром каждой из них.
' Каждая запись — отдельный компонент заказа
7 Do Until Recordset.EOF
' Получение для каждого компонента ID товара и его количество
8 Dim ProductID, Quantity
9 ProductID = Recordset("ProductID"}
10 Quantity = Recordset("Quantity")
' Формирование команды UPDATE,
' которая изменяет уровни запасов
11 Dim UpdateCommand
12 UpdateCommand = _
"UPDATE Products SET UnitsInStock = UnitsInStock-" & _
13 Quantity & " WHERE ID=" & ProductID
' Выполнение команды
14 CurrentDb.Execute UpdateCommand
' Переход к следующему компоненту заказа (если таковой есть)
15 Recordset.MoveNext
16 Loop
' Самое время для очистки
17 Recordset.Close
18 CurrentDb.Close
19 Exit Sub
20 DataAccessError:
' Сюда вы попадаете только при возникновении ошибки.
' Отображение сообщения об ошибке
21 MsgBox Err.Description
22 End Sub
Вот что происходит в программном коде.
■ В строке 1 объявляется новая процедура. Поскольку этот код очень сложен, есть смысл поместить его в отдельную процедуру, которую можно вызывать, когда мышью щелкается кнопка Ship(отправить) и заказ отправляется клиенту.
■ Строка 2 заставляет программу Access перейти в конец процедуры, если возникает ошибка. В программном коде доступа к данным всегда возможны ошибки, поэтому лучше быть начеку.
■ В строках 3—4 создается SQL-команда, необходимая для выбора записей из таблицы OrderDetails,относящихся к текущему заказу. (Дополнительную информацию об SQL-командах SELECT см. в разд. "Анализ запроса" главы 6.)
■ Строки 5—6 выполняют эту команду и получают все соответствующие записи в объекте Recordset.
■ В строке 7начинается цикл, обрабатывающий весь набор Recordset.
■ Строки 8—10 получают поля ProductIDи Quantityдля текущей записи таблицы
OrderDetails(первой в объекте Recordset).
■ Строки 11—13 используют эту информацию для построения SQL-команды UPDATE. Команда вычитает количество заказанных товаров из общего числа хранящихся на складе товаров. Пример полной команды выглядит следующим образом: UPDATE Products SET UnitsInStock = UnitslnStock-4 WHERE ID= 14. Она вычитает 4 единицы из 14 единиц товара.
■ Строка 14 выполняет обновление.
■ В строках 15—16 выполняется переход к следующей записи и повторяется процесс обновления (до тех пор, пока в наборе Recordset не останется ни одного компонента заказа).
■ В строках 17—18 выполняется очистка.
■ В строке 19 — выход из процедуры. Если вы им воспользовались, мои поздравления - все прошло без сучка, без задоринки!
■ Строки 20—22 обрабатываются, только если где-то возникла ошибка. В этом случае описание ошибки выводится в окне сообщения.
Этот код гораздо более амбициозный, чем все, что вы видели до сих пор. Но он построен на приемах, которые вы совершенствовали в последних трех главах. Повторюсь еще раз - самый лучший способ освоения этого кода — загрузить пример БД, проверить его в действии и попытаться изменить его. Удачных экспериментов!
Уголок ностальгии.
DАО ПРОТИВ АDО
Для того чтобы усложнить жизнь, корпорация Microsoft давным-давно ввела еще одну технологию доступа к данным, названную ADO (ActiveX Data Objects, объекты данных ActiveX). И DAO, и ADO выполняют задачи обработки данных с помощью удобных объектов.
Ключевая разница между ними заключается в том, что Microsoft проектировала ADO как универсальную технологию доступа к данным, которая может работать с другими системами управления БД, например SQL Server, a DAO предназначена только для Access.
Некоторые программисты Access считают (неправильно), что ADO — приемник DAO и лучший выбор при написании программного кода для БД Access. (В действительности корпорация Microsoft, возможно, даже заявляла об этом в определенный момент, но все свидетельства этого уничтожены.) В настоящий момент официальная версия заключается в том, что лучше применять DAO, поскольку эта технология настроена для программы Access. Это означает, что DAO легче использовать, и она обеспечивает лучшую производительность в большинстве случаев. ADO применяют лишь опытные VB-программисты, кто уже знает, как работает эта технология, и не хочет тратить время на изучение DAO, или же разработчики, которым требуется какое-нибудь экзотическое средство, имеющееся в ADO и отсутствующее в DAO.
Часть VI