После почти двухлетнего перерыва, связанного со сменой профессональных интересов и поиском красивых решений — продолжаю повествование. Что же поменялось?

Во-первых, я стал более ориентироваться на использование в качестве движка OpenOfficrBase (not OpenOfficeWriter). Это произошло в связи с тем, что 3-я версия офиса поддерживает библиотеки уроня файла базы данных, которые могут удобно распрастраняться внутри файла .odb.

Во-вторых, я перешел на использование соединения JDBC, так как «родные» офисные соединения, к сожалению, не всегда поддерживают возможности JDBC 3…4.

В-третьих, я перешел на использование вода через форму (а не прямо в таблице). Это обусловлено и большей наработкой кода, который позволяет мастерить формы без проблем. И, в большей степени, из-за обнаружившегося ограничения ввода связанных данных через список (или комбобокс) примерно 30 тыс. строк (связано с разядностью целого числа).

Теперь немного кода.

Довольно накладно заполнять форму из базы данных и сохранять значения формы в базе данных. Соблюдая некоторые соглашения об именовании, можно это сделать просто (имя поля равно имени элемента)

Sub FromBaseToDialog(oForm, oDialog)
If oForm.IsNew Or oForm.IsAfterLast() Or oForm.IsBeforeFirst() Then
Exit Sub
End If
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
If Mid(sName, 1, 6) = "_date_" Then
DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
If Mid(sName, 1, 7) = "_combo_" Then
'xRay oForm.Columns.GetByName(Mid(sName, 8))
If oForm.Columns.GetByName(Mid(sName, 8)).String <> "" Then
InitComboBox(oDialog, sName, oForm.Columns.GetByName(Mid(sName, 8)).String)
End If
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
If Mid(sName,1,4) = "date" Then
oForm.Columns.GetByName(sName).UpdateString(ctl.util.Replace(Trim(oDialog.GetControl(sName).GetText()), ",", "."))
Else
oForm.Columns.GetByName(sName).UpdateString(Trim(oDialog.GetControl(sName).GetText()))
End If
End If
If Mid(sName, 1, 6) = "_date_" Then
DateFromControlToBase(ODialog.GetControl(sName), oForm.Columns.GetByName(Mid(sName, 7)))
' DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
If Mid(sName, 1, 7) = "_combo_" Then
oForm.Columns.GetByName(Mid(sName, 8)).UpdateString(ODialog.GetControl(sName).GetModel.Tag)
' DateFromBaseToControl(oForm.Columns.GetByName(Mid(sName, 7)), ODialog.GetControl(sName))
End If
Next I
End Sub

Как видно, есть специальные имена, начинающиеся с знака подчеркивания. Они подойдут для всяких меток, которые не должны обрабатываться. И еще пока что два обрабатываемых имени _date_ и _combo_, которые обрабатываются специальным образом. О списках  (комбобоксах) ма поговорим в следующий раз, а о датах можно поговорить сейчас. OpenOffice удобно обрабатывает даты вводом через календарь, но что касается перевода БД в строку, присваивания строки элементу и обратно — то тут царит полнй хаос. Для PosgreSQL я использую вспомогательные функции:

Function DateToControl(dt) As Long
DateToControl = dt.YEAR*10000 + dt.MONTH*100 + dt.DAY
End Function

Sub DateFromBaseToControl(field, ctl)
If DateToControl(field.DATE) > 0 Then
ctl.SetDate(DateToControl(field.DATE)
Else
ctl.SetText("")
End If
End Sub

Function DateFromControl(dt As Long) As Object
Dim oDt As New com.sun.star.util.Date
Dim NewDate As String
NewDate = dt
If dt > 0 Then
oDt.YEAR = Mid(NewDate,1,4)
oDt.MONTH = Mid(NewDate,5,2)
oDt.DAY = Mid(NewDate,7,2)
End If
DateFromControl = oDt
End Function

Sub DateFromControlToBase(ctl, field)
if ctl.GetDate() <> 0 Then
field.UpdateDate(DateFromControl(ctl.GetDate()))
else
field.UpdateNull()
End If
End Sub

Ну вот собственно и все.

Теперь по кнопке вызываем диалог:

Sub Dogovor_Edit(Event)
Dim oDialog As Object
Dim f_dogovor As Object
f_dogovor = Thiscomponent.DrawPage.Forms.GetByName("f_dogovor")
oDialog = GetDialog("ctl", "dogovor")
If oDialog.Execute() = 1 Then
If Event.Source.Model.Tag = "new" Then
f_dogovor.MoveToInsertRow()
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.InsertRow()
Else
ctl.util.FromDialogToBase(oDialog, f_dogovor)
f_dogovor.UpdateRow()
EndIf
Else
End If
End Sub



Пока.

От Apa Pacy