Stavíme wrapper nad OpenOffice.org s použitím OLE/COM I.

Ač je databáze v Lotus Notes dokumentová a vývoj nám umožňuje poměrně solidní práci s formuláři a pohledy, zhusta potřebujeme pracovat s daty takovým způsobem, který se z hlubin Lotus Notes doluje velmi nesnadno. Spoustu operací provedete v nějakém kancelářském balíku lépe a rychleji. Není tedy od věci, mít možnost rychle vyexpedovat data ven, popř. je naopak importovat do databáze.

Kancelářské balíky, které stojí za úvahu, máme v současnosti na trhu v podstatě dva. V tomto článku popíšu zásadní body vývoje wrapperu pro ten druhý – OpenOffice.org. Použijeme OLE/COM model, takže hned zapomeňte na linuxové či macovské klienty. :-)
Zaměřím se na záseky, best practice, problémy, které jinde než v Lotus Scriptu nenajdete atd.

Základem všeho je služba

Open Office API je striktně typové a konvenční. Základní strukturou jsou services, neboli služby, které se volají při otevírání dokumentu. Jednoduše řečeno, o vše se stará nějaká služba. Pro inicializaci služeb potřebujeme třídu ServiceManager. Instanci této třídy zavoláme takto:

ServiceManager
Visual Basic
1
2
Dim SM as Variant
Set SM = CreateObject(com.sun.star.ServiceManager)

CreateObject je univerzální funkce, která inicializuje OLE objekt s danou signaturou. Aplikace s volaným API musí být vždy na daném počítači nainstalována. V případě, že tento OLE objekt není nalezen, vrátí funkce chybu číslo 208 – Cannot create automation object. Poté, co zavoláme tuto funkci, máme v proměnné SM ServiceManager, který sám o sobě neznamená nic, ale umožní nám volat potřebné služby pro práci s dokumenty OpenOffice.

Základem všeho ostatního je dokument

Základem práce s kancelářským balíkem je dokument. Pro práci s dokumentem je OOo potřeba iniciovat několik služeb.

Služby

Služby

Jak je vidět, těch služeb je celá řada, ale naštěstí to není tak komplikované, jak to na první pohled vypadá. Postačí zavolat službu Desktop a ta se postará o zbytek.

com.sun.star.frame.Desktop
Visual Basic
1
2
Dim Desktop as Variant
Set Desktop = SM.createInstance(com.sun.star.frame.Desktop)

O inicializaci dokumentu se stará třída com.sun.star.frame.Desktop, která implementuje rozhraní com.sun.star.frame.XComponentLoader, jednou jedinou metodou. Open Office API nerozlišuje otevírání stávajícího dokumentu od vytváření nového dokumentu jinak než parametrem této metody.

loadComponentFromURL
Visual Basic
1
2
3
Dim Document as Variant
Dim Args() as variant
Set Document = Desktop.loadComponentFromURL(URL, TargetFrameName, SearchFlags, Args())

Parametr URL je string, který určuje buď cestu k dokumentu, anebo typ nového dokumentu. Další dva parametry (název okna a příznak pro typ vyhledávání) není potřeba příliš řešit, v drtivé většině případů stačí zadat „_blank“ a 0. Poslední parametr je sada argumentů, které určují chování a vzhled otevíraného dokumentu. Je to pole objektů typu com.sun.star.beans.PropertyValue, kterým se jednotlivé parametry předávají formou vlastností Name a Value. Těch parametrů je celá řada a zhusta není potřeba je vůbec využívat. Pro takový případ postačí poslat do tohoto parametru prázdné pole. Ovšem občas tyto argumenty budeme potřebovat a tudíž si musíme umět vytvořit objekt PropertyValue. Budeme k tomu potřebovat objekt typu CoreReflection pro inicializaci vnitřních struktur, na které nevedou přímé reference. K tomuto účelu si zavedeme jednoduchou funkci CreateStruct.

CreateStruct
Visual Basic
1
2
3
4
5
6
7
8
9
10
Function CreateStruct(StructTypeName as Variant) as Variant
Dim CR as Variant
Dim ClassSize As Variant
Dim Struct As Variant
Set CR = SM.createInstance(com.sun.star.reflextion.CoreReflextion)
Set ClassSize = CR.forName(StructTypeName)
Call ClassSize.CreateObject(Struct)
Set CreateStruct = Struct
End Function

