Тверской государственный университет
Опубликован: 13.09.2006 | Доступ: свободный | Студентов: 5136 / 389 | Оценка: 4.23 / 3.83 | Длительность: 28:12:00
Специальности: Программист, Менеджер
Лекция 7:

Создание интерактивных офисных документов в Excel

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

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

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

С программной точки зрения никаких особых новых проблем при передаче данных из полей документа в таблицы базы данных не возникает. Объекты 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 не может предупредить о том, что подобная запись уже существует. В базе данных появится тот же заказ, но с новым кодом. Эта ситуация крайне нежелательна, по этой причине кнопка сохранения заказа должна быть недоступной до тех пор, пока не будет сформирован новый заказ.
  • Кроме выключения кнопки "Сохранить заказ", в заключительной части процедуры делаются невидимыми элементы управления, связанные с заданием НДС, а также для документа задается номер счета, на основании кода заказа.
Чистка полей таблицы заказа

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

Private Sub ClearOrder_Click()
	'Чистка полей заказа
	ClearBookFields
End Sub

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

Public Sub ClearBookFields()
	'Чистка полей документа
	Dim curField As Range
	Set curField = Range("A34:G45")
	curField.ClearContents
	Set curField = Range("I34:I45")
	curField.ClearContents
	
	'Установить свойства элементов управления
	With ThisWorkbook.Worksheets(1).OLEObjects
		.Item("LabelNDS").Visible = False
		.Item("NDS").Visible = False
		.Item("SaveOrder").Object.Enabled = False
	End With

End Sub

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

Обратите внимание на один чисто программистский аспект работы этой процедуры, связанный с OLE-объектами. Свойство Visible доступно для всех элементов коллекции OLEObjects. Но чтобы добраться до свойства Enabled, мне предварительно нужно вызвать свойство Object, и только потом у полученного объекта можно установить значение свойства Enabled.

На этом я заканчиваю рассмотрение интерактивности, добавляемой в раздел заказов нашего документа.

Ольга Гафарова
Ольга Гафарова

Добрый день. Подскажите формулы при решении задачи на рис. 2.2 в лекции №2. Закон Ома, какие должны использоваться формулы для I и R

Курс: Основы офисного программирования и документы Excel

Серегй Лушников
Серегй Лушников