Мир объектов Excel 2000

Сохранение заказа


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

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

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

Private Sub SaveOrder_Click() 'Сохранение заказа OrderSave End Sub

Рассмотрим код процедуры, выполняющей основную работу:

Public Sub OrderSave() 'Сохранение заказа Dim myDate As Object Dim myCombo As ComboBox Dim curField As Range, curField1 As Range Dim i As Integer Dim BCount As Boolean BCount = True Set curField = Range("A34:D34") Set curField1 = Range("F34") With ThisWorkbook.Worksheets(1).OLEObjects Set myDate = .Item("AccountDate").Object Set myCombo = .Item("ListOfTeam").Object End With 'Проверка заполнения полей "Количество" i = 0 Do While (Not IsEmpty(curField.Offset(i))) BCount = BCount And Not IsEmpty(curField1.Offset(i)) i = i + 1 Loop If BCount Then 'Заполнены поля "Количество" 'Добавление записи в таблицу "Заказы" Cmd1.CommandText = "Select * From [Заказы]" With Rst1 If .State = adStateOpen Then .Close .Open Source:=Cmd1, CursorType:=adOpenDynamic, _ LockType:=adLockOptimistic .AddNew !Заказчик = Range("D19").Text !Сотрудник = myCombo.Text !ДатаЗаказа = myDate.Caption !Стоимость = Range("K46") .Update OrderCode = !КодЗаказа


End With 'Добавление нескольких записей в таблицу "Заказано" Cmd1.CommandText = "Select * From [Заказано]" With Rst1 If .State = adStateOpen Then .Close .Open Source:=Cmd1, CursorType:=adOpenDynamic, _ LockType:=adLockOptimistic ' Цикл по строкам таблицы заказов i = 0 Set curField = Range("A34") Set curField1 = Range("F34") Do While (Not IsEmpty(curField.Offset(i))) .AddNew !КодЗаказа = OrderCode !НазваниеКниги = curField.Offset(i) !Количество = curField1.Offset(i) !Стоимость = curField1.Offset(i, 5) .Update i = i + 1 Loop End With 'Выключить кнопку "Сохранить Заказ" With ThisWorkbook.Worksheets(1).OLEObjects .Item("SaveOrder").Object.Enabled = False 'Поле NDS сделать невидимым .Item("NDS").Visible = False .Item("LabelNDS").Visible = False End With 'Номер заказа становится номером счета Range("F16") = OrderCode Else MsgBox ("Задайте значения в полях Количество!") End If End Sub

Приведу комментарии к тексту процедуры:

  • При формировании общих данных о заказе мне понадобится работать с текущей датой, получить информацию о сотруднике, оформляющем заказ. Для этого и введены объекты myDate и myCombo. Объекты curField и curField1 используются, как и в предыдущей процедуре, при работе с областями ячеек нашего документа.
  • Процедура начинает свою работу с инициализации перечисленных выше локальных объектов. Объекты myDate и myCombo связываются с соответствующими OLE-объектами, curField и curField1 устанавливаются в начальное положение, задавая первую запись в таблице заказов.
  • Еще один шаг работы процедуры, предваряющий основные действия, связан с "защитой от дурака". Я уже говорил, что, прежде чем нажать кнопку "Сохранить заказ", квалифицированный пользователь укажет количество для каждого заказываемого товара. Однако кнопка доступна для нажатия и тогда, когда эти данные не указаны. По этой причине, прежде чем пытаться записать данные о заказе в базу данных, я делаю проверку на заполнение этих полей. Если хотя бы одно из этих полей не заполнено, будет выдано предупреждающее сообщение. Соответствующий код этой части процедуры подсвечен.
  • В основной части работы процедуры вначале создается одна запись таблицы "Заказы". Следует обратить внимание на то, что "Код заказа" является для этой таблицы ключевым полем, имеет тип "Счетчик", и создается автоматически при добавлении каждой новой записи. Поэтому уже после того, как запись добавлена в базу данных, то есть после выполнения метода Update, я запоминаю в переменной OrderCode этот код. Он мне понадобится в дальнейшем для достижения двух целей - во-первых, для включения его в записи таблицы "Заказано", во-вторых, этот код будет одновременно служить уникальным номером нашего документа, который указывается в разделе заголовка документа.
  • Создание записей таблицы "Заказано" идет в цикле по числу заполненных строк таблицы заказов документа. Первая встреченная пустая строка служит признаком окончания цикла, по этой причине в таблице заказов не должно быть купюр.
  • Наконец, в заключительной части работы нашей процедуры, которая также выделена цветом, становится недоступной кнопка "Сохранить заказ". Действительно, заказ уже сохранен, повторное нажатие этой кнопки приведет к повторной записи заказа. Более того, поскольку ключом таблицы является счетчик, то сам Access не может предупредить о том, что подобная запись уже существует. В базе данных появится тот же заказ, но с новым кодом. Эта ситуация крайне нежелательна, по этой причине кнопка сохранения заказа должна быть недоступной до тех пор, пока не будет сформирован новый заказ.
  • Кроме выключения кнопки "Сохранить заказ", в заключительной части процедуры делаются невидимыми элементы управления, связанные с заданием НДС, а также для документа задается номер счета, на основании кода заказа.



Содержание раздела