Помощь Выход

Глава 5. Разработка более сложной формы (прием товаров)

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


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

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

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


Краткая справка
1. Чтобы переместить элемент управления на форме, необходимо выделить его и перетащить при помощи мыши в соответствующее место. Изменить размеры элемента управления можно при помощи маркеров выделения, расположенных по периметру элемента.
2. Если область заголовка (примечания) формы отсутствует в окне конструктора, выберите команду Вид\Заголовок/примечание формы.
3. Некоторые элементы управления (поля, списки) имеют присоединенную надпись, которая перемещается вместе с самим элементом. Чтобы перемещать их независимо друг от друга, используются маркеры в верхнем левом углу каждого элемента.
4. Для удаления элемента его нужно выделить и нажать клавишу Delete.
5. Изменение взаимного расположения элементов управления и согласование их размеров весьма эффективно можно выполнить при помощи команд в подменю Выровнять, Размер, Интервал по горизонтали/вертикали меню Формат. Для этого необходимо предварительно выделить группу соответствующих элементов управления. Существует несколько приемов выделения группы: последовательные щелчки мышью при нажатой клавише SHIFT; щелчок и протяжка в области линеек окна конструктора; охват элементов посредством протяжки мыши.

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

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

Поле со списком

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

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

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

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

Значения свойства Источник строк, в зависимости от значения свойства Тип источника строк, перечислены ниже в таблице.

Тип источника строкИсточник строк
Таблица/запросИмя таблицы или запроса (выбирается из списка имеющихся в базе данных таблиц или запросов) или инструкция SQL. Элементами списка в этом случае являются записи из указанной таблицы, сохраненного в базе данных запроса или запроса, написанного на языке SQL. В последнем случае можно воспользоваться конструктором запросов.
Список значенийСписок элементов, разделяемых точкой с запятой (;).
Список полейИмя таблицы, запроса или инструкция SQL. Элементами списка в этом случае является список полей указанной таблицы или запроса.

В нашем случае источником строк следует выбрать таблицу Поставщик, содержащую необходимую информацию в полях Код_поставщика и ФИО_поставщика.

Свойством Число столбцов задается число столбцов списка. В нашем случае это 2 - первые два поля из таблицы Поставщик, которыми как раз и являются Код_поставщика и ФИО_поставщика. Значения из первого поля нужны нам для связи с таблицей Товары, поскольку при выборе элемента списка именно код поставщика должен записываться в соответствующее поле этой таблицы.

Свойство Присоединенный столбец определяет, значение какого столбца становится значением элемента управления при выборе строки из сформированного списка. Если элемент управления присоединен к полю источника записей для формы (т.е. в качестве свойства Данные для этого элемента указано имя поля источника записей), то значение столбца, указанного в свойстве Присоединенный столбец, будет при выборе строки списка заноситься в поле, указанное в качестве значения свойства Данные. Таким образом, при выборе элемента списка в поле Поставщик будет заноситься значение из первого столбца списка, т.е. значение кода поставщика, что и требуется.

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

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


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

Наконец, свойство Автоподстановка (допустимые значения свойства - Да/Нет) определяет, должен ли выполняться автоматический ввод в текстовое поле значения из списка, совпадающего по первым символам с символами, вводимыми в это поле с клавиатуры.


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

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

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


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

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

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

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

Понятие событийной процедуры

Событийная процедура представляет собой последовательность операций, которая выполняется при наступлении некоторого события. Таким событием может быть, например, щелчок кнопкой мыши. События могут генерироваться пользователем (щелчок, протяжка, нажатие клавиши на клавиатуре), системой (события таймера) или сигналами, поступившими от внешних устройств. Таким образом, мы можем определить некоторые действия, которые будут выполняться всякий раз, когда будет происходить то или иное событие. Эти действия в MS Access должны записываться на языке VBA (Visual Basic For Applications) непосредственным вводом с клавиатуры или с помощью мастеров, реализующих наиболее характерные операции при работе с базами данных.

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