Dále si pomocí této funkce vytvoříme instanci třídy PropertyValue, do které nasázíme potřebné parametry startu dokumentu.

MakePropertyValue
Visual Basic
1
2
3
4
5
6
7
8
Public Function MakePropertyValue(pName As Variant, pValue As Variant) As Variant
Dim PropertyValue As Variant
Set PropertyValue = CreateStruct("com.sun.star.beans.PropertyValue")
Let PropertyValue.Name = pName
Let PropertyValue.Value = pValue
Set MakePropertyValue = PropertyValue
End Function

Jak je vidět, nemít Variant, byl by Lotus script ztracený :-)

Vytvořit nový, nebo otevřít stávající? Vše v jednom

A teď si můžeme ukázat jednoduchou funkci pro vytvoření nového dokumentu OpenOffice Calc, který otevřeme skrytý.

CreateNewDocument
Visual Basic
1
2
3
4
5
Sub CreateNewDocument
Dim Args(0) as Variant
Set Args(0) = MakePropertyValue("Hidden", True)
Set Document = Desktop.loadComponentFromURL(private:factory/scalc, "_blank", 0, Args)
End Sub

Jak jsem řekl, rozdíl mezi otevíráním a vytvářením dokumentu je pouze v parametru URL. Funkce pro otevření dokumentu je tedy velmi podobná jako funkce pro vytvoření nového. Abych to nekomplikoval, předpokládejme, že opět chceme dokument otevřít skrytě.

OpenDocument
Visual Basic
1
2
3
4
5
Sub OpenDocument(URL as String)
Dim Args(0) as Variant
Set Args(0) = MakePropertyValue(Hidden, True)
Set Document = Desktop.loadComponentFromURL(ConvertToURL(URL), _blank, 0, Args)
End Sub

Jak jste si všimli, prohnal jsem zadanou cestu jakousi záhadnou funkcí ConvertToURL. API Open Office je totiž velmi citlivé na zadané cesty, nesnese některé znaky, potřebuje speciální prefix a co je hlavní, zásadně neuznává zpětné lomítko, neboli backslash, čemuž naprosto rozumím :-) . A protože každá cesta na OS Windows je tvořena zpětnými lomítky, je potřeba zadanou cestu upravit.

ConvertToURL
Visual Basic
1
2
3
4
5
6
7
8
9
Function ConvertToURL(ByVal URL as String) as String
Let URL = Replace(URL, "\", "/")
Let URL = Replace(URL, ":", "|")
Let URL = Replace(URL, " ", "%20")
If Not Left$(URL, 8) = "file:///" Then
Let URL = "file:///" & URL
End If
Let ConvertToURL = URL
End Function

Jak vidíte, práce s API Open Office má svou logiku. Vše je zde čistě objektové. Na závěr prvního dílu vytvoříme bázovou třídu, která bude mít za úkol obsluhovat základní operace s dokumenty Open Office.

Co všechno budeme do hrnečku potřebovat?

Popsali jsme si základní mechanismy vytváření a otevírání dokumentů. Popsali jsme si práci se službami a strukturami. Zbývá určit si operace, které budeme po našem objektu požadovat.

Bude to bázová třída, chceme tedy pouze jednoduché operace Open, Create, Save, SaveAs, Close. Také by se hodil Print, i když to už je trochu za hranicí základních operačních primitiv. Určitě chceme umět nastavit viditelnost dokumentu. Pak možná nějaké drobnosti jako SelectAll, CopyToClipboard, Paste apod., abychom si ukázali jak na to.

OpenDocument a CreateDocument jsem již nastínil, zaměřím se tedy rovnou na Save a SaveAs. To je v Lotus Scriptu trochu tricky záležitost. Nebo alespoň bývala ve verzi 8.0 – na 8.5.x jsem netestoval.

O co jde? Jde o to, že uložení dokumentu bez udání cesty – tedy klasický Save, nikoliv SaveAs – se volá document.store(). Ten však v LS z neznámého důvodu nefunguje. Je potřeba tedy volat SaveAs a zadat cestu. Cestu si musíme pamatovat v globální proměnné třídy. V případě, že jde o nový dokument, zachováme se správně a neuděláme nic :-) .

Save
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Public Sub Save
    If Not IsEmpty(Me.oDocument) Then
        If Me.oDocument.hasLocation() Then
            ' Have to use SaveAs, because simple Doc.store() doesn't work in LS
            Call Me.SaveAs(Me.FilePath)
        End If
    End If
