Обзор основных функций Access

Access. Программирование на VBA


Access. Программирование на VBA. Часть 1.
Создание объектов с помощью модуля классов.
Создание объектов — один из самых эффективных способов программирования и управления приложениями. Перед рассмотрением преимуществ использования объектов необходимо разобраться с определениями.
Объекты представляют собой различные сущности. Люди, машины и здания — все это разные виды объектов. В программировании слово объект используется для описания одного специфического элемента, например, формы или элемента управления. Вне всяких сомнений, у любого разработчика имеется определенный опыт работы с этими типами встроенных объектов.
Microsoft Access приобретает все более объектно-ориентированный характер, позволяя создавать собственные объекты и добавлять к-ним свойства и методы. Примеры пользовательских объектов могут включать объект клиента, объект счета, объект пользователя, объект подключения данных и звуковой объект. Код данной статьи описывает многочисленные пользовательские объекты (см. базу данных "Creating Objects with Class Modules.mdb", показанную на рис. 1).
Access. Программирование на VBA
РИСУНОК 1. Примеры пользовательских объектов, программный код которых содержится на прилагаемом к книге CD-ROM
Объекты создаются с помощью модулей классов. Модуль класса — это мобильная, самодостаточная единица программного кода, разработанная для специальных целей. Класс указывает свойства и методы для каждого объекта в данном классе.
Разработчики часто путают термины "класс" и "объект". Класс представляет собой описание или шаблон свойств и методов объекта. Сам по себе он не может существовать. Если разработчику нужно использовать код в модуле класса, создается экземпляр класса. Этот экземпляр и представляет собой объект.
Таким образом, нельзя говорить о создании экземпляра объекта. Объект — это и есть экземпляр! Отдельный объект определяется как экземпляр класса. Из одного класса можно создать множество объектов, каждый с разными значениями свойств.


Активный элемент управления передается


ID of current record (ID текущей записи). Сообщает ID текущей записи формы в момент возникновения ошибки. Бывают случаи, когда некоторые записи о клиентах являются причиной большинства программных ошибок. Возвращая ID текущей записи, можно сравнить данную запись о клиенте с другими, не вызывающими ошибок. Часто причиной возникновения такой ошибки является то, что в обязательном поле отсутствуют данные.
Name of program (Имя программы). Сообщает имя приложения, в котором произошла ошибка.
Error level (Уровень ошибки).
Произвольный набор значений ошибок, устанавливаемый разработчиком, например, 1-5. Получив данную информацию, можно судить о серьезности ошибки.
User name (Имя пользователя). Имя зарегистрированного в данный момент пользователя. Бывают случаи, когда большинство ошибок возникает у определенных пользователей. Идентификация пользователя, у которого произошла ошибка, может оказаться весьма полезной. Часто бывает так, что проблема представляет собой не программную ошибку, а заключается в том, что пользователь плохо подготовлен. Чтобы получить имя пользователя, можно воспользоваться экраном регистрации в приложении либо зарегистрированным именем Windows 95/98/NT, вызвав API Windows.


Безопасное изменение установок Jet


Существует три способа, позволяющие изменить установки Jet в системном реестре:
• Непосредственное изменение установок, принятых по умолчанию, с помощью RegEdit.exe,
• Создание пользовательского профиля для отмены установок, принятых по умолчанию, и вызов данного профиля с помощью опции командной строки /profile,
• Временная отмена в приложении установок, принятых по умолчанию, с помощью метода SetOption объекта базы данных.
Наиболее предпочтительна третья опция. Ее использование не только не вызывает сложностей, но и позволяет настроить каждое приложение отдельно. В приложении можно даже изменять установки в разное время, чтобы действительно оптимизировать быстродействие. При таком подходе установки, принятые по умолчанию, никогда не изменяются, поэтому новые проекты начинаются на общей основе.
Для временной отмены установок в системном реестре нет необходимости использовать вызовы API. Механизм баз данных предлагает метод, который использует два аргумента. Синтаксис приведен ниже:
DBEngine.SetOption ConstantNameofSetting, value
Например, производительность пакета обновлений можно повысить, если заставить Jet ожидать несколько дольше перед выполнением неявных транзакций. Соответствующий код для временного увеличения периода ожидания SharedAsync Delay до 1 секунды (1000 миллисекунд) должен быть таким:
DBEngine.SetOptiuon dbSharedAsyncDelay, 1000
Данная установка остается в силе, пока приложение не изменит ее с помощью другого метода — SetOption — либо пока DBEngine не выйдет из области действия, либо пока приложение не прекратит работу. Метод
SetOption
не записывает значения в системный реестр. С помощью метода SetOption нельзя отменить установки, принятые по умолчанию для SystemDB, CompactByPkey или подпроцессов.


Быстрая загрузка изображений


Использование изображений в интерфейсе приложения демонстрирует графическую мощь Access. Однако то, что Northwind быстро отображает фотографии сотрудников, еще не значит, что разработчик может, не задумываясь, применять графику в приложениях. В данном разделе рассматривается использование графики в базе данных.
Следует попытаться использовать для изображений элемент управления Image. Для отображения некоторых видов графики он намного более эффективен, чем связанные или несвязанные фреймы.
При загрузке формы Access должен прорисовать или визуализировать каждый элемент управления. Не удивительно, что визуализация занимает значительно больше времени, чем совмещение. Чтобы убедиться, что тщательно подогнанные элементы управления случайно не перекрываются, необходимо воспользоваться командами Format | Vertical Spacing (Формат | Расстояние по вертикали) и Format | Horizontal Spacing (Формат | Расстояние по горизонтали).
Необходимо использовать минимально возможное количество цветов графических изображений; лучше всего — черно-белый вариант. Чем больше количество цветов данного изображения, тем больше памяти и времени процессора требуется на его обработку.
Графические и другие большие типы данных (заметки и OLE-объекты) следует исключить из первичных форм, а также из начальных таблиц и запросов. Для их отображения необходимо создать отдельную форму или запрос, вызываемый только по требованию пользователя. Это предотвращает затраты времени и ресурсов, необходимых для отображения огромных объектов, в то время как, возможно, отображение данного объекта и не является обязательным. Память, используемая формами, содержащими OLE-объек-ты, не освобождается для приложения до тех пор, пока форма не будет закрыта, поэтому по окончании работы с формами их необходимо закрывать.


Быстрые ссылки на объекты


Для многократных ссылок на объекты следует использовать переменные. Гораздо быстрее обратиться к существующей переменной формы, элемента управления, отчета или запроса, чем снова обращаться к объекту. Вместо повторной ссылки на форму
Forms![frnMyForm].Height=500 Forms![frnMyForm].Width=500
можно объявить переменную и обратиться к ней следующим способом:
Dim frm as Form
Set fnn=Fonns ! [ frmMyFonn]
fnn.Height=500 frm.Width=500
При работе с большим количеством свойств объекта можно уменьшить число ссылок с помощью конструкции With...End With. Такой способ особенно полезен, когда путь, указанный в ссылке, достаточно длинный.
With Forms! [ frmMainForm] ! [txtCu stonier Name]
.left=200
.top=300
.height=200
.width=100
End With
Активную форму представляет ME, поэтому нет необходимости объявлять переменную или ссылаться на объект. Поскольку такая методика работает только в CBF, ее нельзя использовать в общих стандартных модулях.
With ME
.Height=500
.Width=500
 End With


CError.ShowAVIForm


' Состояние ожидания до закрытия формы.
Me.WaitState (True)
' Закрытие AVI-формы.
DoCmd.Close acForm, "frmErrorAVI", acSaveNo
End If
' Открытие формы для ввода примечания пользователя.
If Me.UserEnterNoteFlag Then
DoCmd.OpenFonn "frmErrorNote", acNormal
' Состояние ожидания до закрытия формы. Me.WaitState (True)
' Закрытие формы для примечания.
DoCmd.Close acForm, "frmErrorNote", acSaveNo
End If


Декомпиляция


При редактировании модуль декомпилируется. Отчет или форма декомпилируются при внесении любых изменений, даже если они не задевают код. Создание новой формы или отчета может также декомпилировать код. Во время разработки для компиляции по необходимости можно полагаться на команду Compile on Demand (Компиляция по требованию) во вкладке General меню Tools [ Options. При этом VBA компилирует модули во время выполнения. Еще одна новая опция Access 2000 — фоновая компиляция (Background Compile). При компиляции приложения в фоновом режиме VBA освобождает разработчика от дополнительных затрат времени.
Если выполнить проверку, то оказывается, что скомпилированное приложение занимает больше дискового пространства, чем нескомпилированное. Причина заключается в том, что в скомпилированном приложении хранится как скомпилированный код, так и исходный. Никакого ущерба для производительности здесь нет. Поскольку в память загружается только скомпилированный код, который выполняется быстрее исходного, производительность значительно повышается.
Поскольку Access постоянно загружает модули, необходимо внимательно рассмотреть все модули в данной разработке. Следует убедиться, что в приложении не осталось неиспользуемых функций или процедур. Необходимо удалить весь неиспользуемый код, созданный во время разработки. Если этого не сделать, компилятор будет вынужден обрабатывать невыполняемый код, а это создаст дополнительные задержки. Кроме того, во время разработки рекомендуется время от времени закрывать окно проекта, чтобы очистить память. Даже если приложение полностью скомпилировано, должен загружаться как можно меньший объем кода.


Dim strSQL as String


strSQL = "SELECT * FROM tbIErrorLog" & _
"ORDER BY tbIErrorLog.ErrorLogID;"


Добавление элементов в коллекцию


Чтобы добавить элементы в коллекцию, необходимо воспользоваться методом Add объекта коллекции.
 Collection.Add Item [, Key][, Before];, After]
Затем нужно передать объектную переменную для каждого объекта, добавленного к множеству. Например, чтобы добавить в коллекцию двух пользователей, следует воспользоваться объектной переменной для каждого пользователя: objUser1 и objUserZ.
Следующий параметр — значение Key
(удобочитаемое имя), использующееся для ссылки на объект. Если ключевое значение не указано, ссылка на каждый пункт в коллекции осуществляется по номеру индекса.


Дополнительная информация об ошибках


После рассмотрения процесса обработки синтаксических ошибок, логических ошибок и ошибок рабочего цикла можно привести некоторые дополнительные сведения об ошибках.


Дополнительные примеры объектов


В данной статье приведены многочисленные примеры классов для последующего использования (см. базу данных "Creating Objects with Class Modules.mdb" в сопровождающих статью примерах). Ниже кратко описан каждый из этих объектов.


EndSeb


EndSeb
РИСУНОК 2. Выбор опции Require Variable Declaration для выполнения объявления переменных/
Неправильно записанные слова приведут к возникновению синтаксической ошибки. При вводе кода часто появляются сообщения о таких ошибках, при этом выделяется соответствующий код.


Err.Clear


Метод Clear очищает свойства объекта Err. Любое из приведенных ниже действий очищает свойства объекта Err:
• Вызов метода Clear объекта Err (Err.Clear).
• Использование любого типа оператора
Resume,

• Выход из процедуры.
• Использование оператора On Error.


The number cannot be greater


Ниже приведен пример использования метода

Raise:


Sub Demo (intNiunber)

If intNumber = 110 Then

' Создать ошибку.

Err.Raise vbObjectError + 50, "My Application", _

" The number cannot be greater than 100", _

"С:\МуАрр\МуАрр.Hip", MyContextID

End If

End Sub

Метод Raise использует пять аргументов: Number, Source, Description, HelpFile и HelpContext. (Эти аргументы такие же, как и в объекте

Err.)
Синтаксис должен быть таким:

Err.Raise (Number, Source, Description, HelpFile, HelpContext)

При использовании именованных параметров можно указывать только необходимые аргументы, что делает код самоописательным:


Err. Raise


Метод Raise
генерирует ошибку рабочего цикла. Создание ошибки рабочего цикла может оказаться полезным при тестировании приложения. Можно имитировать ошибку рабочего цикла, указав код ошибки методу Raise
объекта Err. Кроме того, когда приложение вызывает внешнюю динамически связываемую библиотеку (DLL), значение ошибки можно передать назад в приложение для обработки ошибки.
При генерировании ошибок можно допускать ошибки, генерируемые пользователем. Следует убедиться, что номер пользовательской ошибки является уникальным, и присвоить данный номер константе vbObjectError. Например, для создания ошибки номер 50 необходимо присвоить vbObjectError
+ 50 числовому аргументу:


ErrorHandler


Здесь расположен обработчик ошибок, который обрабатывает ошибки рабочего цикла. По соглашению он располагается в конце процедуры. Код обработчика ошибок выполняется только при возникновении программной ошибки. Обработчик ошибок должен включать нечто большее чем просто окно сообщений, как показано в предыдущем примере. Рекомендуется включать выражение Select Case для ответа на все возможные ошибки, которые могут быть учтены разработчиком (см. далее раздел "Реагирование на возникновение ошибок"). В конце обработчика ошибок должен находиться оператор Resume.


ExitHere


Эта метка является точкой выхода для процедуры. Рекомендуется использовать только одну точку выхода в одной процедуре. Если процедура выполняется без ошибок, вызывается код ExitHere и процедура заканчивает работу. Код в ErrorHandler не выполняется, поскольку он находится в самом конце процедуры. Выполнение не доходит до этой точки в процедуре, поскольку выход из процедуры уже состоялся.
Метка
ExitHere
— идеальное место для вставки кода очистки. Например, можно освободить любые объектные переменные, присвоив им пустое значение, закрыть базу данных, возвратить курсор в форме песочных часов на значение, принятое по умолчанию, и включить обновление экрана.
Оператор
On Error Resume

обычно должен быть первым в процедуре выхода. Это необходимо, поскольку некоторые выражения очистки сами по себе могут стать причиной ошибки. Например, если сбой произошел до открытия базы данных и объектной переменной в процедуре выхода присвоено значение Nothing (Set db = Nothing), возникает ошибка.
СОВЕТ
Если процедура выполняется медленно и при этом включается/выключается курсор в форме песочных часов, (соответственно в начале и конце процедуры) необходимо быть очень осторожным, чтобы избежать проблем при возникновении ошибки. Примером кода очистки, который необходимо поместить в код ExitHere
перед выходом из процедуры вне зависимости от того, возникла ошибка или нет, может служить Docmd.Hourglass false,
СОВЕТ
В коде ExitHere необходимо возвратить курсор в форме песочных часов на значение, принятое по умолчанию. Песочные часы можно включить в начале процедуры. При возникновении ошибки перед обычным исчезновением песочных часов в конце процедуры выполнение кода переходит к обработчику ошибок и изображение песочных часов остается на экране. Если в точке выхода курсору возвращается значение, принятое по умолчанию, он в любом случае будет переустановлен.
Ниже приводится пример процедуры выхода с кодом очистки:
ExitHere:
On Error Resume Next
DoCmd.Hourglass False
DoCmd.Echo True
DoCmd.SetWarnings False


Хлеба и зрелищ...


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


Исключение IIF() из кода


Не рекомендуется использовать в коде функцию IIF(). Данная функция перед выдачей результата должна оценить вес выражения, содержащиеся в ней. Стандартная конструкция If...Then...Else работает быстрее.


Исключение логических ошибок


Логические ошибки возникают, когда выполнение кода не приводит к ожидаемым результатам. Возможно, существуют ошибки в логике, или программа выполняется некорректно. В тех случаях, когда код выполняется, но не дает ожидаемых результатов, следует задуматься о возможности логической ошибки.
Для устранения логических ошибок рекомендуется воспользоваться мощным отладчиком Microsoft Access. Полное описание методик отладки приведено в статье «Отладка приложений Access».


Исключение логических ошибок


Следствием логических ошибок является то, что выполнение кода не приводит к ожидаемому результату. Причиной является либо дефект в самой логике, либо некорректное выполнение программ. При выполнении кода и появлении неожиданных результатов следует задуматься о возможном наличии логических ошибок. Большая часть времени, затрачиваемая на отладку приложения, уходит на обнаружение и исправление логических ошибок. В данной статье описаны средства и методы, позволяющие решить связанные с этим проблемы.
Логические ошибки могут происходить по следующим причинам:
• Процедура пытается использовать поле базы данных, не содержащее значений (нулевое значение)
• Неправильные математические расчеты
• Обработка операции в коде в неверном порядке


Исключение ошибок рабочего цикла


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


Исключение синтаксических ошибок


Проще всего работать с синтаксическими ошибками. Синтаксические ошибки возникают в случае неверного написания кода. Примером может служить неправильно используемая переменная, зарезервированное слово или отсутствующий код:
Dim strName as
Очевидно, важный фрагмент кода отсутствует в данном операторе. Тип данных не указан. Правильный оператор должен выглядеть так:
Dim strName as String
Одним из способов устранения синтаксических ошибок является использование Option Explicit
в первой строке каждого модуля. Это потребует явного объявления всех переменных, использующихся в приложении.
Объявление всех переменных важно по нескольким причинам. Неправильно использованное имя переменной может привести к тяжелым последствиям. Если переменная предназначена для вставки значения в базу данных, могут быть вставлены неправильные данные без какого-либо сообщения об ошибке. В конце концов, VBA обращается с неправильно записанной переменной просто как с другой переменной. В следующем примере переменная BankBalance
во второй строке используется некорректно:
BankBalance = 4,576.98 RS!BankBalance = BankBalence
VBA не признает BankBalence как зарезервированное слово, поэтому полагает, что разработчик хочет создать новую переменную типа Variant со значением, принятым по умолчанию. Empty. В результате база данных обновляется значением Empty вместо необходимого значения $4,576.98.
Кроме того, объявление переменных имеет большое значение для оптимизации приложения. Поскольку необъявленные переменные используют тип данных Variant,
теряется значительный объем дисковой памяти. Например, размер переменной, в которой хранится число 5, составляет:
Dim bytNumber as Byte (1 байт)
Необъявленная переменная (для числовых данных)
(16 байтов)
Необъявленная переменная (символьные или строковые данные)
(22 байта)
В данном примере необъявленная переменная получает тип Variant. Чтобы сделать объявление переменных обязательным, необходимо в редакторе Visual Basic открыть модуль кода. Затем в меню следует выбрать команду Tools | Options (Сервис | Параметры). В диалоговом окне Options (Параметры) во вкладке Editor (Редактор) необходимо включить опцию Require Variable Declaration (Требовать объявления переменных) (рис. 2). Данная опция вставляет Option Explicit
в начале каждого нового модуля; однако она не обновляет старые модули. Необходимо проверить уже созданные модули и вставить в них Option Explicit.
Кроме того, могут возникать другие виды синтаксических ошибок, например:


Использование A2KU_Timer


При настройке приложений рекомендуется пользоваться таймером A2KU_Timer, описанным в данной главе. Он работает примерно на 1000% быстрее, чем аналогичные конструкции.


Использование ActiveX и метода раннего связывания


Следует воспользоваться преимуществами раннего связывания. При использовании элементов управления ActiveX необходимо убедиться, что существует ссылка на базовый OCX-файл для данного элемента. Для осуществления проверки выполните команду Tools | References (Сервис | Ссылки). Раннее связывание может значительно повысить производительность.


Использование быстродействующих массивов


Рекомендуется пользоваться массивами. Они хранятся в памяти и выполняются исключительно быстро. Расширение массивов занимает бесконечно малое количество времени, однако они используют только тот объем памяти, который им нужен в данный момент. Если неизвестно, сколько элементов необходимо поместить в массив, можно создать динамическое множество, а не один большой статический массив с массой пустого места.
Если необходимо очистить массив, но не разрушать при этом его структуру, можно использовать ключевое слово Erase. Это позволяет очистить массив определенного размера, не перестраивая его.
Erase MyArray
Наоборот, если нужно расширить массив, не разрушая содержащихся в нем данных, следует использовать
Redim
вместе с Preserve.
ReDim Preserve myArray(Ubound(myArray+l))
Массивы часто могут управлять данными из набора записей. Вместо постоянно открытого набора записей DAO с излишними затратами ресурсов можно применить метод GetRowsQ и закрыть набор записей. Это позволит освободить память и облегчить решение вопросов, связанных с многопользовательской средой. GetRowsQ использует один параметр: количество строк для загрузки в массив.
Dim db as Database
Dim rowArray as Variant
Dim rs as Recordset
Set db=CurrentDB()
Set rs=db.openrecordset("Quarterly Order»")
RowArray=rs.GetRows(rs.RecordCount)
rs.close

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


Использование .Execute вместо RunSQL


По возможности следует избегать кодирования в стиле DoCmd. DoCmd представляет собой высший уровень кода VBA, — потомок макросов. В тех случаях, когда имеется альтернатива, ею следует обязательно воспользоваться.
Выражение
DoCmd RunSQL
работает медленнее, чем
Querydef.Execute


Использование ключевого слова Me вместо Screen.ActiveForm и Screen.ActiveControl


При отладке приложения ключевым окном является окно Immediate. Таким образом, методы Screen.ActiveForm и Screen.ActiveControl не будут работать. Вместо них для обращения к текущей форме используется ключевое слово Me.


Использование констант


Чтобы VBA получил текущее значение переменной, при каждом обращении оно должно быть найдено. Для констант определять значение не нужно. Кроме того, константы улучшают читабельность кода. Вместо ввода числа 12 для представления 12 месяцев года можно создать константу (возможно, с именем AllMonths) и установить ее равной 12. VBA считывает константу гораздо быстрее, а другие разработчики будут знать, о чем идет речь, когда увидят данную константу. Недостаток использования констант заключается в том, что их значение можно установить только один раз и нельзя изменять. Константы можно использовать только для представления значений, внутренних для данного приложения, либо для представления значений, которые не меняются в мире. Коротко говоря, константы можно использовать только для внутренних или неизменных значений.


Использование Len() вместо пустой строки


Чтобы проверить строковую переменную на наличие символов, следует использовать функцию Len() вместо того, чтобы выполнять сравнение с пустой строкой (""). Функция Len()
оценивается быстрее, чем сравнение строки символов со строкой нулевой длины.
Sub CheckString(strString as string)
If Len(strString) then
MsgBox "Hare is the string: " & strString
Endlf
End Sub


Использование методов


Для использования данного метода при запуске приложения необходимо ввести код:
cUser.login
Обратите внимание, что пользователям, которым необходимо обновить значение в базе данных, не обязательно разбираться в коде ADO. Они просто используют доступные свойства и методы объекта, которые отображаются с помощью технологии IntelliSense.


Использование небольших процедур


Большие процедуры тяжелы для понимания и отладки. Рекомендуется разбивать процедуры на малые логические блоки. Следует взять за правило — если нельзя распечатать процедуру на одном
листе бумаги, ее
необходимо разбить на более мелкие процедуры.


Использование номеров индексов коллекций


При работе с коллекциями рекомендуется по возможности пользоваться их индексами. Номера индекса представляют собой внутреннюю идентификацию коллекции. Их использование приводит к гораздо более быстрому выполнению по сравнению с использованием любого другого свойства (например, имени) объекта коллекции. Приведенный ниже пример иллюстрирует два разных способа обращения к текущей базе данных. Ссылка на Currentdb() автоматически обновляет коллекции базы данных, что занимает определенное время. Первая ссылка (dbEngine(0)(0)) не обновляет коллекцию.
Set db=DBEngine(0)(0)
работает быстрее, чем
Set db=Currentdb()
Выражение
Set cntl=Forms!frmMyForm(O)
работает быстрее, чем
Set cntl=Forms![frmMyForm]![myControl]
Использование номера индекса элемента коллекции особенно полезно в циклах.


