воскресенье, 3 июня 2012 г.

OpenOffice Base - что же дальше

Я понимаю, что читатель истосковался по более сложному коду. И он скорo будет опубликован. Мое направление сейчас - обернуть функционалом стандартный котнрол Диалогов - ComboBox.

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

пятница, 1 июня 2012 г.

Объекты Connection, Statement, ResultSet в OpenOffice

Для решения простых задач достаточно декларативно задать объекты данных в Мастерах-построителях или в Палитрах свойств объектов Формы. Если бы на этом возможности OpenOffice заканчивались, то кроме игр с данными ему сложно было бы найти применение. Вспоминаю сколько раз я раскрывал Star/OpenOffice, создавал подключение к серверу баз данных и с грустью закрывал, полистав весьма скудный (и до сих пор это так) Help.

Но время не стоит на месте. В Интернете начала накапливаться полезная информация о макросах OpenOffice и вот мы здесь.

Для начала работы следует получить объект Connection. Его можно получить несколькими способами. В частности из свойства ActiveConnection объекта Form или по символическому имени DataSource, которое можно задавать из Главного меню|OpenOffice Tools|Options|OpenOffice.org Base|Databases. Если вынести функцию GetConnection в скрипт из раздела My Macros, всегда будет достаточно изменить код ровно в одном месте чтобы измененить подключение.

Function GetConnection() As Variant

  Dim DataSource As Variant
  Dim Connection As Variant
  DatabaseContext = CreateUnoService("com.sun.star.sdb.DatabaseContext")
  DataSource = DatabaseContext.GetByName("sourcename")
  GetConnection = DataSource.GetConnection()

End Function

Получив Connection надо создать Satement или PreparedStatement.

oStatement = GetConnection().CreateStatement
oResultSet = Statement.ExecuteQuery("select * from ...")
lCount = Statement.ExecuteUpdate("update ...")

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

pStatement = GetConnection().PrepareStatement("update ... set ... = ? where ... = ?")
pStatement.SetDouble(1, 123.456)
pStatement.SetString(2, "789" )
                                                    ' pStatement.ExecuteQuery
pStatement.ExecuteUpdate


Объект ResultSet, полученный в результате запроса поддерживает удобную (привычную) навигацию и может быть изменяемым. То есть все плюшки, известные по ODBC/JDBC/DAO/ADO  и иже с ними налицо. Впрочем это все уже можно прочитать в Интернете. Я же хотел дать зацепки для поиска нужных моментов. Пока.

четверг, 31 мая 2012 г.

Библиотеки, диалоги и документы Writer при работе с OpenOffice Base

(Важное замечания. В связи с Выходом 3-й версии ООфиса автор изменил точку зрения и применяет библиотеки уровня файла базы данных, которых не было во 2-й версии ООфиса)

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

Начнем собственно с OpenOffice Base. Мы уже отмечали раннее, что Форма открывается как документ Writer  и собственно им и является. Отсюда очевидное решение. Зачем "грузить" многофункциональное IDE Base, если можно сразу разрабатывать Форму в IDE Writer. Результат совершенно аналогичный.

Идем дальше. Программный код хранится во внешних библиотеках, которые представляют собой папку/ каталог на диске и макросах/скриптах, которые представляют собой файл .vba. Внешние скрипты отображаются в разделе  My Macros. Существуют еще и внутренние приватные скрипты, которые хранятся вместе с Формой во внутреннем формате документа Writer. Несмотря на то, что такие скрипты удобно распространять (вместе с файлом), их повторная применяемость исключена,  так как они существуют только внутри Формы/документа Writer.

Без внутренних скриптов не обойтись. Они загружаются вместе со своим документом, в то время как внешние библиотеки должны быть явно загружены таким вот оператором:

GlobalScope.BasicLibraries.LoadLibrary("LibName")

Теперь процедуры и функции библиотеки становятся доступны в текущем контексте. К ним можно обращаться как SomeFunction() или Libname.SomeFunction(). В последнем случае мы застрахованы от переопределения функций в разных библиотеках.

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

Funcion OpenDialog(sLibName, sDialogName)

  GlobalScope.DialogLibraries.LoadLibrary(sLibName)
  oLib = GlobalScope.DialogLibraries.GetByName(sLibName)
  oDialog = oLib.GetByName(sDialogName)
  oDlg = CreateUnoDialog(oDialog)
  oDlg.Execute()
  OpenDialog = oDlg

End Function

Это все, что сегодня я хотел сказать. Пока.

вторник, 29 мая 2012 г.

Подчиненные объекты form и списки в OpenOffice как реляцинные таблицы баз данных

Как мы уже уточнили в прошлом сообщении объект form может непосредственно входить в коллекцию forms,  а может быть подчиненным другому объекту form. Для этого открыв Навигатор форм надо выделить существующую form и правая кнопка мыши|new form.

Вспомним, что объект  form является объектом типа ResultSet. Поэтому с каждой form нужно связать существующую таблицу данных, запрос или SQL-запрос. В подчиненной form отражаются данные отфильтрованные по значению связанных полей в основной form по типу Master/Slave. Для этого в редакторе свойств подчиненной формы нужно заполнить свойства link master fields и link slave fields.

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