End Sub
Public Sub SaveAs(FilePath As String)
    Dim Args(0) As Variant
    If Not IsEmpty(Me.oDocument) Then
        Set Args(0) = Me.OOMakePropertyValue("Overwrite", True)
        Call Me.oDocument.StoreAsURL(Me.OOConvertToURL(FilePath), Args)
    End If
End Sub

Všimněte si vlastnosti dokumentu hasLocation(). Ta vrací true/false, zda jde o existující dokument, nebo jestli pracujeme s novým. PropertyValue jsme si již představili, já jen k názvu funkce přidal OO, abych rozlišil pomocné metody. A jinak se samozřejmě SaveAs v OpenOffice nejmenuje SaveAs, ale StoreAsURL. Jak jinak, že? :-)

Dále stojí za povšimnutí metoda, jak se sestavuje prázdné pole argumentů. V Lotus Scriptu neexistuje klasický null, je tedy potřeba vytvořit inicializované pole s jednou hodnotou, která je prázdná.

Jak takový otevřený dokument zavřeme? Jednoduše.

Close
Visual Basic
1
2
3
4
5
Public Sub Close
    If Not IsEmpty(Me.oDocument) Then
        Call Me.oDocument.Close(True)
    End If
End Sub

A co ten tisk? Není nic jednoduššího.

Print
Visual Basic
1
2
3
4
5
6
7
Public Sub Print
    Dim Args() As Variant
    If Not IsEmpty(Me.oDocument) Then
        Call Me.oDocument.Print(Args)
    End If
End Sub

Visibility, neboli viditelnost dokumentu. Tedy atribut, zda je při práci ten dokument vidět nebo ne. Ptáte se nač to? Pro pochopení problematiky je potřeba vědět, co se stane, když uživatel spustí akci, která pomocí OLE zobrazí třeba OpenOffice Calc a začne do něj cpát data. Ten skript běží třeba 20 sekund, uživatel nevydrží a začne do toho dokumentu chudákovi skriptovi hamtat kurzorem. Začne prostě s tím dokumentem pracovat, aniž by počkal, než export doběhne. V tu ránu celá operace spadne a skript uraženě zahlásí OLE Automation object error. Proto je lepší provést operaci na pozadí a zobrazit uživateli dokument až nakonec. Mezitím mu můžete přehrát nějakou animaci, třeba s pomocí klasického NEMProgressBaru.

SetVisible
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Public Sub SetVisible(IsVisible As Boolean)
    Dim oDocCtrl As Variant
    Dim oDocFrame As Variant
    Dim oDocWindow As Variant
    Dim oDocBook As Variant
    If Not IsEmpty(Me.oDocument) Then
        Set oDocCtrl = Me.oDocument.getCurrentController()
        Set oDocFrame = oDocCtrl.getFrame()
        Set oDocWindow = oDocFrame.getContainerWindow()
        Set oDocBook = oDocFrame.getComponentWindow()
        Call oDocWindow.setVisible(IsVisible)
        Call oDocBook.setVisible(IsVisible)
    End If
End Sub

Pro volání operací jako je SelectAll, Copy, Cut, nebo Paste je potřeba vytvořit instanci dispatcheru – tedy čas na další OO helper.

Dispatcher
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Public Sub OODocumentDispatch(URL As String, Args As Variant)
    Dim oController As Variant
    Dim oFrame As Variant
    Dim oDispatcher As Variant
    If Not IsEmpty(Me.oDocument) Then
        Set oDispatcher = Me.OOCreateService("com.sun.star.frame.DispatchHelper")
        Set oController = Me.oDocument.getCurrentController()
        Set oFrame = oController.getFrame()
    End If
    Call oDispatcher.executeDispatch(oFrame, URL, "", 0, Args)
End Sub

URL je v tomto případě opět nějaký příkaz, který má dispatcher nad dokumentem vykonat a vykonává je nad framem, což není nic jiného, než viewport našeho dokumentu.

Zavolat zmíněné oparece je pak už triviální.

Clipboard operations
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Public Sub SelectAll
    Dim Args() As Variant
    Call Me.OODocumentDispatch(".uno:SelectAll", Args)
End Sub
Public Sub ClipboardCopy
    Dim Args() As Variant
    Call Me.OODocumentDispatch(".uno:Copy", Args)
End Sub
Public Sub ClipboardCut
    Dim Args() As Variant
    Call Me.OODocumentDispatch(".uno:Cut", Args)