Использование объекта


После создания и установки объектной переменной доступ к свойствам и методам объекта можно получить с помощью технологии IntclliSense. Используя точечную нотацию, можно установить и считать значение свойства, а также выполнить метод.
Установка значения свойства: Object.Property = Value
Получение значения свойства: MsgBox Object.Property


Использование объектов с коллекциями VBA


Коллекции VBA позволяют работать с пользовательскими объектами как с группой. Например, если существует пять объектов cUser и необходимо выполнить действие над каждым из них, проще и намного эффективнее обрабатывать пять объектов как группу, а не как отдельные объекты.
Вероятно, разработчик уже знаком со встроенными коллекциями, такими как коллекции форм и элементов управления. Кроме того, VBA содержит объект коллекции. Коллекция — это способ обращения с группой объектов как с одним элементом. В повседневной жизни люди постоянно имеют дело с коллекциями. Дирижер оркестра может сказать: "Все исполнители, играющие на духовых инструментах, встаньте". Это гораздо удобнее и эффективное, чем перечислять: "Мэри, Джим, Джон, Джо, Салли, встаньте". Точно так же можно работать с объектами, составляющими один элемент или коллекцию.
Основная концепция этого подхода заключается в том, что коллекция представляет собой объект со своими собственными свойствами и методами. Коллекция обладает следующими характеристиками:
• Имеет свойства и методы.
• Может быть расширена за счет добавления различных типов объектов.
• Величина коллекции является переменной, а это значит, что коллекция может расширяться и сокращаться при добавлении и удалении элементов.
• . Элементы в выделенной области не могут быть отсортированы.
• Элементы множества являются индексированными (отсчет начинается с цифры "1").


Использование объектов


На данном этапе существует объект cUser со своими свойствами и методами. Чтобы использовать его в модуле класса, достаточно ввести имя объекта и добавить в конце точку. IntelliSense отобразит список свойств и методов объекта.
Для использования объекта в классе, который создает объект, употребляется ключевое слово Me. Например, чтобы присвоить имя пользователя, необходимо ввести:
Me.User = "Steve"
Использование объекта вне модуля класса cUser (в формах либо стандартных модулях) разбивается на два этапа. Во-первых, необходимо определить объектную переменную для использования в качестве ссылки на объект. Во-вторых, используется ключевое слово Set для создания ссылки из объектной переменной
на объект.


Использование обработчика ошибок


При возникновении ошибки обработчик ошибок может помочь сэкономить время и обнаружить оператор, ставший причиной сбоя, выдать информацию о типе ошибки, номере строки и т.д. Более подробная информация об обработчике ошибок приведена в статье «Профессиональная обработка ошибок».


Использование общедоступных переменных


Свойство можно создать с помощью объявления общедоступной переменной в разделе
объявлений
модуля класса. В приведенном ниже примере создается свойство UserType объекта cUser:
Public Name as String
Public UserType as String
После этого несложного объявления пользователи могут устанавливать и получать значения свойства. Для установки значения свойства применяется следующий программный код:
cUser.Name = "Steve"
cUser.UserType = "Management"
Для выборки значения свойства используется следующий программный код (рис. 4);
MagBox cUser.Name


Использование окна Locals


Окно Locals (Переменные) отображает выражения, значения и типы всех переменных, находящихся в области видимости (рис. 9). Чтобы открыть окно переменных, необходимо в меню выбрать команду View Locals Window (Вид | Окно переменных).
Использование окна Locals
РИСУНОК 9. Окно Locals отображает переменные в текущей области видимости


Использование окна отладки


Чтобы открыть окно Immediate, необходимо запустить редактор Visual Basic и выбрать в меню команду View | Immediate Window (Вид | Окно отладки) или нажать клавиши Ctrl+G. Окно отладки можно использовать для оценки и установки переменных, запуска функций и подпрограмм, а также для вывода результатов выражения Debug.Print.


Использование окна Watch


Окно Watch (Наблюдение) можно использовать для оценки выражений во время выполнения приложения. Например, если необходимо увидеть все места, где меняется значение переменной strName, можно воспользоваться окном наблюдения.
Сначала необходимо выбрать в меню пункты Debug | Add Watch (Отладка | Добавить для просмотра). В диалоговом окне Add Watch необходимо ввести выражение, за которым нужно установить наблюдение (например, strName = "Smith"). Кроме того, в диалоговом окне нужно указать, следует ли оценивать данное выражение в определенных процедурах, модулях или во всем приложении (рис. 10). Здесь же нужно указать Watch Type (Тип наблюдения):
• Watch Expression — отслеживать выражение
• Break When the Value is True — остановить выполнение кода в режиме прерываний, если выражение истинно
• Break When Value Changes — остановить выполнение кода в режиме прерываний, когда значение выражения изменяется
Использование окна Watch
РИСУНОК 10. Использование Оии-югового окна Add Watch для установки наблюдения за выражением.
Для быстрой установки наблюдения за выражением можно выделить выражение в тексте кода. Затем в меню необходимо выбрать команду Debug | Quick Watch (Отладка | Быстрый просмотр) или нажать клавиши Shifi+F9. В диалоговом окне Quick Watch необходимо щелкнуть на кнопке Add (Добавить) (рис. 11)
Использование окна Watch
РИСУНОК 11. Использование диалогового окна Quick Watch


Использование Option Explicit


Рекомендуется производить явное объявление всех переменных, использовав опцию Option Explicit в начале каждого модуля. По умолчанию эту опцию можно установить, выбрав опцию программы Require Variable Declaration (Требовать объявления переменных). Объявляя все переменные, можно избежать ошибок, связанных с неправильным написанием имен переменных.


Использование Option Explicit


Рекомендуется всегда использовать Option Explicit. Данная опция требует объявления всех переменных. Если не объявить переменную, VBA вынужден использовать самый большой и самый гибкий тип данных
для использования данной переменной. Обычно этот тип является также и самым медленным. Из соображений читабельности и целостности данных рекомендуется всегда объявлять переменную.


Использование отладчика


В Access 2000 очень просто заниматься отладкой приложений. Для этого нужно просто остановить выполнение кода в определенных местах и, выполняя его шаг за шагом, наблюдать за ходом выполнения.


Использование памяти кодом


Access вызывает в память модули, все подпрограммы и функции, в них содержащиеся, используя метод загрузки дерева вызовов. Это означает, что, если функция А первого модуля вызывает функцию В первого модуля, а последняя, в свою очередь, — функцию С второго модуля, Access загружает в память целиком первый модуль и весь второй модуль. В памяти остаются оба модуля. Таким образом, имеет смысл
группировать модули в логические блоки. Если функции и модули часто вызывают друг друга, их следует записать в один модуль для уменьшения непроизводительных издержек и количества загрузок модулей. Необходимо также удалить все функции и процедуры, не используемые приложением.
VBA, кроме того, загружает модуль, если существует ссылка на глобальные переменные данного модуля. Разработчику следует убедиться, что глобальные переменные разумно сгруппированы в модулях.


Использование поточного кода вместо вызова других функций


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


Использование процедур свойств


Кроме того, свойства можно добавлять к объектам с помощью специальной процедуры VBA, называемой процедурой свойства. Существует три типа процедур свойств:
Property Let
для получения значения свойства. Property Get
— для установки значения свойства и Property Set — для передачи объекта в качестве свойства.
Процедуры свойств позволяют ограничить доступ к значениям свойств. Ключом к пониманию действия процедур свойств является тот факт, что значение свойства хранится в приватной переменной на уровне модуля. Таким образом, первым шагом будет создание приватной переменной на уровне модуля, а затем — создание выражений Property Let и Property Get.


Использование символа конкатенации строк


Очень сложно рассматривать код, если необходимо прокручивать экран вправо, когда код не умещается на одном экране. Следует убедиться, что весь код отображается на одном экране в окне кода, и по необходимости использовать символ конкатенации строк (_). Такие строки обрабатываются как одна строка. Ниже приводится обычный пример SQL-оператора:


Использование событий


Чтобы воспользоваться событием Welcome в модуле формы, необходимо объявить объектную переменную для cUser в разделе объявлений модуля и использовать ключевое слово WithEvents.
Зарезервированное слово WithEvents применяется для отображения и использования событий объекта cUser. Соответствующий код приведен ниже:
' Данное выражение следует поместить в раздел объявлений модуля.
Private WithEvents objUser As cUser


Использование специфических типов данных


Рекомендуется всегда объявлять тип данных и использовать наименьший по занимаемому объему тип данных. Если тип данных не объявлять, используется тип Variant. Это не только неэффективно из-за дополнительных требований к ресурсам, но и может стать причиной появления программных ошибок, поскольку любой тип данных можно присвоить переменной типа Variant. Например, если переменная должна хранить только числа и при этом использован тип Variant, может возникнуть ошибка, когда с переменной используются данные, отличные от чисел, или объекты.


Использование SQL вместо DAO


Работать с наборами записей рекомендуется только в том случае, если нет другой альтернативы. Механизм баз данных Jet для манипуляций над данными и структурами данных оптимизирован на использование SQL. При каждой возможности вместо DAO следует использовать запросы SQL. Очень редко DAO работает быстрее, чем правильно составленный запрос. В отличие от DAO, запросы имеют план выполнения и используют преимущества индексации.
Если необходимо адресовать данные через объектную модель, рекомендуется вместо DAO использовать ADO. ADO — новый стандарт для манипуляций с адресацией данных и определением данных через объектную модель. Разработка дальнейших версий DAO прекращена, и никаких улучшений или расширений в будущем не последует.


Использование стандартных соглашений о наименовании


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


Использование технологии IntelliSense при отладке


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


Использование технологии Microsoft IntelliSense


Для использования объекта разработчику достаточно выбрать данный объект и его свойства или метод с помощью технологии IntelliSense (рис. 2). Например, один из объектов, рассматриваемый в данной статье, представляет собой объект обработчика ошибок, который можно использовать в приложениях Access. Поскольку весь код обработчика ошибок включен в состав объекта сЕггог, разработчику достаточно указать объект и выбрать необходимые свойства или метод. Например, если разработчику нужно, чтобы при возникновении ошибки в приложении было отправлено почтовое сообщение, достаточно вызвать метод "email":
cError.email
Использование технологии Microsoft IntelliSense
РИСУНОК 2. При работе с объектами можно использовать технологию Microsoft IntelliSense.
Обратите внимание на то, как легко использовать объекты. С помощью технологии Microsoft IntelliSense достаточно просто ввести имя объекта (сЕггог) и добавить точку — при этом отображаются все свойства и методы данного объекта. Это сильно упрощает и ускоряет написание программного кода.


Использование True и False вместо нуля


Поскольку True и False являются двоичными величинами, их оценивать проще, чем число 0. True и False можно использовать так:
Function ShowNumber(dblNumber as Double) as string
If dblNumber then
ShowNumber ="The number is " & dblNumber
Endlf
End Function


Использование условной компиляции


Работа с единственной версией приложения представляется гораздо более удобным подходом, чем создание нескольких версий. Предположим, имеется приложение, которое используется несколькими отделами. Большая часть приложения является общей и может использоваться всеми отделами, но небольшие блоки кода должны быть приспособлены под нужды каждого отдела. Если принято решение создать несколько версий, обновление и поддержка всех версий может оказаться непосильной задачей. Каждый новый блок общего кода необходимо добавлять во все версии. Кроме того, большое количество версий усложняет работу с приложением и затрудняет его распространение.
Гораздо удобнее создать единственную версию приложения, которая по-разному выполняется при разных обстоятельствах. Можно выбрать, какая часть кода в приложении компилируется или выполняется в зависимости от обстоятельств.
В качестве примера допустим, что в Лос-Анджелесском отделении предприятия должна выполняться некоторая часть кода, которая не выполняется ни в одном из других отделений. Во-первых, необходимо выбрать константу для данного отделения, например, LA.
Константу нужно ввести как аргумент условной компиляции для приложения. В редакторе Visual Basic в меню необходимо выбрать команду Tools | Apllication's Properties (Сервис | Свойства приложения). Откроется диалоговое окно Project Properties (Свойства проекта). Нужно выбрать вкладку General (Общие). В поле Conditional Compilation Arguments (Аргументы условной компиляции) необходимо ввести LA = -I. Данное выражение позволяет установить константу равной True.
Теперь можно ввести код, который выполняется только для версии LA приложения. Для этого необходимо записать код в конструктив условной компиляции. Например:
#If LA Than
' Данный код выполнятся в IA-версии приложения.
#End If
Кроме того, условная компиляция может оказаться полезным средством отладки. Если необходимо часто комментировать разделы кода, нужно установить аргумент условной компиляции fComment = -1. Данный флаг комментария теперь можно использовать в конструктиве условной компиляции для комментирования разделов кода:
#If fComment Then
' Выполняется данный код.
#End If


Использование зарезервированного слова TypeOf


Часто можно передавать элементы управления в общую процедуру. Например, можно передать
список и
поле со списком в общую процедуру, которая загружает значения с помощью метода Addltem. Если передавать элемент управления, который не является ни списком, ни полем со списком (например, командная кнопка), возникнет ошибка, поскольку данный элемент управления не содержит метод Addltem. В
процедуре для проверки типа элемента управления и устранения ошибки используется зарезервированное слово TypeOf.


Использование шаблона



Использование шаблона

Для создания новой базы данных на основе шаблона используется специальный мастер Access. В комплекте с программой поставляется несколько таких шаблонов, и их применение не требует особых знаний. По сути, нет даже необходимости подробно описывать работу с мастером, поэтому мы остановимся лишь на отдельных ее деталях.

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

1. Воспользовавшись комбинацией клавиш , откройте панель задач и щелкните на ссылке На моем компьютере, находящейся в разделе Шаблоны.

2. Для просмотра существующих шаблонов перейдите на вкладку Базы данных.

3. Дважды щелкните на любом из значков шаблонов, показанных на рис. 2.7, или один раз на значке шаблона, а затем на кнопке ОК. Выберите, например, шаблон Основные фонды.


Изменение значения переменной


Для изменения значения переменной в окне Immediate необходимо ввести имя переменной со знаком равенства и новым значением, например, inti = 10.


Изучение пользовательского интерфейса



Изучение пользовательского интерфейса

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



Компиляция кода


Можно скомпилировать код, выбрав в меню пункты Debug j Compile projectname
(Отладка | Скомпилировать имя_проекта). Перед распространением приложения необходимо обязательно скомпилировать его.


Комплексный обработчик ошибок


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


Контроль обновлений


Необходимо отключить Application.Echo или контролировать обновление экрана. Обновление экрана занимает время, и это может замедлить выполнение приложения.


Метод AccessError


Данный метод можно использовать для возврата описания ошибки Microsoft Access. Например, если ввести ? AccessError(11) в окне Immediate (Отладка), получим Division by zero (рис. 15).
Метод AccessError
РИСУНОК 15. Использование метода AccessError в окне отладки.


Метод Debug.Assert


Метод
Debug.Assert
приостанавливает выполнение отдельной строки кода в зависимости от поставленного условия. Например, если оператор кода считывает Debug.Assert False, код приостанавливает выполнение данной строки. Это позволяет выполнять код по шагам и отладить ошибки.


Метод Debug.Print


С помощью метода
Debug.Print
можно выводить информацию в окне Immediate.
Данный метод можно использовать либо в самом окне Immediate, либо при работе с кодом.


Методики отладки


Код данный главы включает примеры, которые предоставляют возможность попрактиковаться в отладке приложений, используя методики, описанные в данной статье (рис. 13).
Методики отладки
РИСУНОК 13. Использование методик отладки на примерах кода.


Методы объекта cError


Методы объекта сЕггог
обеспечивают разработчиков полезной информацией об ошибке. Например, информация об ошибке может быть отправлена разработчику по электронной почте или записана в базу данных. Методы объекта cError описаны в табл. 2.


«Microsoft Access 2000 Development»


Использование средств отладки Microsoft Access и методик отладки, описанных в данной статье, позволяет сэкономить очень много времени, требующегося для разработки. Время, затраченное на изучение этих средств и методик, с лихвой окупит себя в дальнейшей перспективе.
Не следует полагать, что данные средства отладки нужны только для создания сложных приложений. Даже в самых простых приложениях возникают совершенно нетривиальные программные ошибки, обнаружить которые нелегко. Программные ошибки должны быть немедленно обнаружены и исправлены. Хотя некоторые ошибки практически не вызывают проблем, другие могут привести к повреждению базы данных или к худшим последствиям.


«Microsoft Access 2000 Development»


Признаком профессионального приложения является наличие возможности обработки ошибок. Если приложение не особенно элегантно обрабатывает ошибки, пользователи будут разочарованы вне зависимости от того, насколько сложным является приложение или какими возможностями оно обладает.
Без обработки ошибок программа может неожиданно закончить работу, особенно если используется рабочая версия приложения. Это может смутить пользователей, поскольку они не представляют себе, что произошло и почему и можно ли продолжать работу.
При возникновении ошибки пользователи должны обязательно получать предупреждение, что позволит им разобраться в происходящем и предпринять необходимые действия. Непонятные сообщения об ошибках настолько же плохи, как и отсутствие каких бы то ни было сообщений (рис. 1). Многие ли пользователи понимают или находят полезными сообщения об ошибках типа Illegal Operation, Overflow или General Protection Fault?
«Microsoft Access 2000 Development»

РИСУНОК 1. Пример непонятного сообщения об ошибке.
Без надлежащей обработки ошибок разработчики также теряют ценную информацию о функционировании своих приложений в рабочем режиме. При оказании технических консультаций обнаружение и поиск ошибок поглощает значительную часть времени. Определенно, в лучших интересах разработчика как можно быстрее исправить программные ошибки.
Без обработчиков ошибок программисты вынуждены полагаться на объяснения пользователей о том, что они делали в момент возникновения ошибки. Типичный ответ пользователя: "Я не знаю". Это приводит к ненужным и занимающим время попыткам найти и обнаружить ошибку. В данной главе описан процесс создания мощного обработчика ошибок, который поможет как пользователям приложения, так и разработчику.
Существует три типа программных ошибок: синтаксические ошибки, логические ошибки и ошибки рабочего цикла.


«Microsoft Access 2000 Development»


Оптимизация приложения представляет собой тему для бесконечного обсуждения и споров между разработчиками. Всем нужны оптимальные решения, но что же точно означает термин "оптимальный"? Одни полагают, что "оптимальный" значит самый быстрый, поэтому самая высокоскоростная технология всегда будет оптимальной. Другие утверждают, что оптимальным является такое решение, которое обеспечивает большую надежность, даже если при этом приложение работает медленно и генерирует чрезмерное количество предупреждений. Третьи считают, что целью оптимизации является эксплуатационная надежность и расширяемость. Кто же прав? Ответ заключается в том, что, как часто это бывает в жизни, правы все и все они ошибаются. На самом деле оптимизация представляет собой попытку уравновесить все три представленные мнения.
Оптимальным является такое решение, которое обеспечивает пользователя приемлемым быстродействием приложений. Обычно пользователи не в восторге от медленно выполняющихся приложений. Однако, если оптимальное решение представляет собой лишь способ быстрого разрушения и потери данных, разработчик пошел на неразумный компромисс. Если приложение работает достаточно быстро и доказало свою надежность, существуют неплохие шансы, что пользователи захотят пользоваться таким приложением и дальше. Однако необычные решения по дизайну и неортодоксальное выполнение данного дизайна могут затруднить дальнейшее улучшение и расширение возможностей хорошо работающего приложения.
Приложения с некоторой точки зрения напоминают автомобили. Мало кто захочет оказаться за рулем очень быстрого автомобиля, у которого слабые тормоза и плохая управляемость. Всем нужен автомобиль, который заводится каждый день и доставляет куда нужно без особой суматохи. Наконец, счета за ремонт и обслуживание не должны превышать разумных величин. Хотя в данной статье рассматривается оптимизация скорости работы приложения, необходимо помнить, что приложение, кроме того, должно быть надежным, стабильно работающим и расширяемым.



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

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

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


Модуль класса (объект) ошибки


Модуль класса с именем сЕггог
в коде данной главы содержит свойства и методы, необходимые для эффективного обработчика ошибок. Объект сЕггог включает в себя весь код модуля класса. Благодаря технологии Microsoft IntelliScnsc использование данного объекта является очень простым.


Настраиваемые меню



Настраиваемые меню

Настраиваемые меню были впервые представлены в Office 2000. Подобно подменю они адаптированы к работе пользователя: наиболее часто используемые команды в них отображаются постоянно, а те команды, что применяются сравнительно редко, скрываются.

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

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

1. Выберите команду Вид>Панели инструментов.

2. Задайте опцию Настройка.


Немедленное исправление ошибок


При разработке приложения часто возникает искушение проигнорировать ошибку. Например, разработчик создает новые свойства приложения и наталкивается на ошибку в другой части приложения. Лучше всего остановиться и исправить ошибку. Это достаточно тяжело, потому что основное внимание занято новой разработкой. Однако позже данную ошибку будет труднее обнаружить и воспроизвести. Необходимо взять за железное правило — при нахождении ошибки немедленно исправлять ее.
Использование комментариев
По прошествии нескольких месяцев, недель или даже дней после создания кода очень сложно вспомнить все детали относительно той или иной процедуры. Рекомендуется как можно чаще пользоваться комментариями для упрощения последующей работы с кодом. Комментарии не замедляют выполнение кода, поскольку они удаляются компилятором. Для создания комментария необходимо проставить одинарную кавычку перед текстом. В окне кода закомментированные строки отображаются зеленым цветом.


Никогда не используйте Stop


Не рекомендуется использовать в коде
Stop
для входа в режим прерываний. Как упоминалось выше, вместо этого следует использовать метод Debug.Assert. Правильный синтаксис метода — Debug.Assert False.
Если забыть удалить Stop перед распространением приложения, приложение не будет работать корректно. Метод Debug.Assert удаляется из кода при компиляции приложения.


Нормализация данных в целях повышения производительности


Нормализация уже рассматривалась в данной книге, поэтому здесь приведено лишь несколько замечаний.
• Нормализованная база данных позволяет экономить дисковое пространство, а также препятствует появлению конфликтующих или некорректных данных, поскольку она не содержит повторяющихся данных.
• В нормализованной базе данных используется меньше страниц данных и индексов, что ускоряет поиск.
• Когда имеет смысл нарушать правила нормализации? Иногда имеет смысл создавать некоторые модули приложения на основе ненормализованных таблиц, если данные таблицы являются временными таблицами, создание которых требует много времени. Однако при постоянном хранении данные должны находиться в нормализованной структуре. Следует помнить, что для обновления нормализованной структуры после действий с ненормализованными структурами необходимо создавать специальные процедуры, которые могут повлиять на производительность. Правила нормализации можно нарушать лишь в последнюю очередь.
• Еще один аспект нормальной формы, который обычно можно игнорировать без какого-либо ущерба, — это правило многократности данных, поскольку оно влияет лишь на второстепенные данные. Часто имеются дополнительные биты информации о покупателе или товаре, которые, если строго придерживаться правил, следует хранить в отдельных таблицах. Примером могут служить дневные и вечерние номера телефонов, номера факсов, сотовых телефонов, пейджеров, адреса электронной почты и т.д.
• Правила нормализации можно нарушать в тех случаях, когда это имеет смысл. Нарушение правил нормализации иногда позволяет повысить производительность для некоторых частей приложения. Но всегда следует помнить о том, что такое нарушение может повлиять на надежность, целостность данных и эксплуатационные качества.
Идеальная схема нормализации заставила бы разработчика создать таблицу контактов с полем ID покупателя, полем типа контакта и другими полями для хранения номеров телефонов и адресов электронной почты. Вероятно, такой подход можно считать излишеством, а дополнительная целостность и гибкость не стоят затраченных усилий. Вполне разумно хранить эту информацию в таблице покупателей и воспользоваться преимуществами повышенной производительности. Однако правило заключается в том, что нужно нормализовать все, что возможно. Это то, чего ожидает Jet, так как лучше всего он работает с нормализованными данными.