Мастер кнопки здесь ничем не сможет нам помочь, поскольку такая специфическая задача не попадает в круг его возможностей. Поэтому следует либо отключить кнопку Мастера на панели элементов перед выбором кнопки, либо сразу после запуска Мастера нажать кнопку Отмена. Теперь выделим созданную кнопку и в окне свойств перейдем на вкладку События. Нужное нам событие называется Нажатие кнопки. Это событие наступает, когда мы щелкаем мышью по элементу управления Кнопка. Из списка в этом поле свойства можно выбрать один из макросов, имеющихся в базе данных, или строку Процедура обработки событий. Макросы – это объекты базы данных, представляющие собой комбинацию макрокоманд, каждая из которых выполняет предопределенное действие. Таких макрокоманд в MS Access имеется несколько десятков; они выполняют наиболее характерные для работы с базами данных действия.

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

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


Первая часть этого имени (до символа нижнего подчеркивания «_») является именем элемента управления на форме, поскольку событийная процедура связана с элементом управления; а вторая – название события. Так, например, Click в переводе с английского языка означает щелчок.

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


Внимание
Чтобы работать с кодовым окном было удобнее, рекомендуется давать элементам управления смысловые имена; иначе, имена будут выглядеть так: Кнопка26, Надпись33 и т.д., что видно на нашем примере.
Краткая справка
1. Для обозначения самой формы используется имя Form.
2. Форма также является элементом управления. Работа с мышью вызывает события для формы, если при этом не затрагиваются другие элементы управления, т.к. они находятся как бы над формой. Т.е. если щелкнуть на кнопке, расположенной на форме, то выполнится событийная процедура щелчка по кнопке, а не событийная процедура щелчка на форме, которая вообще не будет в этом случае отрабатывать.
3. Форма имеет и специфичные для нее события, например, загрузка и открытие, которые выполняются, когда форма открывается в режиме «форма».
4. События именуются по-английски. К сожалению, после версии MS Access 97 справка по языку программирования не русифицировалась для локализованной версии MS Office. Тем не менее, чтобы получить справку по конкретному событию, достаточно выделить название события, скажем, слово Click в заголовке процедуры и нажать клавишу F1. В этом случае появится справка по данному событию.

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


Дата_поступления = Date

Здесь в левой части оператора присваивания стоит имя поля (формы! Не путать с именем столбца в таблице) Дата_поступления, служащее для ввода и отображения соответствующей информации. В правой части оператора присваивания используется встроенная функция Date, которая возвращает системную дату. В результате выполнения этого оператора в поле Дата_поступления будет занесена системная (текущая) дата. Напомним, что сохранение записи происходит автоматически при переходе к другой записи. Поэтому указанный оператор пока только изменил содержимое поля на форме, но не в источнике данных. Об этом говорит значок карандаша в области выделения формы, который сменяется на треугольник после сохранения записи. Чтобы принудительно сохранить запись, нужно выполнить команду Записи\Сохранить запись. Если изменение сделано ошибочно, то до сохранения записи можно нажать клавишу ESC, чтобы отменить сделанное изменение содержимого элемента управления.

Однако,мы не ограничились одной этой строкой. Причина состоит в том, что эта событийная процедура будет менять любую имеющуюся дату на системную. Это может стать причиной ошибки при случайном нажатии на кнопку. Поэтому поступим следующим образом. Будем вводить в поле даты приема системную дату только в том случае, если мы добавляем новую запись, т.е. тогда, когда это поле пусто. В языке VBA есть встроенная функция IsNull, которая возвращает значение Истина (True), если ее аргумент содержит значение Null – отсутствие информации в элементе управления или отсутствие значения переменной. Поэтому мы сначала проверяем, заполнено ли поле даты приема на форме и, в случае, если нет, заносим в него системную дату.


В результате событийная процедура примет вид
Private Sub Кнопка26_Click()
If IsNull(Дата_поступления) Then
Дата_поступления = Date
End If
End Sub
Внимание
Аргументом функции IsNull в нашем примере является поле на форме. Путаница может возникнуть по той причине, что имя поля на форме (Дата_поступления) совпадает с именем поля в таблице Товары, которая является источником записей для рассматриваемой формы. Присвоение имен полей источника данных элементам управления на форме возникает при использовании мастеров построения форм или окна списка полей. В данном случае это не вызовет ошибки, поскольку работа с полями таблиц реализуется несколько иначе. Кроме того, если в событийной процедуре используется имя элемента управления без указания формы, на которой он находится, по умолчанию считается, что это поле текущей формы. В других случаях, чтобы отличить элемент управления на форме от поля в источнике данных, можно либо дать другое имя элементу управления (свойство Имя на вкладке Другие), либо явно указать принадлежность.

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