End Sub
Public Sub ClipboardPaste
    Dim Args() As Variant
    Call Me.OODocumentDispatch(".uno:Paste", Args)
End Sub

No a to by pro dnešek bylo vše. Příště bychom si mohli popsat pokročilejší operace, konstanty, které OpenOffice používá a zkusit postavit nějaký sofistikovanější framework pro exporty a importy dat.

Na závěr přidám na ukázku celou bázovou třídu OpenOfficeBase. Enjoy. :-)

OpenOfficeBase
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
%REM
%    Class OpenOfficeBase
%        Base handler for OpenOffice.org wrapper
%    @author Jiri Krakora aka Lokutus
%    @date 20.01.2010
%    @uses TObject
%    @revision 1.00.038 20.01.2010 Release
%END REM
Public Class OpenOfficeBase
    Private oSM As Variant            ' ServiceManager
    Private oDesktop As Variant        ' Desktop
    Private oDocument As Variant    ' Office document
    Private oCR As Variant            ' Core Reflection object to create structs
    Private oIsOpened As Boolean
    Private oIsVisible As Boolean
    Private oError As String
    Public Sub New
        ' First, create a primary object to create necessary services
        Set Me.oSM = CreateObject("com.sun.star.ServiceManager")
        ' Then create a Desktop service to handle document loading
        Set Me.oDesktop = Me.OOCreateService("com.sun.star.frame.Desktop")
        ' To create objects, use a CoreReflection class
        Set oCR = Me.OOCreateService("com.sun.star.reflection.CoreReflection")
    End Sub
    %REM
    %    Create new open office document object, either calc or writer
    %
    %    @param type of the new document
    %            private:factory/swriter for Writer object
    %            private:factory/scalc for Calc object
    %    @return true/false
    %END REM
    Public Function CreateDocument(DocumentType As String) As Boolean
        Dim Args(0) As Variant                ' Open params
        On Error 208 GoTo eh208
        ' If there is another document opened, it must be first saved and closed
        If Me.oIsOpened Then
            Let Me.oError = "Již je otevřen jiný sešit!"
            Exit Function
        End If
        Set Args(0) = Me.OOMakePropertyValue("Hidden", Not Me.oIsVisible)
        Set Me.oDocument = Me.oDesktop.loadComponentFromURL _
        (DocumentType, "_blank", 0, Args)
        Let Me.oIsOpened = True
        Let CreateDocument = True
es:
        Exit Function
eh208:
        Let Me.oError = "Balík OpenOffice.org není pravděpodobně nainstalován!"
        Resume es
    End Function
    %REM
    %    Open existing open office document object, either calc or writer
    %
    %    @param URL of the document to be opened
    %    @return true/false
    %END REM
    Public Function OpenDocument(FilePath As String) As Boolean
        Dim Args(0) As Variant                ' Open params
        On Error 208 GoTo eh208
        ' If there is another document opened, it must be first saved and closed
        If Me.oIsOpened Then
            Let Me.oError = "Již je otevřen jiný sešit!"
            Exit Function
        End If
        ' Check FilePath if it exists
        If Not Me.FileExists(FilePath) Then
            Let Me.oError = "Soubor nebyl nalezen!"
            Exit Function
        End If
        Set Args(0) = Me.OOMakePropertyValue("Hidden", Not Me.oIsVisible)
        Set Me.oDocument = Me.oDesktop.loadComponentFromURL _
        (Me.OOConvertToURL(FilePath), "_blank", 0, Args)
        Let Me.oIsOpened = True
        Let OpenDocument = True
es:
        Exit Function