О происходящем "за кулисами”


Хотя определение времени играет не последнюю роль, но только на основе этой информации невозможно судить о производительности приложения во время разработки. Скорее всего, разработка происходит. на высокоскоростном компьютере, и тестирование производится на небольшом наборе тестовых данных, который наверняка меньше набора, используемого настоящим приложением. Более того, таймер не может сообщить, как будет выполняться приложение на другом компьютере с меньшим объемом памяти или более низкоскоростным диском. Для более точного наблюдения за приложением можно воспользоваться другой недокументированной функцией — ISAMStats. Функция ISAMStats не документирована и не поддерживается, поэтому информацию, которую она сообщает, можно использовать лишь в качестве общих указаний. При запуске функция производит измерение шести важных оказывающих влияние на производительность операций. Она подсчитывает все обращения чтения и записи на диск, обращения чтения в кэше, опережающего чтения, размещения блокировок и освобождения блокировок. Данную функцию можно использовать в Access 2000 и предыдущих версиях Access. Синтаксис функции очень простой:
DBEngine.ISAMStats(опция,[reset])
Существует шесть возможных значений для аргумента опция:

Значение аргумента опция

Описание

0
1
2
3
4
5

Запись на диск
Чтение с диска
Чтение из КЭШа
Чтение из кэша (опережающее чтение)
Размещение блокировки
Освобождение блокировки


Необязательный параметр переустановки позволяет переустановить отдельные счетчики на нулевое значение. Чтобы воспользоваться данной функцией для оценки производительности, необходимо либо вычесть одни показания из предыдущих, либо переустановить счетчик на нулевое значение и затем вы-поднять оценку. В листинге 2 приведен один из способов использования функции ISAMStats
для оценки производительности.
Листинг 2. Один из способов использования ISAMStats
для оценки производительности.
Sub PrintStats()
Dim i As Integer
Debug.Print



Debug.Print "Disk Reads:  " & ISAMStats (0, Falsa)

Debug.Print "Disk Writes:  " & ISAMStats(1, False)

Debug.Print "Cache Reads:  " & ISAMStats(2, False)

Debug.Print "Read-Ahead Cache Reads:  " & ISAMStats(3, False)

Debug.Print "Locks Placed:  " & ISAMStats(4, False)

Debug.Print "Locks Released: " & ISAMStats(5, False)

For i = 0 To 6

ISAMStats i, True

Next

End Sub

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

Функции A2KU_TimeClock и PrintStats

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

Далее в статье приведен пример использования этих функций для сравнения двух различных методик.


Объект Err не сообщает номер строки


Name of the form or report (Имя формы или отчета). Сообщает имя формы или отчета, в котором произошла ошибка. Это всего лишь простая передача имени формы или отчета в обработчик ошибок.
Name of procedure (Имя процедуры). Сообщает имя процедуры, в которой произошла ошибка.
Name of active control (Имя активного элемента управления). Сообщает имя активного элемента управления в момент возникновения ошибки.
Value of active control (Значение активного элемента управления).
Сообщает значение активного элемента управления в момент возникновения ошибки. Часто ошибка происходит только при определенных значениях, введенных в элемент управления. Если, например, ошибка возникает, когда в текстовое поле вводится значение больше 20000, данный тип ошибки можно легко идентифицировать, возвращая значение текстового поля для записи в обработчик ошибок.


Объект Err


VBA содержит объект Err,
который обеспечивает разработчика информацией, необходимой для обработчика ошибок. Объект Err является объектом глобальной области действия, поэтому не нужно создавать его экземпляры.
Объект Err обладает следующими свойствами:
• Err.Number — номер ошибки для текущей ошибки. Этот номер можно использовать для ответа на различные типы возникающих ошибок.
• Err.Description — описание ошибки.
• Err.Source — объект или приложение, сгенерировавшее ошибку.
• Err.HeIpFile — Путь к файлу справки Windows. Данное свойство вместе с HelpContext можно использовать для создания кнопки справки в диалоговом окне сообщения об ошибке.
• Err.HelpContext — идентификационный номер соответствующей
статьи в
справочном файле.
• Err.Last DLL Error — системный код ошибки, возвращаемый путем вызова динамически связываемой библиотеки (DLL).
Объект Err
содержит два метода:


Объект Letter


В код статьи включен модуль класса cLetter,
использующийся для создания писем в Microsoft Word. Письмо составляется автоматически. Для этого используется шаблон Microsoft Word, а данные для письма получает SQL-оператор. Метод ShowWord (Boolean) определяет, отображается ли Word для данного пользователя. Иногда требуется отправлять письма непосредственно на принтер без редактирования.
Код модуля класса cSound приведен ниже;
Option Explicit Private objWord As Word.Application
' Локальные переменные для хранения значений свойств. Private mvarTemplate As String ' локальная копия
Private mvarSQLStatement As String ' локальная копия
Public Property Let SQLStatement(ByVal vData As String)
mvarSQLStatement = vData
End Property
Public Property Get SQLStatement() As String
SQLStatement = mvarSQLStatement
End Property
Public Property Let Template(ByVal vData As String)
mvarTemplate = vData
End Property
Public Property Get Template() As String
Template = mvarTemplate
End Property
Public Sub CreateLetter(DatabasePath As String, ShowWord As Boolean)
' Запись данных о покупателях во временный файл для использования
' почтового слияния. Это быстрее, чем получение данных непосредственно
' из Access.
DoCmd.OutputTo acOutputQuery, "qryCustomers", AcFormatRTF, "С:\Temp.rtf", False
objWord.Documents.Add (Me.Template)
' Запуск почтового слияния.
With objWord.ActiveDocument.MailMerge
.MainDocumentType = wdFormLetters
.OpenDataSource Name:="C:\ Temp.rtf"
.Destination = wdSendToNewDocument
.Execute End With
It ShowWord Then
    Me.ShowWord
End If
End Sub

Friend Sub ShowWord()
' Отображение экрана приложения Word для пользователя.
objWord.Visible = True
End Sub
Private Sub Class_Initialize()
1
Переход к следующей строке после оиибки.

On Error Resume Next
' Попытка использовать приложение Word, окно которого уже открыто. Set objWord =
Get0bject(,  "Word.Application")

' Если истинно. Word не открыт.



If objWord Is Nothing Then

' Запуск новой копии приложения Word.

Set objWord = New Word.Application

' Если истинно, MS Word не установлен.

If objWord Is Nothing Then

MsgBox "MS Word is not installed on your computer"

End If

End If

End Sub

Private Sub Class Terminate()

Set objWord = Nothing

End Sub

Приведенный далее код инициализирует объект objLetter и использует его свойства и методы:

' Переменные Dimension.

Dim objLetter As cLetter

Dim strPath As String

strPath = CurrentProject.Path

' Присваивание объектных переменных объекту cLetter.

Set objLetter = New cLetter

' Шаблон Word для использования в данном документе.

objLetter.Template = strPath & "\Business Services Letter.dot"

' SQL-оператор, использующийся для получения данных для формы.

ObjLetter.SQLStatement = "SELECT * FROM tbICustomers"

' Вызов метода "CreateLetter" для создания письма.

objLetter.CreateLetter strPath С "\0bjects.mdb", True

' Разрушение объектной переменной.

Set objLetter = Nothing


Объект Outlook


В статье приводится код модуля класса cOutlook, используемый для отображения формы Outlook New Message (Новое сообщение) (рис. 12). Если необходимо предоставить пользователям возможность создавать сообщения Outlook из приложения Access, можно воспользоваться методом NewEmailMessage.
Объект Outlook
РИСУНОК 12. Отображение формы Outlook New Message в приложениях Access
Ниже приводится код модуля класса cOutlook:
Option Explicit
Private mobjOutlook As Outlook.Application
Private mMyItem As Object
Public sub NewEmailMessage(EmailAddress As String)
' Создание нового почтового сообщения Outlook.
Set mMyItem = mobjOutlook.CreateItem(olMailItem)
mMyItem.To = EmailAddress
mMyItem.Display
End Sub
Private Sub Class_Initialize()
' Нет никаких причин для использования "GetObject", чтобы
' автоматизировать Outlook. Outlook всегда будет открывать одну копив
' приложения. Используется ключевое слово "New".
' Установка объектной переменной к приложению Outlook.
Set mobjOutlook = New Outlook.Application
' Если истинно, MS Outlook не установлен.
If mobjOutlook Is Nothing Then
MagBox "MS Outlook is not installed on your computer"
End If
End Sub
Private Sub Class_Terminate()
' Освобождение объектной переменной.
Set mobjOutlook = Nothing
End Sub
Приведенный ниже код инициализирует объект objOutlook и вызывает метод NewEMailMessage:
' Объектные переменные Dimension.
Dim objOutlook As cOutlook
' Присваивание объектных переменных объекту cOutlook.
Set objOutlook = New cOutlook
' Вызов метода "NewEMailMessage".
objOutlook.NewEmailMessage nancy@northwind.com
' Разрушение объектной переменной.


Объект Sound


В статье содержится модуль класса cSound, предназначенный для воспроизведения звуков в приложении Access. Модуль класса cSound содержит только один метод (PIaySound), который передает звуковой файл на обработку вызову Windows API:
' Вызов Windows API.


Объект TextFile


В статье приводится код объекта TextFile,
который можно использовать для считывания и записи информации в текстовый файл (рис. 9). Модуль класса включает следующий код:
Объект TextFile
РИСУНОК 9. Пример объекта TextFile.
Private pintFreeFile As Integer
Private pvarlnfo As Variant
Public Function ReadLineText(strFileName Aa String) As String
pintFreeFile = FreeFile
Open StrFileName For Input As pintFreeFile
Line Input #pintFreeFile, pvarlnfo
ReadLineText = pvarlnfo
Close XpintFreeFile
End Function
Public Function ReadAllText(strFileName As String) As String
pintFreeFile = FreeFile
Open strFileName For Input Aa pintFreeFile
Do Until VBA.EOF(pintFreeFile)
Line Input #pintFreeFile, pvarlnfo
ReadAllText = ReadAllText & vbCrLf & pvarlnfo
Loop
Close #pintFreeFile
End Function
Public Sub WriteLineText(strFileName As String, strText Aa String)
pintFreeFile = FreeFile
Open strFileName For Append As pintFreeFile
Write #pintFreeFile, strText
Close #pintFreeFile
End Sub


Объект Timer


В статье приводится код модуля класса cTimer. Данный модуль класса используется, во-первых, как секундомер для учета времени, а во-вторых, для создания "состояния ожидания", чтобы приостановить выполнение кода на заданное число секунд. Код модуля класса cTimer приведен ниже:
Option Explicit
Private msngStart As Single
Public Sub Wait(lngSeconds As Long)
Do Until Timer > msngStart + IngSeconds
DoEvents Loop
End Sub
Public Sub StartTimerO
BsngStart = Timer
End Sub
Public Function ElapsedTime() As Long
Dim sngTimerStop As Single
sngTimerStop = Timer
ElapsedTime = sngTimerStop - asngStart
msngStart = 0 sngTimerStop = 0
End Function
Объект frmTimer в базе данных "Creating Objects with Class Modules, mdb" иллюстрирует использование таймера для определения промежутка времени и создания "состояния ожидания" (рис. 10).
Объект Timer
РИСУНОК 10. Использование таймера для оценки прошедшего времени и  создания состояния ожидания


Объекты, свойства и методы


Перед рассмотрением процесса создания объектов необходимо вспомнить основы. Важно понимать суть терминов объект, свойства и методы, иначе оставшаяся часть статьи будет весьма трудной для восприятия.
Объект — это элемент, которым можно управлять, манипулировать и который можно программировать. В Access объектами являются формы, текстовые поля, командные кнопки и многое другое. В данной статье рассматриваются примеры создания пользовательских объектов.
Свойство — это характеристика объекта. Свойство можно рассматривать и как описание чего-либо, поскольку оно описывает или характеризует объект. В Access свойства текстового поля включают Name, Visible, Forecolor и др. Большинство свойств объекта можно как считывать, так и устанавливать. В данной статье приведены примеры создания пользовательских свойств и описаны способы управления ими.
Метод представляет собой действие, которое можно выполнить над объектом. Метод можно рассматривать как действие. Например, одним из методов формы Access является метод Close. В данной статье приведены примеры создания пользовательских методов.


Объявление переменных в минимальной области действия


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


Объявление переменных в отдельных строках кода


Гораздо проще проверить, объявлена ли переменная, просматривая переменные, записанные в отдельных строках кода, а не в одной длинной текстовой строке. Кроме того, данный подход позволяет избежать проигрыша в скорости.


Объявление типа объекта


Типы объектов необходимо объявлять очень точно. Если код работает с элементами управления текстовых полей формы, объектную переменную следует объявить как текстовое поле, а не просто как элемент управления. В таком случае VBA не понадобится решать, к какому типу элементов управления происходит обращение. Для уменьшения времени выполнения вместо
Sub CycleControls(cnti as control)
необходимо использовать
Sub CycleContrals(cnti as TextBox)


Object Browser


Чтобы открыть Object Browser (Браузер объектов), необходимо в меню выбрать пункты View | Object Browser (Вид | Браузер объектов) или нажать клавишу F2. Браузер объектов используется для просмотра объектов, свойств и методов (рис. 5).
Object Browser
РИСУНОК 5. Браузер объектов.


Обнаружение проблем, возникающих при работе компьютеров


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


Обработчик ошибок процедурного


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


Обработка ошибок для вложенных процедур


Часто в коде одна процедура вызывает другую, а та, в свою очередь, третью и т.д. Как в таком случае обрабатываются ошибки?
Для отслеживания всех вызовов процедур существует список вызовов, который поддерживается автоматически (рис. 14). Список вызовов можно просмотреть в любой момент времени в редакторе Visual Basic, выбрав в меню пункты View | Call Stack (Сервис | Стек вызова).
Обработка ошибок для вложенных процедур
РИСУНОК 14. Окно Call Stack.
При возникновении ошибки обработчик ошибок в текущей процедуре обрабатывает ошибку. Однако если в текущей процедуре ошибки не существует, ошибка обрабатывается обработчиком вызывающей процедуры. Другими словами, VBA производит обратный поиск по списку вызовов, пока не будет найдена ошибка.


Общедоступная переменная и процедуры свойств


Простейший способ создания свойств класса заключается в использовании общедоступных переменных. Однако данный подход имеет некоторые недостатки. Общедоступные переменные всегда отображаются вне модуля. Таким образом, невозможно контролировать доступ к значениям свойств. Если кто-либо меняет значения свойств без ведома других пользователей, это может вызвать нежелательные проблемы.
Еще одно преимущество процедур свойств заключается в том, что можно создать свойства "только для чтения" или "только для записи". Например, если нужно создать свойство Password, можно разрешить пользователям устанавливать пароль, но не получать его (только для записи). Для создания свойства "только для записи" необходимо включить выражение
Property Let,
но не включать выражение Property Get.
Кроме того, с помощью процедур свойств можно выполнять действия в коде в зависимости от того, установлено свойство или получено.


Оценка переменных


Для оценки переменных в окне Immediate необходимо ввести знак вопроса с именем переменной, например, ? strName. Следует также помнить, что значение переменной можно определить, задержав курсор мыши над переменной в режиме прерывания.


Оценка типа результирующего набора для достижения оптимальной производительности


Jet, кроме того, рассматривает запрашиваемый результирующий набор. Например, для представления динамического множества может быть выполнен план, который эффективно представляет первую страницу данных, даже если отображение оставшихся записей происходит медленнее. Для образования динамического множества Jet создает набор уникальных ключевых значений, которые указывают на строки соответствующей базовой таблицы. Таким образом, для Jet достаточно получить только ключевые значения, а оставшиеся записи будут отображены тогда, когда они понадобятся пользователю. Однако в снимках Jet перед представлением результата собирает все записи и столбцы для результирующего набора. Если весь снимок не помещается в памяти, его часть переходит в файл подкачки, что отрицательно сказывается на производительности. Гораздо большую производительность можно получить при использовании большого динамического множества.
Во-первых, Jet оценивает имеющиеся опции доступа к базовым таблицам. Каждый план доступа к базовой таблице получает соответствующую оценку. Затем Jet оценивает имеющиеся опции объединения. Механизм Jet рассматривает только объединение результата отношения с базовой таблицей, а не объединение результатов одной связи с результатами другой. Это помогает ограничить количество времени, которое уходит на оптимизацию запросов. После анализа каждой доступной стратегии объединения с каждой стратегией доступа к базовым таблицам и рассмотрения типа результирующего набора записей Jet выбирает план.
Для выполнения запроса к таблицам, не являющимся таблицами ODBC, Jet очищает план, уменьшает его размер и передает на выполнение.
Компиляция и оптимизация происходят в первый раз при создании или редактировании запроса и выполнении. Запрос может остаться нескомпилированным. Если модифицировать запрос и сохранить его, но не выполнять, запрос остается нескомпилированным. Кроме того, если модифицировать индексы таблиц чли схему данных, оптимизация запросов может нарушиться. Рекомендуется всегда открывать запросы в режиме конструктора, сохранять их и затем выполнять до распространения приложения. Такой подход обеспечивает компиляцию запросов.



Для оптимизации запросов Jet производит сложную оценку стоимости. В число этих сложных оценок входит просмотр статистики базы данных. На основе статистических данных Jet сообщается о количестве страниц данных, страниц индекса, строк в таблицах и т.д. При нестандартном завершении работы базы данных статистика может быть искажена, транзакции отменены либо базе данных может понадобиться сжатие. При оптимизации всегда вначале следует сжимать базу данных.

Как известно. Jet создает план выполнения для каждого запроса. Создав в системном реестре запись

\HKEY_LOCALMACHINS\SOFTWARE\MICROSOFT\JET\4 . 0\ENGINES\DEBUG

и установив значение строки в ON, Jet создает или добавляет текстовый файл в текущей папке плана выполнения запроса. В этот план входит многое из того, что было описано выше. План изменить невозможно, если не изменять схему данных, структуру запроса или ограничения запроса. Чем подробнее план, тем лучше. В листинге 3 приведен план выполнения для запроса Quarterly Orders для фирмы Northwind.

Листинг 3. План выполнения с использованием преимуществ срочной оптимизации.

--- Quarterly Orders ---

- Inputs to Query –

- Table 'Customers'

Using index 'PrimaryKey'

Having Indexes:

PrimaryKey 91 entries, I page, 91 values

which has 1 column, fixed, unique, primary-key, no-null

PostalCode 91 entries, 1 page, 87 values

which has 1 column, fixed

CompanyName 91 entries, 3 pages, 91 values

which has 1 column, fixed

City 91 entries, 1 page, 69 values

which has 1 column, fixed

Table 'Orders'

- End inputs to Query -



01) Restrict rows of table Orders

using rushmore

for expression "Orders.OrderDate Between #1/1/98# And #12/31/98#"

02) Outer Join result of '01)'  to table 'Customers'

using index 'Customers!PrimaryKey'

join expression "Orders.CustomerID=Customers.CustomerID"

03)  Sort Distinct result of '02)'

Можно увидеть раздел базовой таблицы с анализом индексов и количеством записей, баз данных, страниц индекса и оцениваемых значений. Обратите внимание, что данный запрос может быть обработан методом срочной оптимизации, поскольку существует индекс для поля Order Date таблицы Orders. План определяет связь между таблицей Orders и таблицами Customers как внешнюю связь. Индексы и срочная оптимизация прекрасно оптимизируют данный запрос. Если разработчик не уверен в том, насколько хорошо был оптимизирован запрос, можно проверить план выполнения. SHOWPLAN не документирован и не поддерживается. Некоторые запросы не создают планов, и некоторые планы неверны, но с долей осторожности все же можно пользоваться JetShowPlan.



В листинге 4 приводится пример плохо оптимизированного запроса.

Листинг 4. Недостаточно хорошо оптимизированный план выполнения запроса без использования преимуществ оптимизации Jet.

SELECT Customers.CustomerID, Customers.CompanyName

FROM Customers INNER JOIN Orders ON

Customers.CustomerID = Orders.CustomerID

WHERE ((Not (Orders.ShipCountry)="USA")) ;

-— Customers with Shipping Address Outside USA ---

- Inputs to Query –

Table 'Orders'

Table 'Customers'

Using index 'PriearyKey'

Having Indexes:

PrimaryKey 91 entries, 1 page, 91 values

which has 1 column, fixed, unique, primary-key, no-nulls

PostalCode 91 entries, 1 page, 87 values

which has 1 column, fixed

CompanyName 91 entries, 3 pages, 91 values

which has 1 column, fixed

City 91 entries, 1 page, 69 values

which has 1 column, fixed

- End inputs to Query -

01) Restrict rows of table Orders

by scanning

testing expression "Not Orders.ShipCountry="USA""

02) Inner Join result of '01)' to table 'Customers'

using index 'Customers!PrimaryKey'

join expression "Orders.CustomerID=Customers.CustomerID"

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


Оценка встроенных функций


Для оценки встроенных функций в окне Immediate необходимо ввести знак вопроса и имя встроенной функции, например, ? Now.


Ограничение доступа к коду


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


Окно Call Stack


Окно Call Stack (Вызов стека) отображает ранее вызванные процедуры. Чтобы открыть окно стека, необходимо в меню выбрать команду View Call Stack (Вид | Вызов стека) или нажать Ctrl+L). Более подробно окно вызова стека рассматривается далее в данной статье.


Окно Code


Окно Code (Код) отображает код для форм, модулей и модулей класса (рис. 3). Разработчики обычно проводят много часов, вводя и модифицируя код в окне Code. Чтобы открыть окно Code, необходимо в меню выбрать команду View | Code (Вид | Код) или нажать клавишу F7. В верхней части окна Code имеется два раскрывающихся списка. Список с левой стороны используется для выбора объекта, например, формы или элемента управления в форме. Список с правой стороны используется для выбора процедуры данного объекта.
Окно Code
РИСУНОК 3. Окно Code.


Окно Immediate


Окно Immediate (Отладка) можно использовать для оценки и установки переменных, запуска процедур и вывода для выражений Debug.Print. Чтобы открыть окно Immediate, необходимо в меню выбрать команду View | Immediate Window (Вид | Окно отладки) или нажать Ctrl+G. Подробнее окно отладки описано далее в данной статье.


Окно Locals


Окно Locals (Переменные) отображает выражения, значения и типы всех переменных текущей области действия. Чтобы открыть окно Locals, необходимо в меню выбрать команду View | Locals Window (Вид | Окно переменных). Более подробно окно переменных рассматривается далее в этой статье.


Окно Properties Window


Окно Properties (Свойства) используется для установки и просмотра свойств форм, отчетов или элементов управления в формах и отчетах (рис. 4). Чтобы открыть окно Properties, необходимо в меню выбрать пункты View | Properties Window (Вид | Окно свойств) или нажать клавишу F4.
Окно Properties Window
РИСУНОК 4. Окно Properties.