Forms(“Прием товаров”)!Дата_поступления
где символ «!» разделяет имя формы и имя элемента управления.

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


Me!Дата_поступления

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

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


DoCmd.DoMenuItem acFormBar, acRecordsMenu, acSaveRecord, , acMenuVer70

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

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


Цена_розн = Цена_опт * (1 + Наценка/100).

Удобно вводить наценку в процентах; именно поэтому она делится на 100 в вышеприведенной формуле. Вычисление выполняется следующим образом. Сначала вычисляется выражение в круглых скобках, после чего полученный коэффициент умножается (символ «*») на значение оптовой цены товара (поле на форме - = Цена_опт) для текущей записи. Наконец, результат заносится в поле Цена_розн для той же текущей записи. Следует иметь это в виду, нажимая на кнопку.

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

Чтобы нельзя было ввести в поле Наценка нечислового значения, выберем значение Фиксированный в свойстве Формат поля для этого элемента управления (вкладка Макет).

Добавим в событийную процедуру для кнопки Определить розн.цену проверку условия (наценка > 0), чтобы нельзя было назначить розничную цену меньше оптовой. При нарушении этого условия будет появляться сообщение об ошибке, которое выводит встроенная процедура MsgBox, использующая в качестве параметра текст сообщения. В результате все тело процедуры примет вид


If Наценка > 0 Then
Цена_розн = Цена_опт * (1 + Наценка / 100)
DoCmd.DoMenuItem acFormBar, acRecordsMenu, acSaveRecord, , acMenuVer70
Else
MsgBox ("Наценка должна быть больше нуля.")
End If

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

Краткая справка


Событие Загрузка (Load) возникает при открытии формы и выводе на экран ее записей.
Если написать следующую процедуру загрузки формы «Прием товаров»
Private Sub Form_Load()
Наценка = 25
End Sub
то в поле Наценка при загрузке формы будет введено значение 25. Если потребуется использовать какое-либо другое значение наценки, ничто не мешает нам изменить вручную значение в этом поле.

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


[Цена_опт]*[Кол_во_в_упак]*[Кол_во_упак]

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


=Sum(([Цена_розн] - [Цена_опт])*[Кол_во_в_упак]*[Кол_во_упак])
то получим требуемый результат. Для этого поместим в область заголовка свободное поле и введем вышеприведенную формулу в поле свойства Данные. При этом, во избежание ошибок, можно воспользоваться Построителем выражений. Заметим, что знак равенства «=» является обязательным атрибутом вычисляемого поля. Чтобы результат выводился в денежных единицах, на вкладке Макет нужно выбрать формат Денежный для этого поля.
Внимание
При применении фильтра (смотри главу 10) суммироваться будут значения только для отфильтрованных записей.

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

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


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

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

Краткая справка


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

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


Private Sub Form_AfterInsert()
‘ Сохранение значений из списка в переменных Пост, Сотр, Катег
Пост = Поставщик_
Сотр = Сотрудник_
Катег = Категория_
End Sub

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


Private Sub Form_Current()
‘ Проверка того, что мы перешли к новой записи
If (Поставщик_ = 0) And (Сотрудник_ = 0) And (Категория_ = 0) Then
‘ Заполнение полей значениями переменных
Поставщик_ = Пост
Сотрудник_ = Сотр
Категория_ = Катег
End If
End Sub

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

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

Сжатие базы данных

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

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

Чтобы выполнить сжатие текущего файла базы данных, нужно выполнить команду Сервис\Служебные программы\Сжать и восстановить базу данных... . При этом файл .mdb будет перезаписан под тем же именем.

Чтобы сжать базу данных в файл с другим именем или в файл, который не является текущей базой данных, необходимо закрыть базу данных, не выходя из программы Access, и выполнить ту же команду. Закрыть базу данных можно с помощью команды Файл\Закрыть или же простым закрытием окна базы данных. Однако теперь при выполнении команды сжатия нужно будет сначала указать (выбрать в диалоговом окне), какой файл требуется сжать, а затем ввести имя, под которым будет сохранен сжатый файл. Если при этом выбрать имя существующего файла, то он будет заменен сжатым файлом после подтверждения выполнения операции.

Восстановление базы данных

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

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

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