eh208:
        Let Me.oError = "Balík OpenOffice.org není pravděpodobně nainstalován!"
        Resume es
    End Function
    %REM
    %    Save current document
    %END REM
    Public Sub Save
        If Not IsEmpty(Me.oDocument) Then
            If Me.oDocument.hasLocation() Then
                ' Have to use SaveAs, because simple Doc.store() doesn't work in LS
                Call Me.SaveAs(Me.FilePath)
            End If
        End If
    End Sub
    %REM
    %    Save current document - set new filepath
    %
    %    @param filepath
    %END REM
    Public Sub SaveAs(FilePath As String)
        Dim Args(0) As Variant
        If Not IsEmpty(Me.oDocument) Then
            Set Args(0) = Me.OOMakePropertyValue("Overwrite", True)
            Call Me.oDocument.StoreAsURL(Me.OOConvertToURL(FilePath), Args)
        End If
    End Sub
    %REM
    %    Send current document to a printer
    %END REM
    Public Sub Print
        Dim Args() As Variant
        If Not IsEmpty(Me.oDocument) Then
            Call Me.oDocument.Print(Args)
        End If
    End Sub
    %REM
    %    Close current document
    %END REM
    Public Sub Close
        If Not IsEmpty(Me.oDocument) Then
            Call Me.oDocument.Close(True)
        End If
    End Sub
    %REM
    %    Set user visibility of the current document
    %
    %    @param true/false if visible or not
    %END REM
    Public Sub SetVisible(IsVisible As Boolean)
        Dim oDocCtrl As Variant
        Dim oDocFrame As Variant
        Dim oDocWindow As Variant
        Dim oDocBook As Variant
        If Not IsEmpty(Me.oDocument) Then
            Set oDocCtrl = Me.oDocument.getCurrentController()
            Set oDocFrame = oDocCtrl.getFrame()
            Set oDocWindow = oDocFrame.getContainerWindow()
            Set oDocBook = oDocFrame.getComponentWindow()
            Call oDocWindow.setVisible(IsVisible)
            Call oDocBook.setVisible(IsVisible)
        End If
    End Sub
    %REM
    %    Select whole content of the current document
    %        simulate Ctrl+A
    %END REM
    Public Sub SelectAll
        Dim Args() As Variant
        Call Me.OODocumentDispatch(".uno:SelectAll", Args)
    End Sub
    %REM
    %    Copy selection into a clipboard
    %        simulate Ctrl+C
    %END REM
    Public Sub ClipboardCopy
        Dim Args() As Variant
        Call Me.OODocumentDispatch(".uno:Copy", Args)
    End Sub
    %REM
    %    Copy selection into a clipboard and delete content
    %        simulate Ctrl+X
    %END REM
    Public Sub ClipboardCut
        Dim Args() As Variant
        Call Me.OODocumentDispatch(".uno:Cut", Args)
    End Sub
    %REM
    %    Paste content of the clipboard into document
    %        simulate Ctrl+V
    %END REM
    Public Sub ClipboardPaste
        Dim Args() As Variant
        Call Me.OODocumentDispatch(".uno:Paste", Args)
    End Sub