Окно Watch


Окно Watch (Наблюдение) используется для оценки выражений во время выполнения приложения. Чтобы открыть окно Watch, необходимо в меню выбрать пункты View | Watch Window (Вид | Окно наблюдения). Более подробно окно наблюдения рассматривается далее в этой статье.



Данное выражение запрещает обработку ошибок в процедуре. Кроме того, переустанавливается объект Err, при этом он имитирует вызов метода Clear объекта Err (Err.Clear). Метод Err.Clear рассмотрен ранее в данной главе.


On Error GoTo ErrorHandler


Bad Code
ExitHere:
Exit Sub
ErrorHandler:
MsgBox "An error occurred"
Resume ExitHere


On Error GoTo ErrorHandler


Данный оператор по соглашению записывается в начале процедуры после всех операторов Dim. Поскольку оператор находится в начале процедуры, код, который может стать причиной ошибки, выполняет его. Если ошибка возникает в коде, оператор GoTo осуществляет переход (передаст управление) на обработчик ошибок. Обработчик ошибок указывает метка ErrorHandler. ErrorHandler
не является зарезервированным словом, а только именем процедуры обработки ошибок (можно воспользоваться другим именем).


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


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


Операторы Resume


Описанные ниже операторы Resume позволяют осуществить в программе переход к другим выражениям кода при возникновении ошибки.


Определение значений переменных


При отладке приложения значение переменной можно определить, если задержать указатель мыши над соответствующей переменной, находясь в режиме прерывания (рис. 8).
Определение значений переменных
РИСУНОК 8. Определение значения переменной в режиме прерываний.
Для получения значения переменной можно также воспользоваться окном Immediate. Например, следующий текст, введенный в окне отладки, возвращает значение переменной с именем strName:
? strName


Оптимизация аппаратных средств и ОС Windows


Каждый модуль Access 2000 обладает множеством возможностей для настройки приложения, но нельзя рассчитывать на какой-либо успех в работе, если компьютер, на котором выполняется приложение, является устаревшим или если недостаточно оперативной памяти. Обычно дешевле приобрести современное аппаратное обеспечение, чем платить разработчикам за улучшение программы, достигая при этом одинаковой производительности приложений. Аппаратное обеспечение дешевле, чем программное, и обновление оборудования способствует повышению производительности всего совместимого программного обеспечения, которое установлено на данном компьютере.
Естественно предположить, что приложение Access (или любое подобное приложение) будет быстрее работать на более быстродействующем компьютере. Если имеется возможность обновить оборудование, ею следует воспользоваться. Компания Microsoft опубликовала минимальные требования для работы Access или Microsoft Office 2000. Однако разработчики быстро обнаруживают, что попытка запустить приложение Access 2000 на компьютере, удовлетворяющем этим минимальным требованиям, приводит к разочарованию. На самом деле минимальные требования для работы с приложениями должны быть такими:
• Процессор Pentium 133 МГц,
• 32 Мб ОЗУ (особенно под управлением Windows NT),
• Если выбирать между модернизацией процессора и установкой ОЗУ большего объема, следует выбрать ОЗУ. Учитывая мировое падение цен на микросхемы памяти, увеличение объема ОЗУ — самый дешевый способ повышения производительности PC. Необходимо помнить о том, что требования для компьютера разработчика значительно выше. У разработчика должен быть установлен, по крайней мере, процессор Pentium II 233 МГц и 32-64 Мб ОЗУ.
• Даже если объем оперативной памяти пользовательского компьютера достаточно велик, ее все равно может оказаться недостаточно. Access, как и любая другая серьезная база данных, для своей нормальной работы требует значительного объема памяти. Необходимо убедиться в том, что для работы данного приложения достаточно памяти.



• Для экономии оперативной памяти необходимо отказаться от использования любых хранителей экрана, обоев, фоновых картинок и всех других подобных "излишеств". Только необходимые приложения должны использовать ресурсы процессора при выполнении приложения. Чем больше оперативной памяти будет отведено под выполнение приложения, тем быстрее оно будет работать.

• Не следует использовать виртуальные диски, организованные в оперативной памяти. В современной 32-разрядной операционной системе для них нет места.

• Необходимо регулярно очищать корзину и удалять временные файлы (особенно файлы Internet и электронной почты!). Базы данных требует значительного объема дискового пространства, а эти файлы могут поглотить массу места еще до того, как пользователь успеет это осознать.

• Рекомендуется воспользоваться преимуществами утилит дефрагментации диска. В зависимости от используемой операционной системы дефрагментация может производиться автоматически. Компьютерные файлы не хранятся в одном месте. При создании, редактировании, сохранении и удалении файлов используются любые свободные кластеры на жестком диске. Файл .MDB не является исключением. Если жесткий диск сильно фрагментирован, даже простой поиск происходит значительно дольше, потому что компьютер вынужден просматривать весь диск в поисках необходимого результата.

• Следует избегать программного сжатия дисков (включая сжатие NTFS). Выполнение базы данных на сжатом диске приводит к значительному снижению производительности приложения.

• Можно приобрести дополнительный жесткий диск. В зависимости от того, какую задачу решает приложение, может понадобиться в 5-10 раз больше свободного пространства на диске, чем занимает файл .MDB. Недостаток свободного места снижает скорость выполнения больших запросов, длительных операций, компиляции, обслуживания, импорта и запросов действия. В последние годы цены на жесткие диски сильно упали.

• Рекомендуется отключить Journal (Журнал) в Outlook. Журнал Outlook генерирует запись при каждом запуске и выходе из приложения. Этот журнал может стать очень большим и поглощать дисковое пространство и процессорное время, необходимые приложению.


• Необходимо использовать освободившуюся оперативную память. Приложения очень хорошо поглощают оперативную память, но неохотно ее освобождают. Со временем многие приложения, включая Access, уменьшают действительный объем доступной оперативной памяти. Периодический выход из среды Access позволит Windows перераспределить освободившуюся память.

• Windows и Office следует устанавливать с локального местоположения. Рекомендуется не запускать их в

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

• Настройка файла подкачки (файла свопинга или виртуальной памяти) также может помочь повысить производительность приложения. Когда объем памяти для Access недостаточен, он занимает дисковое пространство файла подкачки и обращается с ним как с дополнительным ОЗУ. Если виртуальной памяти недостаточно, Access должен постоянно записывать и считывать информацию с диска, чтобы выполнять необходимые операции. Увеличение объема виртуальной памяти может привести к значительному повышению скорости выполнения приложения. Однако следует помнить, что чтение и запись на диск протекает в сотни раз медленнее, чем работа с ОЗУ. Увеличение объема файла подкачки поможет только в том случае, если диск дефрагментирован.


Оптимизация базы данных


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


Оптимизация форм


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


Оптимизация настройки механизма Jet Database Engine


Хорошо
настроенный компьютер и оптимизированная инсталляция базы данных не помогут повысить производительность, если не оптимизировано само приложение. Настоящее приложение базы данных состоит из нескольких частей. Самой важной из них является механизм баз данных Jet. Механизм Jet — это центр почти всего, что происходит в приложении баз данных Access, и его можно оптимизировать точно так же, как и другие функции Access. Попытки оптимизировать Jet должны быть предприняты после разработки большей части, если не всего, приложения; при этом необходимо затратить достаточное количество времени на оценку различных методик оптимизации.
Jet 4.0, который поставляется вместе с Access 2000, обладает несколькими преимуществами над своими предшественниками. Такие возможности, как новые типы данных, сжатие текста, индексация полей примечаний, внедрение ANSI SQL-92, управление SQL Security, большая гибкость в работе с внешними индексами, улучшенная схема репликации и улучшенные блокировки, обещают способствовать повышению производительности. Все эти прекрасные возможности подробно описываются в других статьях. В этой статье рассматривается только их влияние на производительность.
Механизм Jet выполняет основную оптимизацию без вмешательства разработчика или пользователя. Из всех сложных действий, которые выполняет Jet, можно увидеть только около 15, если заглянуть в системный реестр. Эти установки оказывают серьезное влияние на многие аспекты функционирования системы, поэтому обращаться с ними следует с осторожностью. Изменение установки может привести к результату, совершенно противоположному тому, который ожидался. Даже если приложение на первый взгляд работает быстрее, может оказаться, что нанесен серьезный ущерб стабильности и совместимости. Список установок Jet Registry приведен в табл. 1.
Таблица 1. Установки в системном реестре для Jet 4.0.

Ключ
Описание
Значение по умолчанию
Место нахождения ключа
Константа для метода SetOption
ExclusiveAsyncDelay
В эксклюзивной среде это – количество миллисекунд, в течение которых Jet должен ожидать перед выполнением неявной транзакции.
2000
\HKEY LOCAL MASH1NES
\SOFTWARE\MICROSOFT
\JET\4.0\ENGINES\JET 4.0
dbExclusiveAsyncDelay
FlushTransactionsTimeout
Когда здесь введено значение, задержки SharedAsyncDelay и ExclusiveAsyncDelay отключены. Это значение указывает число миллисекунд перед запуском асинхронных записей, если в кэш не были добавлены страницы.
500
\HKEY LOCAL MASH1NES\SOFTWARE
\MICROSOFT\JET
\SOFTWARE\MICROSOFT\JET
\4.0\ENGINES\JET 4.0
dbPlushTransactions
Timeout
ImplicitCornrnitSync
Определяет, должна ли ожидать система выполнения неявных транзакций перед продолжением процесса. Если ключ установлен в значение No, Jet выполняет неявные транзакции асинхронно.
No
\HKEY LOCAL MASH1NES
\SOFTWARE\MICROSOFT\JET
\4.0\ENGINES\JET 4.0
dblmplicitCommitSync
LockDetay
Число миллисекунд, в течение которых Jet ожидает, прежде чем повторить попытку блокировки.
100
\HKEYLOCALMASHINES
\SOFTWARE\MICROSOFT\JET
\4.0\ENGINES\JET 4.0
dbLockDelay
LockRetry
Количество повторных попыток для блокировки страницы.
20
\HKEY LOCAL MASH1NES
\SOFTWARE\MICROSOFT\JET
\4.0\ENGINES\JET 4.0
dbLockRetry
MaxBufferSize
Размер кэша Jet в килобайтах.
0
\HKEYLOCALMASHINES
\SOFTWARE\MICROSOFT\JEr
\4.0\ENGINES\JET 4.0
dbMaxBufferSize
MaxLocksPerRte
Максимальное количество блокировок, разрешенных для одной операции. Если для транзакции требуется больше блокировок, она разбивается на несколько транзакций, которые могут быть проведены отдельно и частично. Данную установку можно использовать для предотвращения проблем, которые могут возникнуть с проблем, которые могут возникнуть с Novell NetWare 3.1.
9500
\HKEYLOCALMASHINES
\SOFTWARE\MICROSOFT\JET
\4.0\ENGINES\JET 4.0
dbMaxLocksPerRle
<


Ключ

Описание

Значение по умолчанию

Место нахождения ключа

Константа для метода SetOption

Pages LockerfIoTableLock

(Новая возможность Access 2000)

Обеспечивает эксклюзивный доступ к таблице

для проведения обновлений, позволяя

программно управлять количеством блокировок

страницы, перед достижением которого Jet

попытается блокировать всю таблицу.

Значение 50 заставит Jet попытаться

блокировать таблицу на 51-й блокировке

страницы. Если блокировка таблицы не

удастся, Jet совершит новую попытку на 101-

и блокировке странице. При нулевом

значении данная функция отключается.

0

\HKEY.LOCALMASHINES

\SOFTWARE\MICROSOF7\

JET\4.0\ENGINES\JET 4.0

Отсутствует

PageTimeoirt

Количество времени (в миллисекундах), в

течение которого блокированная на

чтение страница удерживается в кэше

перед обновлением.

5000

\HKEYLOCAL MASHINES

\SOFTWARE\MICROSOFT\

JET\4.0\ENGINES\JET 4.0

dbPageTimeout

RecycteLVs

Определяет, будет ли Jet повторно

использовать OLE, примечания и

бинарные страницы.

0 (отключено)

\HKEY LOCAL MASHINES

\SOFTWARE\MICROSOFT

\JET\4.0\ENGINES\JET 4.0

dbRecycteLVs

SharedAsyncDelay

В общей среде это - количество миллисекунд,

в течение которых Jet должен ожидать перед

проведением неявной транзакции.

50

\HKEYLOCAL MASHINES

\SOFTWARE\MICROSOFT

\JET\4.0\ENGINES\JET 4.0

dbSharedAsyncDelay

Threads

Количество фоновых подлроцессов,

использующих Jet.

3

\HKEYLOCAL MASHINES

\SOFTWARE\MICROSOFT

\JET\4.0\ENGINES\JET 4.0

Отсутствует

UserCommitSync

Определяет, ожидает ли система завершения

операций записи перед продолжением процессов.

Если ключ установлен в значение No, механизм

Jet выполняет явные транзакции асинхронно.

Yes

\HKEY LOCAL MASHINES

\SOFTWARE\MICROSOFT

\JET\4.0\ENGINES\JET 4.0

dbllserCommitSync

CompactByPKey

Определяет порядок кодировки начальных

значений. При значении 1 Jet повторно

отсортирует записи по начальному значению.

При значении 0 записи остаются в том

порядке, в котором они были введены

(естественный порядок).

1

\HKEY LOCAL MASHINES

\SOFTWARE\MICROSOFT

\JE7\4.0\ENGINES

Отсутствует

System DB

Полный путь и имя файла рабочей группы.

nyn,Access

\system.md

\HKEY LOCAL MASHINES

\SOFTWARE\MICROSOFT

\JET\4.0\ENGINES

Отсутствует

PrevFormatCompact

WithUNICODECompression

(Новая возможность Access 2000) Разрешает

или предотвращает сжатие хранящихся

текстовых полей и полей примечаний. По

умолчанию сжатие разрешено.

1

\HKEY LOCAL MASHINES

\SOFTWARE\MICROSOFT

\JET\4.0\ENGINES

Отсутствует

JetShowPlan

По умолчанию не инсталлирован. При

создании разработчиком и установке в

значение On (зависит от регистра) Jet

создает в текущей папке текстовый файл с

именем showplan.out. При выполнении

запросов в этом файле регистрируются планы

выполнения. По окончании разработки ключ

необходимо отключить.

По умолчанию

не инсталлирован.

\HKEY LOCAL MASHINES

\SOnWARE\MICROSOFT

\JET\4.0\ENGINES\JET 4.0

Отсутствует


Организация циклов по элементам коллекции


Простейший и наиболее эффективный способ организации цикла по объектам в коллекции — использование цикла For Each. Кроме того, можно воспользоваться циклом For Next, но он выполняется медленнее.
Чтобы применить цикл For Each,
необходимо указать объект для рассмотрения в коллекции. Ниже приведен соответствующий код:
' Необходимо объявить объектную переменную.


Организация кода


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


Ошибки с точки зрения конечного пользователя


Как должна выглядеть обработка ошибок для конечного пользователя? Во-первых, необходимо привлечь внимание пользователя, чтобы он немедленно прекратил работу. Следует помнить, что ошибка может оказаться критической и стать причиной записи поврежденных данных в базу данных.
Путем вызова нескольких методов
сЕггог
можно отобразить Office Assistant, AVI-форму и воспроизвести звуковой файл для уведомления пользователя об ошибке (рис. 5). В коде главы приведена AVI-форма, сообщающая пользователю об ошибке (рис. 6). Если воспользоваться модулем класса
сЕггог,
соответствующий код должен быть таким:
CError.OfficeAssistant cError.AVIFonn сЕггог.Sound
Ошибки с точки зрения конечного пользователя
РИСУНОК 5 Использование Office Assistant для сообщения о возникшей ошибке.
Ошибки с точки зрения конечного пользователя
РИСУНОК 6. Использование А VI-формы для сообщения об ошибке.
Затем можно использовать объект сЕггог для отображения формы примечания об ошибке или окна ввода, которые позволяют пользователям описать свои действия во время возникновения ошибки (рис. 7). Вполне вероятно, что многие пользователи с удовольствием воспользуются возможностью помочь разработчику. Форма Error Note указывает, что ввод примечания необязателен.
Кроме того, можно отобразить окно сообщения с подробной информацией об ошибке (рис. 8).
Ошибки с точки зрения конечного пользователя
РИСУНОК 7. Форма позволяет пользователям ввести примечание.
Ошибки с точки зрения конечного пользователя
РИСУНОК 8. Окно сообщения с подробной информацией об ошибке.
Последний шаг — сообщить пользователю, что ошибка записана и можно продолжать работу (рис. 9). Эту задачу выполняет форма, автоматически закрывающаяся через три секунды.
Ошибки с точки зрения конечного пользователя
РИСУНОК 9. Сообщение пользователю о том, что можно продолжать работу.
Таким образом, при возникновении ошибки пользователи полностью осведомлены о том, что происходит — никто внезапно не прекращает их работу с приложением. Обработчик ошибок позволяет продолжить выполнение кода и работу с приложением. Пользователи немедленно получают сообщение об ошибке и имеют возможность внести свои замечания. Наконец, пользователи уведомлены о том, что ошибка передана разработчику и можно продолжать работу. Если ошибки обрабатываются именно таким образом, пользователи будут восхищены тщательностью разработки приложения.


Ошибки в различных приложениях


В настоящее время приложения Access включают другие приложения и компоненты. Соответственно возникающие ошибки могут иметь различное происхождение. Типовое приложение Access может сгенерировать ошибку, возникшую в самом Access или в VBA, DAO, ADO либо в другом приложении, использующемся в процессе автоматизации, например, Microsoft Word. Каждое приложение имеет собственные коды ошибок, которые можно возвратить обработчику ошибок.


Основы создания быстрых форм


Единственной серьезной проблемой, значительно влияющей на производительность при использовании форм, является количество и тип элементов управления. Каждый элемент управления поглощает память и ресурсы, одни — больше, другие — меньше. Образно говоря, связанный фрейм объекта "весит" примерно в 40 раз больше, чем линия. Элемент управления ActiveX может быть еще "увесистее" в зависимости от того, из чего он состоит и какие действия выполняет.
При выборе элементов управления для данной формы следует учитывать сведения, представленные в табл. 3. Необходимо помнить о том, что чем большей функциональностью обладает элемент управления, тем больше он поглощает ресурсов. В следующей таблице приведен список элементов управления, содержащихся в панели элементов конструктора форм. Подсчет имеющихся свойств каждого элемента управления и сравнение этого числа со сложностью задачи, решаемой каждым элементом управления, позволяет составить таблицу относительного "веса" элемента. Конечно же значения, приведенные в таблице, можно использовать лишь в качестве опорных. На самом деле использование ресурсов элементами форм зависит от их назначения.
Таблица 3. Относительный "вес" элементов форм.

Тип элемента управления

Относительный "вес"

Прямоугольник

1

Линия

1

Разрыв страницы

1

Вкладка (не включая собственные элементы управления)

4

Фрейм изображения (не включая само изображение)

6

Элемент управления вкладки

6

Подчиненная форма (как минимум)

6

Метка

8

Кнопка опции

8

Кнопка команды

8

Флажок

8

Группа опций (не включая собственные элементы управления)

8

Кнопка переключения

9

Текстовое поле

10

Список (как минимум)

10

Поле со списком (как минимум)

20

Элементы управления ActiveX

>= 20

Объектный фрейм (не включая само изображение)

30

Связанный объектный фрейм (не включая само изображение)

40

<


Некоторые элементы управления на несколько порядков "тяжелее", чем другие, поэтому для оптимизации полезно пользоваться подстановкой. Бывает много случаев, когда список может заменяться полем со списком или подчиненной формой. Изображения могут часто использовать элемент изображения вместо фрейма, а элемент вкладки может помочь разделить форму на быстро загружающиеся части, поскольку визуализируются только те элементы управления, которые находятся на текущей отображаемой странице. Учитывая, что в последнее время пользователи привыкли к гипертекстовым ссылкам в Internet, можно попробовать заменить командные кнопки гиперссылками. Если имеется возможность использовать элемент управления с меньшим "весом" без ущерба для функциональности, следует воспользоваться данной возможностью.

Ниже приводятся несколько советов, которые помогут повысить быстродействие элементов управления:

• Рекомендуется ограничивать количество полей, отображаемых в списках и свести к минимуму число полей со списками. Кроме того, необходимо индексировать поля поиска и отображаемые поля. Следует отключить опцию AutoExpand для полей со списками, установив ее в значение No. Если Access реагирует на каждый введенный символ, производительность значительно падает. Данную опцию следует использовать только тогда, когда избежать этого невозможно. Если необходимо использовать опцию AutoExpand,

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

• При необходимости скрыть поле, связанное с полем со списком, следует избегать использования выражений в этом поле или в отображаемых полях. Поле со списком не отображает результаты так быстро, как будто они были подсчитаны заранее и считаны из таблицы.

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



• При обновлении форм или любых элементов управления, которые отображают изменившиеся данные, рекомендуется применять метод Requery,

работающий гораздо быстрее, чем макрос Rcquery Action. Данный метод можно использовать после выполнения удалений, особенно в многопользовательском приложении.

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

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

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

• При создании кода для формы (CBF) используйте ключевое слово Me.

Эта константа всегда ссылается на активную форму и работает быстрее, чем другие ссылки.

• Рекомендуется индексировать поля Link Child и Link Master конструкции главная форма/подчиненная форма. Это позволит значительно ускорить выборку, которая часто производится данными формами.

• Если пользователь не собирается редактировать записи подчиненной формы, необходимо соответствующим образом установить свойства подчиненной формы. Свойства AllowEdits, AllowAppend и AllowDeletes



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

Yes,
чтобы избежать ненужного считывания записи.

• Следует строго относиться к установке свойств форм и элементов управления во время выполнения. Данные свойства следует устанавливать только при необходимости и только в том случае, если это не вредит производительности.

• В каждом конкретном случае рекомендуется проверять, что работает быстрее — динамическое множество или простой снимок.

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

acHidden:


DoCmd.OpenForm "имя_формы",,,,,acHidden

• Когда понадобится отобразить форму для пользователя, следует воспользоваться такой командой:

Forms("имя_формы").setfocus

• На тот случай, если пользователю снова понадобится форма, вместо того чтобы закрывать, ее сле-'дует скрыть. Метод Hide уберет форму с экрана, но при этом сохранит ее в памяти.

Formobject.Hide

• Избегая загрузки запросов, загрузки форм и этапов визуализации элементов управления, можно значительно повысить производительность интерфейса. Недостатки такого подхода заключаются в том, что скрытые формы требовательны к памяти и это может отрицательным образом сказаться на других модулях приложения. Хотя данную методику нельзя использовать для всех форм в приложении, ее рекомендуется применять для часто используемых форм.



Работая с очень большими наборами записей, не следует пытаться представить пользователю все записи за один раз. В любом случае большинство пользователей не знает, что делать с десятками тысяч записей, отображенными одновременно. Но если пользователи работают с многопользовательским приложением и форма открывает набор записей из больших таблиц или запросов, производительность падает по причине заторов в сети, ограничений кэша, блокировок записей и страниц и других перегрузок. Лучше всего отыскать логический способ, позволяющий разбить данные на логические подмножества с определенными ограничениями. Еще лучше отображать для пользователя только одну запись в определенный момент времени, запрашивая начальное значение записи или индекс поля. В небольших приложениях такой подход может привести к снижению производительности, но в больших многопользовательских системах это единственный выход. Для реализации такого решения необходимо переписать SQL-опсратор в коде, программно меняя свойство формы Record Source и многократно запрашивая форму.


