1 # -*- coding: utf-8 -*-
3 # Copyright 2020-2022 Jean-Pierre LEDURE, Rafael LIMA, Alain ROMEDENNE
5 # =====================================================================================================================
6 # === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
7 # === Full documentation is available on https://help.libreoffice.org/ ===
8 # =====================================================================================================================
10 # ScriptForge is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 # ScriptForge is free software; you can redistribute it and/or modify it under the terms of either (at your option):
16 # 1) The Mozilla Public License, v. 2.0. If a copy of the MPL was not
17 # distributed with this file, you can obtain one at http://mozilla.org/MPL/2.0/ .
19 # 2) The GNU Lesser General Public License as published by
20 # the Free Software Foundation, either version 3 of the License, or
21 # (at your option) any later version. If a copy of the LGPL was not
22 # distributed with this file, see http://www.gnu.org/licenses/ .
25 ScriptForge libraries are an extensible and robust collection of macro scripting resources for LibreOffice
26 to be invoked from user Basic or Python macros. Users familiar with other BASIC macro variants often face hard
27 times to dig into the extensive LibreOffice Application Programming Interface even for the simplest operations.
28 By collecting most-demanded document operations in a set of easy to use, easy to read routines, users can now
29 program document macros with much less hassle and get quicker results.
31 ScriptForge abundant methods are organized in reusable modules that cleanly isolate Basic/Python programming
32 language constructs from ODF document content accesses and user interface(UI) features.
34 The scriptforge.py module
35 - implements a protocol between Python (user) scripts and the ScriptForge Basic library
36 - contains the interfaces (classes and attributes) to be used in Python user scripts
37 to run the services implemented in the standard libraries shipped with LibreOffice
41 When Python and LibreOffice run in the same process (usual case): either
42 from scriptforge import * # or, better ...
43 from scriptforge import CreateScriptService
45 When Python and LibreOffice are started in separate processes,
46 LibreOffice being started from console ... (example for Linux with port = 2021)
47 ./soffice --accept='socket,host=localhost,port=2021;urp;'
48 then use next statement:
49 from scriptforge import * # or, better ...
50 from scriptforge import CreateScriptService, ScriptForge
51 ScriptForge(hostname = 'localhost', port = 2021)
53 Specific documentation about the use of ScriptForge from Python scripts:
54 https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_intro.html?DbPAR=BASIC
64 class _Singleton(type):
66 A Singleton metaclass design pattern
67 Credits: « Python in a Nutshell » by Alex Martelli, O'Reilly
71 def __call__(cls
, *args
, **kwargs
):
72 if cls
not in cls
.instances
:
73 cls
.instances
[cls
] = super(_Singleton
, cls
).__call
__(*args
, **kwargs
)
74 return cls
.instances
[cls
]
77 # #####################################################################################################################
78 # ScriptForge CLASS ###
79 # #####################################################################################################################
81 class ScriptForge(object, metaclass
= _Singleton
):
83 The ScriptForge (singleton) class encapsulates the core of the ScriptForge run-time
84 - Bridge with the LibreOffice process
85 - Implementation of the inter-language protocol with the Basic libraries
86 - Identification of the available services interfaces
87 - Dispatching of services
88 - Coexistence with UNO
90 It embeds the Service class that manages the protocol with Basic
93 # #########################################################################
95 # #########################################################################
98 componentcontext
= None
100 SCRIPTFORGEINITDONE
= False
102 # #########################################################################
104 # #########################################################################
105 library
= 'ScriptForge'
106 Version
= '7.6' # Actual version number
108 # Basic dispatcher for Python scripts
109 basicdispatcher
= '@application#ScriptForge.SF_PythonHelper._PythonDispatcher'
110 # Python helper functions module
111 pythonhelpermodule
= 'ScriptForgeHelper.py'
113 # VarType() constants
114 V_EMPTY
, V_NULL
, V_INTEGER
, V_LONG
, V_SINGLE
, V_DOUBLE
= 0, 1, 2, 3, 4, 5
115 V_CURRENCY
, V_DATE
, V_STRING
, V_OBJECT
, V_BOOLEAN
= 6, 7, 8, 9, 11
116 V_VARIANT
, V_ARRAY
, V_ERROR
, V_UNO
= 12, 8192, -1, 16
118 objMODULE
, objCLASS
, objUNO
= 1, 2, 3
119 # Special argument symbols
120 cstSymEmpty
, cstSymNull
, cstSymMissing
= '+++EMPTY+++', '+++NULL+++', '+++MISSING+++'
121 # Predefined references for services implemented as standard Basic modules
122 servicesmodules
= dict([('ScriptForge.Array', 0),
123 ('ScriptForge.Exception', 1),
124 ('ScriptForge.FileSystem', 2),
125 ('ScriptForge.Platform', 3),
126 ('ScriptForge.Region', 4),
127 ('ScriptForge.Services', 5),
128 ('ScriptForge.Session', 6),
129 ('ScriptForge.String', 7),
130 ('ScriptForge.UI', 8)])
132 def __init__(self
, hostname
= '', port
= 0):
134 Because singleton, constructor is executed only once while Python active
135 Arguments are mandatory when Python and LibreOffice run in separate processes
136 :param hostname: probably 'localhost'
137 :param port: port number
139 ScriptForge
.hostname
= hostname
140 ScriptForge
.port
= port
141 # Determine main pyuno entry points
142 ScriptForge
.componentcontext
= self
.ConnectToLOProcess(hostname
, port
) # com.sun.star.uno.XComponentContext
143 ScriptForge
.scriptprovider
= self
.ScriptProvider(self
.componentcontext
) # ...script.provider.XScriptProvider
145 # Establish a list of the available services as a dictionary (servicename, serviceclass)
146 ScriptForge
.serviceslist
= dict((cls
.servicename
, cls
) for cls
in SFServices
.__subclasses
__())
147 ScriptForge
.servicesdispatcher
= None
149 # All properties and methods of the ScriptForge API are ProperCased
150 # Compute their synonyms as lowercased and camelCased names
151 ScriptForge
.SetAttributeSynonyms()
153 ScriptForge
.SCRIPTFORGEINITDONE
= True
156 def ConnectToLOProcess(cls
, hostname
= '', port
= 0):
158 Called by the ScriptForge class constructor to establish the connection with
159 the requested LibreOffice instance
160 The default arguments are for the usual interactive mode
162 :param hostname: probably 'localhost' or ''
163 :param port: port number or 0
164 :return: the derived component context
166 if len(hostname
) > 0 and port
> 0: # Explicit connection request via socket
167 ctx
= uno
.getComponentContext() # com.sun.star.uno.XComponentContext
168 resolver
= ctx
.ServiceManager
.createInstanceWithContext(
169 'com.sun.star.bridge.UnoUrlResolver', ctx
) # com.sun.star.comp.bridge.UnoUrlResolver
171 conn
= 'socket,host=%s,port=%d' % (hostname
, port
)
172 url
= 'uno:%s;urp;StarOffice.ComponentContext' % conn
173 ctx
= resolver
.resolve(url
)
174 except Exception: # thrown when LibreOffice specified instance isn't started
176 'Connection to LibreOffice failed (host = ' + hostname
+ ', port = ' + str(port
) + ')')
178 elif len(hostname
) == 0 and port
== 0: # Usual interactive mode
179 return uno
.getComponentContext()
181 raise SystemExit('The creation of the ScriptForge() instance got invalid arguments: '
182 + '(host = ' + hostname
+ ', port = ' + str(port
) + ')')
185 def ScriptProvider(cls
, context
= None):
187 Returns the general script provider
189 servicemanager
= context
.ServiceManager
# com.sun.star.lang.XMultiComponentFactory
190 masterscript
= servicemanager
.createInstanceWithContext(
191 'com.sun.star.script.provider.MasterScriptProviderFactory', context
)
192 return masterscript
.createScriptProvider("")
195 def InvokeSimpleScript(cls
, script
, *args
):
197 Create a UNO object corresponding with the given Python or Basic script
198 The execution is done with the invoke() method applied on the created object
199 Implicit scope: Either
200 "application" a shared library (BASIC)
201 "share" a library of LibreOffice Macros (PYTHON)
202 :param script: Either
203 [@][scope#][library.]module.method - Must not be a class module or method
204 [@] means that the targeted method accepts ParamArray arguments (Basic only)
205 [scope#][directory/]module.py$method - Must be a method defined at module level
206 :return: the value returned by the invoked script, or an error if the script was not found
209 # The frequently called PythonDispatcher in the ScriptForge Basic library is cached to privilege performance
210 if cls
.servicesdispatcher
is not None and script
== ScriptForge
.basicdispatcher
:
211 xscript
= cls
.servicesdispatcher
214 # Build the URI specification described in
215 # https://wiki.documentfoundation.org/Documentation/DevGuide/Scripting_Framework#Scripting_Framework_URI_Specification
216 elif len(script
) > 0:
217 # Check ParamArray arguments
224 scope
, script
= script
.split('#')
225 if '.py$' in script
.lower(): # Python
227 scope
= 'share' # Default for Python
228 # Provide an alternate helper script depending on test context
229 if script
.startswith(cls
.pythonhelpermodule
) and hasattr(cls
, 'pythonhelpermodule2'):
230 script
= cls
.pythonhelpermodule2
+ script
[len(cls
.pythonhelpermodule
):]
232 scope
, script
= script
.split('#')
233 uri
= 'vnd.sun.star.script:{0}?language=Python&location={1}'.format(script
, scope
)
236 scope
= 'application' # Default for Basic
238 if len(script
.split('.')) < 3:
239 lib
= cls
.library
+ '.' # Default library = ScriptForge
240 uri
= 'vnd.sun.star.script:{0}{1}?language=Basic&location={2}'.format(lib
, script
, scope
)
241 # Get the script object
242 fullscript
= ('@' if paramarray
else '') + scope
+ ':' + script
244 xscript
= cls
.scriptprovider
.getScript(uri
)
247 'The script \'{0}\' could not be located in your LibreOffice installation'.format(script
))
248 else: # Should not happen
251 # At 1st execution of the common Basic dispatcher, buffer xscript
252 if fullscript
== ScriptForge
.basicdispatcher
and cls
.servicesdispatcher
is None:
253 cls
.servicesdispatcher
= xscript
255 # Execute the script with the given arguments
256 # Packaging for script provider depends on presence of ParamArray arguments in the called Basic script
258 scriptreturn
= xscript
.invoke(args
[0], (), ())
260 scriptreturn
= xscript
.invoke(args
, (), ())
263 return scriptreturn
[0] # Updatable arguments passed by reference are ignored
266 def InvokeBasicService(cls
, basicobject
, flags
, method
, *args
):
268 Execute a given Basic script and interpret its result
269 This method has as counterpart the ScriptForge.SF_PythonHelper._PythonDispatcher() Basic method
270 :param basicobject: a Service subclass
271 :param flags: see the vb* and flg* constants in the SFServices class
272 :param method: the name of the method or property to invoke, as a string
273 :param args: the arguments of the method. Symbolic cst* constants may be necessary
274 :return: The invoked Basic counterpart script (with InvokeSimpleScript()) will return a tuple
275 [0] The returned value - scalar, object reference or a tuple
276 [1] The Basic VarType() of the returned value
277 Null, Empty and Nothing have different vartypes but return all None to Python
278 Additionally, when [0] is a tuple:
279 [2] Number of dimensions in Basic
280 Additionally, when [0] is a UNO or Basic object:
281 [2] Module (1), Class instance (2) or UNO (3)
282 [3] The object's ObjectType
283 [4] The object's ServiceName
284 [5] The object's name
285 When an error occurs Python receives None as a scalar. This determines the occurrence of a failure
286 The method returns either
287 - the 0th element of the tuple when scalar, tuple or UNO object
288 - a new Service() object or one of its subclasses otherwise
291 script
= ScriptForge
.basicdispatcher
292 cstNoArgs
= '+++NOARGS+++'
293 cstValue
, cstVarType
, cstDims
, cstClass
, cstType
, cstService
, cstName
= 0, 1, 2, 2, 3, 4, 5
296 # Run the basic script
297 # The targeted script has a ParamArray argument. Do not change next 4 lines except if you know what you do !
299 args
= (basicobject
,) + (flags
,) + (method
,) + (cstNoArgs
,)
301 args
= (basicobject
,) + (flags
,) + (method
,) + args
302 returntuple
= cls
.InvokeSimpleScript(script
, args
)
304 # Interpret the result
305 # Did an error occur in the Basic world ?
306 if not isinstance(returntuple
, (tuple, list)):
307 raise RuntimeError("The execution of the method '" + method
+ "' failed. Execution stops.")
309 # Analyze the returned tuple
310 if returntuple
[cstVarType
] == ScriptForge
.V_OBJECT
and len(returntuple
) > cstClass
: # Avoid Nothing
311 if returntuple
[cstClass
] == ScriptForge
.objUNO
:
314 # Create the new class instance of the right subclass of SFServices()
315 servname
= returntuple
[cstService
]
316 if servname
not in cls
.serviceslist
:
317 # When service not found
318 raise RuntimeError("The service '" + servname
+ "' is not available in Python. Execution stops.")
319 subcls
= cls
.serviceslist
[servname
]
320 if subcls
is not None:
321 return subcls(returntuple
[cstValue
], returntuple
[cstType
], returntuple
[cstClass
],
322 returntuple
[cstName
])
323 elif returntuple
[cstVarType
] >= ScriptForge
.V_ARRAY
:
324 # Intercept empty array
325 if isinstance(returntuple
[cstValue
], uno
.ByteSequence
):
327 elif returntuple
[cstVarType
] == ScriptForge
.V_DATE
:
328 dat
= SFScriptForge
.SF_Basic
.CDateFromUnoDateTime(returntuple
[cstValue
])
330 else: # All other scalar values
332 return returntuple
[cstValue
]
335 def SetAttributeSynonyms():
337 A synonym of an attribute is either the lowercase or the camelCase form of its original ProperCase name.
338 In every subclass of SFServices:
339 1) Fill the propertysynonyms dictionary with the synonyms of the properties listed in serviceproperties
341 serviceproperties = dict(ConfigFolder = False, InstallFolder = False)
342 propertysynonyms = dict(configfolder = 'ConfigFolder', installfolder = 'InstallFolder',
343 configFolder = 'ConfigFolder', installFolder = 'InstallFolder')
344 2) Define new method attributes synonyms of the original methods
348 copyFile, copyfile = CopyFile, CopyFile
352 return key
[0].lower() + key
[1:]
354 for cls
in SFServices
.__subclasses
__():
355 # Synonyms of properties
356 if hasattr(cls
, 'serviceproperties'):
357 dico
= cls
.serviceproperties
358 dicosyn
= dict(zip(map(str.lower
, dico
.keys()), dico
.keys())) # lower case
359 cc
= dict(zip(map(camelCase
, dico
.keys()), dico
.keys())) # camel Case
361 setattr(cls
, 'propertysynonyms', dicosyn
)
362 # Synonyms of methods. A method is a public callable attribute
363 methods
= [method
for method
in dir(cls
) if not method
.startswith('_')]
364 for method
in methods
:
365 func
= getattr(cls
, method
)
367 # Assign to each synonym a reference to the original method
369 setattr(cls
, lc
, func
)
370 cc
= camelCase(method
)
372 setattr(cls
, cc
, func
)
376 def unpack_args(kwargs
):
378 Convert a dictionary passed as argument to a list alternating keys and values
380 dict(A = 'a', B = 2) => 'A', 'a', 'B', 2
382 return [v
for p
in zip(list(kwargs
.keys()), list(kwargs
.values())) for v
in p
]
385 # #####################################################################################################################
386 # SFServices CLASS (ScriptForge services superclass) ###
387 # #####################################################################################################################
389 class SFServices(object):
391 Generic implementation of a parent Service class
392 Every service must subclass this class to be recognized as a valid service
393 A service instance is created by the CreateScriptService method
394 It can have a mirror in the Basic world or be totally defined in Python
396 Every subclass must initialize 3 class properties:
397 servicename (e.g. 'ScriptForge.FileSystem', 'ScriptForge.Basic')
398 servicesynonyms (e.g. 'FileSystem', 'Basic')
399 serviceimplementation: either 'python' or 'basic'
400 This is sufficient to register the service in the Python world
402 The communication with Basic is managed by 2 ScriptForge() methods:
403 InvokeSimpleScript(): low level invocation of a Basic script. This script must be located
404 in a usual Basic module. The result is passed as-is
405 InvokeBasicService(): the result comes back encapsulated with additional info
406 The result is interpreted in the method
407 The invoked script can be a property or a method of a Basic class or usual module
408 It is up to every service method to determine which method to use
410 For Basic services only:
411 Each instance is identified by its
412 - object reference: the real Basic object embedded as a UNO wrapper object
413 - object type ('SF_String', 'DICTIONARY', ...)
414 - class module: 1 for usual modules, 2 for class modules
415 - name (form, control, ... name) - may be blank
417 The role of the SFServices() superclass is mainly to propose a generic properties management
418 Properties are got and set following next strategy:
419 1. Property names are controlled strictly ('Value' or 'value', not 'VALUE')
420 2. Getting a property value for the first time is always done via a Basic call
421 3. Next occurrences are fetched from the Python dictionary of the instance if the property
422 is read-only, otherwise via a Basic call
423 4. Read-only properties may be modified or deleted exceptionally by the class
424 when self.internal == True. The latter must immediately be reset after use
426 Each subclass must define its interface with the user scripts:
428 Property names are proper-cased
429 Conventionally, camel-cased and lower-cased synonyms are supported where relevant
430 a dictionary named 'serviceproperties' with keys = (proper-cased) property names and value = boolean
431 True = editable, False = read-only
432 a list named 'localProperties' reserved to properties for internal use
433 e.g. oDlg.Controls() is a method that uses '_Controls' to hold the list of available controls
435 forceGetProperty = False # Standard behaviour
436 read-only serviceproperties are buffered in Python after their 1st get request to Basic
437 Otherwise set it to True to force a recomputation at each property getter invocation
438 If there is a need to handle a specific property in a specific manner:
440 def myProperty(self):
441 return self.GetProperty('myProperty')
443 a usual def: statement
444 def myMethod(self, arg1, arg2 = ''):
445 return self.Execute(self.vbMethod, 'myMethod', arg1, arg2)
446 Method names are proper-cased, arguments are lower-cased
447 Conventionally, camel-cased and lower-cased homonyms are supported where relevant
448 All arguments must be present and initialized before the call to Basic, if any
450 # Python-Basic protocol constants and flags
451 vbGet
, vbLet
, vbMethod
, vbSet
= 2, 4, 1, 8 # CallByName constants
452 flgPost
= 32 # The method or the property implies a hardcoded post-processing
453 flgDateArg
= 64 # Invoked service method may contain a date argument
454 flgDateRet
= 128 # Invoked service method can return a date
455 flgArrayArg
= 512 # 1st argument can be a 2D array
456 flgArrayRet
= 1024 # Invoked service method can return a 2D array (standard modules) or any array (class modules)
457 flgUno
= 256 # Invoked service method/property can return a UNO object
458 flgObject
= 2048 # 1st argument may be a Basic object
459 flgHardCode
= 4096 # Force hardcoded call to method, avoid CallByName()
461 moduleClass
, moduleStandard
= 2, 1
463 # Define the default behaviour for read-only properties: buffer their values in Python
464 forceGetProperty
= False
465 # Empty dictionary for lower/camelcased homonyms or properties
466 propertysynonyms
= {}
467 # To operate dynamic property getting/setting it is necessary to
468 # enumerate all types of properties and adapt __getattr__() and __setattr__() according to their type
469 internal_attributes
= ('objectreference', 'objecttype', 'name', 'internal', 'servicename',
470 'serviceimplementation', 'classmodule', 'EXEC', 'SIMPLEEXEC')
471 # Shortcuts to script provider interfaces
472 SIMPLEEXEC
= ScriptForge
.InvokeSimpleScript
473 EXEC
= ScriptForge
.InvokeBasicService
475 def __init__(self
, reference
= -1, objtype
= None, classmodule
= 0, name
= ''):
477 Trivial initialization of internal properties
478 If the subclass has its own __init()__ method, a call to this one should be its first statement.
479 Afterwards localProperties should be filled with the list of its own properties
481 self
.objectreference
= reference
# the index in the Python storage where the Basic object is stored
482 self
.objecttype
= objtype
# ('SF_String', 'DICTIONARY', ...)
483 self
.classmodule
= classmodule
# Module (1), Class instance (2)
484 self
.name
= name
# '' when no name
485 self
.internal
= False # True to exceptionally allow assigning a new value to a read-only property
486 self
.localProperties
= [] # the properties reserved for internal use (often empty)
488 def __getattr__(self
, name
):
490 Executed for EVERY property reference if name not yet in the instance dict
491 At the 1st get, the property value is always got from Basic
492 Due to the use of lower/camelcase synonyms, it is called for each variant of the same property
493 The method manages itself the buffering in __dict__ based on the official ProperCase property name
495 if name
in self
.propertysynonyms
: # Reset real name if argument provided in lower or camel case
496 name
= self
.propertysynonyms
[name
]
497 if self
.serviceimplementation
== 'basic':
498 if name
in ('serviceproperties', 'localProperties', 'internal_attributes', 'propertysynonyms',
501 elif name
in self
.serviceproperties
:
502 if self
.forceGetProperty
is False and self
.serviceproperties
[name
] is False: # False = read-only
503 if name
in self
.__dict
__:
504 return self
.__dict
__[name
]
506 # Get Property from Basic and store it
507 prop
= self
.GetProperty(name
)
508 self
.__dict
__[name
] = prop
510 else: # Get Property from Basic and do not store it
511 return self
.GetProperty(name
)
512 # Execute the usual attributes getter
513 return super(SFServices
, self
).__getattribute
__(name
)
515 def __setattr__(self
, name
, value
):
517 Executed for EVERY property assignment, including in __init__() !!
518 Setting a property requires for serviceproperties() to be executed in Basic
519 Management of __dict__ is automatically done in the final usual object.__setattr__ method
521 if self
.serviceimplementation
== 'basic':
522 if name
in ('serviceproperties', 'localProperties', 'internal_attributes', 'propertysynonyms',
525 elif name
[0:2] == '__' or name
in self
.internal_attributes
or name
in self
.localProperties
:
527 elif name
in self
.serviceproperties
or name
in self
.propertysynonyms
:
528 if name
in self
.propertysynonyms
: # Reset real name if argument provided in lower or camel case
529 name
= self
.propertysynonyms
[name
]
530 if self
.internal
: # internal = True forces property local setting even if property is read-only
532 elif self
.serviceproperties
[name
] is True: # True == Editable
533 self
.SetProperty(name
, value
)
536 raise AttributeError(
537 "type object '" + self
.objecttype
+ "' has no editable property '" + name
+ "'")
539 raise AttributeError("type object '" + self
.objecttype
+ "' has no property '" + name
+ "'")
540 object.__setattr
__(self
, name
, value
)
544 return self
.serviceimplementation
+ '/' + self
.servicename
+ '/' + str(self
.objectreference
) + '/' + \
545 super(SFServices
, self
).__repr
__()
548 if self
.serviceimplementation
== 'basic':
549 if self
.objectreference
>= len(ScriptForge
.servicesmodules
): # Do not dispose predefined module objects
550 self
.ExecMethod(self
.vbMethod
, 'Dispose')
551 self
.objectreference
= -1
553 def ExecMethod(self
, flags
= 0, methodname
= '', *args
):
555 flags
= self
.vbMethod
556 if len(methodname
) > 0:
557 return self
.EXEC(self
.objectreference
, flags
, methodname
, *args
)
559 def GetProperty(self
, propertyname
, arg
= None):
561 Get the given property from the Basic world
563 if self
.serviceimplementation
== 'basic':
564 # Conventionally properties starting with X (and only them) may return a UNO object
565 calltype
= self
.vbGet
+ (self
.flgUno
if propertyname
[0] == 'X' else 0)
567 return self
.EXEC(self
.objectreference
, calltype
, propertyname
)
568 else: # There are a few cases (Calc ...) where GetProperty accepts an argument
569 return self
.EXEC(self
.objectreference
, calltype
, propertyname
, arg
)
572 def Properties(self
):
573 return list(self
.serviceproperties
)
575 def basicmethods(self
):
576 if self
.serviceimplementation
== 'basic':
577 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Methods')
581 def basicproperties(self
):
582 if self
.serviceimplementation
== 'basic':
583 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Properties')
587 def SetProperty(self
, propertyname
, value
):
589 Set the given property to a new value in the Basic world
591 if self
.serviceimplementation
== 'basic':
593 if isinstance(value
, datetime
.datetime
):
594 value
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(value
)
595 flag
+= self
.flgDateArg
596 if repr(type(value
)) == "<class 'pyuno'>":
598 return self
.EXEC(self
.objectreference
, flag
, propertyname
, value
)
601 # #####################################################################################################################
602 # SFScriptForge CLASS (alias of ScriptForge Basic library) ###
603 # #####################################################################################################################
607 # #########################################################################
609 # #########################################################################
610 class SF_Array(SFServices
, metaclass
= _Singleton
):
612 Provides a collection of methods for manipulating and transforming arrays of one dimension (vectors)
613 and arrays of two dimensions (matrices). This includes set operations, sorting,
614 importing to and exporting from text files.
615 The Python version of the service provides a single method: ImportFromCSVFile
617 # Mandatory class properties for service registration
618 serviceimplementation
= 'basic'
619 servicename
= 'ScriptForge.Array'
620 servicesynonyms
= ('array', 'scriptforge.array')
621 serviceproperties
= dict()
623 def ImportFromCSVFile(self
, filename
, delimiter
= ',', dateformat
= ''):
625 Difference with the Basic version: dates are returned in their iso format,
626 not as any of the datetime objects.
628 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'ImportFromCSVFile',
629 filename
, delimiter
, dateformat
)
631 # #########################################################################
633 # #########################################################################
634 class SF_Basic(SFServices
, metaclass
= _Singleton
):
636 This service proposes a collection of Basic methods to be executed in a Python context
637 simulating the exact syntax and behaviour of the identical Basic builtin method.
639 SF_Basic.MsgBox('This has to be displayed in a message box')
641 The signatures of Basic builtin functions are derived from
642 core/basic/source/runtime/stdobj.cxx
644 Detailed user documentation:
645 https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_basic.html?DbPAR=BASIC
647 # Mandatory class properties for service registration
648 serviceimplementation
= 'python'
649 servicename
= 'ScriptForge.Basic'
650 servicesynonyms
= ('basic', 'scriptforge.basic')
651 # Basic helper functions invocation
652 module
= 'SF_PythonHelper'
653 # Message box constants
654 MB_ABORTRETRYIGNORE
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON3
= 2, 128, 256, 512
655 MB_ICONEXCLAMATION
, MB_ICONINFORMATION
, MB_ICONQUESTION
, MB_ICONSTOP
= 48, 64, 32, 16
656 MB_OK
, MB_OKCANCEL
, MB_RETRYCANCEL
, MB_YESNO
, MB_YESNOCANCEL
= 0, 1, 5, 4, 3
657 IDABORT
, IDCANCEL
, IDIGNORE
, IDNO
, IDOK
, IDRETRY
, IDYES
= 3, 2, 5, 7, 1, 4, 6
660 def CDate(cls
, datevalue
):
661 cdate
= cls
.SIMPLEEXEC(cls
.module
+ '.PyCDate', datevalue
)
662 return cls
.CDateFromUnoDateTime(cdate
)
665 def CDateFromUnoDateTime(unodate
):
667 Converts a UNO date/time representation to a datetime.datetime Python native object
668 :param unodate: com.sun.star.util.DateTime, com.sun.star.util.Date or com.sun.star.util.Time
669 :return: the equivalent datetime.datetime
671 date
= datetime
.datetime(1899, 12, 30, 0, 0, 0, 0) # Idem as Basic builtin TimeSerial() function
672 datetype
= repr(type(unodate
))
673 if 'com.sun.star.util.DateTime' in datetype
:
674 if 1900 <= unodate
.Year
<= datetime
.MAXYEAR
:
675 date
= datetime
.datetime(unodate
.Year
, unodate
.Month
, unodate
.Day
, unodate
.Hours
,
676 unodate
.Minutes
, unodate
.Seconds
, int(unodate
.NanoSeconds
/ 1000))
677 elif 'com.sun.star.util.Date' in datetype
:
678 if 1900 <= unodate
.Year
<= datetime
.MAXYEAR
:
679 date
= datetime
.datetime(unodate
.Year
, unodate
.Month
, unodate
.Day
)
680 elif 'com.sun.star.util.Time' in datetype
:
681 date
= datetime
.datetime(unodate
.Hours
, unodate
.Minutes
, unodate
.Seconds
,
682 int(unodate
.NanoSeconds
/ 1000))
684 return unodate
# Not recognized as a UNO date structure
688 def CDateToUnoDateTime(date
):
690 Converts a date representation into the ccom.sun.star.util.DateTime date format
691 Acceptable boundaries: year >= 1900 and <= 32767
692 :param date: datetime.datetime, datetime.date, datetime.time, float (time.time) or time.struct_time
693 :return: a com.sun.star.util.DateTime
695 unodate
= uno
.createUnoStruct('com.sun.star.util.DateTime')
696 unodate
.Year
, unodate
.Month
, unodate
.Day
, unodate
.Hours
, unodate
.Minutes
, unodate
.Seconds
, \
697 unodate
.NanoSeconds
, unodate
.IsUTC
= \
698 1899, 12, 30, 0, 0, 0, 0, False # Identical to Basic TimeSerial() function
700 if isinstance(date
, float):
701 date
= time
.localtime(date
)
702 if isinstance(date
, time
.struct_time
):
703 if 1900 <= date
[0] <= 32767:
704 unodate
.Year
, unodate
.Month
, unodate
.Day
, unodate
.Hours
, unodate
.Minutes
, unodate
.Seconds
= \
706 else: # Copy only the time related part
707 unodate
.Hours
, unodate
.Minutes
, unodate
.Seconds
= date
[3:3]
708 elif isinstance(date
, (datetime
.datetime
, datetime
.date
, datetime
.time
)):
709 if isinstance(date
, (datetime
.datetime
, datetime
.date
)):
710 if 1900 <= date
.year
<= 32767:
711 unodate
.Year
, unodate
.Month
, unodate
.Day
= date
.year
, date
.month
, date
.day
712 if isinstance(date
, (datetime
.datetime
, datetime
.time
)):
713 unodate
.Hours
, unodate
.Minutes
, unodate
.Seconds
, unodate
.NanoSeconds
= \
714 date
.hour
, date
.minute
, date
.second
, date
.microsecond
* 1000
716 return date
# Not recognized as a date
720 def ConvertFromUrl(cls
, url
):
721 return cls
.SIMPLEEXEC(cls
.module
+ '.PyConvertFromUrl', url
)
724 def ConvertToUrl(cls
, systempath
):
725 return cls
.SIMPLEEXEC(cls
.module
+ '.PyConvertToUrl', systempath
)
728 def CreateUnoService(cls
, servicename
):
729 return cls
.SIMPLEEXEC(cls
.module
+ '.PyCreateUnoService', servicename
)
732 def CreateUnoStruct(cls
, unostructure
):
733 return uno
.createUnoStruct(unostructure
)
736 def DateAdd(cls
, interval
, number
, date
):
737 if isinstance(date
, datetime
.datetime
):
738 date
= cls
.CDateToUnoDateTime(date
)
739 dateadd
= cls
.SIMPLEEXEC(cls
.module
+ '.PyDateAdd', interval
, number
, date
)
740 return cls
.CDateFromUnoDateTime(dateadd
)
743 def DateDiff(cls
, interval
, date1
, date2
, firstdayofweek
= 1, firstweekofyear
= 1):
744 if isinstance(date1
, datetime
.datetime
):
745 date1
= cls
.CDateToUnoDateTime(date1
)
746 if isinstance(date2
, datetime
.datetime
):
747 date2
= cls
.CDateToUnoDateTime(date2
)
748 return cls
.SIMPLEEXEC(cls
.module
+ '.PyDateDiff', interval
, date1
, date2
, firstdayofweek
, firstweekofyear
)
751 def DatePart(cls
, interval
, date
, firstdayofweek
= 1, firstweekofyear
= 1):
752 if isinstance(date
, datetime
.datetime
):
753 date
= cls
.CDateToUnoDateTime(date
)
754 return cls
.SIMPLEEXEC(cls
.module
+ '.PyDatePart', interval
, date
, firstdayofweek
, firstweekofyear
)
757 def DateValue(cls
, string
):
758 if isinstance(string
, datetime
.datetime
):
759 string
= string
.isoformat()
760 datevalue
= cls
.SIMPLEEXEC(cls
.module
+ '.PyDateValue', string
)
761 return cls
.CDateFromUnoDateTime(datevalue
)
764 def Format(cls
, expression
, format
= ''):
765 if isinstance(expression
, datetime
.datetime
):
766 expression
= cls
.CDateToUnoDateTime(expression
)
767 return cls
.SIMPLEEXEC(cls
.module
+ '.PyFormat', expression
, format
)
770 def GetDefaultContext(cls
):
771 return ScriptForge
.componentcontext
775 return cls
.SIMPLEEXEC(cls
.module
+ '.PyGetGuiType')
778 def GetPathSeparator(cls
):
782 def GetSystemTicks(cls
):
783 return cls
.SIMPLEEXEC(cls
.module
+ '.PyGetSystemTicks')
785 class GlobalScope(object, metaclass
= _Singleton
):
786 @classmethod # Mandatory because the GlobalScope class is normally not instantiated
787 def BasicLibraries(cls
):
788 return ScriptForge
.InvokeSimpleScript(SFScriptForge
.SF_Basic
.module
+ '.PyGlobalScope', 'Basic')
791 def DialogLibraries(cls
):
792 return ScriptForge
.InvokeSimpleScript(SFScriptForge
.SF_Basic
.module
+ '.PyGlobalScope', 'Dialog')
795 def InputBox(cls
, prompt
, title
= '', default
= '', xpostwips
= -1, ypostwips
= -1):
796 if xpostwips
< 0 or ypostwips
< 0:
797 return cls
.SIMPLEEXEC(cls
.module
+ '.PyInputBox', prompt
, title
, default
)
798 return cls
.SIMPLEEXEC(cls
.module
+ '.PyInputBox', prompt
, title
, default
, xpostwips
, ypostwips
)
801 def MsgBox(cls
, prompt
, buttons
= 0, title
= ''):
802 return cls
.SIMPLEEXEC(cls
.module
+ '.PyMsgBox', prompt
, buttons
, title
)
806 return datetime
.datetime
.now()
809 def RGB(cls
, red
, green
, blue
):
810 return int('%02x%02x%02x' % (red
, green
, blue
), 16)
813 def StarDesktop(self
):
814 ctx
= ScriptForge
.componentcontext
817 smgr
= ctx
.getServiceManager() # com.sun.star.lang.XMultiComponentFactory
818 DESK
= 'com.sun.star.frame.Desktop'
819 desktop
= smgr
.createInstanceWithContext(DESK
, ctx
)
822 starDesktop
, stardesktop
= StarDesktop
, StarDesktop
825 def ThisComponent(self
):
827 When the current component is the Basic IDE, the ThisComponent object returns
828 in Basic the component owning the currently run user script.
829 Above behaviour cannot be reproduced in Python.
830 :return: the current component or None when not a document
832 comp
= self
.StarDesktop
.getCurrentComponent()
835 impl
= comp
.ImplementationName
836 if impl
in ('com.sun.star.comp.basic.BasicIDE', 'com.sun.star.comp.sfx2.BackingComp'):
837 return None # None when Basic IDE or welcome screen
840 thisComponent
, thiscomponent
= ThisComponent
, ThisComponent
843 def ThisDatabaseDocument(self
):
845 When the current component is the Basic IDE, the ThisDatabaseDocument object returns
846 in Basic the database owning the currently run user script.
847 Above behaviour cannot be reproduced in Python.
848 :return: the current Base (main) component or None when not a Base document or one of its subcomponents
850 comp
= self
.ThisComponent
# Get the current component
854 sess
= CreateScriptService('Session')
856 if sess
.HasUnoProperty(comp
, 'ImplementationName'):
857 impl
= comp
.ImplementationName
858 if sess
.HasUnoProperty(comp
, 'Identifier'):
859 ident
= comp
.Identifier
861 targetimpl
= 'com.sun.star.comp.dba.ODatabaseDocument'
862 if impl
== targetimpl
: # The current component is the main Base window
864 # Identify resp. form, table/query, table/query in edit mode, report, relations diagram
865 if impl
== 'SwXTextDocument' and ident
== 'com.sun.star.sdb.FormDesign' \
866 or impl
== 'org.openoffice.comp.dbu.ODatasourceBrowser' \
867 or impl
in ('org.openoffice.comp.dbu.OTableDesign', 'org.openoffice.comp.dbu.OQuertDesign') \
868 or impl
== 'SwXTextDocument' and ident
== 'com.sun.star.sdb.TextReportDesign' \
869 or impl
== 'org.openoffice.comp.dbu.ORelationDesign':
870 db
= comp
.ScriptContainer
871 if sess
.HasUnoProperty(db
, 'ImplementationName'):
872 if db
.ImplementationName
== targetimpl
:
876 thisDatabaseDocument
, thisdatabasedocument
= ThisDatabaseDocument
, ThisDatabaseDocument
879 def Xray(cls
, unoobject
= None):
880 return cls
.SIMPLEEXEC('XrayTool._main.xray', unoobject
)
882 # #########################################################################
883 # SF_Dictionary CLASS
884 # #########################################################################
885 class SF_Dictionary(SFServices
, dict):
887 The service adds to a Python dict instance the interfaces for conversion to and from
888 a list of UNO PropertyValues
891 dico = dict(A = 1, B = 2, C = 3)
892 myDict = CreateScriptService('Dictionary', dico) # Initialize myDict with the content of dico
894 print(myDict) # {'A': 1, 'B': 2, 'C': 3, 'D': 4}
895 propval = myDict.ConvertToPropertyValues()
897 dico = dict(A = 1, B = 2, C = 3)
898 myDict = CreateScriptService('Dictionary') # Initialize myDict as an empty dict object
899 myDict.update(dico) # Load the values of dico into myDict
901 print(myDict) # {'A': 1, 'B': 2, 'C': 3, 'D': 4}
902 propval = myDict.ConvertToPropertyValues()
904 # Mandatory class properties for service registration
905 serviceimplementation
= 'python'
906 servicename
= 'ScriptForge.Dictionary'
907 servicesynonyms
= ('dictionary', 'scriptforge.dictionary')
909 def __init__(self
, dic
= None):
910 SFServices
.__init
__(self
)
915 def ConvertToPropertyValues(self
):
917 Store the content of the dictionary in an array of PropertyValues.
918 Each entry in the array is a com.sun.star.beans.PropertyValue.
919 he key is stored in Name, the value is stored in Value.
921 If one of the items has a type datetime, it is converted to a com.sun.star.util.DateTime structure.
922 If one of the items is an empty list, it is converted to None.
924 The resulting array is empty when the dictionary is empty.
927 for key
in iter(self
):
930 if isinstance(value
, dict): # check that first level is not itself a (sub)dict
932 elif isinstance(value
, (tuple, list)): # check every member of the list is not a (sub)dict
933 if len(value
) == 0: # Property values do not like empty lists
936 for i
in range(len(value
)):
937 if isinstance(value
[i
], dict):
940 elif isinstance(value
, (datetime
.datetime
, datetime
.date
, datetime
.time
)):
941 item
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(value
)
942 pv
= uno
.createUnoStruct('com.sun.star.beans.PropertyValue')
948 def ImportFromPropertyValues(self
, propertyvalues
, overwrite
= False):
950 Inserts the contents of an array of PropertyValue objects into the current dictionary.
951 PropertyValue Names are used as keys in the dictionary, whereas Values contain the corresponding values.
952 Date-type values are converted to datetime.datetime instances.
953 :param propertyvalues: a list.tuple containing com.sun.star.beans.PropertyValue objects
954 :param overwrite: When True, entries with same name may exist in the dictionary and their values
955 are overwritten. When False (default), repeated keys are not overwritten.
956 :return: True when successful
959 for pv
in iter(propertyvalues
):
961 if overwrite
is True or key
not in self
:
963 if 'com.sun.star.util.DateTime' in repr(type(item
)):
964 item
= datetime
.datetime(item
.Year
, item
.Month
, item
.Day
,
965 item
.Hours
, item
.Minutes
, item
.Seconds
, int(item
.NanoSeconds
/ 1000))
966 elif 'com.sun.star.util.Date' in repr(type(item
)):
967 item
= datetime
.datetime(item
.Year
, item
.Month
, item
.Day
)
968 elif 'com.sun.star.util.Time' in repr(type(item
)):
969 item
= datetime
.datetime(item
.Hours
, item
.Minutes
, item
.Seconds
, int(item
.NanoSeconds
/ 1000))
970 result
.append((key
, item
))
974 # #########################################################################
976 # #########################################################################
977 class SF_Exception(SFServices
, metaclass
= _Singleton
):
979 The Exception service is a collection of methods for code debugging and error handling.
981 The Exception service console stores events, variable values and information about errors.
982 Use the console when the Python shell is not available, for example in Calc user defined functions (UDF)
983 or during events processing.
984 Use DebugPrint() method to aggregate additional user data of any type.
986 Console entries can be dumped to a text file or visualized in a dialogue.
988 # Mandatory class properties for service registration
989 serviceimplementation
= 'basic'
990 servicename
= 'ScriptForge.Exception'
991 servicesynonyms
= ('exception', 'scriptforge.exception')
992 serviceproperties
= dict()
994 def Console(self
, modal
= True):
995 # From Python, the current XComponentContext must be added as last argument
996 return self
.ExecMethod(self
.vbMethod
, 'Console', modal
, ScriptForge
.componentcontext
)
998 def ConsoleClear(self
, keep
= 0):
999 return self
.ExecMethod(self
.vbMethod
, 'ConsoleClear', keep
)
1001 def ConsoleToFile(self
, filename
):
1002 return self
.ExecMethod(self
.vbMethod
, 'ConsoleToFile', filename
)
1004 def DebugDisplay(self
, *args
):
1005 # Arguments are concatenated in a single string similar to what the Python print() function would produce
1006 self
.DebugPrint(*args
)
1007 param
= '\n'.join(list(map(lambda a
: a
.strip("'") if isinstance(a
, str) else repr(a
), args
)))
1008 bas
= CreateScriptService('ScriptForge.Basic')
1009 return bas
.MsgBox(param
, bas
.MB_OK
+ bas
.MB_ICONINFORMATION
, 'DebugDisplay')
1011 def DebugPrint(self
, *args
):
1012 # Arguments are concatenated in a single string similar to what the Python print() function would produce
1013 # Avoid using repr() on strings to not have backslashes * 4
1014 param
= '\t'.join(list(map(lambda a
: a
.strip("'") if isinstance(a
, str) else repr(a
),
1015 args
))).expandtabs(tabsize
= 4)
1016 return self
.ExecMethod(self
.vbMethod
, 'DebugPrint', param
)
1019 def PythonShell(cls
, variables
= None):
1021 Open an APSO python shell window - Thanks to its authors Hanya/Tsutomu Uchino/Hubert Lambert
1022 :param variables: Typical use
1023 PythonShell.({**globals(), **locals()})
1024 to push the global and local dictionaries to the shell window
1026 if variables
is None:
1027 variables
= locals()
1028 # Is APSO installed ?
1029 ctx
= ScriptForge
.componentcontext
1030 ext
= ctx
.getByName('/singletons/com.sun.star.deployment.PackageInformationProvider')
1031 apso
= 'apso.python.script.organizer'
1032 if len(ext
.getPackageLocation(apso
)) > 0:
1033 # APSO is available. However, PythonShell() is ignored in bridge mode
1034 # because APSO library not in pythonpath
1035 if ScriptForge
.port
> 0:
1037 # Directly derived from apso.oxt|python|scripts|tools.py$console
1038 # we need to load apso before import statement
1039 ctx
.ServiceManager
.createInstance('apso.python.script.organizer.impl')
1040 # now we can use apso_utils library
1041 from apso_utils
import console
1042 kwargs
= {'loc': variables
}
1043 kwargs
['loc'].setdefault('XSCRIPTCONTEXT', uno
)
1045 # An interprocess call is necessary to allow a redirection of STDOUT and STDERR by APSO
1046 # Choice is a minimalist call to a Basic routine: no arguments, a few lines of code
1047 SFScriptForge
.SF_Basic
.GetGuiType()
1049 # The APSO extension could not be located in your LibreOffice installation
1050 cls
._RaiseFatal
('SF_Exception.PythonShell', 'variables=None', 'PYTHONSHELLERROR')
1053 def RaiseFatal(cls
, errorcode
, *args
):
1055 Generate a run-time error caused by an anomaly in a user script detected by ScriptForge
1056 The message is logged in the console. The execution is STOPPED
1057 For INTERNAL USE only
1059 # Direct call because RaiseFatal forces an execution stop in Basic
1062 return cls
.SIMPLEEXEC('@SF_Exception.RaiseFatal', (errorcode
, *args
)) # With ParamArray
1065 def _RaiseFatal(cls
, sub
, subargs
, errorcode
, *args
):
1067 Wrapper of RaiseFatal(). Includes method and syntax of the failed Python routine
1068 to simulate the exact behaviour of the Basic RaiseFatal() method
1069 For INTERNAL USE only
1071 ScriptForge
.InvokeSimpleScript('ScriptForge.SF_Utils._EnterFunction', sub
, subargs
)
1072 cls
.RaiseFatal(errorcode
, *args
)
1073 raise RuntimeError("The execution of the method '" + sub
.split('.')[-1] + "' failed. Execution stops.")
1075 # #########################################################################
1076 # SF_FileSystem CLASS
1077 # #########################################################################
1078 class SF_FileSystem(SFServices
, metaclass
= _Singleton
):
1080 The "FileSystem" service includes common file and folder handling routines.
1082 # Mandatory class properties for service registration
1083 serviceimplementation
= 'basic'
1084 servicename
= 'ScriptForge.FileSystem'
1085 servicesynonyms
= ('filesystem', 'scriptforge.filesystem')
1086 serviceproperties
= dict(FileNaming
= True, ConfigFolder
= False, ExtensionsFolder
= False, HomeFolder
= False,
1087 InstallFolder
= False, TemplatesFolder
= False, TemporaryFolder
= False,
1088 UserTemplatesFolder
= False)
1089 # Force for each property to get its value from Basic - due to FileNaming updatability
1090 forceGetProperty
= True
1091 # Open TextStream constants
1092 ForReading
, ForWriting
, ForAppending
= 1, 2, 8
1094 def BuildPath(self
, foldername
, name
):
1095 return self
.ExecMethod(self
.vbMethod
, 'BuildPath', foldername
, name
)
1097 def CompareFiles(self
, filename1
, filename2
, comparecontents
= False):
1098 py
= ScriptForge
.pythonhelpermodule
+ '$' + '_SF_FileSystem__CompareFiles'
1099 if self
.FileExists(filename1
) and self
.FileExists(filename2
):
1100 file1
= self
._ConvertFromUrl
(filename1
)
1101 file2
= self
._ConvertFromUrl
(filename2
)
1102 return self
.SIMPLEEXEC(py
, file1
, file2
, comparecontents
)
1106 def CopyFile(self
, source
, destination
, overwrite
= True):
1107 return self
.ExecMethod(self
.vbMethod
, 'CopyFile', source
, destination
, overwrite
)
1109 def CopyFolder(self
, source
, destination
, overwrite
= True):
1110 return self
.ExecMethod(self
.vbMethod
, 'CopyFolder', source
, destination
, overwrite
)
1112 def CreateFolder(self
, foldername
):
1113 return self
.ExecMethod(self
.vbMethod
, 'CreateFolder', foldername
)
1115 def CreateTextFile(self
, filename
, overwrite
= True, encoding
= 'UTF-8'):
1116 return self
.ExecMethod(self
.vbMethod
, 'CreateTextFile', filename
, overwrite
, encoding
)
1118 def DeleteFile(self
, filename
):
1119 return self
.ExecMethod(self
.vbMethod
, 'DeleteFile', filename
)
1121 def DeleteFolder(self
, foldername
):
1122 return self
.ExecMethod(self
.vbMethod
, 'DeleteFolder', foldername
)
1124 def ExtensionFolder(self
, extension
):
1125 return self
.ExecMethod(self
.vbMethod
, 'ExtensionFolder', extension
)
1127 def FileExists(self
, filename
):
1128 return self
.ExecMethod(self
.vbMethod
, 'FileExists', filename
)
1130 def Files(self
, foldername
, filter = ''):
1131 return self
.ExecMethod(self
.vbMethod
, 'Files', foldername
, filter)
1133 def FolderExists(self
, foldername
):
1134 return self
.ExecMethod(self
.vbMethod
, 'FolderExists', foldername
)
1136 def GetBaseName(self
, filename
):
1137 return self
.ExecMethod(self
.vbMethod
, 'GetBaseName', filename
)
1139 def GetExtension(self
, filename
):
1140 return self
.ExecMethod(self
.vbMethod
, 'GetExtension', filename
)
1142 def GetFileLen(self
, filename
):
1143 py
= ScriptForge
.pythonhelpermodule
+ '$' + '_SF_FileSystem__GetFilelen'
1144 if self
.FileExists(filename
):
1145 file = self
._ConvertFromUrl
(filename
)
1146 return int(self
.SIMPLEEXEC(py
, file))
1150 def GetFileModified(self
, filename
):
1151 return self
.ExecMethod(self
.vbMethod
+ self
.flgDateRet
, 'GetFileModified', filename
)
1153 def GetName(self
, filename
):
1154 return self
.ExecMethod(self
.vbMethod
, 'GetName', filename
)
1156 def GetParentFolderName(self
, filename
):
1157 return self
.ExecMethod(self
.vbMethod
, 'GetParentFolderName', filename
)
1159 def GetTempName(self
):
1160 return self
.ExecMethod(self
.vbMethod
, 'GetTempName')
1162 def HashFile(self
, filename
, algorithm
):
1163 py
= ScriptForge
.pythonhelpermodule
+ '$' + '_SF_FileSystem__HashFile'
1164 if self
.FileExists(filename
):
1165 file = self
._ConvertFromUrl
(filename
)
1166 return self
.SIMPLEEXEC(py
, file, algorithm
.lower())
1170 def MoveFile(self
, source
, destination
):
1171 return self
.ExecMethod(self
.vbMethod
, 'MoveFile', source
, destination
)
1173 def Normalize(self
, filename
):
1174 return self
.ExecMethod(self
.vbMethod
, 'Normalize', filename
)
1176 def MoveFolder(self
, source
, destination
):
1177 return self
.ExecMethod(self
.vbMethod
, 'MoveFolder', source
, destination
)
1179 def OpenTextFile(self
, filename
, iomode
= 1, create
= False, encoding
= 'UTF-8'):
1180 return self
.ExecMethod(self
.vbMethod
, 'OpenTextFile', filename
, iomode
, create
, encoding
)
1182 def PickFile(self
, defaultfile
= ScriptForge
.cstSymEmpty
, mode
= 'OPEN', filter = ''):
1183 return self
.ExecMethod(self
.vbMethod
, 'PickFile', defaultfile
, mode
, filter)
1185 def PickFolder(self
, defaultfolder
= ScriptForge
.cstSymEmpty
, freetext
= ''):
1186 return self
.ExecMethod(self
.vbMethod
, 'PickFolder', defaultfolder
, freetext
)
1188 def SubFolders(self
, foldername
, filter = ''):
1189 return self
.ExecMethod(self
.vbMethod
, 'SubFolders', foldername
, filter)
1192 def _ConvertFromUrl(cls
, filename
):
1193 # Alias for same function in FileSystem Basic module
1194 return cls
.SIMPLEEXEC('ScriptForge.SF_FileSystem._ConvertFromUrl', filename
)
1196 # #########################################################################
1198 # #########################################################################
1199 class SF_L10N(SFServices
):
1201 This service provides a number of methods related to the translation of strings
1202 with minimal impact on the program's source code.
1203 The methods provided by the L10N service can be used mainly to:
1204 Create POT files that can be used as templates for translation of all strings in the program.
1205 Get translated strings at runtime for the language defined in the Locale property.
1207 # Mandatory class properties for service registration
1208 serviceimplementation
= 'basic'
1209 servicename
= 'ScriptForge.L10N'
1210 servicesynonyms
= ('l10n', 'scriptforge.l10n')
1211 serviceproperties
= dict(Folder
= False, Languages
= False, Locale
= False)
1214 def ReviewServiceArgs(cls
, foldername
= '', locale
= '', encoding
= 'UTF-8',
1215 locale2
= '', encoding2
= 'UTF-8'):
1217 Transform positional and keyword arguments into positional only
1219 return foldername
, locale
, encoding
, locale2
, encoding2
1221 def AddText(self
, context
= '', msgid
= '', comment
= ''):
1222 return self
.ExecMethod(self
.vbMethod
, 'AddText', context
, msgid
, comment
)
1224 def AddTextsFromDialog(self
, dialog
):
1225 dialogobj
= dialog
.objectreference
if isinstance(dialog
, SFDialogs
.SF_Dialog
) else dialog
1226 return self
.ExecMethod(self
.vbMethod
+ self
.flgObject
, 'AddTextsFromDialog', dialogobj
)
1228 def ExportToPOTFile(self
, filename
, header
= '', encoding
= 'UTF-8'):
1229 return self
.ExecMethod(self
.vbMethod
, 'ExportToPOTFile', filename
, header
, encoding
)
1231 def GetText(self
, msgid
, *args
):
1232 return self
.ExecMethod(self
.vbMethod
, 'GetText', msgid
, *args
)
1236 # #########################################################################
1238 # #########################################################################
1239 class SF_Platform(SFServices
, metaclass
= _Singleton
):
1241 The 'Platform' service implements a collection of properties about the actual execution environment
1243 the hardware platform
1244 the operating system
1245 the LibreOffice version
1247 All those properties are read-only.
1248 The implementation is mainly based on the 'platform' module of the Python standard library
1250 # Mandatory class properties for service registration
1251 serviceimplementation
= 'basic'
1252 servicename
= 'ScriptForge.Platform'
1253 servicesynonyms
= ('platform', 'scriptforge.platform')
1254 serviceproperties
= dict(Architecture
= False, ComputerName
= False, CPUCount
= False, CurrentUser
= False,
1255 Extensions
= False, FilterNames
= False, Fonts
= False, FormatLocale
= False,
1256 Locale
= False, Machine
= False, OfficeLocale
= False, OfficeVersion
= False,
1257 OSName
= False, OSPlatform
= False, OSRelease
= False, OSVersion
= False,
1258 Printers
= False, Processor
= False, PythonVersion
= False, SystemLocale
= False)
1259 # Python helper functions
1260 py
= ScriptForge
.pythonhelpermodule
+ '$' + '_SF_Platform'
1263 def Architecture(self
):
1264 return self
.SIMPLEEXEC(self
.py
, 'Architecture')
1267 def ComputerName(self
):
1268 return self
.SIMPLEEXEC(self
.py
, 'ComputerName')
1272 return self
.SIMPLEEXEC(self
.py
, 'CPUCount')
1275 def CurrentUser(self
):
1276 return self
.SIMPLEEXEC(self
.py
, 'CurrentUser')
1280 return self
.SIMPLEEXEC(self
.py
, 'Machine')
1284 return self
.SIMPLEEXEC(self
.py
, 'OSName')
1287 def OSPlatform(self
):
1288 return self
.SIMPLEEXEC(self
.py
, 'OSPlatform')
1291 def OSRelease(self
):
1292 return self
.SIMPLEEXEC(self
.py
, 'OSRelease')
1295 def OSVersion(self
):
1296 return self
.SIMPLEEXEC(self
.py
, 'OSVersion')
1299 def Processor(self
):
1300 return self
.SIMPLEEXEC(self
.py
, 'Processor')
1303 def PythonVersion(self
):
1304 return self
.SIMPLEEXEC(self
.py
, 'PythonVersion')
1306 # #########################################################################
1308 # #########################################################################
1309 class SF_Region(SFServices
, metaclass
= _Singleton
):
1311 The "Region" service gathers a collection of functions about languages, countries and timezones
1314 - Numbers and dates formatting
1316 - Timezones conversions
1317 - Numbers transformed to text
1319 # Mandatory class properties for service registration
1320 serviceimplementation
= 'basic'
1321 servicename
= 'ScriptForge.Region'
1322 servicesynonyms
= ('region', 'scriptforge.region')
1323 serviceproperties
= dict()
1325 # Next functions are implemented in Basic as read-only properties with 1 argument
1326 def Country(self
, region
= ''):
1327 return self
.GetProperty('Country', region
)
1329 def Currency(self
, region
= ''):
1330 return self
.GetProperty('Currency', region
)
1332 def DatePatterns(self
, region
= ''):
1333 return self
.GetProperty('DatePatterns', region
)
1335 def DateSeparator(self
, region
= ''):
1336 return self
.GetProperty('DateSeparator', region
)
1338 def DayAbbrevNames(self
, region
= ''):
1339 return self
.GetProperty('DayAbbrevNames', region
)
1341 def DayNames(self
, region
= ''):
1342 return self
.GetProperty('DayNames', region
)
1344 def DayNarrowNames(self
, region
= ''):
1345 return self
.GetProperty('DayNarrowNames', region
)
1347 def DecimalPoint(self
, region
= ''):
1348 return self
.GetProperty('DecimalPoint', region
)
1350 def Language(self
, region
= ''):
1351 return self
.GetProperty('Language', region
)
1353 def ListSeparator(self
, region
= ''):
1354 return self
.GetProperty('ListSeparator', region
)
1356 def MonthAbbrevNames(self
, region
= ''):
1357 return self
.GetProperty('MonthAbbrevNames', region
)
1359 def MonthNames(self
, region
= ''):
1360 return self
.GetProperty('MonthNames', region
)
1362 def MonthNarrowNames(self
, region
= ''):
1363 return self
.GetProperty('MonthNarrowNames', region
)
1365 def ThousandSeparator(self
, region
= ''):
1366 return self
.GetProperty('ThousandSeparator', region
)
1368 def TimeSeparator(self
, region
= ''):
1369 return self
.GetProperty('TimeSeparator', region
)
1372 def DSTOffset(self
, localdatetime
, timezone
, locale
= ''):
1373 if isinstance(localdatetime
, datetime
.datetime
):
1374 localdatetime
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(localdatetime
)
1375 return self
.ExecMethod(self
.vbMethod
+ self
.flgDateArg
, 'DSTOffset', localdatetime
, timezone
, locale
)
1377 def LocalDateTime(self
, utcdatetime
, timezone
, locale
= ''):
1378 if isinstance(utcdatetime
, datetime
.datetime
):
1379 utcdatetime
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(utcdatetime
)
1380 localdate
= self
.ExecMethod(self
.vbMethod
+ self
.flgDateArg
+ self
.flgDateRet
, 'LocalDateTime',
1381 utcdatetime
, timezone
, locale
)
1382 return SFScriptForge
.SF_Basic
.CDateFromUnoDateTime(localdate
)
1384 def Number2Text(self
, number
, locale
= ''):
1385 return self
.ExecMethod(self
.vbMethod
, 'Number2Text', number
, locale
)
1387 def TimeZoneOffset(self
, timezone
, locale
= ''):
1388 return self
.ExecMethod(self
.vbMethod
, 'TimeZoneOffset', timezone
, locale
)
1390 def UTCDateTime(self
, localdatetime
, timezone
, locale
= ''):
1391 if isinstance(localdatetime
, datetime
.datetime
):
1392 localdatetime
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(localdatetime
)
1393 utcdate
= self
.ExecMethod(self
.vbMethod
+ self
.flgDateArg
+ self
.flgDateRet
, 'UTCDateTime', localdatetime
,
1395 return SFScriptForge
.SF_Basic
.CDateFromUnoDateTime(utcdate
)
1397 def UTCNow(self
, timezone
, locale
= ''):
1398 now
= self
.ExecMethod(self
.vbMethod
+ self
.flgDateRet
, 'UTCNow', timezone
, locale
)
1399 return SFScriptForge
.SF_Basic
.CDateFromUnoDateTime(now
)
1401 # #########################################################################
1403 # #########################################################################
1404 class SF_Session(SFServices
, metaclass
= _Singleton
):
1406 The Session service gathers various general-purpose methods about:
1408 - the invocation of external scripts or programs
1410 # Mandatory class properties for service registration
1411 serviceimplementation
= 'basic'
1412 servicename
= 'ScriptForge.Session'
1413 servicesynonyms
= ('session', 'scriptforge.session')
1414 serviceproperties
= dict()
1416 # Class constants Where to find an invoked library ?
1417 SCRIPTISEMBEDDED
= 'document' # in the document
1418 SCRIPTISAPPLICATION
= 'application' # in any shared library (Basic)
1419 SCRIPTISPERSONAL
= 'user' # in My Macros (Python)
1420 SCRIPTISPERSOXT
= 'user:uno_packages' # in an extension installed for the current user (Python)
1421 SCRIPTISSHARED
= 'share' # in LibreOffice macros (Python)
1422 SCRIPTISSHAROXT
= 'share:uno_packages' # in an extension installed for all users (Python)
1423 SCRIPTISOXT
= 'uno_packages' # in an extension but the installation parameters are unknown (Python)
1426 def ExecuteBasicScript(cls
, scope
= '', script
= '', *args
):
1427 if scope
is None or scope
== '':
1428 scope
= cls
.SCRIPTISAPPLICATION
1430 args
= (scope
,) + (script
,) + (None,)
1432 args
= (scope
,) + (script
,) + args
1433 # ExecuteBasicScript method has a ParamArray parameter in Basic
1434 return cls
.SIMPLEEXEC('@SF_Session.ExecuteBasicScript', args
)
1437 def ExecuteCalcFunction(cls
, calcfunction
, *args
):
1439 # Arguments of Calc functions are strings or numbers. None == Empty is a good alias for no argument
1440 args
= (calcfunction
,) + (None,)
1442 args
= (calcfunction
,) + args
1443 # ExecuteCalcFunction method has a ParamArray parameter in Basic
1444 return cls
.SIMPLEEXEC('@SF_Session.ExecuteCalcFunction', args
)
1447 def ExecutePythonScript(cls
, scope
= '', script
= '', *args
):
1448 return cls
.SIMPLEEXEC(scope
+ '#' + script
, *args
)
1450 def HasUnoMethod(self
, unoobject
, methodname
):
1451 return self
.ExecMethod(self
.vbMethod
, 'HasUnoMethod', unoobject
, methodname
)
1453 def HasUnoProperty(self
, unoobject
, propertyname
):
1454 return self
.ExecMethod(self
.vbMethod
, 'HasUnoProperty', unoobject
, propertyname
)
1457 def OpenURLInBrowser(cls
, url
):
1458 py
= ScriptForge
.pythonhelpermodule
+ '$' + '_SF_Session__OpenURLInBrowser'
1459 return cls
.SIMPLEEXEC(py
, url
)
1461 def RunApplication(self
, command
, parameters
):
1462 return self
.ExecMethod(self
.vbMethod
, 'RunApplication', command
, parameters
)
1464 def SendMail(self
, recipient
, cc
= '', bcc
= '', subject
= '', body
= '', filenames
= '', editmessage
= True):
1465 return self
.ExecMethod(self
.vbMethod
, 'SendMail', recipient
, cc
, bcc
, subject
, body
, filenames
, editmessage
)
1467 def UnoObjectType(self
, unoobject
):
1468 return self
.ExecMethod(self
.vbMethod
, 'UnoObjectType', unoobject
)
1470 def UnoMethods(self
, unoobject
):
1471 return self
.ExecMethod(self
.vbMethod
, 'UnoMethods', unoobject
)
1473 def UnoProperties(self
, unoobject
):
1474 return self
.ExecMethod(self
.vbMethod
, 'UnoProperties', unoobject
)
1476 def WebService(self
, uri
):
1477 return self
.ExecMethod(self
.vbMethod
, 'WebService', uri
)
1479 # #########################################################################
1481 # #########################################################################
1482 class SF_String(SFServices
, metaclass
= _Singleton
):
1484 Focus on string manipulation, regular expressions, encodings and hashing algorithms.
1485 The methods implemented in Basic that are redundant with Python builtin functions
1488 # Mandatory class properties for service registration
1489 serviceimplementation
= 'basic'
1490 servicename
= 'ScriptForge.String'
1491 servicesynonyms
= ('string', 'scriptforge.string')
1492 serviceproperties
= dict()
1495 def HashStr(cls
, inputstr
, algorithm
):
1496 py
= ScriptForge
.pythonhelpermodule
+ '$' + '_SF_String__HashStr'
1497 return cls
.SIMPLEEXEC(py
, inputstr
, algorithm
.lower())
1499 def IsADate(self
, inputstr
, dateformat
= 'YYYY-MM-DD'):
1500 return self
.ExecMethod(self
.vbMethod
, 'IsADate', inputstr
, dateformat
)
1502 def IsEmail(self
, inputstr
):
1503 return self
.ExecMethod(self
.vbMethod
, 'IsEmail', inputstr
)
1505 def IsFileName(self
, inputstr
, osname
= ScriptForge
.cstSymEmpty
):
1506 return self
.ExecMethod(self
.vbMethod
, 'IsFileName', inputstr
, osname
)
1508 def IsIBAN(self
, inputstr
):
1509 return self
.ExecMethod(self
.vbMethod
, 'IsIBAN', inputstr
)
1511 def IsIPv4(self
, inputstr
):
1512 return self
.ExecMethod(self
.vbMethod
, 'IsIPv4', inputstr
)
1514 def IsLike(self
, inputstr
, pattern
, casesensitive
= False):
1515 return self
.ExecMethod(self
.vbMethod
, 'IsLike', inputstr
, pattern
, casesensitive
)
1517 def IsSheetName(self
, inputstr
):
1518 return self
.ExecMethod(self
.vbMethod
, 'IsSheetName', inputstr
)
1520 def IsUrl(self
, inputstr
):
1521 return self
.ExecMethod(self
.vbMethod
, 'IsUrl', inputstr
)
1523 def SplitNotQuoted(self
, inputstr
, delimiter
= ' ', occurrences
= 0, quotechar
= '"'):
1524 return self
.ExecMethod(self
.vbMethod
, 'SplitNotQuoted', inputstr
, delimiter
, occurrences
, quotechar
)
1526 def Wrap(self
, inputstr
, width
= 70, tabsize
= 8):
1527 return self
.ExecMethod(self
.vbMethod
, 'Wrap', inputstr
, width
, tabsize
)
1529 # #########################################################################
1530 # SF_TextStream CLASS
1531 # #########################################################################
1532 class SF_TextStream(SFServices
):
1534 The TextStream service is used to sequentially read from and write to files opened or created
1535 using the ScriptForge.FileSystem service..
1537 # Mandatory class properties for service registration
1538 serviceimplementation
= 'basic'
1539 servicename
= 'ScriptForge.TextStream'
1540 servicesynonyms
= ()
1541 serviceproperties
= dict(AtEndOfStream
= False, Encoding
= False, FileName
= False, IOMode
= False,
1542 Line
= False, NewLine
= True)
1545 def AtEndOfStream(self
):
1546 return self
.GetProperty('AtEndOfStream')
1548 atEndOfStream
, atendofstream
= AtEndOfStream
, AtEndOfStream
1552 return self
.GetProperty('Line')
1556 def CloseFile(self
):
1557 return self
.ExecMethod(self
.vbMethod
, 'CloseFile')
1560 return self
.ExecMethod(self
.vbMethod
, 'ReadAll')
1563 return self
.ExecMethod(self
.vbMethod
, 'ReadLine')
1566 return self
.ExecMethod(self
.vbMethod
, 'SkipLine')
1568 def WriteBlankLines(self
, lines
):
1569 return self
.ExecMethod(self
.vbMethod
, 'WriteBlankLines', lines
)
1571 def WriteLine(self
, line
):
1572 return self
.ExecMethod(self
.vbMethod
, 'WriteLine', line
)
1574 # #########################################################################
1576 # #########################################################################
1577 class SF_Timer(SFServices
):
1579 The "Timer" service measures the amount of time it takes to run user scripts.
1581 # Mandatory class properties for service registration
1582 serviceimplementation
= 'basic'
1583 servicename
= 'ScriptForge.Timer'
1584 servicesynonyms
= ('timer', 'scriptforge.timer')
1585 serviceproperties
= dict(Duration
= False, IsStarted
= False, IsSuspended
= False,
1586 SuspendDuration
= False, TotalDuration
= False)
1587 # Force for each property to get its value from Basic
1588 forceGetProperty
= True
1591 def ReviewServiceArgs(cls
, start
= False):
1593 Transform positional and keyword arguments into positional only
1598 return self
.ExecMethod(self
.vbMethod
, 'Continue')
1601 return self
.ExecMethod(self
.vbMethod
, 'Restart')
1604 return self
.ExecMethod(self
.vbMethod
, 'Start')
1607 return self
.ExecMethod(self
.vbMethod
, 'Suspend')
1609 def Terminate(self
):
1610 return self
.ExecMethod(self
.vbMethod
, 'Terminate')
1612 # #########################################################################
1614 # #########################################################################
1615 class SF_UI(SFServices
, metaclass
= _Singleton
):
1617 Singleton class for the identification and the manipulation of the
1618 different windows composing the whole LibreOffice application:
1620 - Windows moving and resizing
1621 - Statusbar settings
1622 - Creation of new windows
1623 - Access to the underlying "documents"
1625 # Mandatory class properties for service registration
1626 serviceimplementation
= 'basic'
1627 servicename
= 'ScriptForge.UI'
1628 servicesynonyms
= ('ui', 'scriptforge.ui')
1629 serviceproperties
= dict(ActiveWindow
= False, Height
= False, Width
= False, X
= False, Y
= False)
1632 MACROEXECALWAYS
, MACROEXECNEVER
, MACROEXECNORMAL
= 2, 1, 0
1633 BASEDOCUMENT
, CALCDOCUMENT
, DRAWDOCUMENT
, IMPRESSDOCUMENT
, MATHDOCUMENT
, WRITERDOCUMENT
= \
1634 'Base', 'Calc', 'Draw', 'Impress', 'Math', 'Writer'
1637 def ActiveWindow(self
):
1638 return self
.ExecMethod(self
.vbMethod
, 'ActiveWindow')
1640 activeWindow
, activewindow
= ActiveWindow
, ActiveWindow
1642 def Activate(self
, windowname
= ''):
1643 return self
.ExecMethod(self
.vbMethod
, 'Activate', windowname
)
1645 def CreateBaseDocument(self
, filename
, embeddeddatabase
= 'HSQLDB', registrationname
= '', calcfilename
= ''):
1646 return self
.ExecMethod(self
.vbMethod
, 'CreateBaseDocument', filename
, embeddeddatabase
, registrationname
,
1649 def CreateDocument(self
, documenttype
= '', templatefile
= '', hidden
= False):
1650 return self
.ExecMethod(self
.vbMethod
, 'CreateDocument', documenttype
, templatefile
, hidden
)
1652 def Documents(self
):
1653 return self
.ExecMethod(self
.vbMethod
, 'Documents')
1655 def GetDocument(self
, windowname
= ''):
1656 return self
.ExecMethod(self
.vbMethod
, 'GetDocument', windowname
)
1658 def Maximize(self
, windowname
= ''):
1659 return self
.ExecMethod(self
.vbMethod
, 'Maximize', windowname
)
1661 def Minimize(self
, windowname
= ''):
1662 return self
.ExecMethod(self
.vbMethod
, 'Minimize', windowname
)
1664 def OpenBaseDocument(self
, filename
= '', registrationname
= '', macroexecution
= MACROEXECNORMAL
):
1665 return self
.ExecMethod(self
.vbMethod
, 'OpenBaseDocument', filename
, registrationname
, macroexecution
)
1667 def OpenDocument(self
, filename
, password
= '', readonly
= False, hidden
= False,
1668 macroexecution
= MACROEXECNORMAL
, filtername
= '', filteroptions
= ''):
1669 return self
.ExecMethod(self
.vbMethod
, 'OpenDocument', filename
, password
, readonly
, hidden
,
1670 macroexecution
, filtername
, filteroptions
)
1672 def Resize(self
, left
= -1, top
= -1, width
= -1, height
= -1):
1673 return self
.ExecMethod(self
.vbMethod
, 'Resize', left
, top
, width
, height
)
1675 def RunCommand(self
, command
, *args
, **kwargs
):
1676 params
= tuple(list(args
) + ScriptForge
.unpack_args(kwargs
))
1677 if len(params
) == 0:
1678 params
= (command
,) + (None,)
1680 params
= (command
,) + params
1681 return self
.SIMPLEEXEC('@SF_UI.RunCommand', params
)
1683 def SetStatusbar(self
, text
= '', percentage
= -1):
1684 return self
.ExecMethod(self
.vbMethod
, 'SetStatusbar', text
, percentage
)
1686 def ShowProgressBar(self
, title
= '', text
= '', percentage
= -1):
1687 # From Python, the current XComponentContext must be added as last argument
1688 return self
.ExecMethod(self
.vbMethod
, 'ShowProgressBar', title
, text
, percentage
,
1689 ScriptForge
.componentcontext
)
1691 def WindowExists(self
, windowname
):
1692 return self
.ExecMethod(self
.vbMethod
, 'WindowExists', windowname
)
1695 # #####################################################################################################################
1696 # SFDatabases CLASS (alias of SFDatabases Basic library) ###
1697 # #####################################################################################################################
1700 The SFDatabases class manages databases embedded in or connected to Base documents
1704 # #########################################################################
1706 # #########################################################################
1707 class SF_Database(SFServices
):
1709 Each instance of the current class represents a single database, with essentially its tables, queries
1711 The exchanges with the database are done in SQL only.
1712 To make them more readable, use optionally square brackets to surround table/query/field names
1713 instead of the (RDBMS-dependent) normal surrounding character.
1714 SQL statements may be run in direct or indirect mode. In direct mode the statement is transferred literally
1715 without syntax checking nor review to the database engine.
1717 # Mandatory class properties for service registration
1718 serviceimplementation
= 'basic'
1719 servicename
= 'SFDatabases.Database'
1720 servicesynonyms
= ('database', 'sfdatabases.database')
1721 serviceproperties
= dict(Queries
= False, Tables
= False, XConnection
= False, XMetaData
= False)
1724 def ReviewServiceArgs(cls
, filename
= '', registrationname
= '', readonly
= True, user
= '', password
= ''):
1726 Transform positional and keyword arguments into positional only
1728 return filename
, registrationname
, readonly
, user
, password
1730 def CloseDatabase(self
):
1731 return self
.ExecMethod(self
.vbMethod
, 'CloseDatabase')
1733 def DAvg(self
, expression
, tablename
, criteria
= ''):
1734 return self
.ExecMethod(self
.vbMethod
, 'DAvg', expression
, tablename
, criteria
)
1736 def DCount(self
, expression
, tablename
, criteria
= ''):
1737 return self
.ExecMethod(self
.vbMethod
, 'DCount', expression
, tablename
, criteria
)
1739 def DLookup(self
, expression
, tablename
, criteria
= '', orderclause
= ''):
1740 return self
.ExecMethod(self
.vbMethod
, 'DLookup', expression
, tablename
, criteria
, orderclause
)
1742 def DMax(self
, expression
, tablename
, criteria
= ''):
1743 return self
.ExecMethod(self
.vbMethod
, 'DMax', expression
, tablename
, criteria
)
1745 def DMin(self
, expression
, tablename
, criteria
= ''):
1746 return self
.ExecMethod(self
.vbMethod
, 'DMin', expression
, tablename
, criteria
)
1748 def DSum(self
, expression
, tablename
, criteria
= ''):
1749 return self
.ExecMethod(self
.vbMethod
, 'DSum', expression
, tablename
, criteria
)
1751 def GetRows(self
, sqlcommand
, directsql
= False, header
= False, maxrows
= 0):
1752 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'GetRows', sqlcommand
, directsql
, header
, maxrows
)
1754 def OpenFormDocument(self
, formdocument
):
1755 return self
.ExecMethod(self
.vbMethod
, 'OpenFormDocument', formdocument
)
1757 def OpenQuery(self
, queryname
):
1758 return self
.ExecMethod(self
.vbMethod
, 'OpenQuery', queryname
)
1760 def OpenSql(self
, sql
, directsql
= False):
1761 return self
.ExecMethod(self
.vbMethod
, 'OpenSql', sql
, directsql
)
1763 def OpenTable(self
, tablename
):
1764 return self
.ExecMethod(self
.vbMethod
, 'OpenTable', tablename
)
1766 def RunSql(self
, sqlcommand
, directsql
= False):
1767 return self
.ExecMethod(self
.vbMethod
, 'RunSql', sqlcommand
, directsql
)
1769 # #########################################################################
1770 # SF_Datasheet CLASS
1771 # #########################################################################
1772 class SF_Datasheet(SFServices
):
1774 A datasheet is the visual representation of tabular data produced by a database.
1775 A datasheet may be opened automatically by script code at any moment.
1776 The Base document owning the data may or may not be opened.
1777 Any SELECT SQL statement may trigger the datasheet display.
1779 # Mandatory class properties for service registration
1780 serviceimplementation
= 'basic'
1781 servicename
= 'SFDatabases.Datasheet'
1782 servicesynonyms
= ('datasheet', 'sfdatabases.datasheet')
1783 serviceproperties
= dict(ColumnHeaders
= False, CurrentColumn
= False, CurrentRow
= False,
1784 DatabaseFileName
= False, Filter
= True, LastRow
= False, OrderBy
= True,
1785 ParentDatabase
= False, Source
= False, SourceType
= False, XComponent
= False,
1786 XControlModel
= False, XTabControllerModel
= False)
1789 return self
.ExecMethod(self
.vbMethod
, 'Activate')
1791 def CloseDatasheet(self
):
1792 return self
.ExecMethod(self
.vbMethod
, 'CloseDatasheet')
1794 def CreateMenu(self
, menuheader
, before
= '', submenuchar
= '>'):
1795 return self
.ExecMethod(self
.vbMethod
, 'CreateMenu', menuheader
, before
, submenuchar
)
1797 def GetText(self
, column
= 0):
1798 return self
.ExecMethod(self
.vbMethod
, 'GetText', column
)
1800 def GetValue(self
, column
= 0):
1801 return self
.ExecMethod(self
.vbMethod
, 'GetValue', column
)
1803 def GoToCell(self
, row
= 0, column
= 0):
1804 return self
.ExecMethod(self
.vbMethod
, 'GoToCell', row
, column
)
1806 def RemoveMenu(self
, menuheader
):
1807 return self
.ExecMethod(self
.vbMethod
, 'RemoveMenu', menuheader
)
1809 def Toolbars(self
, toolbarname
= ''):
1810 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Toolbars', toolbarname
)
1813 # #####################################################################################################################
1814 # SFDialogs CLASS (alias of SFDialogs Basic library) ###
1815 # #####################################################################################################################
1818 The SFDialogs class manages dialogs defined with the Basic IDE
1822 # #########################################################################
1824 # #########################################################################
1825 class SF_Dialog(SFServices
):
1827 Each instance of the current class represents a single dialog box displayed to the user.
1828 The dialog box must have been designed and defined with the Basic IDE previously.
1829 From a Python script, a dialog box can be displayed in modal or in non-modal modes.
1831 In modal mode, the box is displayed and the execution of the macro process is suspended
1832 until one of the OK or Cancel buttons is pressed. In the meantime, other user actions
1833 executed on the box can trigger specific actions.
1835 In non-modal mode, the floating dialog remains displayed until the dialog is terminated
1836 by code (Terminate()) or until the LibreOffice application stops.
1838 # Mandatory class properties for service registration
1839 serviceimplementation
= 'basic'
1840 servicename
= 'SFDialogs.Dialog'
1841 servicesynonyms
= ('dialog', 'sfdialogs.dialog')
1842 serviceproperties
= dict(Caption
= True, Height
= True, Modal
= False, Name
= False,
1843 OnFocusGained
= True, OnFocusLost
= True, OnKeyPressed
= True,
1844 OnKeyReleased
= True, OnMouseDragged
= True, OnMouseEntered
= True,
1845 OnMouseExited
= True, OnMouseMoved
= True, OnMousePressed
= True,
1846 OnMouseReleased
= True,
1847 Page
= True, Visible
= True, Width
= True, XDialogModel
= False, XDialogView
= False)
1848 # Class constants used together with the Execute() method
1849 OKBUTTON
, CANCELBUTTON
= 1, 0
1852 def ReviewServiceArgs(cls
, container
= '', library
= 'Standard', dialogname
= ''):
1854 Transform positional and keyword arguments into positional only
1855 Add the XComponentContext as last argument
1857 return container
, library
, dialogname
, ScriptForge
.componentcontext
1859 # Methods potentially executed while the dialog is in execution require the flgHardCode flag
1861 return self
.ExecMethod(self
.vbMethod
+ self
.flgHardCode
, 'Activate')
1863 def Center(self
, parent
= ScriptForge
.cstSymMissing
):
1864 parentclasses
= (SFDocuments
.SF_Document
, SFDocuments
.SF_Base
, SFDocuments
.SF_Calc
, SFDocuments
.SF_Writer
,
1865 SFDialogs
.SF_Dialog
)
1866 parentobj
= parent
.objectreference
if isinstance(parent
, parentclasses
) else parent
1867 return self
.ExecMethod(self
.vbMethod
+ self
.flgObject
+ self
.flgHardCode
, 'Center', parentobj
)
1869 def CloneControl(self
, sourcename
, controlname
, left
= 1, top
= 1):
1870 return self
.ExecMethod(self
.vbMethod
, 'CloneControl', sourcename
, controlname
, left
, top
)
1872 def Controls(self
, controlname
= ''):
1873 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
+ self
.flgHardCode
, 'Controls', controlname
)
1875 def CreateButton(self
, controlname
, place
, toggle
= False, push
= ''):
1876 return self
.ExecMethod(self
.vbMethod
, 'CreateButton', controlname
, place
, toggle
, push
)
1878 def CreateCheckBox(self
, controlname
, place
, multiline
= False):
1879 return self
.ExecMethod(self
.vbMethod
, 'CreateCheckBox', controlname
, place
, multiline
)
1881 def CreateComboBox(self
, controlname
, place
, border
= '3D', dropdown
= True, linecount
= 5):
1882 return self
.ExecMethod(self
.vbMethod
, 'CreateComboBox', controlname
, place
, border
, dropdown
, linecount
)
1884 def CreateCurrencyField(self
, controlname
, place
, border
= '3D', spinbutton
= False, minvalue
= -1000000,
1885 maxvalue
= +1000000, increment
= 1, accuracy
= 2):
1886 return self
.ExecMethod(self
.vbMethod
, 'CreateCurrencyField', controlname
, place
, border
, spinbutton
,
1887 minvalue
, maxvalue
, increment
, accuracy
)
1889 def CreateDateField(self
, controlname
, place
, border
= '3D', dropdown
= True,
1890 mindate
= datetime
.datetime(1900, 1, 1, 0, 0, 0, 0),
1891 maxdate
= datetime
.datetime(2200, 12, 31, 0, 0, 0, 0)):
1892 if isinstance(mindate
, datetime
.datetime
):
1893 mindate
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(mindate
)
1894 if isinstance(maxdate
, datetime
.datetime
):
1895 maxdate
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(maxdate
)
1896 return self
.ExecMethod(self
.vbMethod
+ self
.flgDateArg
, 'CreateDateField', controlname
, place
, border
,
1897 dropdown
, mindate
, maxdate
)
1899 def CreateFileControl(self
, controlname
, place
, border
= '3D'):
1900 return self
.ExecMethod(self
.vbMethod
, 'CreateFileControl', controlname
, place
, border
)
1902 def CreateFixedLine(self
, controlname
, place
, orientation
):
1903 return self
.ExecMethod(self
.vbMethod
, 'CreateFixedLine', controlname
, place
, orientation
)
1905 def CreateFixedText(self
, controlname
, place
, border
= 'NONE', multiline
= False, align
= 'LEFT',
1906 verticalalign
= 'TOP'):
1907 return self
.ExecMethod(self
.vbMethod
, 'CreateFixedText', controlname
, place
, border
, multiline
, align
,
1910 def CreateFormattedField(self
, controlname
, place
, border
= '3D', spinbutton
= False,
1911 minvalue
= -1000000, maxvalue
= +1000000):
1912 return self
.ExecMethod(self
.vbMethod
, 'CreateFormattedField', controlname
, place
, border
, spinbutton
,
1915 def CreateGroupBox(self
, controlname
, place
):
1916 return self
.ExecMethod(self
.vbMethod
, 'CreateGroupBox', controlname
, place
)
1918 def CreateHyperlink(self
, controlname
, place
, border
= 'NONE', multiline
= False, align
= 'LEFT',
1919 verticalalign
= 'TOP'):
1920 return self
.ExecMethod(self
.vbMethod
, 'CreateHyperlink', controlname
, place
, border
, multiline
, align
,
1923 def CreateImageControl(self
, controlname
, place
, border
= '3D', scale
= 'FITTOSIZE'):
1924 return self
.ExecMethod(self
.vbMethod
, 'CreateImageControl', controlname
, place
, border
, scale
)
1926 def CreateListBox(self
, controlname
, place
, border
= '3D', dropdown
= True, linecount
= 5,
1927 multiselect
= False):
1928 return self
.ExecMethod(self
.vbMethod
, 'CreateListBox', controlname
, place
, border
, dropdown
,
1929 linecount
, multiselect
)
1931 def CreateNumericField(self
, controlname
, place
, border
= '3D', spinbutton
= False,
1932 minvalue
= -1000000, maxvalue
= +1000000, increment
= 1, accuracy
= 2):
1933 return self
.ExecMethod(self
.vbMethod
, 'CreateNumericField', controlname
, place
, border
, spinbutton
,
1934 minvalue
, maxvalue
, increment
, accuracy
)
1936 def CreatePatternField(self
, controlname
, place
, border
= '3D', editmask
= '', literalmask
= ''):
1937 return self
.ExecMethod(self
.vbMethod
, 'CreatePatternField', controlname
, place
, border
,
1938 editmask
, literalmask
)
1940 def CreateProgressBar(self
, controlname
, place
, border
= '3D', minvalue
= 0, maxvalue
= 100):
1941 return self
.ExecMethod(self
.vbMethod
, 'CreateProgressBar', controlname
, place
, border
, minvalue
, maxvalue
)
1943 def CreateRadioButton(self
, controlname
, place
, multiline
= False):
1944 return self
.ExecMethod(self
.vbMethod
, 'CreateRadioButton', controlname
, place
, multiline
)
1946 def CreateScrollBar(self
, controlname
, place
, orientation
, border
= '3D', minvalue
= 0, maxvalue
= 100):
1947 return self
.ExecMethod(self
.vbMethod
, 'CreateScrollBar', controlname
, place
, orientation
, border
,
1950 def CreateTableControl(self
, controlname
, place
, border
= '3D', rowheaders
= True, columnheaders
= True,
1951 scrollbars
= 'None', gridlines
= False):
1952 return self
.ExecMethod(self
.vbMethod
, 'CreateTableControl', controlname
, place
, border
,
1953 rowheaders
, columnheaders
, scrollbars
, gridlines
)
1955 def CreateTextField(self
, controlname
, place
, border
= '3D', multiline
= False,
1956 maximumlength
= 0, passwordcharacter
= ''):
1957 return self
.ExecMethod(self
.vbMethod
, 'CreateTextField', controlname
, place
, border
,
1958 multiline
, maximumlength
, passwordcharacter
)
1960 def CreateTimeField(self
, controlname
, place
, border
= '3D',
1961 mintime
= datetime
.datetime(1899, 12, 30, 0, 0, 0, 0),
1962 maxtime
= datetime
.datetime(1899, 12, 30, 23, 59, 59, 0)):
1963 if isinstance(mintime
, datetime
.datetime
):
1964 mintime
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(mintime
)
1965 if isinstance(maxtime
, datetime
.datetime
):
1966 maxtime
= SFScriptForge
.SF_Basic
.CDateToUnoDateTime(maxtime
)
1967 return self
.ExecMethod(self
.vbMethod
+ self
.flgDateArg
, 'CreateTimeField', controlname
, place
, border
,
1970 def CreateTreeControl(self
, controlname
, place
, border
= '3D'):
1971 return self
.ExecMethod(self
.vbMethod
, 'CreateTreeControl', controlname
, place
, border
)
1973 def EndExecute(self
, returnvalue
):
1974 return self
.ExecMethod(self
.vbMethod
+ self
.flgHardCode
, 'EndExecute', returnvalue
)
1976 def Execute(self
, modal
= True):
1977 return self
.ExecMethod(self
.vbMethod
+ self
.flgHardCode
, 'Execute', modal
)
1979 def GetTextsFromL10N(self
, l10n
):
1980 l10nobj
= l10n
.objectreference
if isinstance(l10n
, SFScriptForge
.SF_L10N
) else l10n
1981 return self
.ExecMethod(self
.vbMethod
+ self
.flgObject
, 'GetTextsFromL10N', l10nobj
)
1983 def OrderTabs(self
, tabslist
, start
= 1, increment
= 1):
1984 return self
.ExecMethod(self
.vbMethod
, 'OrderTabs', tabslist
, start
, increment
)
1986 def Resize(self
, left
= -99999, top
= -99999, width
= -1, height
= -1):
1987 return self
.ExecMethod(self
.vbMethod
+ self
.flgHardCode
, 'Resize', left
, top
, width
, height
)
1989 def SetPageManager(self
, pilotcontrols
= '', tabcontrols
= '', wizardcontrols
= '', lastpage
= 0):
1990 return self
.ExecMethod(self
.vbMethod
, 'SetPageManager', pilotcontrols
, tabcontrols
, wizardcontrols
,
1993 def Terminate(self
):
1994 return self
.ExecMethod(self
.vbMethod
, 'Terminate')
1996 # #########################################################################
1997 # SF_NewDialog CLASS
1998 # #########################################################################
1999 class SF_NewDialog(SFServices
):
2001 Pseudo service never returned from the Basic world. A SF_Dialog instance is returned instead.
2002 Main purpose: manage the arguments of CreateScriptService() for the creation of a dialog from scratch
2004 # Mandatory class properties for service registration
2005 serviceimplementation
= 'basic'
2006 servicename
= 'SFDialogs.NewDialog'
2007 servicesynonyms
= ('newdialog', 'sfdialogs.newdialog')
2008 serviceproperties
= dict()
2011 def ReviewServiceArgs(cls
, dialogname
= '', place
= (0, 0, 0, 0)):
2013 Transform positional and keyword arguments into positional only
2014 Add the XComponentContext as last argument
2016 outsideprocess
= len(ScriptForge
.hostname
) > 0 and ScriptForge
.port
> 0
2018 return dialogname
, place
, ScriptForge
.componentcontext
2020 return dialogname
, place
2022 # #########################################################################
2023 # SF_DialogControl CLASS
2024 # #########################################################################
2025 class SF_DialogControl(SFServices
):
2027 Each instance of the current class represents a single control within a dialog box.
2028 The focus is clearly set on getting and setting the values displayed by the controls of the dialog box,
2029 not on their formatting.
2030 A special attention is given to controls with type TreeControl.
2032 # Mandatory class properties for service registration
2033 serviceimplementation
= 'basic'
2034 servicename
= 'SFDialogs.DialogControl'
2035 servicesynonyms
= ()
2036 serviceproperties
= dict(Border
= True, Cancel
= True, Caption
= True, ControlType
= False, CurrentNode
= True,
2037 Default
= True, Enabled
= True, Format
= True, Height
= True, ListCount
= False,
2038 ListIndex
= True, Locked
= True, MultiSelect
= True, Name
= False,
2039 OnActionPerformed
= True, OnAdjustmentValueChanged
= True, OnFocusGained
= True,
2040 OnFocusLost
= True, OnItemStateChanged
= True, OnKeyPressed
= True,
2041 OnKeyReleased
= True, OnMouseDragged
= True, OnMouseEntered
= True,
2042 OnMouseExited
= True, OnMouseMoved
= True, OnMousePressed
= True,
2043 OnMouseReleased
= True, OnNodeExpanded
= True, OnNodeSelected
= True,
2044 OnTextChanged
= True, Page
= True, Parent
= False, Picture
= True,
2045 RootNode
= False, RowSource
= True, TabIndex
= True, Text
= False, TipText
= True,
2046 TripleState
= True, URL
= True, Value
= True, Visible
= True, Width
= True,
2047 X
= True, Y
= True, XControlModel
= False, XControlView
= False,
2048 XGridColumnModel
= False, XGridDataModel
= False, XTreeDataModel
= False)
2050 # Root related properties do not start with X and, nevertheless, return a UNO object
2052 def CurrentNode(self
):
2053 return self
.EXEC(self
.objectreference
, self
.vbGet
+ self
.flgUno
, 'CurrentNode')
2057 return self
.EXEC(self
.objectreference
, self
.vbGet
+ self
.flgUno
, 'RootNode')
2059 def AddSubNode(self
, parentnode
, displayvalue
, datavalue
= ScriptForge
.cstSymEmpty
):
2060 return self
.ExecMethod(self
.vbMethod
+ self
.flgUno
, 'AddSubNode', parentnode
, displayvalue
, datavalue
)
2062 def AddSubTree(self
, parentnode
, flattree
, withdatavalue
= False):
2063 return self
.ExecMethod(self
.vbMethod
, 'AddSubTree', parentnode
, flattree
, withdatavalue
)
2065 def CreateRoot(self
, displayvalue
, datavalue
= ScriptForge
.cstSymEmpty
):
2066 return self
.ExecMethod(self
.vbMethod
+ self
.flgUno
, 'CreateRoot', displayvalue
, datavalue
)
2068 def FindNode(self
, displayvalue
, datavalue
= ScriptForge
.cstSymEmpty
, casesensitive
= False):
2069 return self
.ExecMethod(self
.vbMethod
+ self
.flgUno
, 'FindNode', displayvalue
, datavalue
, casesensitive
)
2071 def Resize(self
, left
= -99999, top
= -99999, width
= -1, height
= -1):
2072 return self
.ExecMethod(self
.vbMethod
, 'Resize', left
, top
, width
, height
)
2075 return self
.ExecMethod(self
.vbMethod
, 'SetFocus')
2077 def SetTableData(self
, dataarray
, widths
= (1,), alignments
= '', rowheaderwidth
= 10):
2078 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayArg
, 'SetTableData', dataarray
, widths
, alignments
,
2081 def WriteLine(self
, line
= ''):
2082 return self
.ExecMethod(self
.vbMethod
, 'WriteLine', line
)
2085 # #####################################################################################################################
2086 # SFDocuments CLASS (alias of SFDocuments Basic library) ###
2087 # #####################################################################################################################
2090 The SFDocuments class gathers a number of classes, methods and properties making easy
2091 managing and manipulating LibreOffice documents
2095 # #########################################################################
2097 # #########################################################################
2098 class SF_Document(SFServices
):
2100 The methods and properties are generic for all types of documents: they are combined in the
2101 current SF_Document class
2102 - saving, closing documents
2103 - accessing their standard or custom properties
2104 Specific properties and methods are implemented in the concerned subclass(es) SF_Calc, SF_Base, ...
2106 # Mandatory class properties for service registration
2107 serviceimplementation
= 'basic'
2108 servicename
= 'SFDocuments.Document'
2109 servicesynonyms
= ('document', 'sfdocuments.document')
2110 serviceproperties
= dict(Description
= True, DocumentType
= False, ExportFilters
= False, ImportFilters
= False,
2111 IsBase
= False, IsCalc
= False, IsDraw
= False, IsFormDocument
= False,
2112 IsImpress
= False, IsMath
= False, IsWriter
= False, Keywords
= True, Readonly
= False,
2113 Subject
= True, Title
= True, XComponent
= False)
2114 # Force for each property to get its value from Basic - due to intense interactivity with user
2115 forceGetProperty
= True
2118 def ReviewServiceArgs(cls
, windowname
= ''):
2120 Transform positional and keyword arguments into positional only
2125 return self
.ExecMethod(self
.vbMethod
, 'Activate')
2127 def CloseDocument(self
, saveask
= True):
2128 return self
.ExecMethod(self
.vbMethod
, 'CloseDocument', saveask
)
2130 def CreateMenu(self
, menuheader
, before
= '', submenuchar
= '>'):
2131 return self
.ExecMethod(self
.vbMethod
, 'CreateMenu', menuheader
, before
, submenuchar
)
2133 def Echo(self
, echoon
= True, hourglass
= False):
2134 return self
.ExecMethod(self
.vbMethod
, 'Echo', echoon
, hourglass
)
2136 def ExportAsPDF(self
, filename
, overwrite
= False, pages
= '', password
= '', watermark
= ''):
2137 return self
.ExecMethod(self
.vbMethod
, 'ExportAsPDF', filename
, overwrite
, pages
, password
, watermark
)
2139 def PrintOut(self
, pages
= '', copies
= 1):
2140 return self
.ExecMethod(self
.vbMethod
, 'PrintOut', pages
, copies
)
2142 def RemoveMenu(self
, menuheader
):
2143 return self
.ExecMethod(self
.vbMethod
, 'RemoveMenu', menuheader
)
2145 def RunCommand(self
, command
, *args
, **kwargs
):
2146 params
= tuple([command
] + list(args
) + ScriptForge
.unpack_args(kwargs
))
2147 return self
.ExecMethod(self
.vbMethod
, 'RunCommand', *params
)
2150 return self
.ExecMethod(self
.vbMethod
, 'Save')
2152 def SaveAs(self
, filename
, overwrite
= False, password
= '', filtername
= '', filteroptions
= ''):
2153 return self
.ExecMethod(self
.vbMethod
, 'SaveAs', filename
, overwrite
, password
, filtername
, filteroptions
)
2155 def SaveCopyAs(self
, filename
, overwrite
= False, password
= '', filtername
= '', filteroptions
= ''):
2156 return self
.ExecMethod(self
.vbMethod
, 'SaveCopyAs', filename
, overwrite
,
2157 password
, filtername
, filteroptions
)
2159 def SetPrinter(self
, printer
= '', orientation
= '', paperformat
= ''):
2160 return self
.ExecMethod(self
.vbMethod
, 'SetPrinter', printer
, orientation
, paperformat
)
2162 def Toolbars(self
, toolbarname
= ''):
2163 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Toolbars', toolbarname
)
2165 # #########################################################################
2167 # #########################################################################
2168 class SF_Base(SF_Document
, SFServices
):
2170 The SF_Base module is provided mainly to block parent properties that are NOT applicable to Base documents
2171 In addition, it provides methods to identify form documents and access their internal forms
2172 (read more elsewhere (the "SFDocuments.Form" service) about this subject)
2174 # Mandatory class properties for service registration
2175 serviceimplementation
= 'basic'
2176 servicename
= 'SFDocuments.Base'
2177 servicesynonyms
= ('base', 'scriptforge.base')
2178 serviceproperties
= dict(DocumentType
= False, IsBase
= False, IsCalc
= False, IsDraw
= False,
2179 IsFormDocument
= False, IsImpress
= False, IsMath
= False, IsWriter
= False,
2183 def ReviewServiceArgs(cls
, windowname
= ''):
2185 Transform positional and keyword arguments into positional only
2189 def CloseDocument(self
, saveask
= True):
2190 return self
.ExecMethod(self
.vbMethod
, 'CloseDocument', saveask
)
2192 def CloseFormDocument(self
, formdocument
):
2193 return self
.ExecMethod(self
.vbMethod
, 'CloseFormDocument', formdocument
)
2195 def FormDocuments(self
):
2196 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'FormDocuments')
2198 def Forms(self
, formdocument
, form
= ''):
2199 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Forms', formdocument
, form
)
2201 def GetDatabase(self
, user
= '', password
= ''):
2202 return self
.ExecMethod(self
.vbMethod
, 'GetDatabase', user
, password
)
2204 def IsLoaded(self
, formdocument
):
2205 return self
.ExecMethod(self
.vbMethod
, 'IsLoaded', formdocument
)
2207 def OpenFormDocument(self
, formdocument
, designmode
= False):
2208 return self
.ExecMethod(self
.vbMethod
, 'OpenFormDocument', formdocument
, designmode
)
2210 def OpenQuery(self
, queryname
):
2211 return self
.ExecMethod(self
.vbMethod
, 'OpenQuery', queryname
)
2213 def OpenTable(self
, tablename
):
2214 return self
.ExecMethod(self
.vbMethod
, 'OpenTable', tablename
)
2216 def PrintOut(self
, formdocument
, pages
= '', copies
= 1):
2217 return self
.ExecMethod(self
.vbMethod
, 'PrintOut', formdocument
, pages
, copies
)
2219 def SetPrinter(self
, formdocument
= '', printer
= '', orientation
= '', paperformat
= ''):
2220 return self
.ExecMethod(self
.vbMethod
, 'SetPrinter', formdocument
, printer
, orientation
, paperformat
)
2222 # #########################################################################
2224 # #########################################################################
2225 class SF_Calc(SF_Document
, SFServices
):
2227 The SF_Calc module is focused on :
2228 - management (copy, insert, move, ...) of sheets within a Calc document
2229 - exchange of data between Basic data structures and Calc ranges of values
2231 # Mandatory class properties for service registration
2232 serviceimplementation
= 'basic'
2233 servicename
= 'SFDocuments.Calc'
2234 servicesynonyms
= ('calc', 'sfdocuments.calc')
2235 serviceproperties
= dict(CurrentSelection
= True, Sheets
= False,
2236 Description
= True, DocumentType
= False, ExportFilters
= False, ImportFilters
= False,
2237 IsBase
= False, IsCalc
= False, IsDraw
= False, IsFormDocument
= False,
2238 IsImpress
= False, IsMath
= False, IsWriter
= False, Keywords
= True, Readonly
= False,
2239 Subject
= True, Title
= True, XComponent
= False)
2240 # Force for each property to get its value from Basic - due to intense interactivity with user
2241 forceGetProperty
= True
2244 def ReviewServiceArgs(cls
, windowname
= ''):
2246 Transform positional and keyword arguments into positional only
2250 # Next functions are implemented in Basic as read-only properties with 1 argument
2251 def FirstCell(self
, rangename
):
2252 return self
.GetProperty('FirstCell', rangename
)
2254 def FirstColumn(self
, rangename
):
2255 return self
.GetProperty('FirstColumn', rangename
)
2257 def FirstRow(self
, rangename
):
2258 return self
.GetProperty('FirstRow', rangename
)
2260 def Height(self
, rangename
):
2261 return self
.GetProperty('Height', rangename
)
2263 def LastCell(self
, rangename
):
2264 return self
.GetProperty('LastCell', rangename
)
2266 def LastColumn(self
, rangename
):
2267 return self
.GetProperty('LastColumn', rangename
)
2269 def LastRow(self
, rangename
):
2270 return self
.GetProperty('LastRow', rangename
)
2272 def Range(self
, rangename
):
2273 return self
.GetProperty('Range', rangename
)
2275 def Region(self
, rangename
):
2276 return self
.GetProperty('Region', rangename
)
2278 def Sheet(self
, sheetname
):
2279 return self
.GetProperty('Sheet', sheetname
)
2281 def SheetName(self
, rangename
):
2282 return self
.GetProperty('SheetName', rangename
)
2284 def Width(self
, rangename
):
2285 return self
.GetProperty('Width', rangename
)
2287 def XCellRange(self
, rangename
):
2288 return self
.ExecMethod(self
.vbGet
+ self
.flgUno
, 'XCellRange', rangename
)
2290 def XSheetCellCursor(self
, rangename
):
2291 return self
.ExecMethod(self
.vbGet
+ self
.flgUno
, 'XSheetCellCursor', rangename
)
2293 def XSpreadsheet(self
, sheetname
):
2294 return self
.ExecMethod(self
.vbGet
+ self
.flgUno
, 'XSpreadsheet', sheetname
)
2297 def A1Style(self
, row1
, column1
, row2
= 0, column2
= 0, sheetname
= '~'):
2298 return self
.ExecMethod(self
.vbMethod
, 'A1Style', row1
, column1
, row2
, column2
, sheetname
)
2300 def Activate(self
, sheetname
= ''):
2301 return self
.ExecMethod(self
.vbMethod
, 'Activate', sheetname
)
2303 def Charts(self
, sheetname
, chartname
= ''):
2304 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Charts', sheetname
, chartname
)
2306 def ClearAll(self
, range, filterformula
= '', filterscope
= ''):
2307 return self
.ExecMethod(self
.vbMethod
, 'ClearAll', range, filterformula
, filterscope
)
2309 def ClearFormats(self
, range, filterformula
= '', filterscope
= ''):
2310 return self
.ExecMethod(self
.vbMethod
, 'ClearFormats', range, filterformula
, filterscope
)
2312 def ClearValues(self
, range, filterformula
= '', filterscope
= ''):
2313 return self
.ExecMethod(self
.vbMethod
, 'ClearValues', range, filterformula
, filterscope
)
2315 def CompactLeft(self
, range, wholecolumn
= False, filterformula
= ''):
2316 return self
.ExecMethod(self
.vbMethod
, 'CompactLeft', range, wholecolumn
, filterformula
)
2318 def CompactUp(self
, range, wholerow
= False, filterformula
= ''):
2319 return self
.ExecMethod(self
.vbMethod
, 'CompactUp', range, wholerow
, filterformula
)
2321 def CopySheet(self
, sheetname
, newname
, beforesheet
= 32768):
2322 sheet
= (sheetname
.objectreference
if isinstance(sheetname
, SFDocuments
.SF_CalcReference
) else sheetname
)
2323 return self
.ExecMethod(self
.vbMethod
+ self
.flgObject
, 'CopySheet', sheet
, newname
, beforesheet
)
2325 def CopySheetFromFile(self
, filename
, sheetname
, newname
, beforesheet
= 32768):
2326 sheet
= (sheetname
.objectreference
if isinstance(sheetname
, SFDocuments
.SF_CalcReference
) else sheetname
)
2327 return self
.ExecMethod(self
.vbMethod
+ self
.flgObject
, 'CopySheetFromFile',
2328 filename
, sheet
, newname
, beforesheet
)
2330 def CopyToCell(self
, sourcerange
, destinationcell
):
2331 range = (sourcerange
.objectreference
if isinstance(sourcerange
, SFDocuments
.SF_CalcReference
)
2333 return self
.ExecMethod(self
.vbMethod
+ self
.flgObject
, 'CopyToCell', range, destinationcell
)
2335 def CopyToRange(self
, sourcerange
, destinationrange
):
2336 range = (sourcerange
.objectreference
if isinstance(sourcerange
, SFDocuments
.SF_CalcReference
)
2338 return self
.ExecMethod(self
.vbMethod
+ self
.flgObject
, 'CopyToRange', range, destinationrange
)
2340 def CreateChart(self
, chartname
, sheetname
, range, columnheader
= False, rowheader
= False):
2341 return self
.ExecMethod(self
.vbMethod
, 'CreateChart', chartname
, sheetname
, range, columnheader
, rowheader
)
2343 def CreatePivotTable(self
, pivottablename
, sourcerange
, targetcell
, datafields
= ScriptForge
.cstSymEmpty
,
2344 rowfields
= ScriptForge
.cstSymEmpty
, columnfields
= ScriptForge
.cstSymEmpty
,
2345 filterbutton
= True, rowtotals
= True, columntotals
= True):
2346 return self
.ExecMethod(self
.vbMethod
, 'CreatePivotTable', pivottablename
, sourcerange
, targetcell
,
2347 datafields
, rowfields
, columnfields
, filterbutton
, rowtotals
, columntotals
)
2349 def DAvg(self
, range):
2350 return self
.ExecMethod(self
.vbMethod
, 'DAvg', range)
2352 def DCount(self
, range):
2353 return self
.ExecMethod(self
.vbMethod
, 'DCount', range)
2355 def DMax(self
, range):
2356 return self
.ExecMethod(self
.vbMethod
, 'DMax', range)
2358 def DMin(self
, range):
2359 return self
.ExecMethod(self
.vbMethod
, 'DMin', range)
2361 def DSum(self
, range):
2362 return self
.ExecMethod(self
.vbMethod
, 'DSum', range)
2364 def ExportRangeToFile(self
, range, filename
, imagetype
= 'pdf', overwrite
= False):
2365 return self
.ExecMethod(self
.vbMethod
, 'ExportRangeToFile', range, filename
, imagetype
, overwrite
)
2367 def Forms(self
, sheetname
, form
= ''):
2368 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Forms', sheetname
, form
)
2370 def GetColumnName(self
, columnnumber
):
2371 return self
.ExecMethod(self
.vbMethod
, 'GetColumnName', columnnumber
)
2373 def GetFormula(self
, range):
2374 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'GetFormula', range)
2376 def GetValue(self
, range):
2377 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'GetValue', range)
2379 def ImportFromCSVFile(self
, filename
, destinationcell
, filteroptions
= ScriptForge
.cstSymEmpty
):
2380 return self
.ExecMethod(self
.vbMethod
, 'ImportFromCSVFile', filename
, destinationcell
, filteroptions
)
2382 def ImportFromDatabase(self
, filename
= '', registrationname
= '', destinationcell
= '', sqlcommand
= '',
2384 return self
.ExecMethod(self
.vbMethod
, 'ImportFromDatabase', filename
, registrationname
,
2385 destinationcell
, sqlcommand
, directsql
)
2387 def InsertSheet(self
, sheetname
, beforesheet
= 32768):
2388 return self
.ExecMethod(self
.vbMethod
, 'InsertSheet', sheetname
, beforesheet
)
2390 def MoveRange(self
, source
, destination
):
2391 return self
.ExecMethod(self
.vbMethod
, 'MoveRange', source
, destination
)
2393 def MoveSheet(self
, sheetname
, beforesheet
= 32768):
2394 return self
.ExecMethod(self
.vbMethod
, 'MoveSheet', sheetname
, beforesheet
)
2396 def Offset(self
, range, rows
= 0, columns
= 0, height
= ScriptForge
.cstSymEmpty
,
2397 width
= ScriptForge
.cstSymEmpty
):
2398 return self
.ExecMethod(self
.vbMethod
, 'Offset', range, rows
, columns
, height
, width
)
2400 def OpenRangeSelector(self
, title
= '', selection
= '~', singlecell
= False, closeafterselect
= True):
2401 return self
.ExecMethod(self
.vbMethod
, 'OpenRangeSelector', title
, selection
, singlecell
, closeafterselect
)
2403 def Printf(self
, inputstr
, range, tokencharacter
= '%'):
2404 return self
.ExecMethod(self
.vbMethod
, 'Printf', inputstr
, range, tokencharacter
)
2406 def PrintOut(self
, sheetname
= '~', pages
= '', copies
= 1):
2407 return self
.ExecMethod(self
.vbMethod
, 'PrintOut', sheetname
, pages
, copies
)
2409 def RemoveDuplicates(self
, range, columns
= 1, header
= False, casesensitive
= False, mode
= 'COMPACT'):
2410 return self
.ExecMethod(self
.vbMethod
, 'RemoveDuplicates', range, columns
, header
, casesensitive
, mode
)
2412 def RemoveSheet(self
, sheetname
):
2413 return self
.ExecMethod(self
.vbMethod
, 'RemoveSheet', sheetname
)
2415 def RenameSheet(self
, sheetname
, newname
):
2416 return self
.ExecMethod(self
.vbMethod
, 'RenameSheet', sheetname
, newname
)
2418 def SetArray(self
, targetcell
, value
):
2419 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayArg
, 'SetArray', targetcell
, value
)
2421 def SetCellStyle(self
, targetrange
, style
, filterformula
= '', filterscope
= ''):
2422 return self
.ExecMethod(self
.vbMethod
, 'SetCellStyle', targetrange
, style
, filterformula
, filterscope
)
2424 def SetFormula(self
, targetrange
, formula
):
2425 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayArg
, 'SetFormula', targetrange
, formula
)
2427 def SetValue(self
, targetrange
, value
):
2428 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayArg
, 'SetValue', targetrange
, value
)
2430 def ShiftDown(self
, range, wholerow
= False, rows
= 0):
2431 return self
.ExecMethod(self
.vbMethod
, 'ShiftDown', range, wholerow
, rows
)
2433 def ShiftLeft(self
, range, wholecolumn
= False, columns
= 0):
2434 return self
.ExecMethod(self
.vbMethod
, 'ShiftLeft', range, wholecolumn
, columns
)
2436 def ShiftRight(self
, range, wholecolumn
= False, columns
= 0):
2437 return self
.ExecMethod(self
.vbMethod
, 'ShiftRight', range, wholecolumn
, columns
)
2439 def ShiftUp(self
, range, wholerow
= False, rows
= 0):
2440 return self
.ExecMethod(self
.vbMethod
, 'ShiftUp', range, wholerow
, rows
)
2442 def SortRange(self
, range, sortkeys
, sortorder
= 'ASC', destinationcell
= ScriptForge
.cstSymEmpty
,
2443 containsheader
= False, casesensitive
= False, sortcolumns
= False):
2444 return self
.ExecMethod(self
.vbMethod
, 'SortRange', range, sortkeys
, sortorder
, destinationcell
,
2445 containsheader
, casesensitive
, sortcolumns
)
2447 # #########################################################################
2448 # SF_CalcReference CLASS
2449 # #########################################################################
2450 class SF_CalcReference(SFServices
):
2452 The SF_CalcReference class has as unique role to hold sheet and range references.
2453 They are implemented in Basic as Type ... End Type data structures
2455 # Mandatory class properties for service registration
2456 serviceimplementation
= 'basic'
2457 servicename
= 'SFDocuments.CalcReference'
2458 servicesynonyms
= ()
2459 serviceproperties
= dict()
2461 # #########################################################################
2463 # #########################################################################
2464 class SF_Chart(SFServices
):
2466 The SF_Chart module is focused on the description of chart documents
2467 stored in Calc sheets.
2468 With this service, many chart types and chart characteristics available
2469 in the user interface can be read or modified.
2471 # Mandatory class properties for service registration
2472 serviceimplementation
= 'basic'
2473 servicename
= 'SFDocuments.Chart'
2474 servicesynonyms
= ()
2475 serviceproperties
= dict(ChartType
= True, Deep
= True, Dim3D
= True, Exploded
= True, Filled
= True,
2476 Legend
= True, Percent
= True, Stacked
= True, Title
= True,
2477 XChartObj
= False, XDiagram
= False, XShape
= False, XTableChart
= False,
2478 XTitle
= True, YTitle
= True)
2480 def Resize(self
, xpos
= -1, ypos
= -1, width
= -1, height
= -1):
2481 return self
.ExecMethod(self
.vbMethod
, 'Resize', xpos
, ypos
, width
, height
)
2483 def ExportToFile(self
, filename
, imagetype
= 'png', overwrite
= False):
2484 return self
.ExecMethod(self
.vbMethod
, 'ExportToFile', filename
, imagetype
, overwrite
)
2486 # #########################################################################
2488 # #########################################################################
2489 class SF_Form(SFServices
):
2491 Management of forms defined in LibreOffice documents. Supported types are Base, Calc and Writer documents.
2492 It includes the management of subforms
2493 Each instance of the current class represents a single form or a single subform
2494 A form may optionally be (understand "is often") linked to a data source manageable with
2495 the SFDatabases.Database service. The current service offers rapid access to that service.
2497 # Mandatory class properties for service registration
2498 serviceimplementation
= 'basic'
2499 servicename
= 'SFDocuments.Form'
2500 servicesynonyms
= ()
2501 serviceproperties
= dict(AllowDeletes
= True, AllowInserts
= True, AllowUpdates
= True, BaseForm
= False,
2502 Bookmark
= True, CurrentRecord
= True, Filter
= True, LinkChildFields
= False,
2503 LinkParentFields
= False, Name
= False,
2504 OnApproveCursorMove
= True, OnApproveParameter
= True, OnApproveReset
= True,
2505 OnApproveRowChange
= True, OnApproveSubmit
= True, OnConfirmDelete
= True,
2506 OnCursorMoved
= True, OnErrorOccurred
= True, OnLoaded
= True, OnReloaded
= True,
2507 OnReloading
= True, OnResetted
= True, OnRowChanged
= True, OnUnloaded
= True,
2509 OrderBy
= True, Parent
= False, RecordSource
= True, XForm
= False)
2512 return self
.ExecMethod(self
.vbMethod
, 'Activate')
2514 def CloseFormDocument(self
):
2515 return self
.ExecMethod(self
.vbMethod
, 'CloseFormDocument')
2517 def Controls(self
, controlname
= ''):
2518 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Controls', controlname
)
2520 def GetDatabase(self
, user
= '', password
= ''):
2521 return self
.ExecMethod(self
.vbMethod
, 'GetDatabase', user
, password
)
2523 def MoveFirst(self
):
2524 return self
.ExecMethod(self
.vbMethod
, 'MoveFirst')
2527 return self
.ExecMethod(self
.vbMethod
, 'MoveLast')
2530 return self
.ExecMethod(self
.vbMethod
, 'MoveNew')
2532 def MoveNext(self
, offset
= 1):
2533 return self
.ExecMethod(self
.vbMethod
, 'MoveNext', offset
)
2535 def MovePrevious(self
, offset
= 1):
2536 return self
.ExecMethod(self
.vbMethod
, 'MovePrevious', offset
)
2539 return self
.ExecMethod(self
.vbMethod
, 'Requery')
2541 def Subforms(self
, subform
= ''):
2542 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Subforms', subform
)
2544 # #########################################################################
2545 # SF_FormControl CLASS
2546 # #########################################################################
2547 class SF_FormControl(SFServices
):
2549 Manage the controls belonging to a form or subform stored in a document.
2550 Each instance of the current class represents a single control within a form, a subform or a tablecontrol.
2551 A prerequisite is that all controls within the same form, subform or tablecontrol must have
2554 # Mandatory class properties for service registration
2555 serviceimplementation
= 'basic'
2556 servicename
= 'SFDocuments.FormControl'
2557 servicesynonyms
= ()
2558 serviceproperties
= dict(Action
= True, Caption
= True, ControlSource
= False, ControlType
= False,
2559 Default
= True, DefaultValue
= True, Enabled
= True, Format
= True,
2560 ListCount
= False, ListIndex
= True, ListSource
= True, ListSourceType
= True,
2561 Locked
= True, MultiSelect
= True, Name
= False,
2562 OnActionPerformed
= True, OnAdjustmentValueChanged
= True,
2563 OnApproveAction
= True, OnApproveReset
= True, OnApproveUpdate
= True,
2564 OnChanged
= True, OnErrorOccurred
= True, OnFocusGained
= True, OnFocusLost
= True,
2565 OnItemStateChanged
= True, OnKeyPressed
= True, OnKeyReleased
= True,
2566 OnMouseDragged
= True, OnMouseEntered
= True, OnMouseExited
= True,
2567 OnMouseMoved
= True, OnMousePressed
= True, OnMouseReleased
= True, OnResetted
= True,
2568 OnTextChanged
= True, OnUpdated
= True, Parent
= False, Picture
= True,
2569 Required
= True, Text
= False, TipText
= True, TripleState
= True, Value
= True,
2570 Visible
= True, XControlModel
= False, XControlView
= False)
2572 def Controls(self
, controlname
= ''):
2573 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Controls', controlname
)
2576 return self
.ExecMethod(self
.vbMethod
, 'SetFocus')
2578 # #########################################################################
2579 # SF_FormDocument CLASS
2580 # #########################################################################
2581 class SF_FormDocument(SF_Document
, SFServices
):
2583 The orchestration of Base form documents (aka Base Forms, but this is confusing)
2584 and the identification of and the access to their controls.
2585 Form documents are always contained in a Base document.
2586 They should not be confused with Writer documents containing forms,
2587 even if it is easy to convert the former to the latter.
2589 # Mandatory class properties for service registration
2590 serviceimplementation
= 'basic'
2591 servicename
= 'SFDocuments.FormDocument'
2592 servicesynonyms
= ('formdocument', 'sfdocuments.formdocument')
2593 serviceproperties
= dict(DocumentType
= False, IsBase
= False, IsCalc
= False, IsDraw
= False,
2594 IsFormDocument
= False, IsImpress
= False, IsMath
= False, IsWriter
= False,
2595 Readonly
= False, XComponent
= False)
2598 def ReviewServiceArgs(cls
, windowname
= ''):
2600 Transform positional and keyword arguments into positional only
2604 def CloseDocument(self
):
2605 return self
.ExecMethod(self
.vbMethod
, 'CloseDocument')
2607 def Forms(self
, form
= ''):
2608 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Forms', form
)
2610 def GetDatabase(self
, user
= '', password
= ''):
2611 return self
.ExecMethod(self
.vbMethod
, 'GetDatabase', user
, password
)
2613 def PrintOut(self
, pages
= '', copies
= 1, printbackground
= True, printblankpages
= False,
2614 printevenpages
= True, printoddpages
= True, printimages
= True):
2615 return self
.ExecMethod(self
.vbMethod
, 'PrintOut', pages
, copies
, printbackground
, printblankpages
,
2616 printevenpages
, printoddpages
, printimages
)
2618 # #########################################################################
2620 # #########################################################################
2621 class SF_Writer(SF_Document
, SFServices
):
2623 The SF_Writer module is focused on :
2626 # Mandatory class properties for service registration
2627 serviceimplementation
= 'basic'
2628 servicename
= 'SFDocuments.Writer'
2629 servicesynonyms
= ('writer', 'sfdocuments.writer')
2630 serviceproperties
= dict(Description
= True, DocumentType
= False, ExportFilters
= False, ImportFilters
= False,
2631 IsBase
= False, IsCalc
= False, IsDraw
= False, IsFormDocument
= False,
2632 IsImpress
= False, IsMath
= False, IsWriter
= False, Keywords
= True, Readonly
= False,
2633 Subject
= True, Title
= True, XComponent
= False)
2634 # Force for each property to get its value from Basic - due to intense interactivity with user
2635 forceGetProperty
= True
2638 def ReviewServiceArgs(cls
, windowname
= ''):
2640 Transform positional and keyword arguments into positional only
2644 def Forms(self
, form
= ''):
2645 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'Forms', form
)
2647 def PrintOut(self
, pages
= '', copies
= 1, printbackground
= True, printblankpages
= False,
2648 printevenpages
= True, printoddpages
= True, printimages
= True):
2649 return self
.ExecMethod(self
.vbMethod
, 'PrintOut', pages
, copies
, printbackground
, printblankpages
,
2650 printevenpages
, printoddpages
, printimages
)
2653 # #####################################################################################################################
2654 # SFWidgets CLASS (alias of SFWidgets Basic library) ###
2655 # #####################################################################################################################
2658 The SFWidgets class manages toolbars and popup menus
2662 # #########################################################################
2664 # #########################################################################
2665 class SF_Menu(SFServices
):
2667 Display a menu in the menubar of a document or a form document.
2668 After use, the menu will not be saved neither in the application settings, nor in the document.
2669 The menu will be displayed, as usual, when its header in the menubar is clicked.
2670 When one of its items is selected, there are 3 alternative options:
2671 - a UNO command (like ".uno:About") is triggered
2672 - a user script is run receiving a standard argument defined in this service
2673 - one of above combined with a toggle of the status of the item
2674 The menu is described from top to bottom. Each menu item receives a numeric and a string identifier.
2676 # Mandatory class properties for service registration
2677 serviceimplementation
= 'basic'
2678 servicename
= 'SFWidgets.Menu'
2679 servicesynonyms
= ('menu', 'sfwidgets.menu')
2680 serviceproperties
= dict(ShortcutCharacter
= False, SubmenuCharacter
= False)
2682 def AddCheckBox(self
, menuitem
, name
= '', status
= False, icon
= '', tooltip
= '',
2683 command
= '', script
= ''):
2684 return self
.ExecMethod(self
.vbMethod
, 'AddCheckBox', menuitem
, name
, status
, icon
, tooltip
,
2687 def AddItem(self
, menuitem
, name
= '', icon
= '', tooltip
= '', command
= '', script
= ''):
2688 return self
.ExecMethod(self
.vbMethod
, 'AddItem', menuitem
, name
, icon
, tooltip
, command
, script
)
2690 def AddRadioButton(self
, menuitem
, name
= '', status
= False, icon
= '', tooltip
= '',
2691 command
= '', script
= ''):
2692 return self
.ExecMethod(self
.vbMethod
, 'AddRadioButton', menuitem
, name
, status
, icon
, tooltip
,
2695 # #########################################################################
2696 # SF_PopupMenu CLASS
2697 # #########################################################################
2698 class SF_PopupMenu(SFServices
):
2700 Display a popup menu anywhere and any time.
2701 A popup menu is usually triggered by a mouse action (typically a right-click) on a dialog, a form
2702 or one of their controls. In this case the menu will be displayed below the clicked area.
2703 When triggered by other events, including in the normal flow of a user script, the script should
2704 provide the coordinates of the topleft edge of the menu versus the actual component.
2705 The menu is described from top to bottom. Each menu item receives a numeric and a string identifier.
2706 The execute() method returns the item selected by the user.
2708 # Mandatory class properties for service registration
2709 serviceimplementation
= 'basic'
2710 servicename
= 'SFWidgets.PopupMenu'
2711 servicesynonyms
= ('popupmenu', 'sfwidgets.popupmenu')
2712 serviceproperties
= dict(ShortcutCharacter
= False, SubmenuCharacter
= False)
2715 def ReviewServiceArgs(cls
, event
= None, x
= 0, y
= 0, submenuchar
= ''):
2717 Transform positional and keyword arguments into positional only
2719 return event
, x
, y
, submenuchar
2721 def AddCheckBox(self
, menuitem
, name
= '', status
= False, icon
= '', tooltip
= ''):
2722 return self
.ExecMethod(self
.vbMethod
, 'AddCheckBox', menuitem
, name
, status
, icon
, tooltip
)
2724 def AddItem(self
, menuitem
, name
= '', icon
= '', tooltip
= ''):
2725 return self
.ExecMethod(self
.vbMethod
, 'AddItem', menuitem
, name
, icon
, tooltip
)
2727 def AddRadioButton(self
, menuitem
, name
= '', status
= False, icon
= '', tooltip
= ''):
2728 return self
.ExecMethod(self
.vbMethod
, 'AddRadioButton', menuitem
, name
, status
, icon
, tooltip
)
2730 def Execute(self
, returnid
= True):
2731 return self
.ExecMethod(self
.vbMethod
, 'Execute', returnid
)
2733 # #########################################################################
2735 # #########################################################################
2736 class SF_Toolbar(SFServices
):
2738 Each component has its own set of toolbars, depending on the component type
2739 (Calc, Writer, Basic IDE, ...).
2740 In the context of the actual class, a toolbar is presumed defined statically:
2741 - either by the application
2742 - or by a customization done by the user.
2744 # Mandatory class properties for service registration
2745 serviceimplementation
= 'basic'
2746 servicename
= 'SFWidgets.Toolbar'
2747 servicesynonyms
= ('toolbar', 'sfwidgets.toolbar')
2748 serviceproperties
= dict(BuiltIn
= False, Docked
= False, HasGlobalScope
= False, Name
= False,
2749 ResourceURL
= False, Visible
= True, XUIElement
= False)
2751 def ToolbarButtons(self
, buttonname
= ''):
2752 return self
.ExecMethod(self
.vbMethod
+ self
.flgArrayRet
, 'ToolbarButtons', buttonname
)
2754 # #########################################################################
2755 # SF_ToolbarButton CLASS
2756 # #########################################################################
2757 class SF_ToolbarButton(SFServices
):
2759 A toolbar consists in a series of graphical controls to trigger actions.
2760 The "Toolbar" service gives access to the "ToolbarButton" service to manage
2761 the individual buttons belonging to the toolbar.
2763 # Mandatory class properties for service registration
2764 serviceimplementation
= 'basic'
2765 servicename
= 'SFWidgets.ToolbarButton'
2766 servicesynonyms
= ('toolbarbutton', 'sfwidgets.toolbarbutton')
2767 serviceproperties
= dict(Caption
= False, Height
= False, Index
= False, OnClick
= True, Parent
= False,
2768 TipText
= True, Visible
= True, Width
= False, X
= False, Y
= False)
2771 return self
.ExecMethod(self
.vbMethod
, 'Execute')
2774 # ##############################################False##################################################################
2775 # CreateScriptService() ###
2776 # #####################################################################################################################
2777 def CreateScriptService(service
, *args
, **kwargs
):
2779 A service being the name of a collection of properties and methods,
2780 this method returns either
2781 - the Python object mirror of the Basic object implementing the requested service
2782 - the Python object implementing the service itself
2784 A service may be designated by its official name, stored in its class.servicename
2785 or by one of its synonyms stored in its class.servicesynonyms list
2786 If the service is not identified, the service creation is delegated to Basic, that might raise an error
2787 if still not identified there
2789 :param service: the name of the service as a string 'library.service' - cased exactly
2790 or one of its synonyms
2791 :param args: the arguments to pass to the service constructor
2792 :return: the service as a Python object
2794 # Init at each CreateScriptService() invocation
2795 # CreateScriptService is usually the first statement in user scripts requesting ScriptForge services
2796 # ScriptForge() is optional in user scripts when Python process inside LibreOffice process
2797 if ScriptForge
.SCRIPTFORGEINITDONE
is False:
2800 def ResolveSynonyms(servicename
):
2802 Synonyms within service names implemented in Python or predefined are resolved here
2803 :param servicename: The short name of the service
2804 :return: The official service name if found, the argument otherwise
2806 for cls
in SFServices
.__subclasses
__():
2807 if servicename
.lower() in cls
.servicesynonyms
:
2808 return cls
.servicename
2812 # Check the list of available services
2813 scriptservice
= ResolveSynonyms(service
)
2814 if scriptservice
in ScriptForge
.serviceslist
:
2815 serv
= ScriptForge
.serviceslist
[scriptservice
]
2816 # Check if the requested service is within the Python world
2817 if serv
.serviceimplementation
== 'python':
2819 # Check if the service is a predefined standard Basic service
2820 elif scriptservice
in ScriptForge
.servicesmodules
:
2821 return serv(ScriptForge
.servicesmodules
[scriptservice
], classmodule
= SFServices
.moduleStandard
)
2824 # The requested service is to be found in the Basic world
2825 # Check if the service must review the arguments
2826 if serv
is not None:
2827 if hasattr(serv
, 'ReviewServiceArgs'):
2828 # ReviewServiceArgs() must be a class method
2829 args
= serv
.ReviewServiceArgs(*args
, **kwargs
)
2830 # Get the service object back from Basic
2832 serv
= ScriptForge
.InvokeBasicService('SF_Services', SFServices
.vbMethod
, 'CreateScriptService', service
)
2834 serv
= ScriptForge
.InvokeBasicService('SF_Services', SFServices
.vbMethod
, 'CreateScriptService',
2839 createScriptService
, createscriptservice
= CreateScriptService
, CreateScriptService
2841 # ######################################################################
2842 # Lists the scripts, that shall be visible inside the Basic/Python IDE
2843 # ######################################################################
2845 g_exportedScripts
= ()