'---+----+10--+----+20--+----+30--+----+40--+----+50--+----+60--+----+70--+----+
' ____ ____ ___ ___ ______ __ __
' / __ \/ __ \ ___ / _ | / _ \/ _/ // /__ / /__ ___ _______
' / /_/ / /_/ // _ \/ __ |/ ___// // _ / -_) / _ Y -_) __(_-<
' \____/\____(_)___/_/ |_/_/ /___/_//_/\__/_/ .__|__/_/ /___/
' /_/
'---+----+10--+----+20--+----+30--+----+40--+----+50--+----+60--+----+70--+----+
    %REM
    %    Create new service using service manager
    %
    %    @param service type name (e.g. com.sun.star.frame.Desktop)
    %    @return newly create instance of the required service
    %END REM
    Public Function OOCreateService(ServiceTypeName As String) As Variant
        Set OOCreateService = Me.oSM.createInstance(ServiceTypeName)
    End Function
    %REM
    %    Create new structure using CoreReflexion class
    %
    %    @param structure type name (e.g. com.sun.star.beans.PropertyValue)
    %    @return newly create instance of the required structure
    %END REM
    Public Function OOCreateStruct(StructTypeName As String) As Variant
        Dim ClassSize As Variant
        Dim oStruct As Variant
        Set ClassSize = Me.oCR.forName(StructTypeName)
        Call ClassSize.CreateObject(oStruct)
        Set OOCreateStruct = oStruct
    End Function
    %REM
    %    Create command dispatcher and perform a dispatch action
    %
    %    @param url or the command (e.g. .uno:Copy)
    %    @param arguments
    %END REM
    Public Sub OODocumentDispatch(URL As String, Args As Variant)
        Dim oController As Variant
        Dim oFrame As Variant
        Dim oDispatcher As Variant
        If Not IsEmpty(Me.oDocument) Then
            Set oDispatcher = Me.OOCreateService("com.sun.star.frame.DispatchHelper")
            Set oController = Me.oDocument.getCurrentController()
            Set oFrame = oController.getFrame()
        End If
        Call oDispatcher.executeDispatch(oFrame, URL, "", 0, Args)
    End Sub
    %REM
    %    Create an instance of the property object with key and value
    %
    %    @param required property name
    %    @param required property value
    %    @return instance of the PropertyValue object
    %END REM
    Public Function OOMakePropertyValue(pName As Variant, pValue As Variant) _
    As Variant
        Dim oPropertyValue As Variant
        Set oPropertyValue _
        = Me.OOCreateStruct("com.sun.star.beans.PropertyValue")
        Let oPropertyValue.Name = pName
        Let oPropertyValue.Value = pValue
        Set OOMakePropertyValue = oPropertyValue
    End Function
    %REM
    %    Return converted url
    %
    %    @param url to be converted
    %    @return converted url
    %END REM
    Public Function OOConvertToURL(ByVal URL As String) As String
        Let URL = Replace(URL, "\", "/")
        Let URL = Replace(URL, ":", "|")
        Let URL = Replace(URL, " ", "%20")
        If Not Left$(URL, 8) = "file:///" Then
            Let URL = "file:///" & URL
        End If
        Let OOConvertToURL = URL
    End Function
    %REM
    %    Return current instance of the service manager object
    %
    %    @return current instance of the service manager object
    %END REM
    Public Property Get Application As Variant
        Set Application = Me.oSM
    End Property
    %REM
    %    Return current instance of the desktop object
    %
    %    @return current instance of the desktop object
    %END REM
    Public Property Get Desktop As Variant
        Set Desktop = Me.oDesktop
    End Property
    %REM
    %    Return current instance of the document object
    %
    %    @return current instance of the document object
    %END REM
    Public Property Get Document As Variant
        Set Document = Me.oDocument
    End Property
    Public Property Get Error As String
        Let ~Error = Me.oError
    End Property
    %REM
    %    Set current instance of the document object
    %
    %    @param document object
    %END REM
    Public Property Set Document As Variant
        Set Me.oDocument = Document
    End Property
    %REM
    %    Return filepath of the current document
    %
    %    @return filepath of the current document
    %END REM
    Public Property Get FilePath As String
        If Not IsEmpty(Me.oDocument) Then
            If Me.oDocument.hasLocation() Then
                Let FilePath = Me.oDocument.getURL()
            End If
        End If
    End Property
    %REM
    %    Return filename of the current document
    %
    %    @return filename of the current document
    %END REM
    Public Property Get FileName As String
        Let FileName = StrRightBack(Me.FilePath, "/")
    End Property
    %REM
    %    Return current instance of the core reflection object
    %
    %    @return current instance of the core reflection object
    %END REM
    Public Property Get CoreReflection As Variant
        Set CoreReflection = Me.oCR
    End Property
    %REM
    %    Return current instance of the core reflection object
    %
    %    @return current instance of the core reflection object
    %END REM
    Public Property Get CR As Variant
        Set CR = Me.oCR
    End Property
    %REM
    %    Return true/false if current document is modified
    %
    %    @return true/false
    %END REM
    Public Property Get IsModified As Variant
        Set IsModified = Me.oDocument.isModified()
    End Property
    %REM
    %    Return true/false if current document is visible
    %
    %    @return true/false
    %END REM
    Public Property Get IsVisible As Boolean
        Let IsVisible = Me.oIsVisible
    End Property
    %REM
    %    Set user visibility of the current document
    %
    %    @return true/false
    %END REM
    Public Property Set IsVisible As Boolean
        Let Me.oIsVisible = IsVisible
        Call Me.SetVisible(IsVisible)
    End Property
    %REM
    %    Check if Open Office is installed on the current computer
    %        throw OLE Automation error if not
    %
    %    @return true/false
    %END REM
    Public Property Get IsOfficeInstalled As Boolean
        Dim tmp As Variant
        On Error 208 GoTo eh208
        Set tmp = CreateObject("com.sun.star.ServiceManager")
        Let IsOfficeInstalled = True
es:
        Exit Property
eh208:
        Let Me.oError = "Balík OpenOffice.org není pravděpodobně nainstalován!"
        Resume es
    End Property
    %REM
    %    Check if the file exists
    %
    %    @param filepath
    %    @return true/false
    %END REM
    Private Function FileExists(Path As String) As Boolean
        On Error 53 GoTo eh53
        If (GetFileAttr(Path) And 16) = 0 Then
            Let FileExists = True
        End If
es:
        Exit Function
eh53:
        Resume es
    End Function
End Class

Komentování je uzavřeno.