Освобождение объекта


Закончив работу с объектной переменной, ее необходимо освободить, установив значение объекта равным Nothing. Таким образом можно высвободить ценные ресурсы. Соответствующий синтаксис приведен ниже:
' Освобождение объектной переменной.
Set objUser = Nothing


Освобождение объектной переменной


Поскольку коллекции — это объекты, не следует забывать об освобождении объектной переменной, устанавливая ее значение равным Nothing.
' Освобождение объектной переменной.
Set Users = Nothing


Отчетность


После рассмотрения процесса обработки ошибок с точки зрения пользователя необходимо ознакомиться с тем, что же дает обработчик ошибок разработчику. С помощью объекта сЕггог можно скомпилировать и проанализировать программные ошибки несколькими способами:
• Error handler Access report (Отчет Access об обработке ошибок). Отчет обработчика ошибок в базе данных Access содержит всю информацию из таблицы ошибок для всех ошибок (рис. 10).
• Email individual errors (Электронные сообщения об отдельных ошибках). Каждый раз при возникновении ошибки можно отправить подробную информацию об ошибке по электронной почте путем вызова метода Email (рис. 11).
Отчетность
РИСУНОК 10. Отчет Access обо всех ошибках
Отчетность
РИСУНОК 11. Отправка электронного сообщения об отдельной программной ошибке.
• Email all errors (Электронное сообщение обо всех ошибках). Можно отправить по электронной почте всю информацию об ошибках в таблице ошибок в качестве вложения в сообщение Outlook с помощью метода
EmailAllErrors.
Таблица ошибок сохраняется как таблица Excel и вкладывается в электронное сообщение.
• Save error information in an Access database (Сохранение информации об ошибках в базе данных Access). С помощью метода WriteErrorToTable
при каждом возникновении ошибки можно записать ошибку в таблицу ошибок в базе данных Access.
• 5ave error information in a text file (Сохранение информации об ошибках в текстовом файле). С помощью метода WriteErrorToTextFile можно записать все ошибки в выбранный текстовый файл для последующего анализа.
• Save error information or an Outlook calendar (Сохранение информации об ошибках в календаре Outlook). Все ошибки можно записать в календарь Outlook, так что данные могут быть отображены в различных встроенных представлениях Outlook либо в пользовательском представлении. Метод AddToErrorHandlerOutlookCalendar
упрощает отправку всей информации об ошибках в календарь обработчика ошибок (рис. 12).
Отчетность
РИСУНОК 12. Календарь обработчика ошибок Outlook.
Пользуясь одним или несколькими из указанных методов, можно получить немедленное уведомление о возникновении ошибки. Будет собрана вся необходимая для обнаружения и исправления ошибки информация, которую, кроме того, можно использовать при дальнейшем анализе.


Отключение панели задач



Отключение панели задач

Ранее в этой главе описывалось, как использовать ссылки панели задач для открытия или создания файлов. Панель задач отображается автоматически при запуске Access и содержит ссылки для открытия и создания не только базы данных, но и некоторых проектов Access. При необходимости отключить панель задач выполните такие действия.

1. Выберите команду Сервис >Параметры.


Отладка с помощью окон сообщений


Раньше при отладке часто использовались окна сообщений. Идея заключается в том, чтобы разместить в окне кода окна сообщений для более легкого способа обнаружения ошибки:
Sub Demo()
MsgBox 1
Select Case rst.States
MegBox 2
Case "Washington"
MsgBox 3
MsgBox "Washington"
MsgBox 4
Case "Oregon"
MsgBox 5
MsgBox "Oregon"
MsgBox 6
Case "California"
MsgBox 7
MsgBox "California"
MsgBox 8
End Select
MsgBox 9
End Sub
Наблюдая за тем, какое окно сообщений появляется перед сбоем, разработчик может определить строку кода, содержащую ошибку. Гораздо более удобный подход — установить точку прерывания и выполнять код в режиме прерываний. Установка точки прерывания более удобна, потому что:
• Установить прерывание гораздо быстрее, чем вводить массу окон сообщений.
• Окна сообщений модальны, поэтому нельзя переключиться в окно кода для просмотра.
• При выполнении кода в режиме прерываний можно наблюдать значения переменных, изменять их и т.д.
• После исправления ошибки не нужно удалять окна сообщений.
• Можно не беспокоиться о случайном распространении приложения с оставшимися окнами сообщений.


Отсчет с 0 или 1?


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


Панель инструментов База данных



Панель инструментов База данных

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


Переключение True и False


Установку флага в положение "истинно" (true) или "ложно" (false) не обязательно проверять с помощью условия If...Then...Else. Можно сохранить время и уменьшить объем кода, изменив значение на обратное с помощью оператора NOT. Установив булеву переменную в значение, которое не присвоено данной переменной, получим обратное значение. Ниже приводится соответствующий пример кода:
Вместо этого фрагмента:
If bFlag = False then
bFlag=True
Else
BFlag=False
EndIF
можно использовать строку:
bFlag=Not bFlag
Выполнение одной строки кода занимает намного меньше времени, чем выполнение нескольких строк с оценкой.


Перемещение в окне отладки


Для передвижения курсора используются мышь и клавиши со стрелками. С помощью клавиши Home можно передвинуть курсор к началу текущей строки кода, а с помощью клавиши End — к концу строки.
Клавиши Page Up и Page Down позволяют переместиться на страницу вверх и вниз соответственно. Для установки курсора в начало окна Immediate необходимо нажать клавиши Ctrl+Home. Для перехода в конец окна отладки используется комбинация клавиш Ctrl+End.


Переносимость кода


Поскольку модуль класса является автономной единицей кода, его с легкостью можно использовать в разных приложениях Access.


Подведем итоги...



Подведем итоги...

В этой главе мы познакомились с главным рабочим окном Access, панелью инструментов, строкой меню и панелью задач (в следующих главах приводится более подробное описание этих элементов). Кроме того, вы узнали:
  • как запустить Access;
  • как открыть и создать файл базы данных;
  • что такое элементы интерфейса главного рабочего окна Access.



Полезные функции обработки ошибок


Ниже приводятся полезные функции обработки ошибок:
• IsError
— используется для определения того, является ли Variant типом данных ошибки (возвращает булево значение).
• CVErr
— преобразовывает значение в тип данных ошибки, присваивая его переменной типа Variant.


Полезные советы


Поскольку значительную часть времени разработчик проводит в работе с окном Immediate, приведенные ниже советы могут оказаться полезными.


Получение дополнительной информации об ошибках


Обработчик ошибок должен автоматически записывать всю информацию об ошибках, которая необходима разработчику. Чем больше информации соберет обработчик ошибок, тем легче разработчику обнаружить и исправить ошибку.
Хотя объект Err предоставляет значительный объем информации, он не может охватить все, что нужно. Хороший обработчик ошибок должен предоставлять следующую дополнительную информацию об ошибке:
• Line number (Номер строки). Идентифицирует номер строки, в которой возникла ошибка. Следует учесть возможность использования определенного диапазона номеров строк в каждом модуле. Номера строк можно вставить в левой части модуля перед выражениями. С помощью опции глобального поиска, имеющейся в Access, можно быстро перейти к необходимой строке, в которой произошла ошибка, если номера строк не повторяются. В процедуре номера строк не обязательно должны следовать по порядку.


Построение конструкции Select Case


При использовании конструкции Select Case наиболее часто встречающиеся случаи следует разместить в верхней части структуры. Поскольку проверяется каждый случай по порядку, такая компоновка позволяет обеспечить максимально быстрый выход из структуры.


Повторное выполнение кода


После обнаружения и исправления ошибки в пошаговом режиме можно выполнить код повторно, не останавливаясь и не перезапуская приложение. Желтая стрелка на левой границе показывает, какой оператор кода будет выполнен следующим. Можно щелкнуть на желтой стрелке, перетащить се вверх к предыдущей строке кода и выполнить код повторно.


Повышение производительности запросов


Хотя пользователи могут никогда и не увидеть запрос в приложении, большую часть работы выполняют именно запросы. Реляционная база данных была бы бесполезной без возможности выполнять запросы к данным. Однако запросы создаются по-разному. Даже если разработчик принял все меры для нормализации данных и создал все необходимые индексы, можно иметь запросы, которые выполняются не так быстро, как могли бы. Может даже существовать два запроса, дающие идентичный результат, но выполняющиеся по-разному.
Чтобы понять, как оптимизировать запросы, необходимо понимать, как их обрабатывает Jet. Каждый запрос проходит четыре этапа:
1. Определение — создается SQL-оператор с помощью одного из нескольких инструментальных средств.
2. Компиляция — SQL-строка разбивается на составные части.
3. Оптимизация — используя алгоритм оценки стоимости. Jet формулирует и тестирует несколько различных способов получения результата, который удовлетворяет данному SQL-оператору.
4. Выполнение — используя план оптимизации, Jet передает результирующий набор пользователю.
Можно определить запрос с помощью QBE Grid, SQL-строки, выполняющейся в коде, SQL-строки в свойстве источника формы, отчета или элемента управления либо с помощью любого другого средства, которое способно создавать SQL-операторы.
Jet размещает составные части строки в иерархической внутренней структуре. Эти части весьма напоминают ключевые слова SQL-оператора. В основе лежат базовые таблицы, используемые запросом (Из). Потом устанавливаются столбцы результата (Выбор). Далее следуют условия отбора или ограничения, заданные запросом (Где). Затем оцениваются отношения базовых таблиц (Объединение). Наконец, происходит сортировка результирующего набора (Сортировка). Такая структура переходит в фазу оптимизации.
Оптимизация представляет собой самый сложный этап. Jet оценивает и рассчитывает стоимость каждого возможного подхода. Это делается путем рассмотрения запроса под двумя различными углами: с точки зрения доступа к базовым таблицам и с точки зрения исследований связей между ними. Понимание действий Jet может способствовать разработке более быстрых запросов в дальнейшем.



Для Jet существует три способа получения строк данных из таблиц:

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

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

• Срочная оптимизация (Rushmorc Optimizations). Этот способ доступен только в тех случаях, когда установлены ограничения более чем для одного индекса в запросе. Срочная оптимизация позволяет Jet считать намного меньше страниц данных, иногда вообще ни одной. При использовании способа срочной оптимизации Jet читает только индексные страницы, что весьма эффективно.

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

• Запросы должны содержать множественные индексы.

• Для данных индексированных полей должны быть заданы условные ограничения.

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

• Перекрытие индексов. Условие отбора с оператором AND. Jet может применить способ срочной оптимизации на данном наборе ограничений, поскольку индексированы оба поля.

WHERE CompanyName='Ernst Handle' And City='Graz'

• Объединение индексов. Условие отбора с оператором "OR". Jet может применить способ срочной оптимизации на данном наборе ограничений, поскольку индексированы оба поля.



WHERE CompanyName='Ernst Handle' Or City='Graz'

• Счетчики индексов. Составные запросы, возвращающие только счетчик записей. При срочной оптимизации обрабатывается каждый запрос, даже если не существует набора ограничений в условии Where.

SELECT Count(*) FROM Customers

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

После того как Jet определит способ доступа к данным в отдельных таблицах, он должен определить отношения таблиц между собой. Начинается этап объединения процесса оптимизации. Учитывая сведения о типах соединения, приведенные в табл. 2, можно определить вероятные стратегии соединения плана выполнения.

Таблица 2. Типы объединения: принцип работы и отличительные признаки.

Тип объединения

Принцип работы

Отличительные признаки

Возможное использование

Индексное слияние

Основную работу выполняют индексы.

С обеих сторон связи используются индексы. По крайней мере, один из индексов не допускает нулевых значений (начальное значение). Все таблицы должны соответствовать собственному формату Jet.

Везде, где возможно.

Индекс

Первая таблица сканируется, а затем строки второй таблицы выбираются по индексу.

Существует индекс для связанных полей второй таблицы. В данных индексах  разрешены нулевые значения. Ограничения не используют индексы.

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

Слияние

Обе таблицы сканируются

одновременно

Две таблицы сортируются по связанным полям. В результирующем наборе отображены данные из обеих таблиц.

Обе таблицы достаточно большие и сортируются по связанным полям.

Выборка

Вторая таблица сканируется и сортируется перед объединением.

Нет индексов для связанных полей таблицы.

Когда вторая таблица имеет небольшие размеры и для связанных полей второй таблицы не существует индексов.

Вложенная итерация

Построчная итерация по каждой таблице в отношении.

Ни с одной стороны объединения не существует индексов.

Только для очень малых таблиц и если нет другого выбора.

Jet выбирает один из этих планов в зависимости от таких факторов, как:

• Число записей в каждой базовой таблице,

• Число страниц данных, используемых базовыми таблицами,

• Местонахождение и тип таблицы — локальная ISAM или ODBC,

• Избирательность индексов таблиц — разрешены ли нулевые значения или повторения,

• Число страниц индекса.


Повышение скорости печати отчетов


Какой смысл в быстродействующей базе данных, если она целый день распечатывает отчет? Единственная большая и оказывающая влияние на производительность разница между формами и отчетами заключается в способе обработки разделов. В форме существует заголовок формы, область данных и примечание формы. В отчете имеются заголовок и примечание отчета, заголовок и примечание страницы, заголовки и примечания разделов, а также область данных. При открытии формы запрос, на котором она основана, выполняется только один раз. При открытии отчета он должен создать запрос (основываясь на запросе в источнике записей) для каждого раздела. Если запрос очень сложен, отчет должен выполнять его или ^некоторые его части несколько раз.
Ниже приводятся советы, следуя которым можно повысить скорость создания отчетов.
• Запрос, на котором основывается отчет, должен быть как можно более простым.
• Рекомендуется перенести вычисления в отчет. Если поместить вычисления в запрос, они будут выполняться для каждой строки. Однако, если поместить вычисления в отчет, они будут выполняться только при необходимости и пользователь сразу после расчета одной страницы данных Access увидит результат.
• Следует основывать запрос на возможно меньшем количестве таблиц. Поскольку отчет выполняет запрос больше чем один раз, может оказаться полезным создать таблицу необходимого результирующего набора. Отчет может обработать эту таблицу гораздо быстрее, чем снова выполнить запрос. Данный подход особенно полезен в том случае, если отчет основан на запросах с подчиненными запросами.
• Необходимо избегать использования подчиненных запросов в источнике отчета. Отчетам необходим большой объем памяти, а запрос с подчиненными запросами поглощает больше памяти, чем требуется в действительности.
• Следует проверить, необходим ли на самом деле подчиненный отчет. Подчиненные отчеты не только усложняют форматирование вывода, но и поглощают память, а также снижают производительность отчета. Тем не менее, подчиненные отчеты имеют широкое применение. Если существует несколько доменных функций, может оказаться, что подчиненный отчет выполняется быстрее, чем несколько вызовов данных функций.



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

• Рекомендуется индексировать все поля, использующиеся для сортировки или группировки. Поскольку индексы по умолчанию сортируют записи, отчет без особых сложностей может отсортировать и сгруппировать данные непосредственно из индексированных полей.

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

• Нет смысла в отображении для пользователей пустого отчета с записями #Еггог. Если отчет не содержит данных, следует отправить пользователю соответствующее сообщение и закрыть отчет. Определить, содержит ли отчет данные для отображения, можно с помощью свойств HasData или NoData.

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


Повышение скорости выполнения запросов


Оптимизация запросов в Jet — процесс довольно сложный, но это не значит, что в нем невозможно разобраться. Ниже приведены советы, которые помогут ускорить выполнение запросов:
• Рекомендуется создавать индексы для всех полей, которые будут использованы для определения критерия отбора.
Необходимо создавать индексы с обеих сторон связей в запросах.
• Вместо уникальных индексов лучше пользоваться начальными значениями. Поскольку начальные значения запрещают использование пулевых значений, запрос может использовать преимущества большего количества типов объединения.
• В результирующем наборе не следует отображать
какие-либо лишние столбцы. Обработка и отображение каждого столбца занимает дополнительное время.
• Рекомендуется воздерживаться от употребления сложных выражений в запросах.
• Следует избегать функции IIF() (немедленное IF). IIF() оценивает и истинное, и ложное значения перед тем, как выдать результат. Если выполнять данную операцию для каждой записи, это может сильно повлиять на производительность.
• При использовании вложенных запросов рекомендуется записывать все вычисления в последнем запросе серии.
• Вместо Count([Customer]) лучше применять Count(*),
поскольку при срочной оптимизации Count(*) обрабатывается быстрее — перед подсчетом не нужно проверять нулевые значения.
• По возможности следует пользоваться оператором Between для уменьшения количества строк в результирующем наборе вместо операторов "больше чем" и "меньше чем".
• Обычно размещение условия со стороны "один" отношения "один-ко-многим" — самый эффективный способ, но не всегда. Можно попробовать передвинуть ограничение к стороне "многие", чтобы проверить, не изменится ли производительность. После каждого изменения условий отбора необходимо тщательно проверять результирующий набор.
• Нормализованные таблицы могут хранить данные с использованием меньшего количества страниц данных и страниц индекса. Нормализация должна стать правилом, и нарушать ее можно лишь при отсутствии другой альтернативы.



• Рекомендуется по возможности поэкспериментировать с подчиненными запросами вместо исполь зования объединений или сложных условий OR. Оптимальный выбор зависит от многих дискретных факторов, и только эксперимент поможет решить, какой подход использовать.

• Внешние связи следует использовать только при крайней необходимости, поскольку они автоматически требуют проведения сканирования доминантной (сохраняемой) таблицы в объединении.

• Вместо SQL-операторов в коде рекомендуется использовать сохраненные запросы с параметрами. Jet уже скомпилировал запросы с параметрами и создал для них план выполнения (хотя эти планы недоступны в SHOWPLAN.OUT). Использование скомпилированных и сохраненных запросов устраняет необходимость оценки и оптимизации SQL-строки. Access компилирует SQL-строки, использующиеся в качестве источника записей или источника строк для форм, отчетов или элементов управления, поэтому они остаются нетронутыми.

• Рекомендуется всегда использовать скомпилированные запросы.

• Для манипуляций с данными вместо DAO по возможности следует пользоваться запросами. Для решения этих задач запросы (SQL) всегда выполняются быстрее, чем DAO.

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

• При открытии набора записей только для добавления данных следует использовать опцию dbAppendOnly.

При этом строки не считываются.

• При использовании данных клиент/сервер необходимо тестировать запросы к серверу. Кроме того, рекомендуется ознакомиться с новыми возможностями Access 2000, имеющими отношение к архитектуре клиент/сервер. Запросы к серверу не всегда выполняются быстрее, чем запросы к вложенным серверным таблицам, но сетевой трафик при их использовании меньше.

• Большие запросы действия могут выполняться лучше, если присвоить свойству UseTransaction значение False. При проведении транзакций Access создает временные файлы. Иногда эти таблицы становятся слишком большими и уменьшают скорость выполнения запросов.



• При запрашивании данных с сервера необходимо применять методы CacheStart, FillCache и EndCache для

обработки данных, поступающих с сервера.

• При работе с серверными данными следует избегать локальной обработки. Локальная обработка напоминает использование сложного выражения Group By с ключевым словом Distinct,

использование оператора LIKE в текстовых полях или полях заметок, множественных агрегирующих функций в перекрестном запросе или перекрестных запросов без условий ORDER.

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

• Необходимо регулярно сжимать базу данных и проверять статистические показатели, используемые механизмом Jet для оптимизации запросов.

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

• Рекомендуется индексировать поля для сортировки.

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

• Необходимо избегать использования доменных агрегирующих функций (DIookupO) для таблиц, которых нет в запросе.

Запросы представляют собой наиболее сложный аспект Access. К счастью, большую часть работы по оптимизации запросов выполняет механизм Jet. Информация, изложенная в данном разделе, поможет разработчику оказать механизму Jet содействие при оптимизации. Следует проверить результаты экспериментов в SHOWPLAN и с помощью подпрограмм PrintStats и QueryTimer,

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


Правильное использование закладок


Для возврата к предыдущей записи рекомендуется пользоваться закладками. Закладки представляют собой исключительно быстрый способ передвижения по записям в интерфейсе. Следует помнить, что существует два различных вида закладок: один — для форм, а другой — для наборов записей. Закладка формы представляет собой массив переменных, динамически присваиваемых каждой записи в базовой копии набора записей. Закладка DAO — это байтовый массив, идентифицирующий каждую запись в наборе записей. Закладки являются удобными средствами навигации, они разрушаются и воссоздаются вместе с наборами записей и копиями. Не следует на них полагаться, за исключением полностью контролируемых или простых ситуаций. Закладки не представляют собой записи и не имеют никакого отношения к начальному значению. Они представляют только временное положение записи в наборе строк. Любая манипуляция с данными должна проводиться с учетом методик разработки реляционной базы данных, а не с учетом текущего положения в наборе записей или копии. Поскольку разработчик должен всегда пользоваться методом повторного запроса после обновлений и удалений, он каждый раз разрушает и воссоздаст закладки. Если интерфейс использует закладки в таких обстоятельствах, необходимо тщательно отслеживать удаления и обновления.
Приведенный ниже код может использовать закладку формы для возврата к предыдущей записи после обновления:
Private Sub Findit_AfterUpdate()
Dim redone As Recordset
Dim recordID As Variant
Dim IDValue As Long
Set rsclone = Me.RecordsetClone
IDValue = Me![Findit]
recordID = "ID = " & IDValue
rsclone.FindFirst recorded
cm = rsclone.Bookmark
Me.Bookmark = bm
End Sub
Использование закладки для возврата к предыдущей записи позволяет ускорить выполнение на 1300% по сравнению с использованием FindFirst
для решения той же задачи.


ПРЕДОСТЕРЕЖЕНИЕ


Рекомендуется всегда объявлять операторы Dim и Set в отдельных строках. Не следует комбинировать данные операторы в одной строке, как, например, Dim objUser = New cUser. При этом код выполняется медленнее и момент и, образования объекта (записи в память) определить невозможно.


Преимущества использования объектов


Существует много преимуществ использования объектов, среди которых возможность создания сложного программного кода, использования IntelliSense, упрощенное создание и поддержка программного кода и т.д.


Преобразование формата базы данных



Преобразование формата базы данных

В Access 2003 по умолчанию используется формат файлов Access 2000, необходимый для обеспечения обратной совместимости с базами данных предыдущих версий. Для того чтобы изменить формат файлов открытой базы данных, выберите команду Сервис > Служебные программы>Преобразовать базу данных и укажите нужный формат в последнем подменю (рис. 2.10). Появится запрос на ввод нового имени для преобразованной базы, и когда вы это сделаете, щелкните на кнопке Сохранить. Учтите, что преобразование файла в формат более старой версии может стать причиной недоступности некоторых функций, не поддерживаемых этой версией Access.

Используемый по умолчанию формат файлов каждой новой базы данных также можно изменить. Для этого выберите команду Сервис >Параметры, щелкните на вкладке Другие и укажите в списке Формат файла по умолчанию (в правой части вкладки) формат Access 2002—2003, как показано на рис. 2.11 (для получения доступа к меню Сервис необходимо предварительно открыть какую-либо базу данных). Этот формат следует выбирать в том случае, если планируется совместное использование базы данных только с пользователями, применяющими Access версий 2002 и 2003 (но не версии 2000 или еще более ранней!). Изменение формата позволяет в полной мере задействовать все возможности Access 2003.


