Главная страница

Краткое содержание 29 Об этих стрелках 30 о сочетаниях клавиш 32 о щелчках кнопкой мыши 33 Примеры 33


Скачать 19.64 Mb.
НазваниеКраткое содержание 29 Об этих стрелках 30 о сочетаниях клавиш 32 о щелчках кнопкой мыши 33 Примеры 33
АнкорAccess_2007.doc
Дата16.03.2017
Размер19.64 Mb.
Формат файлаdoc
Имя файлаAccess_2007.doc
ТипКраткое содержание
#3862
страница49 из 65
1   ...   45   46   47   48   49   50   51   52   ...   65

Обработка ошибок

Некоторые ошибки возникают не по вашей вине. Быть может, вы пытаетесь выполнить за­дачу с данными, которые получаете от кого-то, и эти данные некорректны. Представьте себе, что произойдет, если кто-нибудь вызовет функцию ValidateCard и передаст в нее номер кредитной карты, содержащий буквы и знаки пунктуации!

Несмотря на то, что такие ошибки могут произойти в результате чьей-то небрежности, именно вы должны обработать их наилучшим образом. Следует объяснить возникшую про­блему с помощью понятного окна сообщения и закончить текущую задачу (или перейти к следующему шагу). Вы можете позаботиться об этом, добавив код обработки ошибок.
Подсказка

Лучше всего с помощью отладки найти и исправить все проблемы во фрагменте кода. После завершения этого процесса можно добавить код обработки ошибок, рассчитанный на непред­виденные проблемы. Если код обработки ошибок вставить раньше, отладить ваше приложе­ние, возможно, будет немного труднее.

Обычно, когда программа Access обнаруживает ошибку, она переходит к коду, вызвав­шему проблему, переключается в режим прерывания и отображает сообщение об ошибке. Такое поведение полезно, если вы планируете устранять проблему, но оно лишь травмирует обычных пользователей, которые, возможно, работают с вашей БД. Мало того, что они ни­когда раньше не видели программного кода, они окажутся в большой опасности, попытав­шись исправить его, и создадут новые проблемы.

Вместо этого вам нужен способ обработки ошибки средствами программного кода. В языке Visual Basic есть специальный оператор, сообщающий программе Access о том, как поступать с ошибками. Это оператор On Error.

Оператор On Error предоставляет несколько вариантов. Можно заставить программу Access пропустить ошибки и попытаться выполнить очередную строку кода, например, сле­дующим образом:
On Error Resume Next

Этот вариант почти всегда — не лучший выбор. Если ошибка возникла, за ней вероятнее всего последуют другие. В худшем случае такая ситуация может вынудить вашу программу делать вовсе не то, для чего она предназначена.

Можно также заставить программу Access перейти в конкретное место кода. Далее при­веден пример.
On Error Goto ErrorHandlingCode

В данном примере программа Access переходит к разделу, названному ErrorHandlingCode, как только она обнаруживает какую-либо проблему. Вы должны обо­значить этот раздел, указав в отдельной строке его имя и следом за ним вставив двоеточие (:), например, так:

ErrorHandlingCode:

' Если возникла ошибка, Access начинает выполнять ваш код с этой точки

Очень легко понять, как действует система обработки ошибок, если рассмотреть ее ис­пользование на примере функции ValidateCard:

Function ValidateCard(CardNumber As String)

On Error Goto ErrorHandlingCode
' Здесь расположен код, реализующий алгоритм Луна

Exit Function

ErrorHandlingCode:

MsgBox "Oops. Did your credit card number have letters?"

ValidateCard = False

End Function

Перечислим несколько важных деталей. Во-первых, оператор On Error помещается в cамом начале программного кода процедуры, поэтому вы можете обнаружить ошибки, возникшие в любом месте последующего кода. Во-вторых, обратите внимание на то, что после ого, как закончен код проверки номера, процедуру завершает оператор Exit Function. Этот оператор не дает программе Access попасть в следующий далее код обработки ошибок, если никакой ошибки не произошло. Наконец, код обработки ошибок выводит окно сообщения, в котором сообщается о нарушении естественного хода событий и возвращается результат, ясно обозначающий проблему. Чаще всего разработчики именно так обрабатывают ошибки. Только помните об обязательном использовании оператора Exit Sub или Exit Function, чтобы избежать случайного выполнения кода обработки ошибок.

Примечание

Как было указано ранее, пользователь, применяющий форму AddCreditCard, может получить два типа сообщений об ошибке — одно, объясняющее проблему, связанную с включением в номер карты букв и знаков пунктуации, и второе, констатирующее очевидный факт недопусти­мости номера. Если это сообщение кажется ненужным наказанием, вы можете перенести код обработки ошибок из функции ValidateCard в обработчик события При обновлении (On Update), с которым он на самом деле связан. В этом случае в обработчике события При об­новлении (On Update) можно выбрать точный способ решения проблемы. Для того чтобы уви­деть преобразованный код, посмотрите загружаемые из Интернета примеры к данной главе.

У вас есть еще только один вариант обработки ошибок. Можно заставить программу Ac­cess немедленно остановить выполнение и перейти в режим отладки с помощью следующего оператора:

On Error Goto 0

Конечно, такое поведение уже стало стандартным при обработке ошибок. Указанный оператор следует применять только, если вы переключаетесь многократно между разными методами обработки ошибок в одной и той же процедуре.
Углубленное рассмотрение объектов