Второй тип связи, который мы рассмотрим - связь типа Справочник. Это распространенный случай. Мы храним в таблице данных ключ объекта (GUID, autoincrement и т.п.) а в отображаемой таблице выводим его полное наименование. Для этого есть удобный механизм. В визуальном Конструкторе таблицы выделяем колонку правая кнопка мыши|Replace With|List Box. Далее редактируем список свойств колонки. На закладке data свойству Тype of List Content присваиваем значение SQL. Запрос в свойстве List Content должен в первой колонке содержать отображаемое значение, а свойство Bound Field индекс колонки с ключевым полем (если считать, что первая колонка имеет индекс 0). То есть в подавляющем большинстве запросов это будет 1 для запросов типа

SELECT USERNAME, USERID FROM USERS ORDER BY USERNAME

Еще одна плюшка - накладывать фильтр на таблицу данных можно по значению введенному в текстовое поле. Для этого напишем на языке OO Basic процедуру обрабатывающую событие от клавиатуры.


Sub TextBox_onKeyUp(oEvent)
 
  oDocument = ThisComponent
  oDocument.LockControllers
  sText = oEvent.Source.text

  if Len(sText) > 3 Then
    oForm =  ThisComponent.Drawpage.Forms.getByName("MyForm")
    oForm.Filter = "USERNAME LIKE '" + sText  + "%'"
    oForm.reload()
  End If

  oDocument.UnlockControllers 

End Sub

Свяжем его с событием Key released текстового поля (на закладке event списка свойств). Заметим, что это поле должно быть расположено в другой form, чтобы перезагрузка form не "обнуляло" его текущее значение, введенное с клавиатуры. Пока.

воскресенье, 27 мая 2012 г.

Формы, Forms и Form в OpenOffice Base

С формами в OpenOffice Base произошла некоторая путаница. Я не ошибся в названии. Дело в том, что в процессе эволюции программного обеспечения оказалось, что Формы, Forms и Form - это немного не одно и то же. И Form - это не только Form. Поясню подробнее.

Когда Вы открываете базу данных OpenOffice Base в режиме редактирования, то видите в левой части экрана четыре закладки. В русифицированной версии это будет звучать как
  • Таблицы
  • Запросы
  • Формы
  • Отчеты
В этом смысле Форма является некоторым самостоятельным приложением, которое запускается в отдельном окне Windows. Замечу еще, что на самом деле это окно в котором запускается экземпляр OpenOffice Writer (ну и ну!)

OpenOffice Base - подключение к серверу баз данных

В предыдущем сообщении описан процесс установки среды для работы с базами данных - сервер PostgreSQL и пакет OpenOffice версии 2.4.1 или выше. Кроме того описано как установить некоторые плагины/расширения для OpenOffice. Сейчас для нас важно иметь плагин/расширение postgresql-sdbc для прямого доступа к серверу PostgreSQL. Не все релизы плагинов/расширений совместимы с конкретным релизом OpenOffice. О чем могут выдаваться предупреждающе сообщения, а могут и не выдаваться.

Если плагин/расширение установлен правильно, он должен иметь статус Enabled в окне Tolls|Extension Manager, вызываемого из Главного меню OpenOffice. Если это так - подключимся к существующей базе данных PostgreSQL. (Создание баз данных в PostgreSQL выходит за рамки этой серии сообщений, поскольку уже хорошо описано в документации PostgreSQL).

суббота, 26 мая 2012 г.

Начинаем работу с OpenOffice Base

Кому предназначен этот пост - прежде всего мне. Если Вы ищете средство для быстрой разработки интерфейса к серверу баз данных, например PostgreSQL - значит, возможно, и Вам.

Для 99% случаев, данные стоит хранить на SQL-сервере, не обязательно MS. Не ввязываясь в полемику какой сервер круче, замечу, что бесплатных и легко администрируемых серверов в настоящее время предостаточно. К известным всем решениям я могу добавить только свеженький Cubrid-сервер.

Сервер баз данных - это, конечно, хорошо. Но на чем писать клиентскую часть? Практически все средства быстрой разработки коммерческие. И даже если это стоит недорого - никто не застрахован от наличия в руководстве зациклившихся на своем Эго субъектов, от которых зависит решение. Мне приходилось слышать разные типы отказов от "то же самое можно сделать и в Excel" до "я Вам напишу это за день на Делфях и оба будем счастливы". И вот по крайней мере с версии 2.0 OpenOffice уже содержит хороший набор средств для быстрой разработки клиентской части баз данных. Эти средства пока мало востребованы. Основная причина, на мой взгляд - отсутствие документации. Прошло 5 лет, вышел очередной релиз - OpenOffice 3, наконец, фрагменты кода стали гулять в Интернете. Вышла подробная книга на английском языке и первая книга на русском о программировании на языке OO Basic для OpenOffice и OpenOffice Base.