Преобразования в архитектуре клиент/сервер


При разработке приложения следует учитывать возможность преобразований в SQL-Server или Oracle. При этом можно применить запросы к серверу и использовать хранимые процедуры на сервере. Данный подход позволяет значительно повысить производительность.


Если приложение использует источник данных


Если приложение использует источник данных ODBC, установки в системном реестре следует искать в ключе д., t- \HKEY_LOCAL_MACHINES\SOFTWARE\MICROSOFT\JET\4.0\ENGINES\ODBC.

Применение объекта обработчика ошибок


Рассмотрим пример кода из статьи «Профессиональная обработка ошибок.». Модуль класса обеспечивает обширную обработку ошибок, включая:
• Регистрацию ошибок в таблице Access
• Регистрация ошибок в текстовом файле
• Обработку ошибок электронной почты
• Обработку ошибок записей в календаре Outlook
Рассмотрим объект сЕггог в браузере объектов, как показано на рис. 13.
Применение объекта обработчика ошибок
РИСУНОК 13. Объект сЕггог и браузере объектов


Присваивание объектной переменной объекту


Для установки ссылки объектной переменной на объект используется ключевое слово Set. Например:
Set objUser = New cUser


Private Declare Function sndPlaySound Lib "winmm.dll" Alias _


"sndPlaySoundA" (ByVal IpszSoundName As String, ByVal uFlags As Long) As Long
Public Sub PIaySound(SoundFile As String)
' Воспроизведение звукового файла.
sndPlaySound SoundFile, 1
End Sub
Следующий код инициализирует и обрабатывает объект objSound (рис. 11):
Dim objSound As cSound
Set objSound = New Sound
' При использовании Windows NT необходимо указывать путь "C:\WINMT".
objSound.PIaySound "C:\Windows\chimes.wav"
Set objSound = Nothing
Private Declare Function sndPlaySound Lib

РИСУНОК 11. Пример объекта Sound.


Процедура Property Get


Процедура Property Get
позволяет получить значение свойства. Если не нужно, чтобы другие пользователи могли получить значение свойства, не следует включать оператор Property Get.
Оператор Property Get получает значение, хранящееся в приватной переменной, и возвращает его в качестве значения свойства. Приведенный ниже пример представляет собой оператор Property Get для свойства Name объекта cUser:
Public Property Get Name () as String
' Получение значения, записанного в приватной переменной (mstrName),
' и запись его в значение свойства.
Name = mstrName
End Property
Пользователь легко может получить значение свойства (если существует выражение Property Get), воспользовавшись следующим кодом:
MsgBox cUser.Name


Процедура Property Let


Процедура Property Let
используется для установки значения свойства. Если не нужно, чтобы другие пользователи устанавливали значение свойства, не следует включать процедуру Property Let. Ниже приведен пример создания процедуры Property Let для свойства Name объекта cUser:
Public Property Let Name (UserName as String)
' Принимается значение, передаваемое в UserName, и сохраняется
' в приватной переменной (mstxName).
mstrName = UserName
End Property
Рассмотрим данную процедуру подробнее. Во-первых, поскольку существует процедура Property Let, можно устанавливать свойство Name, так как данное свойство отображается вне модуля. Разработчик мог бы присвоить этому свойству следующее значение:
cUser.Name = "James"
Значение
James,
передаваемое в процедуру свойства, сохраняется в переменной UserName.
Процедура Property Let принимает значение переменной UserName (James) и записывает его в приватной переменной модуля mstrName. Рассматриваемая процедура передает один параметр, хотя на самом деле процедуры свойств могут передавать много параметров. Значение свойства может быть получено только в том случае, когда существует процедура Property Get.


Процедура Property Set


Процедура Property Set позволяет создать процедуру свойства, в ходе которой устанавливается ссылка на объект. При присваивании объекта в процедуре Property Set используется ключевое слово Set.
В данном примере используется объект cForm. Объект cForm
содержит свойство Form, которое должно быть передано как объект Form. Код в модуле класса cForm приведен ниже:
Option Compare Database
' Объявление приватной переменной на уровне модуля.
Private mobjForm As Form
Public Property Get Form() As Variant
' Получение объекта, скрытого в приватной переменной (mobjForm) ,
' и запись его в значение свойства.
Set Form = mobjForm
End Property
Public Property Set Form(FormObject)
' Получение переданного объекта (FonnObject)
' и запись его в приватную переменную (mobjForm).
Set mobjForm = FormObject
End Property
При загрузке frmPropertySet форма передается в свойство Form. Поскольку это объект, используется ключевое слово Set. Затем можно получить имя объекта формы для окна сообщений. Ниже приведен код для формы frmPropertySet:
' В данном примере используется объект "cForm" . Об"ьект "cForm"
' содержит свойство "Form". При загрузке этой формы (frmPropertySet) она
' передается как объект в свойство "Form". При щелчке на кнопке
' "Property Set" считывается имя формы.
Private mobjForm As cForm Private Sub cmdClose_Click()
DoCmd.Close acForm, "frmPropertySet", acSaveNo
End Sub
Private Sub cmdPropertySet_Cliclt()
MsgBox "The form object (in the 'Form' property) has a name of: " _
mobjForm.Form.Name, vblnfonnation, "Property Set Example"
End Sub
Private Sub Form_Load()
Set mobjForm = New cForm
Set mobjForm.Form = Forms!frmPropertySet End Sub
Private Sub Form_Unload(Cancel As Integer)
Set mobjForm = Nothing
End Sub


Процедуры события ошибки


Формы и отчеты Access содержат процедуру события ОпЕггог, которая полезна для отображения собственных сообщений об ошибках при возникновении ошибки Access. Процедура события ОпЕггог
использует два аргумента:
• DataErr — номер ошибки, возвращаемый объектом Err. Используя данный аргумент, можно обработать соответствующий тип ошибки. Если, например,
DataErr
равен 11, значит, произошло деление на нуль.
• Response — определяет, отображено ли сообщение об ошибке. Используя данный аргумент, можно контролировать отчетность. Чтобы проигнорировать ошибку и отобразить собственное сообщение об ошибке, необходимо воспользоваться константой acDataErrContinue.
Для отображения сообщения об ошибке, принятого в Access по умолчанию, можно воспользоваться константой acDataErrDisplay.
Ниже приводится типичный пример соответствующего кода:
private Sub FormError(DataErr As Integer, Response As Integer)
Dim strMessage As String
If DataErr = 11 Then
Response = acDataErrContinue
strttoisage = "Check the value, you have divided a number by zero."
MsgBox strMessage
End If
End Sub


Продолжение выполнения кода


После тестирования кода в пошаговом режиме можно продолжить выполнение кода с нормальной скоростью. Для этого в меню необходимо выбрать команду Run | Continue (Выполнить | Продолжить) или нажать клавишу F5.


Project Explorer


Project Explorer (Проводник проектов) отображает список форм, отчетов и модулей класса в данном приложении Access (рис. 2). Для просмотра кода необходимо щелкнуть правой кнопкой мыши на каком-либо из этих объектов или перейти в режим конструктора формы. Чтобы открыть Project Explorer, необходимо в меню выбрать команду View | Project Explorer (Вид | Проводник проектов) или использовать комбинацию клавиш Ctrl+R.
Project Explorer
РИСУНОК 2. Окно Project Explorer.


Просмотр объекта cError в браузере объектов


Объект cError,
приведенный в коде данной главы, содержит много свойств и методов. Для быстрого просмотра свойств и методов объекта необходимо открыть браузер объектов и выбрать модуль класса cError (рис. 4).
Просмотр объекта cError в браузере объектов
РИСУНОК 4. Объект cError в браузере объектов.
Обработка ошибки
При возникновении программной ошибки обработчик ошибок в процедуре передает информацию в Объект
сЕггог.
Метод ProssesError
определяет, как обрабатывается ошибка. Данный метод отсылает к таблице tbIErrorOptions (которая рассматривается далее в данной главе) за дополнительной информаци-ей, например, о том, вводили ли пользователи примечания об ошибке и было ли отослано электронное сообшение с информацией об ошибке. Ниже приводится код метода ProssesError:
Public Sub ProcessErrorO
Dim rst As ADODB. Recordset
Dim strSQL As String
Dim strVal As String
strSQL = "SELECT * FROM tbIErrorOptions"
' Создание набора записей ADO.
Set rst = New ADODB.Recordset
' Открытия набора записей ADO.
rst.Open strSQL, CurrentProject.Connection, adOpenKeyset, _
adLockOptimistic
Me.ErrorTextFile = rst!ErrorTextFileName
Me.UserEnterNoteFlag = rst!UserEnterNoteAboutError
Me.AVIFileLocation = CurrentProject.Path & rst!AVIFileLocation
Me.SoundFile = CurrentProject.Path & rst!SoundFile
Me.OfficeID = rst!OfficeID
Me.OfficeName = rst!OfficeName
Me.OfficePhoneNuitiber =
rst!OfficePhoneNumber

Me.OfficeFaxNumber = rst!OfficeFaxNumber
If rat!PlaySound Then
' Воспроизведение звука при возникновении ошибки.
CError.PlaySound
End If


Просмотр объектов в браузере объектов


Упаковка кода в классы позволяет разработчикам использовать Object Browser (Браузер объектов) для просмотра свойств, методов и другой информации. Далее в данной статье будет представлен пользовательский объект, просматриваемый с помощью браузера объектов.


Просмотр в окне Call Stack


Приложение может включать процедуры, которые вызывают другие процедуры, а те, в свою очередь, вызывают третьи процедуры и т.д. При отладке приложения можно попасть в безвыходную ситуацию или запутаться в списке выполненных процедур. В таких случаях можно воспользоваться окном Call Stack (Вызов стека).
Окно вызова стека можно представлять себе следующим образом. При выполнении кода точка наблюдения передвигается в будущее. Call Stack представляет собой окно истории. Оно показывает, какие процедуры уже были выполнены (рис. 12). Чтобы открыть окно Call Stack, необходимо в меню выбрать команду View | Call Stack (Вид | Вызов стека) или использовать комбинацию клавиш Ctrl+L.
Просмотр в окне Call Stack
РИСУНОК 12. Окно Call Stack используется для отображения списка выполненных процедур


Простой обработчик ошибок


Перед рассмотрением сложного обработчика ошибок приведем простой пример:
Sub Demo ( )
Dim I as Integer
On Error GoTo ErrorHandler
' Программная ошибка в этой строке кода. ExitHere:
Exit Sub ErrorHandler:
MsgBox "An error occurred"
Resume ExitHere
End Sub
Данный простой обработчик ошибок следует обычным программным соглашениям, которые описаны далее.


Проверка эффективности транзакций


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


Работа с модулями


Перед выполнением модулей VBA должен скомпилировать их. Это не значит, что модули не будут работать, если их специально не скомпилировать, просто перед выполнением модуля VBA будет вынужден временно скомпилировать его. Кроме того, модуль будет компилироваться каждый раз, когда его необходимо выполнить. Это может сильно сказаться на производительности.
При компиляции модуля VBA преобразовывает его в гораздо более меньший по размеру, быстрее выполняющийся блок. Хотя исходный код всегда хранится в файле .MDB, Access загружает и выполняет только скомпилированный код VBA. Код VBA, кроме того, не содержит пробелов, комментариев, заголовков и занимает гораздо меньший объем памяти, чем созданный разработчиком исходный код. При попытке выполнить нескомпилированную процедуру VBA должен загрузить весь исходный код (с пробелами, комментариями и невыполняемым кодом) в память и скомпилировать перед выполнением. То же самое происходит при выполнении кода форм и отчетов.


Работа с объектом Debug


Объект
Debug
содержит два метода, которые могут оказаться полезными при отладке приложений:
Debug.Print и Debug.Assert.


Работа в среде разработки Visual Basic (IDE)


Среда разработки в Access 2000 претерпела радикальные изменения. В настоящее время в Access включена Integrated Development Environment (IDE) (интегрированная среда разработки) Visual Basic, имеющиеся также в Visual Basic 5/6, Word 97 и других программных продуктах Office 97/2000. Эта среда редактирования включает стандартные средства разработки приложений для различных программных продуктов. Методики отладки, описанные в данной статье, с одинаковым успехом могут использоваться как в разработках Access, так и в разработках Visual Basic и Microsoft Office. Чтобы открыть IDE, находясь в режиме конструктора, необходимо в меню выбрать команду View | Code (Вид | Код). Среда IDE включает различные окна, которые можно открывать и закрывать, например, окно Project (Проект), окно Properties (Свойства), окно Immediate (Отладка) и др. Чтобы открыть окно в IDE, необходимо выбрать данное окно в меню View. Закрыть окно можно, щелкнув на кнопке закрытия окна в верхнем правом углу окна. При следующем запуске IDE все окна будут отображены в том же состоянии, в котором они находились в момент выхода из среды IDE. Когда в окне Design (Конструктор) открыта форма, можно работать с элементами управления и свойствами, как и в предыдущих версиях Access. Однако для просмотра кода формы необходимо открыть IDE Visual Basic (рис. 1). На самом деле это совершенно отдельное от Access приложение.
Работа в среде разработки Visual Basic (IDE)
РИСУНОК 1. Интегрированная среда разработки (IDE) Visual Basic.
Хотя IDE Visual Basic является отдельным приложением, оно работает вместе с Access. Если IDE Visual Basic открыта, при выходе из Access она закрывается. Чтобы закрыть IDE Visual Basic, необходимо в меню выбрать пункты File | Close | Return to Microsoft Access (Файл | Закрыть | Вернуться в Microsoft Access).
Рассмотрим окна IDE Visual Basic.


Раннее создание отношений для повышения производительности


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


Разрушение объектных переменных


Разрушение объектных переменных позволяет уменьшить вероятность ошибок ресурсов. Если существует объектная переменная с именем objWord, необходимо разрушить ее в конце процедуры с помощью выражения Set objWord = Nothing.


Реагирование на возникновение ошибок


Значительную часть кода в процедуре обработки ошибок должен занимать оператор Select Case.
Следует попытаться учесть все возможные ошибки, которые могут произойти, и создать список номеров ошибок в выражении Select Case обработчика ошибок. Затем можно создать код обработки для каждой ошибки.
Ожидаемая ошибка может быть обработана различными способами:
• Окно сообщения может предупредить пользователя об ошибке.
• Окно сообщения может предоставить пользователю информацию, необходимую для исправления ошибки (например. There is no disk in the disk drive (В этом дисководе нет диска)).
• Ошибку можно проигнорировать и продолжить выполнение кода.
• Ошибку можно проигнорировать и выйти из процедуры.
• Можно принять меры по исправлению ошибки в коде для продолжения успешного выполнения кода.
• Можно осуществить переход в другое место кода. Приведенный ниже код иллюстрирует вышесказанное:
ErrorHandler:
Select Case Err.Number
Case 11
If MsgBox("You divided a number by zero, enter a " & _
" different number. Do you want to try again? ", _
vbQuestion + vbYesNo) = vbYes Then
Resume
Else
Resume ExitHere
End If
Case Else
MsgBox "An unexpected occurred. Error Number: " & _
Err.Number & " Error Description: " & Err.Description
Resume ExitHere
End Select
End Sub
Можно даже создать общую процедуру обработки ошибок определенного типа. Например, если просмотреть таблицу ошибок Access и Jet в файле Access and Jet Database Errors, mdb, можно заметить, что ошибки с номерами 58-76 относятся к файловым ошибкам. Сюда входят File already exists. Disk Full, Too many files и другое. Можно создать общую процедуру, работающую с данной группой ошибок, и вызывать эту процедуру из выражения Case Select обработчика ошибок:
ErrorHandler:
Select Case Err.Number
Case 58 To 76
' Общая процедура, обрабатывающая файловые ошибки.
Call FileTypeErrors
Case Else
MsgBox "An unexpected occurred. Error Number: " & _
Err.Number & " Error Description: " & Err.Description
Resume ExitHer
End Select
End Sub


Resume ExitHere


Данное выражение позволяет передать управление коду ExitHere.


Resume Next


Данное выражение передает управление в строку кода, следующую за той строкой, где произошел сбой. Таким образом, можно выполнить оставшийся код процедуры.
Приведенная на рис. 3 диаграмма иллюстрирует ход выполнения программы в случае использования разных операторов Resume:
Resume Next
РИСУНОК 3. Обработка ошибок с помощью оператора Resume.


Resume


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


В данной главе описаны методики


В данной главе описаны методики оптимизации приложения. Время реакции хорошо работающего приложения обычно составляет менее одной секунды для большинства операций получения данных. Методики, изложенные в данной главе, помогут разработчику придерживаться такого стандарта.
Простейший способ обеспечения быстрой работы приложения заключается в модернизации компьютера, на котором оно выполняется. Кроме того, можно изменить установки в системном реестре, чтобы они соответствовали требованиям выполняющегося процесса. В этой главе подробно описано составление таблиц и запросов, обеспечивающее приложению основу для достижения высокой производительности. Рассмотрены подходы к дизайну интерфейса, помогающие создать надлежащий вид приложения и позволяющие уведомить пользователей о ходе процесса. Наконец, изложены способы кодирования, обеспечивающие использование каждой миллисекунды для повышения быстродействия приложения.
Начав с аппаратного обеспечения, пробуя различные описанные подходы и проверяя их в той или иной ситуации, разработчик сможет добиться самой высокой производительности приложения. Совокупное применение приведенных методик может иметь поразительный эффект в каждом конкретном случае.
Access. Программирование на VBA. Часть 2.
Отладка приложений Access.

Access 2000 содержит мощные средства


Access 2000 содержит мощные средства отладки. Изучение работы данных средств является обязательным для любого разработчика Access. В данной статье приведены советы и подсказки по использованию интегрированной среды разработки (IDE), окна отладки, окна переменных и окна наблюдения. Рассматриваются отладчик и различные методики отладки. Кроме того, рассмотрена условная компиляция и приведены советы по написанию надежного кода. Использование информации и методик, изложенных в данной статье, упрощает и ускоряет процесс создания приложения и работу с ними.
Access. Программирование на VBA. Часть 3.
Профессиональная обработка ошибок.

Обработка ошибок имеет решающее значение.


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

Создание объектов представляет собой эффективный


Создание объектов представляет собой эффективный способ написания и работы с приложениями. Это значительно улучшает организацию кода, упрощает его написание и использование, в том числе с помощью технологии IntelliSense, а также делает код переносимым. Кроме того, можно скрыть сложную "начинку" от разработчиков, использующих объект. Разработчики могут создавать многочисленные экземпляры данного объекта.
Access. Программирование на VBA. Часть 4.
Оптимизация приложений.

Set Next Statement


При пошаговом выполнении кода можно установить следующий оператор, который необходимо выполнить. Для этого нужно щелкнуть правой кнопкой мыши на той строке кода, которую необходимо выполнить следующей. Затем в контекстном меню следует выбрать пункт Set Next Statement (Установить следующий оператор).


Сохранение стекового пространства с помощью строковых переменных


Строковая переменная — один из наиболее часто употребляемых в коде типов данных. Их можно разделить на три вида:
• Локальные фиксированной длины (не более 64 символов) — эти переменные используют два байта на символ и не используют область динамической памяти.
• Локальные фиксированной длины (более 65 символов) — эти строки также используют два байта на символ, но в динамической памяти. Кроме того, им нужны четыре байта в стеке для указания на переменную в динамической структуре.
• Локальные переменной длины (длина не имеет значения) — объем динамической памяти зависит от длины строки. Для указания на переменную в динамической структуре используется четыре байта стека.
При работе со строками необходимо стремиться к уменьшению объема используемого стека. Можно попытаться изменить строки на локальные строки переменной длины или на статические строки фиксированной длины. Ниже приведен пример строки переменной длины, объявленной как статическая строка фиксированной длины для сохранения стековой памяти.
Dim strString as string
Static strString as string * 30


Сокрытие сложного программного кода


Возможность сокрытия сложного программного кода является одним из преимуществ использования объектов. Опытный разработчик может создавать сложные программы, такие как процедуры Windows API, процедуры доступа к данным, обработки строк и т.д. Менее опытные разработчики могут воспользоваться преимуществами объекта, используя вызов его свойств и методов. При этом нет необходимости разбираться в рабочем коде объекта.


Составление файла .MDE


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


Составление таблиц данных


Кроме обычных правил оптимизации, при построении таблиц необходимо помнить о следующем:
• При работе со связанными таблицами следует создавать постоянные связи.
• Использование простых подтаблиц в таблицах, где подтаблица является другой таблицей, а связи главный/подчиненный используют индексированные поля, оказывает ничтожно малое отрицательное влияние на производительность; однако более сложная подтаблица может значительно уменьшить скорость выполнения приложения. Вместо таблиц в запросах следует использовать подтаблицы. В данном случае они используются только при необходимости, а не каждый раз при открытии таблицы.
• Шаблоны ввода, поиска и правила верификации также должны использоваться только там, где они действительно необходимы, — в формах. Лучше всего создавать как можно более простые и легкие таблицы.
• Не рекомендуется создавать поля данных, размер которых будет больше, чем необходимо. Access предоставляет место для данных по размеру поля этих данных. Можно впустую потратить массу свободного места (и времени), используя типы данных или установки свойств, слишком большие для данных, содержащихся в этих полях.


Полезно присваивать коллекции имя, представляющее


Полезно присваивать коллекции имя, представляющее собой множественное число от имен объектов, содержащихся в данной коллекции. В данном примере в коллекцию добавляется объект User. Таким образом, коллекции следу-вд. ет присвоить имя Users.

Настоятельно рекомендуется указывать ключевое значение.


Настоятельно рекомендуется указывать ключевое значение. Ключевые значения упрощают написание кода и более ,j надежны, чем номера индекса. Номера индекса могут измениться при удалении элементов из коллекции или при '3 вставке в указанные места коллекции с помощью параметров метода Add.
В приведенном ниже примере в коллекцию Users будут добавлены два пользователя:
Dim User1 as cUser
Dim User2 as cUser
Dim Users as Collection
Set User1 = New cUser
Set User2 = New cUser
Set Users = New Collection
User1.Name = "James"
User2.Name = "Steve"
Users.Add User1, User1.Name
Users.Add User2, User2.Name
Set User1 = Nothing
Set User2 = Nothing
Set Users = Nothing
Данный код добавляет в коллекцию объект
User1. С помощью свойства Name
объекта указано ключевое значение. Точно так же добавляется объект User2.
Обратите внимание, что метод Add
коллекции содержит аргументы "до" и "после" для
определения порядка объектов в коллекции.

В приведенном примере проверяется каждый


В приведенном примере проверяется каждый пользователь в коллекции. Обратите внимание, что отдельным пользователям соответствуют отдельные объектные переменные Useri и User2. Чтобы воспользоваться циклом For Each, необходимо указать общую объектную переменную под именем User. Данную объектную переменную не обязательно присваивать с помощью ключевого слова Set. Ее единственное назначение — использование в цикле For Each.

Следует убедиться, что файл подкачки


Следует убедиться, что файл подкачки не размещен на сжатом диске или в разделе. Работа со сжатым диском замедляет чтение и запись временных файлов.
Может оказаться, что многие из приведенных советов осуществить невозможно, но при разработке приложения Access их обязательно следует учитывать и соответственно предлагать для реализации. Другими возможностями оптимизации разработчик Access может воспользоваться во всей полноте.

У многих разработчиков приложений компьютеры


