Программирование 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 обратите, пожалуйста, внимание на отмеченные на рисунке стрелками свойства, которые позволяют отображать данные в нужном формате и использовать выпадающий календарь для выбора конкретной даты.

Рисунок
image


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

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

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

Чтобы вызвать на экран редактор Диалогов, необходимо выбрать в меню Tools→Macros→Organize Macros→LibreOffice Basic→Organizer→Dialog→New|Edit|Delete. Хотелось бы иметь более быстрый способ добраться до этого редактора. После чего откроется редактор диалога (увы, не самый удобный), в котором мы создадим поля с именами полей таблицы базы данных. Как Вы помните Диалоги не связываются автоматически с таблицами базы данных поэтому мы напишем макрос, который сделает это. И в качестве соглашения об именовании определим имена полей ввода и полей таблицы базы данных одинаковыми.

Редактор с готовой формой будет выглядеть примерно так:

Рисунок
image


Далее, добавим в Диалог две кнопки. Имена кнопкам дадим произвольные, но начинающиеся с подчеркивания, чтобы отличить их от полей базы данных. Каждой кнопке в палитре свойств можно задать действие. Зададим одой кнопке действие 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 возможностью поиска по первым введенным буквам слова.

© Habrahabr.ru