В жизни любого программиста Access наступает момент, когда вы осознаете, что знаете дос­таточно о языке VB, чтобы сводить концы с концами. С этого момента вы будете проводить большую часть времени, изучая различные объекты, а это гораздо более трудоемкая задача.

В программе Access есть несколько десятков встроенных объектов, которые собранные вместе формируют то, что программисты называют объектной моделью. Наряду с объектами элементов управления и форм, которые вы хорошо знаете, в программе есть объекты, пред­ставляющие запросы, проекты, отчеты, смарт-теги, принтеры и многое другое. Вы не сможе­те познакомиться со всеми этими объектами в одной главе. Но даже если бы могли, то обнаружили бы, что многие из них вам просто не интересны. Однако следует знать достаточно для того, чтобы найти нужные вам средства, когда принимаетесь за особенно трудную зада­чу на языке VB.

Вы можете изучить объектную модель программы Access несколькими способами:

  • воспользоваться справочной системой программы Access (см. указания по поиску нужной информации в разд. "Применение объектов" главы 16);

  • использовать интерактивное руководство по языку VBA (Visual Basic for Applications), предоставляемое корпорацией Microsoft (перейдите на страницу http://msdn.microsoft.com/office/reference/vba).

Д
аже если вы освоили раскидистую объектную модель программы Access, за ее предела­ми остается еще много дополнительных объектов. Если же вы обладатель черного пояса как VB-программист, то можете выбрать вариант создания собственных объектов. Если нет, возможно, вы решите применить какой-нибудь компонент, предоставляющий еще больше объектов для работы.
Примечание

На языке программистов компонент — это просто файл, содержащий некоторые объекты, ко­торые можно использовать в вашем программном-коде. В файле acedao.dll есть объекты, ко­торые можно применять для непосредственного взаимодействия с вашей БД (см. разд. "Обновление единиц наличного запаса" далее в этой главе).
Рис. 17.7. Для добавления ссылки на компонент, который хотите использовать, найдите его в списке и затем установите флажок, расположенный рядом с ним. Компоненты, на которые есть ссылки в данный момент, приведены в верхней части списка. Здесь показаны объекты, на которые автоматически устанавливаются ссылки в каждой БД, — объекты, встроенные в язык Visual Basic и поставляемые вместе с программой Access, и объекты доступа к данным, которые можно применять для непосредственного чтения и редактирования БД
Позже в этой главе вы узнаете, как использовать DAO (Data Access Objects, объекты дос­тупа к данным) для взаимодействия с вашей БД. Технология DAO — настолько популярная составляющая программирования в Access, что большинство считают эту библиотеку встро­енной частью объектной модели Access. Однако технически DAO состоит из набора объектов,

предоставляемых отдельным компонентом, поддерживаемым программой Access. Мно­жество дополнительных компонентов ждут, чтобы вы нашли их.

Для применения нового компонента необходимо добавить ссылку на него в вашу БД. Для этого в меню редактора Visual Basic выберите последовательность команд ToolsReferences (Сервис Ссылки). Вы увидите диалоговое окно References, показанное на рис. 17.7.

Проблема диалогового окна References заключается в том, что вам нужно точно знать, какой компонент вы хотите использовать. Список Available References (доступные ссылки) полон компонентов со звучными именами, которые не предназначены для использования в программе Access и не будут корректно работать с вашим программным кодом. Среди ком­понентов, которыми можно воспользоваться, есть компоненты Microsoft, позволяющие взаимодействовать с другими приложениями пакета Office. Но, самостоятельно экспери­ментируя, вы не многого добьетесь. Следует найти пример кода в Интернете или в справоч­ной системе программы Access.

Часто задаваемый вопрос.

Запуск других Windows-программ
Как мне открыть Word (или Excel, или Блокнот (Notepad) или танцевальную видеоигру Dance Dance Revolution)?

В язык Visual Basic включена функция shell, которая позволяет запускать другую про­грамму. Для применения функции Shell необходимо задать полный путь, указываю­щий на файл программы. Вот приведен пример запуска Windows-программы Калькуля­тор:

Shell "C:\Windows\calc.exe"

Когда вы применяете функцию shell, ОС Windows запускает запрошенную програм­му, а ваш код продолжает выполняться. Но у вашего программного кода нет реальной возможности взаимодействовать с программой. Вы не можете заставить ее сделать что-либо или выяснить, что она закрыта.

Shell кажется удобной функцией, но у нее есть существенная проблема. Для того чтобы использовать функцию Shell, нужно знать точное местонахождение программы. Вы не можете просто сказать: "Запусти Microsoft Word" или "Открой этот документ". Вместо этого вы должны глубоко зарыться в файловую систему жесткого диска, чтобы найти файл нужной программы (который обычно находится где-то в зоне вашего компьютера с именем Program Files). Хуже того, после того как вы заставили функцию Shell рабо­тать на вашем компьютере, нет никакой гарантии, что она заработает на какой-либо дру­гой машине — в конце концов, та же программа может быть установлена где-то совсем в другом месте.

И как с этим бороться? Можно воспользоваться гиперссылкой, которая запускает нуж­ную программу автоматически, если по ссылке щелкнуть кнопкой мыши. Но некоторые программы, включая других членов семейства Microsoft Office, предлагают лучший ва­риант. Они предоставляют собственные объекты, которыми можно манипулировать в коде на языке Visual Basic. Благодаря этим объектам можно применять эти программы, не беспокоясь об их местонахождении. Вы конечно же можете делать с ними гораздо больше, задавая различные свойства и вызывая разнообразные методы.

Можно заставить программу Word открыть документ, добавить в него некоторый текст, отправить 10 копий на принтер и затем завершить программу.

Объекты, реализующие этот процесс, не рассматриваются в данной книге, но далее при­веден очень простой пример, который запускает программу Word, выводит на экран ок­но программы и загружает в нее документ GothicWedding.doc:

Dim Word As Object

Set Word = CreateObject("Word.Application")

Word.Visible = True

Word.Documents.Open CurrentProject.Path & "\GothicWedding.doc"

Если эта технология заинтересовала вас, обратитесь к справочной системе программы Word, из нее можно узнать гораздо больше об объектной модели Word. Другой полез­ный ресурс — Microsoft's Office Developer Center (Центр разработчиков Microsoft Office) на Web-сайте http://msdn.microsoft.com/office.

Объект DoCmd
Объект DoCmd — единственный наиболее полезный объект в мире программирования Access. Он обеспечивает "покупку всего нужного в одном месте" для самых разнообразных задач, таких как открытие форм и отчетов, запуск других программ, поиск записей и выпол­нение макросов.

В отличие от виденных вами ранее объектов, у объекта DoCmd нет никаких свойств. Вме­сто этого он состоит из методов, выполняющих разные действия. Если нужно открыть фор­му с именем ProductCatalog, можно использовать метод OpenForm следующим образом:

DoCmd.OpenForm "ProductCatalog"

Как большинство методов объекта DoCmd, OpenForm может использовать несколько не­обязательных параметров. Visual Basic подскажет, отобразив список возможных параметров в процессе ввода имени метода. Далее показан пример, в котором пропущены второй и тре­тий параметры (обратите внимание на запятые без значений между ними), но задается фильтр в четвертом параметре и режим данных в пятом:

DoCmd.OpenForm "ProductCatalog", , ,"ID=5", acFormReadOnly

Эта команда открывает форму ProductCatalog, применяет фильтр для вывода на экран одной записи с ID (Код), равным 5, и использует режим "только чтение" для запрета каких-либо изменений.
Примечание

В данном примере используется константа acFormReadOnly. Константы — это числовые значения, которым присвоены более информативные имена. Таким образом вместо запомина­ния числа, обозначающего режим "только чтение", можно применять более осмысленную кон­станту acFormReadOnly. Всегда, когда встречается переменная, начинающаяся с ас или vb, и вы ее не создавали сами, знайте, что это константа. Конечно, для того чтобы пользоваться константами, нужно все-таки знать их имена, но в этом может помочь средство IntelliSense, как показано на рис. 17.8.





Рис. 17.8. Когда вы добираетесь до параметра режима данных, редактор Visual Basic выводит на экран список всех допустимых констант, которые можно использовать. Для того чтобы выяснить, что они означают (если это не очевидно), следует обратиться к справочной системе Access

Метод OpenForm может показаться знакомым, потому что вы уже видели такие же функции в макрокоманде ОткрытьФорму (OpenForm) (см. главу 15). В действительности все методы объекта DoCmd соотносятся с макрокомандами, которые вы изучали в главе15. В табл. 17.1 перечислены наиболее полезные методы.

Таблица 17.1. Полезные методы объекта DoCmd

Метод

Описание

ApplyFilter

Применяет фильтр к таблице, форме, запросу или отчету для того, чтобы сконцентрировать внимание на интересующих вас записях

Веер

Производит некоторый сигнал. Обычно используется для привле­чения внимания к возникшей проблеме

Close

Закрывает текущий объект БД (или конкретный объект, который задан)

CopyDatabaseFile

Предоставляет быстрый способ создания резервной копии БД

FindRecord, FindNext и GoToRecord

Предоставляет разные способы поиска нужной записи

Hourglass

Включает отображение указателя мыши в виде песочных часов (или выключает). Применяется для того, чтобы дать знать пользо­вателю о том, что выполняется требующая времени задача и сле­дует остыть

Таблица 17.1 (окончание)

Метод

Описание

OpenForm, OpenQuery, OpenReport и ОреnТаblе

Открывает соответствующий объект БД в нужном вам режиме пред­ставления с параметрами фильтрации и необязательными уточне­ниями. Как вы узнали в главе 15, можно применять макрокоманду ОткрытьОтчет (OpenReport) для печати отчетам команду От-крытьЗапрос (OpenQuery) для выполнения запроса на изменение

Printout

Предлагает один вариант печати данных из текущего объекта БД

Quit

Завершает работу программы Access

RunCommand

Замещающая команда, которая позволяет выполнить различные команды Access, представленные на ленте. Необходимо только задать правильную константу. В разд. "Управление выполнением заказов" далее в этой главе приведен пример, в котором про­граммист применяет метод RunCommand для немедленного со­хранения текущей записи

RunMacro

Выполняет макрос

RunSQL

Выполняет групповой SQL-оператор. Эту команду нельзя исполь­зовать для извлечения данных из вашей БД. Она позволяет вы­полнять команды, которые изменяют записи или таблицы

ShowAllRecords

Удаляет параметры текущего фильтра, поэтому можно увидеть все записи в таблице, форме, запросе или отчете



Преобразование макроса в VB-код
Если хотите узнать больше о языке Visual Basic и объекте DoCmd, можно взять существую­щий макрос и преобразовать его в чистый программный код, подпрограмму. Далее приведе­ны необходимые действия.

  1. В области переходов выберите макрос, который хотите использовать.

  2. Выберите на ленте Работа с базами данных Макрос Преобразовать макросы (Database Tools Macro Convert Macros to Visual Basic). Можно также преобразовать внедренный в форму макрос, открыв форму и выбрав на ленте Работа с базами данных Макрос Преобразовать макросы формы (Database Tools Macro Convert Form's Macros to Visual Basic).

Н
а экране появится окно с двумя параметрами для выбора (рис. 17.9).
Рис. 17.9. Вы увидите это окно, если попросите программу Access преобразовать макрос FindHayEater

3. Если хотите добавить базовую обработку ошибок, убедитесь в том, что флажок Добавить программу обработки ошибок (Add error handling to generated functions) установлен.

Немного обработки ошибок никогда не помешает.

4. Если хотите включить комментарии макроса в комментарии VB, убедитесь в том, что установлен флажок Добавить примечания макросов (Include macro comments).

Если вы потратили время на добавление пояснительного текста, стоит сохранить его.

5. Щелкните мышью кнопку Преобразовать (Convert).

Программа Access создаст новый модуль для преобразованного кода и даст ему имя, по­добное имени Преобразованный макрос-[ИмяВашегоМакроса] (Converted Macro-[YourMacroName]). Внутри модуля Access создаст функцию с именем как у вашего мак­роса. Если преобразуется группа макросов (см. разд. "Группы макросов" главы 15), Access вставит по одной подпрограмме для каждого макроса в группе.

После завершения процесса преобразования программа Access откроет ваш модуль в ре­дакторе Visual Basic, чтобы вы могли просмотреть код.

В следующем примере показан результат преобразования макроса из главы 15 (приведенного в разд. "Поиск записи" главы 15), который ищет определенный текст в табли­це AnimalTypes:

Function FindHayEater ( )

On Error GoTo FindHayEater_Err

DoCmd.OpenForm "AnimalTypes", acNormal, " ", " ", , acNormal

DoCmd.GoToControl "Diet"

DoCmd.FindRecord "=""hay""", acAnywhere, False, , _

False, acCurrent, False
FindHayEater_Exit : Exit Function

FindHayEater_Err:

MsgBox Error$

Resume FindHayEater_Exit End Function

Вы заметите, что в преобразованном коде интенсивно используется объект DoCmd — действительно почти в каждой строке кода встречается объект DoCmd. Сначала он применяется в методе OpenForm для открытия формы, затем — в методе GoToControl для перехода в поле Diet и, наконец, он ищет первую запись, в которой встречается текст "hay". Эта строка выглядит причудливо, поскольку в ней удваиваются знаки кавычек (""). В языке Visual Basic знаки кавычек имеют особый смысл (они показывают, где начинается и заканчиваетсятекст). Если в текстовом фрагменте вы хотите на самом деле использовать кавычки, нужно поместить знаки кавычек дважды, одни за другими. Стрнно, но правильно.

Завершается код процедурой обработки ошибок, названной FindHayEater__Err, которая просто сообщает о проблеме в окне сообщения и затем завершает работу.

Примечание

Когда макрос преобразуется в программный код, программа Access всегда генерирует функ­цию, а не процедуру. Но функция не возвращает результат, т. к. этого не требуется. (По-видимому, Access действует таким образом, чтобы дать вам возможность позже воспользо­ваться возвращаемым результатом.)

Улучшение работы компании средствами Visual Basic
На протяжении последних 16 глав вы узнали и полюбили БД компании Boutique Fudge, которая представляет собой БД действительных продаж, отслеживающую данные о клиен­тах, товарах и заказах. Однако, несмотря на то, что в БД Boutique Fudge хранится вся необ­ходимая информация, она все еще не полностью интегрирована в повседневную деятель­ность компании. И прежде чем вы попытаетесь это исправить, следует понять, почему выигрыш столь мал.

Большинство людей, работающих в компаниях, подобных Boutique Fudge, не думают о таблицах и операциях над данными (таких как добавление, обновление и удаление записей). Они мыслят задачами, например, размещение заказа, доставка заказа и обработка жалобы клиента.

Многие задачи тесно связаны с операциями над данными и в этом случае у вас нет проблем. Задача "регистрация нового клиента" включает открытие таблицы Customers и последующее добавление новой записи. Следить за ней можно с помощью простой формы. Задача "размещение заказа" немного сложнее. Она включает добавление записей в несколько таблиц (таблицы Orders и OrderDetails) и использование данных из связанных таблиц (таблицы Products и Customers) для заполнения заказа. Можно создать обычную форму для выполне­ния этой работы, но она не будет действовать так, как хотели бы продавцы (рис. 17.10).

То же справедливо и в отношении задачи "доставка заказа". Этой задаче требуется не­сколько шагов — изменение статуса заказа, регистрация отправки заказа, обновления коли­чества единиц товара на складе. Вы можете интерпретировать эту задачу как несколько опе­раций над данными, но гораздо лучше создать единую форму, которая будет заботиться о процессе в целом.

Сейчас очень пригодится VB. С помощью подходящего программного кода вы сможете спроектировать интеллектуальную форму, которая будет соответствовать методам работы сотрудников компании. Интеллектуальная форма — это не просто способ добавления, редак­тирования и удаления записей в таблице — это средство, помогающее вести коммерческую деятельность. В следующих разделах вы увидите, как разрабатывать улучшенные формы с некоторыми программируемыми свойствами. К этим формам относятся следующие:

  • PlaceOrder позволяет создать новый заказ. Она действует в месте с подчиненной формой PlaceOrder_Subform, позволяющей включать отдельные товары в заказ;

  • AddProduct позволяет создать новый товар. Вы можете использовать ее непосредственно из формы PlaceOrder для вставки товара внутрь заказа;

S
hipOrders позволяет обновить заказ сведениями о доставке. Она также работает с фор­мой ReviewOrderDetails для вывода на экран компонентов заказа.
Рис. 17.10. Эта форма позволяет добавлять записи в таблицы Orders и OrderDetails. Но ей не хватает нескольких украшений, которые пользователи рассчитывают увидеть на форме для заказа — например, автоматическое заполнение поля с ценой каждого товара, заказанного вами, вычисление промежуточных итогов по мере заполнения заказа и возможность добавить товар на лету

Проверить конечный результат можно с помощью загружаемых из Интернета БД, пред­назначенных для данной главы (см. разд. "Примеры" во введении).

Подсказка

Всегда хорошо называть форму в соответствии с выполняемой ею задачей (размещение зака­за, доставка заказа и т. д.), а не таблицей, которую она использует. Такой подход поможет вам запомнить, кто пользуется каждой формой, поэтому вы сможете приспособить ее для соответ­ствующей аудитории.

Хранение промежуточного итога
Лишь немногие клиенты настолько бесстрашны, чтобы поместить заказ без точных сведе­ний о его стоимости. В типичной форме для заказа в строке отображается стоимость каждо-

го элемента (за счет перемножения цены товара и его количества) и еще более важная ито­говая стоимость заказа (рис. 17.11).
Р
ис. 17.11.
Форма PlaceOrder с промежуточными итогами и общим итогом

Примечание

Форма PlaceOrder также включает несколько уже знакомых вам тонкостей, например, разме­щение адресной информации клиента на отдельной вкладке, перенос автоматически генери­руемых полей (идентификационный номер заказа ID и дата заказа) в нижнюю часть окна, где они не будут никого отвлекать, и установка в их свойстве Блокировка (Locked) значения Да для запрета изменений. В свойстве формы Ввод данных (Data Entry) также установлено зна­чение Да, что позволяет начать создавать новый заказ сразу после открытия формы.
Код не нужен только для строчного итога. Действительно, эту проблему можно решить, добавив элемент управления Поле, использующий следующее выражение в подчиненной форме PlaceOrder_Subform:

=Quantity * Price

Это выражение действует, поскольку нужная информация (поля Price и Quantity) располагается на той же форме, что и вычисляемое поле. А вот общий итог получить не так легко.

Для пущей важности можно соединить это выражение с функцией Format, чтобы быть уверенным в том, что выводится нужное число десятичных знаков и символ валюты ($):

=Format (Quantity * Price, "Currency")

Для вычисления общей суммы необходимо использовать данные полей Quantity и Price в таблице OrderDetails. К сожалению, у формы PlaceOrder нет легкого способа получить эту информацию. Дело не только в том, что она находится где-то еще (на подчиненной фор­ме), но и в том, что она включает несколько отдельных записей. Даже если извлечь данные полей Quantity и Price из подчиненной формы, можно будет получить значения только для текущей записи, а не для всего списка заказанных товаров.

Для решения этой проблемы нужна специализированная функция Access, называемая статистической функцией по подмножеству или функцией обработки набора записей (domain function). Функция по подмножеству может обработать целую таблицу и вернуть одну порцию данных. Дополнительную информацию см. в следующем разделе.

На профессиональном уровне.

Станьте знатоком статистических функции по подмножеству
Статистические функции по подмножеству похожи на групповые функции, которые ис­пользовались при подсчете итогов в запросах. Эти функции принимают диапазон запи­сей, затем выполняют вычисления или поиск и возвращают одно значение.

В программу Access включено восемь статистических функций по подмножеству.

  • DSum вычисляет сумму нескольких значений. Ее можно использовать для подсчета общей стоимости заказа.

  • DAvg рассчитывает среднее арифметическое нескольких значений. Ее можно применить для расчета средней цены товаров.

  • DCount считает количество соответствующих записей. Она используется для вычисления числа элементов в заказе или количества заказов, сделанных клиентом.

  • DMin и DMax находят наименьшее или наибольшее значение в подмножестве. Их можно использовать для поиска удешевленных или самых дорогих товаров.

  • DFirst и DLast извлекают первое или последнее значение из подмножества. Если отсортировать список заказов по датам, можно найти самый старый и самый свежий заказы.

  • DLookup находит значение, удовлетворяющее заданным критериям. Ее можно применять для просмотра таблицы и поиска названия товара с заданным ID.

Все статистические функции по подмножеству принимают три одинаковых параметра. Первый — поле (или вычисляемое выражение), которое хотите извлечь или использо­вать в вычислении. Второй — применяемая таблица или запрос. Третий параметр со­держит любые условия отбора, используемые для сокращения числа строк. Если вы хо­тите найти среднюю цену всех напитков, продаваемых компанией Boutique Fudge, нужно использовать поле Price (в качестве первого параметра), таблицу Products (как второй параметр) и отфильтровать ее, включив в подсчет товары с категорией Beverages (напитки) (третий параметр).

Для вычисления стоимости всех компонентов заказа применяется функция DSum. Нуж­ная вам информация хранится в таблице OrderDetails, но вы хотите отобрать только те записи, у которых поле OrderlD совпадает с идентификационным номером текущего заказа. Наконец, нужно сложить вместе стоимости всех компонентов заказа. И как вы знаете из ранее изложенного, стоимость в строке заказа вычисляется перемножением полей Price и Quantity.

Держа все это в голове, можно создать следующее вычисляемое поле:

=DSum("Price*Quantity","OrderDetails","OrderID=" & [ID])

Первый аргумент — вычисляемое поле, которое берется из каждой записи. Второй аргу­мент — имя используемой таблицы. Третий аргумент отбирает только те записи, которые соответствуют текущему заказу. Если у текущего заказа идентификационный номер (ID) 455, последний параметр отберет все записи из таблицы OrderDetails, у которых OrderID=4 55. И снова вы сможете охватить все разом с помощью функции Format, если хотите, чтобы окончательный результат выглядел как денежная сумма.

У данного вычисляемого поля есть одна хитрость, но сначала придется внести еще одно усовершенствование. Обычно программа Access подсчитывает вычисляемые ноля при пер­вом отображении записи. Однако вам нужна гарантия того, что общий итог вычисляется заново при каждом изменении в списке элементов заказа. Для этого необходимо вызывать метод Form.Recalc, когда запись из таблицы OrderDetails добавляется, обновляется или удаляется. Далее приведен программный код, реализующий этот прием:

Private Sub Form_Afterlnsert()

Forms("PlaceOrder").Recalc

End Sub

Private Sub Form_AfterUpdate()

Forms("PlaceOrder").Recalc

End Sub

Private Sub Form_AfterDelConfirm(Status As Integer)

Forms("PlaceOrder").Recalc

End Sub

Теперь можно создать и заполнить заказ, не строя догадок о его общей стоимости.

Получение сведений о цене
Как вы узнали из главы 5, иногда в таблице приходится хранить моментальные данные - информацию, которая копируется из одной таблицы в другую, поскольку может меняться со временем. Хороший пример — цены товаров, которые эволюционируют со временем ("эволюционирование" — это мягкий аналог "неуклонного роста"). Итак, у текущего товара необязательно та же цена, по которой вы заказывали его на прошлой неделе. Для того чтобы отслеживать величину вашего долга компании, в таблице OrderDetails нужно хранить про­дажную цену товара.

Но эта система создает проблему при заполнении заказа. Выбрать компонент заказа до­вольно легко — нужно выделить товар в списке подстановки. Но список подстановки уста­навливает только поле ProductID для записи таблицы OrderDetails. Целиком ваша задача — выяснить правильную цену и скопировать ее из таблицы Products в новую запись.

К счастью, это можно сделать довольно легко. Можно отреагировать на событие On Change (Изменение) в списке ProductID, которое возникает при каждом выборе товара. Затем можно применить статистическую функцию по подмножеству DLookup для поиска соответствующей цены и вставить ее в поле Price автоматически. Далее приведен код, де­лающий это:

Private Sub ProductID_Change ( )

Price = DLookup("Price", "Products", "ID=" & ProductID)

Quantity =1

End Sub

В данном коде также задается значение 1 для поля Quantity, что служит важной отправ­ной точкой. Если необходимо, можно изменить значения полей Price и Quantity после того, как товар выбран. Или создать более строгую форму — можно задать значение Да в свойстве, Блокировка (Locked) элемента управления Price, чтобы запретить любые изменения цены 1 (как сделано в БД Boutique Fudge). В этом случае, когда создается заказ, вы вынуждены использовать действующую в данный момент цену без возможности скидок.

Примечание

Этот метод можно применять для заполнения других моментальных или зависящих от времени данных. Можно извлечь адресные данные текущего клиента и использовать их как отправную точку для адреса доставки. Можно даже применить функцию DLookup для создания более сложных процедур проверки на значения. Можно использовать этот способ в БД школы Саcophone Music для поиска предварительных условий и максимального размера класса, прежде чем зачислить студента в данный класс.

Добавление нового товара во время заполнения заказа
Boutique Fudge — управляемая клиентами компания. Если кому-то нужен самый новый то­вар, которого еще нет в каталоге товаров (например, картофель в шоколадной глазури), компания готова создать его по требованию.

Обычно список подстановки для поля ProductID не разрешает такого рода создание но­вого товара на лету. Если попытаться ввести название несуществующего товара, вы получи­те строгую отповедь от программы Access. Но добавление новых элементов в список на ходу — распространенный метод программирования в Access и специальное событие разработано, чтобы помочь вам в этом: Отсутствие в списке (On Not In List).

Если ввести несуществующий товар и применить событие Отсутствие в списке (On Not

In List), программа Access начнет с кода обработки события. Можно создать элемент списка, вывести сообщение или исправить проблему до того, как Access выразит недовольство.

У события Отсутствие в списке (On Not In List) два параметра: NewData и Response. NewData — это данные, которые набираются в поле списка и которых еще нет в списке. Response — это значение, предоставляемое для того, чтобы сообщить программе Access о том, как решать проблему.

Далее приведен базовый скелет подпрограммы, создаваемой Access, если выбрана обра­ботка события Отсутствие в списке (On Not In List) для поля с именем ProductID:

Private Sub ProductID_NotInList(NewData As String, Response As Integer) End Sub

Когда возникает событие Отсутствие в списке (On Not In List), прежде всего, нужно спросить пользователей, работающих с формой, означает ли это — желание ввести несуще­ствующий товар. Выполнить этот шаг можно с помощью знакомой функции MsgBox, ис­пользуемой необычным образом. Сначала нужно сообщить программе Access о необходимо­сти создать окно сообщения с двумя кнопками: Да (Yes) и Нет (No). Затем нужно суметь перехватить возвращаемое функцией MsgBox значение, чтобы определить, какая кнопка была нажата:

Dim ButtonClicked

ButtonClicked = MsgBox("Do you want to add a new product?", vbYesNo)

В данном коде создается переменная ButtonClicked и затем отображается сообщение. Когда пользователь закрывает окно сообщения (щелкнув мышью кнопку Да или Нет), Vis­ual Basic помещает в переменную ButtonClicked число, которое сообщает вам о том, что произошло. Число равно 6, если была нажата кнопка Да, и 7, если была нажата кнопка Нет. Но вместо того, чтобы обрабатывать непосредственно числа и увеличивать риск ошибки, можно воспользоваться полезными константами vbYes (которая равна 6) и vbNo (которая равна 7).

Далее приведен до некоторой степени законченный код обработчика события Отсутст­вие в списке (On Not In List). Он выводит на экран сообщение, запрашивающее о необходи­мости добавления нового элемента в список (рис. 17.12), и затем отменяет редактирование списка, если пользователь, работающий с формой, нажал кнопку Нет:

Private Sub ProductID_NotInList(NewData As String, Response As Integer) ' Отображает сообщение Да/Нет и получает результат

Dim ButtonClicked

ButtonClicked = MsgBox("Do you want to add a new product for " & _

NewData & "?", vbYesNo)

' Visual Basic предоставляет удобные константы vbYes и vbNo,

' которые можно использовать для определения нажатой кнопки

If ButtonClicked = vbNo Then

' Отмена редактирования

ProductID.Undo

' Сообщает Access о запрете вывода сообщения об ошибке.

' Вы уже обработали ее

Response = acDataErrContinue

Else

' (Поместите сюда код для добавления нового товара в список)

End If End Sub
Р
ис
. 17.12. Картофель в шоколадной глазури — в данный момент не предлагается в списке продуктов. Если его ввести и нажать клавишу , программный код запросит подтверждение для добавления этого продукта в список
Далее предлагается код, добавляющий новый товар. В этом примере кода нет смысла са­мостоятельно включать товар полностью — в конце концов, для этого товара нужно предос-|тавить дополнительную информацию (например, цену или категорию), прежде чем считать [его допустимым. Вместо этого нужно отобразить другую форму для добавления товаров. Ключом решения может стать метод DoCmd. OpenForm:

' Попросите Access не беспокоиться, поскольку вы сами добавите

‘ пропущенный товар Response = acDataErrAdded

' Откройте форму AddProduct с тремя дополнительными аргументами

DoCmd.OpenForm "AddProduct", , , , , acDialog, NewData

Два аргумента, используемые в методе OpenForm, особенно важны.

  • acDialog открывает форму в диалоговом режиме, т. е. программа Access задерживает вызов кода в ProductID_NotInList до тех пор, пока форма AddProduct закрыта. Этот шаг важен, поскольку после завершения процесса добавления вам понадобится выполнить дополнительный код для обновления формы PlaceOrder.

  • N
    ewData принимает вновь введенные данные и присваивает их свойству AddProduct.OpenArgs. В этом случае форма AddProduct может извлечь их, когда запустится, и самостоятельно откорректировать.

Далее приведен программный код, который нужно вставить в форму AddProduct для копирования вновь введенного названия товара (значение, переданное с помощью перемен­ной NewData в предыдущем фрагменте кода) в поле ProductName при первой загрузке формы AddProduct.

Private Sub Form_0pen(Cancel As Integer)

ProductName = Form.OpenArgs

End Sub

На рис. 17.13 показано, как выглядит эта форма.
Рис. 17.13. Форма AddProduct позволяет ввести остальные данные для нового товара, который вы хотите создать. Обратите внимание на то, что форма открывается как всплывающая, и программа Access автоматически считает, что вы вставляете новую запись (а не просматриваете имеющиеся товары). Access действует таким образом, поскольку в свойствах формы Всплывающее окно (Pop Up) и Ввод данных (Data Entry) задано значение Да

После того как вся информация о товаре введена, можно закрыть форму AddProduct. В этот момент в процедуре ProductID_NotInList выполняется немного дополнительного кода. Он расположен сразу после оператора DoCmd. OpenForm. Его задача — обновить новый элемент заказа, чтобы использовать товар, который вы только что ввели:

' Отмена редактирования, поскольку нужно обновить список

' прежде, чем вы сможете выбрать новый товар ProductID.Undo

' Обновление списка ProductlD.Requery

' Теперь ищется ProductID для вновь введенного товара с помощью DLookup

Product ID = DLookup (“ID”, "Products", "ProductName='" & NewData & '"")
Примечание

Этот код выполняется, даже если вы отменили вставку нового товара, нажав клавишу в форме AddProduct. В этом случае функция DLookup не сможет ничего найти, поэтому вернет Null (пустое значение) в поле ProductlD. В результате вы получите знакомое предупреж­дающее сообщение программы Access, извещающее о том, что выбранного вами товара нет в списке.

Еще одно уточнение. Когда возникает событие Отсутствие в списке (On Not In List), со­бытие Изменение (On Change) уже произошло. Таким образом, вы уже упустили возмож­ность выполнить код, применявшийся ранее для вставки соответствующей цены в поле Price списка элементов заказа.

К счастью, эту проблему можно решить довольно легко. Нужно добавить еще одну стро­ку кода, которая заставит программу Access двигаться дальше, и снова выполнить обработ­чик события (процедуру ProductID_Change): Product ID_Change

Для того чтобы увидеть полный программный код к этому примеру, обратитесь к БД Boutique Fudge в примерах к данной главе.

Управление выполнением заказов
Теперь, когда процесс размещения заказов отлажен, можно уделить внимание дальнейшим действиям.

В БД Boutique Fudge у каждой записи в таблице Orders есть поле OrderStatus (состояние заказа), отслеживающее его состояние или статус. У вновь созданных заказов статус New (новый). На складе сотрудники хранилища ищут заказы со статусом New (новый) и выбирают один из них для обработки. В этот момент они изменяют статус заказа на In Progress (выполняющийся в данный момент), поэтому никто больше в это же время не попытается его доставить. Наконец, когда заказ укомплектован, его статус меняется на Shipped (отправлен) и затем в поле ShipDate записывается точное время отправки.

Л
огически эта модель вполне осмыслена. Но немного трудно применять к ней обычные таблицы и формы. Для того чтобы следовать этому технологическому процессу, работники склада должны несколько раз изменять статус в записи заказа, помнить о необходимости зафиксировать дату отправки и при этом не изменять другие данные о заказе. Если они про­пустят какой-нибудь этап — скажем, никогда не переведут статус заказа в In Progress (выполняющийся в данный момент) — вполне возможно, что кто-то из сотрудников попы­тается выполнить тот же самый заказ.

Решением может быть создание формы ShipOrders, которая проведет работников склада через все нужные этапы. Вначале эта форма отображает список заказов с минимальной ин­формацией (рис. 17.14).
Рис. 17.14. Список заказов отсортирован, так что самые старые заказы (которые следует обработать первыми) появляются в верхней части списка. Свойство Блокировка (Locked) для всех полей задано со значением Да, поэтому никто не сможет изменить никакие данные. Рядом с каждым заказом расположена кнопка Process (обработка), которая начинает процесс выполнения заказа (в форму можно добавить фильтр, позволяющий отображать только заказы с определенными статусами)
Когда кто-либо щелкает мышью кнопку Process (обработка), должны выполняться не­сколько действий. Далее приводится последовательный разбор программного кода, пооче­редно, один фрагмент за другим.

Сначала ваш код должен обновить запись. Этот шаг помогает определить, не начал ли кто-то еще выполнять данный заказ на другом компьютере:

Private Sub ProcessOrder_Click()

Form.Refresh

Далее необходимо проверить статус записи. Если у нее статус не New, значит, она не го­дится для обработки:

' StatusID для статуса New равен 2

If StatusID о 2 Then

MsgBox "This order is not available."

В противном случае нужно изменить статус на In Progress (выполняющийся в данный момент) и сразу сохранить запись, чтобы никто другой не пытался выполнить этот заказ:

Else

' StatusID для статуса In Progress равен 3

StatusID = 3

' Сохранение изменения

DoCmd.RunCommand acCmdSaveRecord

Примечание

В подобной ситуации крайне важно сохранить запись (с помощью метода DoCmd. RunCommand, как показано в примере). В противном случае запись заказа останется в режиме редактирования и новый статус не сохранится в БД. Другие работники могут начать выполнять его, поскольку у них нет возможности узнать о том, что вы изменили статус этого заказа.

Теперь самое время запустить форму ReviewOrderDetails, которая выводит предназна­ченное только для чтения представление всех компонентов заказа (рис. 17.15). Форма от­крывается в диалоговом режиме, который блокирует открытие формы ShipOrders до тех пор, пока не завершится процесс выполнения заказа:

DoCmd.OpenForm "ReviewOrderDetails", , , _

"OrderID =" & ID, , acDialog End If

End Function

Форма ReviewOrderDetails предоставляет сотрудникам склада два варианта для выбора. Если они щелкают мышью кнопку Ship (доставить), программа Access изменяет статус за­каза на Shipped (отправлен) и процесс завершается.

Private Sub Ship_Click( ) ' Эта форма закрывается DoCmd.Close

' Обратный переход к форме ShipOrders DoCmd.OpenForm "ShipOrders"

' Обновление заказа

' StatusID для статуса Shipped равен 4 Forms ("ShipOrders").StatusID = 4 DoCmd.RunCommand acCmdSaveRecord

End Sub





Рис. 17.15. В форму ReviewOrderDetails не нужно включать подробности, касающиеся цены товара. Она разработана просто для того, чтобы представить наиболее эффективным способом работникам склада нужную им информацию. Форма ReviewOrderDetails применяет запрос с объединением для получения некоторых связанных данных, например, поля
1   ...   45   46   47   48   49   50   51   52   ...   65


написать администратору сайта