У многих разработчиков приложений компьютеры намного более быстродействующие, чем компьютеры, на которых будет выполняться приложение. Необходимо протестировать приложение на компьютере, сравнимом с компьютерами пользователей. Если аппаратное обеспечение отличается от компьютера к компьютеру, приложение следует разрабатывать, рассчитывая на самый низкоскоростной компьютер.

МDЕ необходимо убедиться, что пользователи


Перед инсталляцией . МDЕ необходимо убедиться, что пользователи осведомлены о невозможности внесения ими изменений в приложение. Учитывая все возрастающую популярность Access, в последнее время многие пользователи настаивают на возможности дальнейшей модификации приложения. Кроме того, необходимо тщательно протестировать приложения, поскольку МDЕ выдают сложные для понимания сообщения об ошибках.

Для определения размера текстовых полей


Для определения размера текстовых полей фиксированной ширины можно пользоваться размерами полей таблиц.

в IDE можно отобразить достаточно


Как рассматривалось ранее, в IDE можно отобразить достаточно большое количество окон. В IDE гораздо удобнее работать, если установить разрешение экрана 1024х768 или выше. Еще лучше воспользоваться функцией поддержки нескольких мониторов Windows 98/Windows 2000.
Для ускорения работы с окнами необходимо изучить клавиши быстрого доступа, используемые для открытия и закрытия окон. Размеры и положение окон можно изменять по необходимости. Иногда бывает сложно изменить размеры или восстановить положение окна, если неаккуратно передвигать его. В таких случаях можно выполнить двойной щелчок мыши на строке заголовка, чтобы восстановить окно.

При тестировании выражений или выполнении


Для вывода информации в окне Immediate необходимо в коде использовать метод Debug.Print. При тестировании выражений или выполнении функций в окне Immediate не обязательно вводить Debug.Print. Вместо этого достаточно ввести знак вопроса ?,
что приводит к тому же результату.
В окне Immediate можно протестировать встроенные функции, значения в наборе записей и др. (рис. 6). Например, на рис. 6 показаны результаты тестирования встроенной функции Len.
Если использовать метод
Debug.Print в коде, значения и другая информация будут выводиться в окне Immediate. При выполнении следующего кода значение состояния будет выведено в окне Immediate
Sub Demo ( )
Debug.Print rat.States
Select Case rst.States
Case "Washington”
MsgBox "Washington"
Case "Oregon”
MsgBox "Oregon"
Case "California"
MsgBox "California
End Select
End Sub
При тестировании выражений или выполнении
РИСУНОК 6. Использование метода Debug.Print для тестирования встроенных функций.
В окне Immediate не производится перенос текста на следующую строку, поэтому объем выводимой информации по возможности следует сократить. Удалять операции Debug.Print из кода нет необходимости, поскольку пользователь никогда не увидит окно Immediate. Однако, если количество операторов окажется слишком большим, это может несколько повлиять на производительность.

в коде зарезервированное слово Stop.


Никогда не используйте в коде зарезервированное слово Stop. Следует учитывать, что, если оставить это ключевое слово, выполнение кода остановится при запуске приложения пользователем. Рекомендуется всегда использовать Debug.Assert False, поскольку данный оператор всегда удаляется компилятором.

Присваивать имя модулю класса следует


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

При запуске подпрограммы или функции


При запуске подпрограммы или функции в окне Immediate необходимо ввести имя подпрограммы или функции (знак вопроса перед именем подпрограммы не используется). Если подпрограмма или функция находится в модуле формы, перед именем процедуры следует ввести имя формы (например, frmTest. MySubProcedure).

Некоторые разработчики предпочитают пользоваться панелью


Некоторые разработчики предпочитают пользоваться панелью инструментов Debug. Чтобы открыть панель инструментов, необходимо в меню выбрать команду View | Toolbars | Debug (Вид | Панели инструментов | Отладка).       Л

Окно Locals можно использовать для


Окно Locals можно использовать для изменения значения переменных. Для этого необходимо дважды щелкнуть на значении переменной и ввести новое значение.

к определенной процедуре можно выбрать


Для перехода к определенной процедуре можно выбрать ее в окне Call Stack и щелкнуть на кнопке Show (Показать) (или просто дважды щелкнуть на процедуре).

Кроме того, группировка объявляемых переменных


Кроме того, группировка объявляемых переменных по типу данных также упрощает обращение к переменным.

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


Для комментирования блока кода и удаления комментария используйте команды Comment Block (Комментировать блок) и Uncomment Block (Раскомментировать блок) из панели инструментов Edit (Справка) в IDE.

в диалоговом окне Options во


В редакторе Visual Basic в диалоговом окне Options во вкладке Editor можно выключить опцию Auto Syntax Check (Автоматическая проверка синтаксиса). Синтаксическая проверка при этом не отключается, но исчезнет раздражающее диалоговое окно, которое всплывает при каждой синтаксической ошибке. Ошибка все равно будет отображаться, при этом код выделяется красным цветом.
В диалоговом окне Options можно модифицировать некоторые установки компилятора. Во вкладке General опция Compile on Demand (Компиляция, выполняемая по требованию) позволяет приложению выполняться быстрее, поскольку модули не компилируются до тех пор, пока не загружаются для выполнения. На современных быстродействующих компьютерах для устранения возможных ошибок рекомендуется включать эту опцию.
Кроме того, во вкладке General имеется опция Background Compile (Фоновая компиляция). Включение данной опции позволяет производить фоновую компиляцию, когда имеются свободные системные ресурсы. Опция Background Compile может повысить скорость выполнения компиляции. Чтобы воспользоваться этой возможностью, опция Compile on Demand также должна быть включена.
Очень важно скомпилировать и сохранить все модули перед распространением приложения, чтобы убедиться в том, что все синтаксические ошибки исключены. Для этого в меню необходимо выбрать пункты Debug | Compile and Save All Modules (Отладка | Скомпилировать и сохранить все модули) вне зависимости от того, загружены в данный момент все модули базы данных или нет.

Найти метки очень просто, поскольку


Найти метки очень просто, поскольку они размещены в левой части кода и снабжены двоеточием,

Программный код данной статьи включает


Программный код данной статьи включает многочисленные примеры объектов. На следующих нескольких страницах в иллюстративных целях используется простейший пример — объект cUser. Объект
cUser содержит информацию о текущем зарегистрированном пользователе, включая его имя. Данный объект можно использовать в случаях, когда в приложении необходимо узнать имя пользователя, например, при обработке ошибок либо при записи имени автора примечаний или документов. В приведенном примере объект cUser используется для отображения приветствия пользователю при регистрации.

Процедуры свойств могут быть общедоступными


Процедуры свойств могут быть общедоступными или приватными, как и любые другие процедуры. Общедоступные процедуры свойств доступны всем другим процедурам во всех модулях; приватные процедуры свойств доступны только процедурам того модуля, в котором они были объявлены,

Тип данных процедуры Property Let


Тип данных процедуры Property Let должен быть таким же, как и для процедуры Property Get. Например, Property  Let для свойства Name принимает строковый аргумент. Таким образом, процедура Property Get также должна воз- вращать строковый тип данных.

Используемые значения свойств не ограничиваются


Используемые значения свойств не ограничиваются перечисляемыми типами данных. В предыдущем примере перечисляемый тип данных включает три члена: Manager, Staff и Unknown. VBA не препятствует разработчику проигнорировать значения в списке и ввести другое значение (например, FullTime). Чтобы ограничить выбор пунктами в списке, необходимо воспользоваться числовыми значениями перечисляемых пунктов. Например, если в списке имеется три пункта (и нумерация начинается с нуля), можно запретить использование любых элементов, значения которых меньше нуля и больше двух.

Событие WithEvents можно использовать только


Событие WithEvents можно использовать только в модулях класса (модули форм являются модулями класса). В стандартных модулях WithEvents использовать нельзя.
После объявления переменной на уровне модуля с помощью ключевого слова WithEvents необходимо в левом поле со списком в верхней части окна модуля выбрать объект cUser. В правом поле со списком будут отображены события объекта cUser. Выберите событие Welcome, и в окне кода появится процедура, в которой можно записать соответствующий код для ответа на событие.
На рис. 7 приведен код, отвечающий на событие Welcome.
Событие WithEvents можно использовать только
РИСУНОК 7. Процедура, использующая событие Welcome объекта cUser.
В результате пользователь при каждом запуске приложения увидит всплывающий экран с приветствием (рис. 8).
 
Событие WithEvents можно использовать только
РИСУНОК 8. Всплывающий экран с приветствием

Если при попытке использования объекта


Если при попытке использования объекта обнаружилось, что IntelliSense не отображает свойств и методов объекта, возможно, это свидетельствует о том, что не создана либо не установлена объектная переменная. Однако иногда IntelliSense не отображает элементы даже в том случае, когда код правилен. В данном случае следует предположить, что код правилен, и проверить его. Компания Microsoft не предусматривала работу IntelliSense со всеми элементами кода.

При создании объектной переменной рекомендуется


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

В данной статье описывается создание


В данной статье описывается создание объектов с помощью модулей класса. Следует помнить, что модули формы представляют собой модули класса. Можно добавлять свойства и методы к формам таким же способом, что и к пользовательским объектам.

Создание быстрых циклов


При работе с циклами по коллекции рекомендуется использовать For...Each вместо For...Next. При работе с циклами по элементам управления на форме код
For Each cnti on fcm
Next
выполняется быстрее, чем простой цикл For...Each.
Если необходимо создать цикл по коллекции объектов, следует избегать ненужного обновления коллекции. Даже в маленькой базе данных обновление коллекции может значительно снизить быстродействие приложения.
При использовании цикла For—Next можно сэкономить время, не повторяя переменную в строке Next.
For i=l to 100
.... .необходимый код
Next
Преимущества такого подхода особенно заметны при использовании вложенных циклов. Кроме того, не следует пересчитывать предельное значение для строки For.
Верхнее предельное значение должно быть установлено перед входом в цикл.
reccount=rs.recordcount/2
 For i=l to reccount
Next
Если не установить заранее значение верхнего предела, цикл пересчитывает значение при каждом проходе, а это — потеря времени.


Создание индексов, ускоряющих выполнение запросов


• Индексы могут ускорить процесс получения данных примерно в 10 раз.
• Индексы, кроме того, могут замедлить обновления и ввод данных, поэтому их не следует создавать без особой необходимости.
• Рекомендуется создать такое начальное значение, которое что-нибудь значит для разработчика и пользователей. С точки зрения производительности нельзя разрешать Access создавать начальное значение путем вставки поля AutoNumber. Пока у пользователей нет других средств для идентификации своих записей данных, необходимо пользоваться чем-то более удобочитаемым. Можно попробовать применить номер телефона, номер карточки социального обеспечения, номер счета, код поставщика и т.д. Для того чтобы индекс на самом деле приводил к повышению производительности, необходимо его использовать вместе с запросами.
• Можно проиндексировать все поля, для которых приложение применяет условие отбора. Создание индексов на множественных полях в таблицах упростит оптимизацию запросов, созданных позже в процессе разработки.
• Можно проиндексировать поля с обеих сторон ожидаемой связки. Поскольку поля Order Number относятся как к таблице Order Detail, так и к таблице Orders, обе таблицы должны иметь соответствующий индекс. Но если необходимо выполнять много отчетов по дате заказа, возможно, данные поля также необходимо проиндексировать.


Создание экземпляров объекта


Рассмотрим повторно используемый в приложении программный код. Фактически его можно использовать одновременно в нескольких экземплярах объекта. Примером может служить код подключения к данным. Каждый раз, когда пользователь осуществляет поиск покупателя, открывает форму или получает доступ к полю со списком, с сервера должны быть получены данные. Вместо того чтобы дублировать код для каждой из данных процедур, лучше создать объект Data Connection, позволяющий получить данные с сервера.


Создание классов


Для создания классов используются модули класса. Класс определяет свойства, методы и события, обеспечивая четко определенный и полностью документированный пользовательский интерфейс.


Создание коллекции VBA


Поскольку коллекции представляют собой объекты, коллекции создаются тем же способом, что и объекты. Во-первых, необходимо объявить объектную переменную для использования в качестве ссылки на коллекцию. Во-вторых, нужно воспользоваться ключевым словом Set для создания ссылки из объектной переменной на коллекцию. Следующий код создает коллекцию пользователей:
Dim Users as Collection
Set Users = New Collection


Создание методов


Метод — это действие, которое может быть выполнено над объектом. Чтобы создать метод для класса, достаточно создать общедоступную подпрограмму или функцию. Предположим, что нужно отслеживать дату и время каждой регистрации пользователя. Приведенный ниже код создает метод Login,
который вводит в таблицу дату и время регистрации пользователя.
Public Sub Login()
' Создание объектной переменной для набора записей.
Dim rst As ADODB.Recordset
' Создание строковой переменной.
Dim strSQL As String
' SQL-оператор для tbIUsers.
StrSQL = "SELECT * FROM tbIUsers"
' Создание набора записей ADO.
Set rst = New ADODB.Recordset
' Открытие набора записей.
rst.Open strSQL, CurrentProject.Connection, adOpenKeyset, adLockOptimistic
' Добавление новой записи.
rstAddNew
' Запись даты и времени регистрации пользователя.
With rst
!Name = Me.Name
!Date = Date
!Time = Time End With
' Сохранение новой записи.
rst.Update
' Закрытие набора записей.
rst.Close
' Уничтожение объектной переменной.
Set rst = Nothing
End Sub


Создание надежного кода


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


Создание нескольких экземпляров объекта


Класс содержит определенный набор свойств и методов. Этим он напоминает шаблон или каркас. Для иллюстрации рассмотрим открытие нового документа в Microsoft Word. При создании нового документа
Word можно воспользоваться шаблоном, например. Contemporary Letter (Современное письмо). После выбора шаблона в документ можно внести изменения. Данные изменения вносятся в новый документ, а не в шаблон. Тот же самый принцип действует в случае с классами.
При инициализации (создании) класса экземпляр объекта содержит базовый набор свойств и методов (шаблон). С этого момента объект становится уникальным, обладая собственным набором значений свойств и методов.
Одно из преимуществ модулей класса заключается в том, что можно создать много экземпляров класса. Каждый экземпляр создастся с базовым набором свойств и методов, но после создания каждый из них может быть изменен различным образом. Например, предположим, создано пять объектов cUser.
Вес пять объектов могут иметь разные значения свойств и разные методы. Например, значение свойства Name в одном объекте может быть James, а в
другом — Steve.
Для создания нескольких экземпляров объекта достаточно создать дополнительные объектные переменные и присвоить каждую объектную переменную новому объекту. Соответствующий код приведен ниже.
Public Sub ManyUsersO
Dim objUser1 as cUser
Dim objUser2 as cUser
Set objUser1 = New cUser
Set objUser2 = New cUser
ObjUser1.Name = "James"
ObjUser2.Name = "Steve"
MsgBox "Current users are:  " & objUser1.Name & " and " objUser2.Name
Set objUser1 = Nothing
Set objUser2 = Nothing
End Sub


Создание объектной переменной


Переменная — это участок памяти, отведенный для хранения или использующийся при считывании информации. Вне всяких сомнений, у разработчиков имеется громадный опыт работы с простыми переменными, такими как строковые и целочисленные переменные. Ниже приведены примеры объявления и использования двух простых переменных:
Dim sfcrNaor aa String
Dim I as integer
strNama =
"James"

I = 10
В этих примерах переменные включают специфический тип данных, и информация может храниться и считываться по необходимости.
Переменная Object
объявляется с помощью выражения Dim, как и простые переменные:
Dim objUser as cUser


Создание перечисляемых типов данных


Перечисляемый тип — это значение свойства, которое может быть передано разработчику при использовании объекта. Например, при установке свойства Visible
для формы после ввода знака равенства можно заметить, что возможен выбор значений True и False
в раскрывающемся списке (рис. 5).
Создание перечисляемых типов данных 
РИСУНОК 5. Выбор True или False в раскрывающемся списке.
Точно так же можно передать эти значения, создав перечисляемые типы.
В разделе объявлений модуля класса для указания значений свойств необходимо воспользоваться ключевым словом Enum. Например, если для свойства Type объекта cUser
необходимо создать раскрывающийся список со значениями Manager, Staff или Unknown, в разделе объявлений можно использовать следующий код:
Public Enum UserList
Manager
Staff
Unknown
End Enum
Следующий шаг — использование перечисляемого типа данных (UserList) в качестве типа данных свойства Type класса cUser. Приведенный ниже пример иллюстрирует, как это сделать. В данном случае свойство было создано как общедоступная переменная.
Пример 1. Свойство объявляется как строковая переменная.
Public UserType as String
Пример 2. Свойство объявляется как перечисляемый тип данных.
Public UserType as UserList
Значения свойств можно установить с помощью раскрывающегося списка, предусмотренного технологией IntelliSense (рис. 6).
Создание перечисляемых типов данных
РИСУНОК 6. Пример перечисляемого типа данных
Чтобы показать, что значение свойства было выбрано из перечисляемых типов данных, каждый тип данных пронумерован, начиная с нуля, по возрастанию.


Создание приватной переменной модуля


При использовании процедур свойств значение свойства хранится в приватной переменной модуля. Создатель класса определяет, отображается ли данное свойство вне модуля.
Ниже приведен пример создания приватной переменной на уровне модуля для свойств Name и Type объекта cUser.
Option Explicit
' Создание приватной переменной в разделе объявлений.
Private mstrName as String
Private mUserType as String
Создание приватной переменной модуля
РИСУНОК 4. Установка и получение значений свойств объекта с помощью IntelliSense.


Создание событий


Объекты Access включают события. Например, объект формы содержит событие Load, а командная кнопка — событие Click.
Можно создавать события для пользовательских объектов. Для этого в разделе объявлений необходимо воспользоваться ключевым словом Event и указать имя события. Например, можно добавить событие Welcome, которое выполняется при запуске приложения пользователем. Для создания данного события в разделе объявлений модуля класса необходимо ввести следующий код:
Event Welcome()
Чтобы воспользоваться событием, его необходимо сформировать с помощью инструкции Raise в методе объекта. Событие Welcome можно сформировать в методе Login объекта cUser.
Когда пользователь запускает приложение, вызывается метод Login.
Благодаря этому вызывается событие Welcome,
которое отображает всплывающий экран с персональным приветствием данному пользователю. Используется следующий программный код:
Public Sub Login()
RaiseEvent Welcome
End Sub
Это все, что нужно предпринять для создания события и формирования его в модуле класса. В следующем разделе описано использование события в форме.


Создание свойств


Существует два способа создания свойств класса: глобальные переменные либо процедуры свойств.


Создание высокопроизводительного кода


Что касается кода, существует несколько способов, обеспечивающих более быстрое выполнение функций и подпрограмм. Хотя разница в скорости между одной методикой и другой заключается лишь в долях секунды, использование самой быстрой методики может предоставить больше возможностей для последующего повышения производительности. Когда к разработчику обращаются пользователи с просьбой о модификации, всегда лучше иметь некоторый резервный запас функциональных свойств, которым можно воспользоваться для вставки аудиторских следов и сложных контрольных процедур, чтобы не испытывать терпение пользователей.
Разработчик обнаружит, что внедрение некоторых методик, описанных выше в данной статье, позволяет упростить оптимизацию кода. Самая большая помеха для кода — это плохо разработанная база данных. Если база данных разработана плохо, почти каждая функция и подпрограмма будет содержать ошибки и использовать обходные пути. Применение искусственных приемов всегда замедляет выполнение программы по сравнению со стандартной методикой.
Однако существует несколько простых правил, которых необходимо придерживаться, и несколько альтернативных методик, используя которые можно добиться максимальной скорости выполнения функций и подпрограмм приложения. Очень не многие из описанных подходов сами по себе оказывают более или менее значительный эффект, но их совместное и многократное применение приводит к поразительным результатам.


Создание новой базы данных



Создание новой базы данных

Существует несколько способов создания базы данных, однако чаше всего создается пустая база данных, не содержащая информации или каких-либо объектов, описанных в главе 1, «Добро пожаловать в мир баз данных». В таких случаях говорят, что база данных создается с нуля.

Итак, мы приступаем к созданию базы данных.

1. Щелкните на ссылке Новая база данных в меню Создание файла. Если панель задач не открыта, щелкните на кнопке Создать на панели База данных, выберите команду Файл>Создать или нажмите комбинацию клавиш .

2. В списке Папка в верхней области диалогового окна выберите опцию Мои документы (как это следует делать по умолчанию).

3. В поле Имя файла введите имя базы данных — в нашем случае Моя база.

4. Не изменяйте тип файла, используемый по умолчанию для баз данных Access (это файлы с расширением *.mdb). На рис. 2.3 показано диалоговое окно Файл новой базы данных. Безусловно, перечень представленных здесь файлов будет отличаться от того, который вы видим на своем компьютере.

5. Щелкните на кнопке Создать, и на экране появится основное рабочее окно Access (рис. 2.4). Более подробная информация о работе с ним содержится в главе 3, «Изучение главного рабочего окна Access».

Безопасность Access — это обширная тема, которая в данной - книге не затрагивается. Файлы с расширением *.mdw рекомендуется создавать только в том случае, если вы хорошо знакомы с различными аспектами безопасной работы Access, поскольку использование таких файлов может стать причиной неумышленного (а иногда и намеренного) повреждения базы данных.


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

1. Выберите команду Сервис>Параметры.

2. Перейдите на вкладку Общие.

3. Введите полный путь к папке, которая будет отображаться в диалоговом окне Файл новой базы данных, расположенном в разделе Рабочий каталог нижней области вкладки Общие.

4. Щелкните на кнопке ОК, чтобы вернуться к главному рабочему окну, или на кнопке Применить, чтобы сохранить внесенные изменения, не закрывая диалоговое окно Параметры.


Создание новой базы данных на основе уже существующей



Создание новой базы данных на основе уже существующей

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


Средства оценки производительности


Разработчику важно знать, какое же влияние оказали на приложение все предпринятые усилия. Для отслеживания и оценки относительной производительности, достигнутой с помощью той или иной методики, можно использовать несколько разных инструментальных средств. Первый способ — это таймер для измерения количества времени, которое занимает выполнение процесса. Второй способ — недокументированная функция для подсчета операций с диском, кэшем и операций блокировки. Третий способ — способность Access отобразить план выполнения запросов для просмотра разработчиком. Первые два способа можно применять для оценки производительности практически каждой методики, описанной в данной статье. Планы выполнения запросов относятся только к оптимизации запросов.
Хотя VBA содержит функцию Timer(), она может оказаться не совсем точной для оценки предпринятых усилий по оптимизации. Функция VBA Timer() записывает в секундах промежуток времени, прошедший с полуночи. Поскольку измеренное время кодируется однозначным числом, в данном случае эта функция может оказаться не совсем точной, особенно для оценки промежутков времени меньше 1 секунды. Многие разработчики, кроме того, используют функцию GetTickCount.
Поскольку эта функция привязана к часовому таймеру PC, она возвращает время не в миллисекундах, а в приращениях 1/18 секунды. API Windows предлагает таймер, который отслеживает время в миллисекундах. Функция timeGetTimeO измеряет промежуток времени с момента запуска Windows. Поскольку она использует другой аппаратный счетчик, то возвращает время с точностью до миллисекунды.
Используя timeGetTime(),
можно вставить строку кода до и после выполнения любой критической операции и получить очень точное измерение времени, которое понадобилось для завершения действия.
Для использования вызова API необходимы две вещи: объявление функции и глобальная переменная для хранения времени запуска таймера. В разделе объявлений модуля необходимо ввести следующие три строки:



