Программирование LibreOffice Base. Часть 3
Сегодня мы рассмотрим использование диалоговых окон при редактировании данных в LibreOffice Base (OpenOffice Base). Как мы выяснили в предыдущих сообщениях, Форма LibreOffice Base (OpenOffice Base) — это фактически экземпляр текстового редактора LibreOffice (OpenOffice) Writer. Для организации оконного интерфейса внутри Формы используется Диалоги — которые удобно создаются во встроенным визуальном интерфейсе, но не имеют поддержки для связи с таблицами базы данных. Эту связь будем организовывать макросами OO Basic.
Начнем по-порядку. Создадим две таблицы в базе данных:
products
— id (целое, первичный ключ)
— name (строка)
orders
— id (целое, первичный ключ)
— productId (целое)
— count (целое)
— date (тип данных Дата)
Создадим форму orders, добавим в форму элемент Form с именем orders. А также Table Control с источником данных orders. Как это сделать рассматривалось в Части 2 серии сообщений.
При задании свойств колонки date обратите, пожалуйста, внимание на отмеченные на рисунке стрелками свойства, которые позволяют отображать данные в нужном формате и использовать выпадающий календарь для выбора конкретной даты.
Теперь прямо в таблице можно добавлять и изменять данные. До определенного момента это удобно, похоже на привычную работу клиента с табличным процессором. Но в какой-то момент начинаются проблемы, также характерные для работы с табличными процессорами. Данные можно изменить случайно, даже не заметив этого. А заметив невозможно откатить все как было. Места для новых колонок мало, и может образоваться неприятная горизонтальная прокрутка. Заголовки колонок также имеют ограничение по размеру (иначе не поместятся по горизонтали), и это не позволяет дать подробное описание данных.
В качестве полумеры можно рядом с таблицей разместить обычные поля для ввода данных (Text Control, Numeric Control и т.д.). В качестве источника данных задать соответствующие поля таблицы orders и все будет работать. При навигации по набору данных будут меняться данные в полях ввода. При изменении данных в полях ввода будут меняться данные в таблице базы данных. Но выглядеть это решение будет не очень красиво.
Поэтому реализуем такой функционал при помощи Диалогов. У Диалогов есть одно существенное ограничение. Поля ввода Диалогов не связаны с таблицей базы данных. Поэтому заполнение полей ввода Диалога из таблицы базы данных, и сохранение полей ввода в таблицу базы данных нужно будет делать макросом OO Basic. Впрочем, это и хорошо, т.к. позволяет рассмотреть возможности программирования OO Basic (до этого в моих сообщениях была описана работа только со средой, но все это было подготовкой к сегодняшнему сообщению).
Чтобы вызвать на экран редактор Диалогов, необходимо выбрать в меню Tools→Macros→Organize Macros→LibreOffice Basic→Organizer→Dialog→New|Edit|Delete. Хотелось бы иметь более быстрый способ добраться до этого редактора. После чего откроется редактор диалога (увы, не самый удобный), в котором мы создадим поля с именами полей таблицы базы данных. Как Вы помните Диалоги не связываются автоматически с таблицами базы данных поэтому мы напишем макрос, который сделает это. И в качестве соглашения об именовании определим имена полей ввода и полей таблицы базы данных одинаковыми.
Редактор с готовой формой будет выглядеть примерно так:
Далее, добавим в Диалог две кнопки. Имена кнопкам дадим произвольные, но начинающиеся с подчеркивания, чтобы отличить их от полей базы данных. Каждой кнопке в палитре свойств можно задать действие. Зададим одой кнопке действие OK — она закроет Диалог с подтверждением действия. А второй — Cancel — она закроет диалог без подтверждения действия.
Закроем редактор Диалогов, и вернемся в редактор Формы. Создадим кнопку, вызывающую диалог и назначим ей процедуру-обработчик Order_Edit, в которой будем заполнять Диалог из таблицы базы данных FromBaseToDialog (oForm, oDialog), и сохранять данные из Диалога таблицу базы данных FromDialogToBase (oDialog, oForm).
Sub Order_Edit(Event)
Dim oDialog As Object
Dim orders As Object
orders = Thiscomponent.DrawPage.Forms.GetByName("orders")
DialogLibraries.LoadLibrary("Standard")
oDialog = CreateUnoDialog(DialogLibraries.Standard.dialogOrder)
FromBaseToDialog(orders, oDialog)
If oDialog.Execute() = 1 Then
FromDialogToBase(oDialog, orders)
orders.UpdateRow()
End If
End Sub
Sub FromBaseToDialog(oForm, oDialog)
Dim I
Dim sName As String
For I = 0 To Ubound(oDialog.Model.ElementNames)
sName = oDialog.Model.ElementNames(I)
If Mid(sName, 1, 1) <> "_" And Mid(sName, 1, 5) <> "Label" Then
ODialog.GetControl(sName).SetText(oForm.Columns.GetByName(sName).String)
End If
Next I
End Sub
Sub FromDialogToBase(oDialog, oForm)
Dim I
Dim sName As String
For I = 0 To Ubound(oDialog.Model.ElementNames)
sName = oDialog.Model.ElementNames(I)
If Mid(sName, 1, 1) <> "_" And Mid(sName, 1, 5) <> "Label" Then
oForm.Columns.GetByName(sName).UpdateString(Trim(oDialog.GetControl(sName).GetText()))
End If
Next I
End Sub
Предполагается, что Диалог был сохранен в библиотеке Standard под именем dialogOrder. Естественно, Вы можете выбрать другие имена. Имена контролов, начинающиеся с подчеркивания пропускаются и не обрабатываются. Также не обрабатываются имена, начинающиеся с Label, которые используются для текстовых заголовков полей.
Вызов oDialog.Execute () = 1 отображает Диалог внутри окна Формы и приостанавливает работу макроса до нажатия кнопки OK или Cancel. При нажатии на кнопку OK выполнится равенство возвращаемого значения единице.
Вы, наверное, обратили внимание что мы создали таблицу products, которую пока не использовали. В следующем сообщении бы реализуем в Диалоге компонент аналогичный Combobox c возможностью поиска по первым введенным буквам слова.