Private Declare Function a2ku apigettime Lib "winmm.dll" _

Alias "timeGetTime" () As Long

Dim Ingstartingtime As Long

Затем можно создать подпрограмму для запуска часов и функцию остановки часов.

Sub a2kuStartClock()

Ingstartingtime = a2ku_apigettime()

End Sub

Function a2kuEndClock()

a2kuEndClock = a2ku_apigettime() - Ingstartingtime

End Function

Использование данных функций для оценки производительности запроса иллюстрирует код, приведенный в листинге 1.

Листинг 1. Определение времени выполнения запроса.

Sub QueryTimer(strQueryName As String)

Dim db As Database

Dim qry As QueryDef

Dim rs as Recordset

Set db = CurrentDb()

Set qry =

db.QueryDefs(strQueryName)


'Запуск часов. a2kuStartClock

Set rs = qry.OpenRecordset()

'Остановка часов и вывод результата в окне отладки.

Debug.Print strQueryName & " executed in:  " & a2kuEndClock & _

" milliseconds"

rs.Close

End Sub

ПРИМЕЧАНИЕ

Для достижения наибольшей точности измерения необходимо разместить вызов процедур a2kuStartClock и a2kuEndClock как можно ближе к местонахождению рассматриваемой процедуры.


Ссылка на специфический объект


К объектам в коллекции можно обращаться либо по номеру, либо по ключевому значению. При ссылке на элементы в коллекции по номеру необходимо помнить, что все элементы индексированы, а это означает, что отсчет начинается с 1. Проще обращаться к объекту в коллекции по ключевому значению. Приведенный ниже код иллюстрирует ссылку на специфический объект User2 с помощью обоих методов. Хотя указывать метод Item не обязательно (он действует по умолчанию), явное обращение способствует повышению восприимчивости кода.
' Обращение к объекту в коллекции по номеру индекса.
MsgBox Users.Item(2).Type
' Обращение к объекту в коллекции по ключевому значении.
MsgBox Users.Item("Steve").Type


Step Into


Для выполнения одного оператора кода одновременно необходимо в меню редактора Visual Basic выбрать команду Debug | Step Into (Отладка | Построчно) или нажать клавишу F8. Построчное выполнение кода — самый эффективный способ наблюдения за выполнением программы и значениями переменных в коде.


Step Out


Предположим, в пошаговом режиме выполняется процедура, вызывающая другую процедуру. Находясь в вызванной процедуре, можно быстро закончить выполнение оставшегося кода и возвратиться в исходную процедуру. Для этого в меню необходимо выбрать пункты Debug | Step Out (Отладка | Выход из блока) или нажать клавиши Ctrl+Shift+F8. Такая опция зачастую бывает достаточно полезной.
Run to Cursor
При пошаговом выполнении кода можно выполнить блок кода целиком до того места, где находится курсор. Такая опция полезна при работе в пошаговом режиме, когда необходимо перейти к следующему разделу кода. Одним из примеров может служить цикл. Проверив цикл несколько раз в пошаговом режиме, чтобы убедиться в его правильной работе, можно перевести курсор в конец цикла и выбрать в меню команду Debug | Run to Cursor (Отладка | Выполнить до курсора) или нажать клавиши Ctrl+F8.


Step Over


Иногда одна процедура вызывает другие процедуры. Вызываемая процедура может быть абсолютно надежной (иными словами, полностью протестированной и свободной от ошибок). Для выполнения вызванной процедуры целиком, без пошагового перехода от строки к строке, необходимо в меню выбрать команду Debug | Step Over (Отладка | Выполнение блока) Shift+FS.
После того как вызванная процедура завершится, снова произойдет останов. С этого места можно продолжить построчное выполнение кода.


Строка меню



Строка меню

В этом разделе описываются элементы строки меню, расположенной в верхней области рабочего окна Access. С помощью команд меню можно выполнять следующие действия:
  • управлять файлами базы данных;
  • создавать и изменять объекты базы данных;
  • использовать данные совместно с другими программами пакета Office;
  • изменять различные параметры Access.

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

Обратите внимание на подчеркнутые буквы в названиях команд меню — это так называемые горячие клавиши. Нажатие такой клавиши позволяет запустить нужную команду. К примеру, для отображения меню Файл следует нажать комбинацию клавиш , а затем — букву, которая в названии требуемой команды подчеркнута. Например, в команде Создать (в меню Файл) подчеркнута буква а, поэтому для открытия диалогового окна Создать нужно нажать клавишу <А>.




Свойства и методы коллекции VBA


Объект коллекции имеет очень простую структуру и содержит только одно свойство и три метода, как показано в табл. 1.
Таблица 1. Свойства и методы объекта множества.

Имя

Тип

Описание

Count

Свойство

Указывает, сколько элементов содержится в коллекции.

Add

Метод

Используется для добавления элементов в коллекцию.

Remove

Метод

Используется для удаления элементов из коллекции.

Item

Метод

Используется для ссылки на элементы в коллекции. Данный метод действует по умолчанию.




Свойства объекта сЕггог


Объект сЕггог
содержит свойства, значения которых могут быть использованы обработчиком ошибок. Описание приводится в табл. 1.


Свойства сЕггог.



Свойство

Описание

Application

Название программы, создавшей приложение (например, MS Access).

AVIFileLocation

Имя и полный путь к видеофайлу AVI, который используется для предупреждения об ошибке в форме или диалоговом окне.

Class

Имя модуля класса.

ComputerName

Имя компьютера, на котором произошла ошибка.

ComputerTotalMemory

Общий объем памяти, установленный в компьютере.

ComputerAvailableMemory

Объем доступной памяти в компьютере.

ComputerOperatingSystem

Информация об операционной системе и версии.

ComputerProcessor

Информация о процессоре компьютера.

ControlName

Имя активного элемента управления.

ControlValue

Значение активного элемента управления.

CurrentRecordID

ID текущей записи.

Description

Описание ошибки, возвращаемое объектом Егг.

EmailAddress

Адрес электронной почты, использующийся для отправки сообщения об ошибке.

ErrorDatabase

Имя и полный путь к базе данных (например, базе данных Access или SQL Server), содержащей таблицу ошибок.

ErrorNumber

Номер ошибки, возвращаемы объектом Err.

ErrorTextFile

Имя и полный путь к текстовому файлу, содержащему информацию об ошибке.

HelpContext

ID статьи файла справки, возвращаемый объектом Егг.

HelpFile

Имя и полный путь к файлу справки, возвращаемые объектом Err.

LastDIIError

Код системной ошибки для последнего вызова DLL.

Level

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

LineNumber

Номер строки оператора, в котором возникла ошибка.

Note

Примечание пользователя о том, что он делал во время возникновения ошибки.

Now

Дата и время возникновения ошибки.

Procedure

Имя процедуры

SoundFile

Имя и полный путь к звуковому файлу.

Source

Имя объекта или приложения, сгенерировавшего ошибку.

User

Имя пользователя, у которого произошла ошибка.

WaitStateFlag

Флаг, использующийся в целях установки состояния ожидания, необходимого для останова выполнения кода

UserEnterNoteFlag

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


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


Методы cError.



Метод

Описание

AddToErrorHandlerOutlookCalendar

Добавляет информацию об ошибке в календарь Outlook, вызвавший Error Handler.

Clear

Очищает объект Егг.

Email

При возникновении ошибки отправляет разработчику электронное сообщение с помощью Outlook.

EmailAIIErrors

Отправляет разработчику электронное сообщение с вложением, включающим всю информацию в таблице ошибок.

GetActiveControlValue

Получает значение активного элемента управления при возникновении ошибок.

MessageBox

Отображает окно сообщения с информацией об ошибке.

MsgErrorDetails

Обобщает информацию об ошибке для окна сообщения или для электронного сообщения

OfficeAssistant

При возникновении ошибки вызывает Office Assistant (помощника) и спрашивает пользователя, не желает ли он ввести примечание, относящееся к ошибке.

PlaySound

Воспроизводит звук при возникновении ошибки для привлечения внимания пользователя.

ProcessError

Контролирует обработку информации об ошибке в зависимости от опций, установленных в данной организации.

ShowAVIForm

Вызывает форму, включающую AVI-файл, для оповещения пользователей о возникновении ошибки

UserlnputBox

Отображает окно ввода для пользователя, чтобы они могли ввести свои замечания.

UserName

Получает зарегистрированное имя пользователя в Windows/Windows NT.

WaitState

Создает состояние ожидания для остановки выполнения кода.

WriteErrorToTable

Записывает информацию об ошибке в таблицу ошибок базы данных.

WriteErrorToTextFile

Записывает информацию об ошибке в текстовый файл.




Опции обработчика ошибок.



Опция

Описание

Тип данных

AccessErrorTableName

Имя таблицы Access, которая содержит информацию об ошибках.

Да/Нет

AddToErrorHandlerCalendar

Добавить ошибку и календарь обработчика ошибок.

Да/Нет

AVIFileLocation

Полный путь к AVI-файлу, использующемуся в AVI-форме.

Текст

DatabaseName

Имя базы данных, в которой находится таблица ошибок.

Текст

DatabasePath

Полный путь к базе данных.

Текст

EmailAddress

Адрес электронной почты для отправки сообщений об ошибках.

Текст

EmailErrors

Отправить сообщение при возникновении ошибки.

Да/Нет

ErrorsToAccessTable

Сохранить информацию об ошибке в таблице Access.

Текст

ErrorsToTextFile

Сохранить информацию об ошибке в текстовом файле.

Текст

PlaySound

Воспроизвести звук при возникновении ошибки.

Да/Нет

ShowAVIForm

Отобразить AVI-форму при возникновении ошибки.

Да/Нет

ShowMsgBoxErrors

Отобразить окно сообщения с информацией об ошибке.

Да/Нет

ShowOfficeAssistant

Отобразить помощник при возникновении ошибки.

Да/Нет

JoundFile

Полный путь к звуковому файлу.

Текст

UserEnterNoteAboutError

Пользователь ввел примечание.

Да/Нет


В зависимости от того, какие опции выбраны, обработчик ошибок работает по-разному. Для хранения информации об опциях обработки ошибок используется таблица, поэтому код "управляется таблицей". Вместо записи в коде новых значений опций достаточно ввести опции в таблице Error Options. Поскольку код обращается за информацией к таблице Error Options, работать таким образом гораздо удобнее.
Конечно, разработчику не нужно, чтобы пользователи вводили данные непосредственно в таблицу Access. Форма fnnErrorOptions позволяет сотрудникам обновлять и изменять опции обработки ошибок (рис. 13).
Созданный обработчик ошибок не только функционален и эффективен, но и удобен в использовании для сотрудников организации.
Опции обработчика ошибок.
РИСУНОК  Форма опций обработки ошибок, использующаяся для выбора соответствующих опций.


Тестирование приложения


Перед распространением приложения Access необходимо полностью его протестировать. Более подробная информация относительно тестирования приведена в статье «Планирование процесса разработки».


Удаление кода в окне отладки


Для быстрого выделения всего кода в окне отладки в целях последующего удаления используется комбинация клавиш Shift+Ctrl+Home, если курсор находится в конце кода в окне Immediate. Весь код будет выделен, и можно нажать клавишу Delete для его удаления.
Если курсор находится в начале кода в окне Immediate, необходимо использовать комбинацию клавиш Shift+Ctrl+End для выделения всего кода. Затем можно нажать клавишу Delete.


Удаление отдельных объектов


Чтобы удалить отдельные объекты из множества, необходимо воспользоваться номером индекса объекта либо ключевым значением.
' Удаление объекта по номеру индекса.
Users.Remove 2
' Удаление объекта по ключевому значению.


Удаление всех объектов


Чтобы удалить все объекты из коллекции, не обязательно создавать цикл по всем элементам множества и вызывать метод удаления. Гораздо проще переназначить объект коллекции в новую коллекцию.
' Удаление всех объектов из коллекции.
Set Users = New Collection


Упрощение кода в целях последующей поддержки и обновления


С помощью классов единственный фрагмент кода можно использовать в приложении множество раз без повтора кода. Если, например, код доступа к данным один и тот же в нескольких процедурах, необходимо найти все места, где появляется данный блок кода, и проверить, не нужно ли внести изменения. Такой подход занимает очень много времени и совершенно неэффективен. С другой стороны, если используется объект Data Connection, все обновления или изменения кода доступа к данным необходимо внести лишь в одном месте — модуле класса.


Установка опций обнаружения ошибок


В редакторе Visual Basic (вкладка General (Общие) в меню Tools | Options (Сервис | Параметры)) можно найти некоторые дополнительные опции обработки ошибок Access (рис. 16).
Установка опций обнаружения ошибок
РИСУНОК 16. Установка опций обнаружения ошибок.
Break on All Errors (Прерывание на всех ошибках). При возникновении ошибки код прекращает выполнение на данной строке вне зависимости от наличия обработчика ошибок. Данная опция полезна для отладки приложения, но перед распространением приложения ее необходимо отключить.
Break in Class Module
(Прерывание в модуле класса). При возникновении ошибки код прекращает выполнение на данной строке только в модулях класса, если нет обработчика ошибок.
Break on Unhandled Errors (Прерывание на необрабатываемых ошибках). При возникновении ошибки код прекращает выполнение на данной строке во всех процедурах, которые не содержат обработчик ошибок.


Установка прерываний


Прерывание останавливает выполнение кода. Для установки точки прерывания необходимо поместить курсор на оператор и в меню редактора Visual Basic выбрать команду Run | Toggle Breakpoint (Выполнить | Переключить прерывания) или нажать клавишу F9. Следует помнить, что нельзя установить прерывание  на пустой строке, строке комментария или строке кода, содержащей оператор Dim. Еще один способ установки прерывания — щелкнуть на сером левом поле окна кода рядом с соответствующей строкой кода. При этом на левой границе появится большая красная точка, которая указывает на установленную точку прерывания.
При запуске программы выполнение приостанавливается на том операторе, где установлено прерывание (рис. 7). Автоматически открывается модуль кода, и оператор кода будет выделен желтым цветом. Можно шаг за шагом проходить по коду, просматривать или менять значения переменных и т.п.
Установка прерываний
РИСУНОК 7. Выполнение кода приостановлено на точке прерывания
Для удаления точки прерывания необходимо в меню выбрать команду Run | Clear All Breakpoints (Выполнить | Убрать прерывания) или нажать клавиши Ctrl+Shift+F9.


Установка приложения с учетом достижения оптимальной производительности


Способ настройки файлов приложения может оказать ощутимый эффект на скорость его выполнения. Следующие указания помогут вам оптимизировать работу приложения и в полной мере воспользоваться советами, которые приведены в других разделах данной статьи.
• Необходимо отделять данные от приложения. В качестве стандартной практики рекомендуется создавать один файл .MDB для хранения таблиц и размещать его в сети, а другой файл .MDB — для хранения запросов, форм, отчетов и т.д. Это поможет повысить производительность, улучшить работу в многопользовательской среде и обслуживание. Из всех советов, приведенных в данной статье, от этого следует отказываться только по очень важной причине.
• Рекомендуется использовать текущую версию файла рабочей группы (system, mdw). Хотя в приложении можно пользоваться предыдущими версиями файла рабочей группы, текущая версия обеспечивает более высокую производительность.
• Необходимо регулярно производить сжатие базы данных. Кроме того, базу данных следует сжимать после выполнения обширных операций импорта, удаления и обновления. Сжатие базы данных обеспечивает использование свободного места между страницами данных (резерва) и позволяет выполнить перерасчет статистики базы данных, использующейся при оптимизации запросов. (Более подробно данная тема рассмотрена дальше в этой статье.) Сжатие базы данных, кроме того, позволяет освободить дисковое пространство для других целей. Access 2000 предлагает новую возможность — сжатие базы данных при выходе из базы данных. Для этого необходимо установить флажок Compact on Close (Сжимать при закрытии) во вкладке General (Общие) диалогового окна Options (Параметры) в меню Tools | Options (Сервис | Параметры). Некоторые разработчики обнаружили, что предыдущие версии Access следует сжимать дважды, чтобы добиться хороших результатов. Можно попробовать запустить базу данных из отдельного файла .MDB и позволить этому стартовому приложению выполнить сжатие при запуске базы данных. В сочетании с опцией Compact on Close при каждом выполнении будет производиться двойное сжатие.
• При возможности следует установить версию .MDE для приложения. При этом существует несколько преимуществ. Версия .MDE требует наличия скомпилированных модулей, а скомпилированные модули выполняются быстрее, чем нескомпилированные. Кроме того, для .MDE требуется меньший объем ОЗУ и меньше дискового пространства, чем для .MDB, что повышает производительность.


В начале...


При запуске приложения первое, что видят пользователи, — начальная форма. Она может представлять собой всплывающий экран с названием приложения и другой информацией или кнопочную панель для навигации по приложению. В любом случае из данной формы следует удалить код. Код запуска формы следует записать в стандартный модуль и выполнять только те процедуры, которые необходимы для запуска приложения. Поскольку такая форма будет загружаться быстрее, она создаст у пользователя хорошее первое впечатление. Возможно, выполнение некоторых операций можно отложить на какое-то время. После удаления модуля из формы свойству HasModule необходимо присвоить значение No. Это поможет создать простую форму, которая будет выполняться быстрее. Однако, изменив значение свойства HasModule, разработчик уничтожает весь код формы и код элементов управления. Перед изменением данного свойства следует убедиться, что все подпрограммы и функции размещены в стандартном модуле.
Начальная форма не должна содержать элементы управления ActiveX. Элементы ActiveX замедляют процесс загрузки больше, чем все другие элементы управления. Если в начальной форме необходимо использовать элемент ActiveX, возможно, следует ограничить количество других элементов управления.
Вместо макросов AutoExec лучше воспользоваться опцией Startup Form.


Вставка модуля класса


Создание класса не вызывает никаких сложностей. Добавление свойств и методов к объекту требует несколько больших усилий.
Для создания класса необходимо вставить модуль класса в приложение Access и присвоить ему имя. Имя модуля класса является именем объекта.
Чтобы вставить модуль класса, необходимо в меню выбрать пункты Insert | Class Module (Вставка | Модуль класса). После этого откроется окно редактора Visual Basic. В окне кода можно определять любые свойства, методы и события для данного объекта. Перед тем как продвигаться дальше, необходимо присвоить имя модулю класса (рис. 3).
Вставка модуля класса
РИСУНОК 3. Присваивание имени модулю класса.


Выбор размеров переменных


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


Выполнение кода в пошаговом режиме


Когда выполнение кода приостанавливается из-за прерывания, выражение кода, выделенное желтым цветом, не выполняется. Продолжить выполнение кода можно несколькими способами.


Выполнение операторов в окне Immediate


Для выполнения оператора кода в окне отладки необходимо поместить курсор где-нибудь в операторе. Курсор не обязательно должен находиться в начале или в конце оператора кода.
Если в окне Immediate отображается несколько операторов кода, не обязательно удалять операторы, находящиеся после требуемого оператора. Достаточно поместить курсор где-нибудь в операторе кода, который необходимо выполнить, и нажать клавишу Enter.


Выполнение пользовательских функций


Для запуска пользовательских функций в окне Immediate необходимо ввести знак вопроса, имя функции и соответствующие параметры, например, ? MyFunction.


Выполнение пользовательских подпрограмм


Для выполнения пользовательских подпрограмм в окне Immediate необходимо ввести имя подпрограммы и соответствующие параметры, например, MySubProcedure. Перед именем подпрограммы знак вопроса не ставится.


Выполнение программы с обработкой ошибок


Рассмотрим изменение хода выполнения программы при наличии обработчика ошибок. Если в коде не содержится ошибок, программа выполняется так (обработчик ошибок не вызывается):
Sub Demo ( )
On Error GoTo ErrorHandler
Good code
ExitHere:
Exit Sub
ErrorHandler:
MsgBox "An error occurred"
Resume ExitHere End Sub
Если какое-либо выражение кода содержит ошибку, программа выполняется по-другому, поскольку выполняется обработчик ошибок:
Sub Demo ( )


Вызов API Windows для получения


• Date and time (Дата и время). Дата и время возникновения ошибки. Эта информация полезна для анализа частоты возникновения ошибок. Простой график должен показывать, что со временем программные ошибки возникают реже.
• Notes about the error (Комментарии к ошибке). Пользователи могут вводить информацию о том, что они делали в момент возникновения ошибки, или свои замечания. Эта информация может быть введена в отдельном поле или форме. Пользователи могут воспользоваться простой формой для сообщения о том, что происходило в момент появления ошибки. Необходимо сообщить пользователям, что данная информация необязательна. Возможно, одни пользователи никогда ничего не напишут о возникающей ошибке, в то время как другие захотят сообщить полезную информацию.
Благодаря информации, которая может быть получена с помощью объекта Err и других методов, разработчики могут быстро и эффективно устранить ошибки рабочего цикла.


Вызов событий Initialize и Terminate


Модули класса автоматически включают события инициализации и завершения. Для использования данных событий необходимо выбрать событие в поле со списком в верхней части окна кода.
Событие инициализации вызывается при создании объекта. Например, если нужно, чтобы выполнялся определенный код при создании объекта cUser,
данный код можно поместить в событие Initialize.
Событие завершения происходит при разрушении объекта. Здесь удобно записывать код очистки, выполняющийся при закрытии подключений к базам данных, освобождении объектных переменных и т.д.


Вызовы API Windows


Все выполняемые функции комплексного обработчика ошибок нельзя запрограммировать в Microsoft Access, необходим вызов нескольких API Windows.
Обработчик ошибок получает имя пользователя, у которого произошла ошибка. Вместо того чтобы регистрировать пользователя в приложении для получения этой информации, обработчик ошибок получаст имя пользователя из API Windows. Вызов API Windows считывает зарегистрированное имя пользователя в Windows 95/98/NT.
' Вызов API Windows для получения имени пользователя.
Private Declare Function GetUserNmae Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal IpBuffer As String, nSize As Long)
При возникновении ошибки можно воспроизвести звуковой сигнал для предупреждения пользователей. Для этого также необходим вызов API Windows:
' Вызов API Windows для воспроизведения звука.
Private Declare Function sndPlaySound32 Lib "wirumn.dll" Alias _
"sndPlaySoundA" (ByVal IpszSoundName As String, ByVal uFlags As Long) As Long
Другие вызовы API Windows получают имя компьютера, информацию об объеме памяти компьютера, операционной системе и информацию о процессоре.


Закрытие и разрушение избыточных данных


Быстрый код — это чистый код. Необходимо убедиться, что по окончании работы с наборами записей они будут закрыты, а объектам, когда они будут не нужны, присвоены пустые значения. Ненужные объекты поглощают значительный объем памяти, который мог бы быть использован другими частями приложения.
rs.Close
Set db=Nothing


Завершение работы



Завершение работы

После праведных трудов необходимо корректно завершить работу с базой данных и Access. Закройте активную базу данных, щелкнув на кнопке Закрыть (X) в правом углу строки заголовка окна База данных. Кроме того, это можно сделать с помощью команды Файл>Закрыть.

Для завершения работы с Access также можно щелкнуть на кнопке Закрыть в правом углу строки заголовка или выбрать команду Файл>Выход. Существует возможность закрыть Access одновременно с активной базой данных — для этого подойдет любой из описанных выше методов.

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




    Базы данных: Разработка - Управление - Excel