calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / wizards / source / scriptforge / python / scriptforge.py
blobb3b79132d4b21d4548885bace1547f56b91e9d0a
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/ .
24 """
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
39 Usage:
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
55 """
57 import uno
59 import datetime
60 import time
61 import os
64 class _Singleton(type):
65 """
66 A Singleton metaclass design pattern
67 Credits: « Python in a Nutshell » by Alex Martelli, O'Reilly
68 """
69 instances = {}
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):
82 """
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
91 """
93 # #########################################################################
94 # Class attributes
95 # #########################################################################
96 hostname = ''
97 port = 0
98 componentcontext = None
99 scriptprovider = None
100 SCRIPTFORGEINITDONE = False
102 # #########################################################################
103 # Class constants
104 # #########################################################################
105 library = 'ScriptForge'
106 Version = '7.4' # 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
117 # Object types
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
155 @classmethod
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
170 try:
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
175 raise SystemExit(
176 'Connection to LibreOffice failed (host = ' + hostname + ', port = ' + str(port) + ')')
177 return ctx
178 elif len(hostname) == 0 and port == 0: # Usual interactive mode
179 return uno.getComponentContext()
180 else:
181 raise SystemExit('The creation of the ScriptForge() instance got invalid arguments: '
182 + '(host = ' + hostname + ', port = ' + str(port) + ')')
184 @classmethod
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("")
194 @classmethod
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
212 fullscript = script
213 paramarray = True
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
218 paramarray = False
219 if script[0] == '@':
220 script = script[1:]
221 paramarray = True
222 scope = ''
223 if '#' in script:
224 scope, script = script.split('#')
225 if '.py$' in script.lower(): # Python
226 if len(scope) == 0:
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):]
231 if '#' in script:
232 scope, script = script.split('#')
233 uri = 'vnd.sun.star.script:{0}?language=Python&location={1}'.format(script, scope)
234 else: # Basic
235 if len(scope) == 0:
236 scope = 'application' # Default for Basic
237 lib = ''
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
243 try:
244 xscript = cls.scriptprovider.getScript(uri)
245 except Exception:
246 raise RuntimeError(
247 'The script \'{0}\' could not be located in your LibreOffice installation'.format(script))
248 else: # Should not happen
249 return None
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
257 if paramarray:
258 scriptreturn = xscript.invoke(args[0], (), ())
259 else:
260 scriptreturn = xscript.invoke(args, (), ())
263 return scriptreturn[0] # Updatable arguments passed by reference are ignored
265 @classmethod
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
290 # Constants
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 !
298 if len(args) == 0:
299 args = (basicobject,) + (flags,) + (method,) + (cstNoArgs,)
300 else:
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:
312 pass
313 else:
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):
326 return ()
327 elif returntuple[cstVarType] == ScriptForge.V_DATE:
328 dat = SFScriptForge.SF_Basic.CDateFromUnoDateTime(returntuple[cstValue])
329 return dat
330 else: # All other scalar values
331 pass
332 return returntuple[cstValue]
334 @staticmethod
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
340 Example:
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
345 Example:
346 def CopyFile(...):
347 # etc ...
348 copyFile, copyfile = CopyFile, CopyFile
351 def camelCase(key):
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
360 dicosyn.update(cc)
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)
366 if callable(func):
367 # Assign to each synonym a reference to the original method
368 lc = method.lower()
369 setattr(cls, lc, func)
370 cc = camelCase(method)
371 if cc != lc:
372 setattr(cls, cc, func)
373 return
375 @staticmethod
376 def unpack_args(kwargs):
378 Convert a dictionary passed as argument to a list alternating keys and values
379 Example:
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:
427 1. The properties
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
434 When
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:
439 @property
440 def myProperty(self):
441 return self.GetProperty('myProperty')
442 2 The methods
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()
460 # Basic class type
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',
499 'forceGetProperty'):
500 pass
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]
505 else:
506 # Get Property from Basic and store it
507 prop = self.GetProperty(name)
508 self.__dict__[name] = prop
509 return 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',
523 'forceGetProperty'):
524 pass
525 elif name[0:2] == '__' or name in self.internal_attributes or name in self.localProperties:
526 pass
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
531 pass
532 elif self.serviceproperties[name] is True: # True == Editable
533 self.SetProperty(name, value)
534 return
535 else:
536 raise AttributeError(
537 "type object '" + self.objecttype + "' has no editable property '" + name + "'")
538 else:
539 raise AttributeError("type object '" + self.objecttype + "' has no property '" + name + "'")
540 object.__setattr__(self, name, value)
541 return
543 def __repr__(self):
544 return self.serviceimplementation + '/' + self.servicename + '/' + str(self.objectreference) + '/' + \
545 super(SFServices, self).__repr__()
547 def Dispose(self):
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):
554 if flags == 0:
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)
566 if arg is None:
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)
570 return None
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')
578 else:
579 return []
581 def basicproperties(self):
582 if self.serviceimplementation == 'basic':
583 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Properties')
584 else:
585 return []
587 def SetProperty(self, propertyname, value):
589 Set the given property to a new value in the Basic world
591 if self.serviceimplementation == 'basic':
592 flag = self.vbLet
593 if isinstance(value, datetime.datetime):
594 value = SFScriptForge.SF_Basic.CDateToUnoDateTime(value)
595 flag += self.flgDateArg
596 if repr(type(value)) == "<class 'pyuno'>":
597 flag += self.flgUno
598 return self.EXEC(self.objectreference, flag, propertyname, value)
601 # #####################################################################################################################
602 # SFScriptForge CLASS (alias of ScriptForge Basic library) ###
603 # #####################################################################################################################
604 class SFScriptForge:
605 pass
607 # #########################################################################
608 # SF_Array CLASS
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 # #########################################################################
632 # SF_Basic CLASS
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.
638 Typical example:
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
659 @classmethod
660 def CDate(cls, datevalue):
661 cdate = cls.SIMPLEEXEC(cls.module + '.PyCDate', datevalue)
662 return cls.CDateFromUnoDateTime(cdate)
664 @staticmethod
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 TimeSeria() 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))
683 else:
684 return unodate # Not recognized as a UNO date structure
685 return date
687 @staticmethod
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 = \
705 date[0:6]
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
715 else:
716 return date # Not recognized as a date
717 return unodate
719 @classmethod
720 def ConvertFromUrl(cls, url):
721 return cls.SIMPLEEXEC(cls.module + '.PyConvertFromUrl', url)
723 @classmethod
724 def ConvertToUrl(cls, systempath):
725 return cls.SIMPLEEXEC(cls.module + '.PyConvertToUrl', systempath)
727 @classmethod
728 def CreateUnoService(cls, servicename):
729 return cls.SIMPLEEXEC(cls.module + '.PyCreateUnoService', servicename)
731 @classmethod
732 def CreateUnoStruct(cls, unostructure):
733 return uno.createUnoStruct(unostructure)
735 @classmethod
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)
742 @classmethod
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)
750 @classmethod
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)
756 @classmethod
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)
763 @classmethod
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)
769 @classmethod
770 def GetDefaultContext(cls):
771 return ScriptForge.componentcontext
773 @classmethod
774 def GetGuiType(cls):
775 return cls.SIMPLEEXEC(cls.module + '.PyGetGuiType')
777 @classmethod
778 def GetPathSeparator(cls):
779 return os.sep
781 @classmethod
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')
790 @classmethod
791 def DialogLibraries(cls):
792 return ScriptForge.InvokeSimpleScript(SFScriptForge.SF_Basic.module + '.PyGlobalScope', 'Dialog')
794 @classmethod
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)
800 @classmethod
801 def MsgBox(cls, prompt, buttons = 0, title = ''):
802 return cls.SIMPLEEXEC(cls.module + '.PyMsgBox', prompt, buttons, title)
804 @classmethod
805 def Now(cls):
806 return datetime.datetime.now()
808 @classmethod
809 def RGB(cls, red, green, blue):
810 return int('%02x%02x%02x' % (red, green, blue), 16)
812 @property
813 def StarDesktop(self):
814 ctx = ScriptForge.componentcontext
815 if ctx is None:
816 return None
817 smgr = ctx.getServiceManager() # com.sun.star.lang.XMultiComponentFactory
818 DESK = 'com.sun.star.frame.Desktop'
819 desktop = smgr.createInstanceWithContext(DESK, ctx)
820 return desktop
822 starDesktop, stardesktop = StarDesktop, StarDesktop
824 @property
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()
833 if comp is None:
834 return None
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
838 return comp
840 thisComponent, thiscomponent = ThisComponent, ThisComponent
842 @property
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
851 if comp is None:
852 return None
854 sess = CreateScriptService('Session')
855 impl, ident = '', ''
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
863 return comp
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:
873 return db
874 return None
876 thisDatabaseDocument, thisdatabasedocument = ThisDatabaseDocument, ThisDatabaseDocument
878 @classmethod
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
890 Usage:
891 dico = dict(A = 1, B = 2, C = 3)
892 myDict = CreateScriptService('Dictionary', dico) # Initialize myDict with the content of dico
893 myDict['D'] = 4
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
900 myDict['D'] = 4
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)
911 dict.__init__(self)
912 if dic is not None:
913 self.update(dic)
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.
926 result = []
927 for key in iter(self):
928 value = self[key]
929 item = value
930 if isinstance(value, dict): # check that first level is not itself a (sub)dict
931 item = None
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
934 value = None
935 else:
936 for i in range(len(value)):
937 if isinstance(value[i], dict):
938 value[i] = None
939 item = value
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')
943 pv.Name = key
944 pv.Value = item
945 result.append(pv)
946 return result
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
958 result = []
959 for pv in iter(propertyvalues):
960 key = pv.Name
961 if overwrite is True or key not in self:
962 item = pv.Value
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))
971 self.update(result)
972 return True
974 # #########################################################################
975 # SF_Exception CLASS
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)
1018 @classmethod
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:
1036 return None
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)
1044 console(**kwargs)
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()
1048 else:
1049 # The APSO extension could not be located in your LibreOffice installation
1050 cls._RaiseFatal('SF_Exception.PythonShell', 'variables=None', 'PYTHONSHELLERROR')
1052 @classmethod
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
1060 if len(args) == 0:
1061 args = (None,)
1062 return cls.SIMPLEEXEC('@SF_Exception.RaiseFatal', (errorcode, *args)) # With ParamArray
1064 @classmethod
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)
1103 else:
1104 return False
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))
1147 else:
1148 return 0
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())
1167 else:
1168 return ''
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)
1191 @classmethod
1192 def _ConvertFromUrl(cls, filename):
1193 # Alias for same function in FileSystem Basic module
1194 return cls.SIMPLEEXEC('ScriptForge.SF_FileSystem._ConvertFromUrl', filename)
1196 # #########################################################################
1197 # SF_L10N CLASS
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)
1213 @classmethod
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)
1234 _ = GetText
1236 # #########################################################################
1237 # SF_Platform CLASS
1238 # #########################################################################
1239 class SF_Platform(SFServices, metaclass = _Singleton):
1241 The 'Platform' service implements a collection of properties about the actual execution environment
1242 and context :
1243 the hardware platform
1244 the operating system
1245 the LibreOffice version
1246 the current user
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'
1262 @property
1263 def Architecture(self):
1264 return self.SIMPLEEXEC(self.py, 'Architecture')
1266 @property
1267 def ComputerName(self):
1268 return self.SIMPLEEXEC(self.py, 'ComputerName')
1270 @property
1271 def CPUCount(self):
1272 return self.SIMPLEEXEC(self.py, 'CPUCount')
1274 @property
1275 def CurrentUser(self):
1276 return self.SIMPLEEXEC(self.py, 'CurrentUser')
1278 @property
1279 def Machine(self):
1280 return self.SIMPLEEXEC(self.py, 'Machine')
1282 @property
1283 def OSName(self):
1284 return self.SIMPLEEXEC(self.py, 'OSName')
1286 @property
1287 def OSPlatform(self):
1288 return self.SIMPLEEXEC(self.py, 'OSPlatform')
1290 @property
1291 def OSRelease(self):
1292 return self.SIMPLEEXEC(self.py, 'OSRelease')
1294 @property
1295 def OSVersion(self):
1296 return self.SIMPLEEXEC(self.py, 'OSVersion')
1298 @property
1299 def Processor(self):
1300 return self.SIMPLEEXEC(self.py, 'Processor')
1302 @property
1303 def PythonVersion(self):
1304 return self.SIMPLEEXEC(self.py, 'PythonVersion')
1306 # #########################################################################
1307 # SF_Region CLASS
1308 # #########################################################################
1309 class SF_Region(SFServices, metaclass = _Singleton):
1311 The "Region" service gathers a collection of functions about languages, countries and timezones
1312 - Locales
1313 - Currencies
1314 - Numbers and dates formatting
1315 - Calendars
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)
1371 # Usual methods
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,
1394 timezone, locale)
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 # #########################################################################
1402 # SF_Session CLASS
1403 # #########################################################################
1404 class SF_Session(SFServices, metaclass = _Singleton):
1406 The Session service gathers various general-purpose methods about:
1407 - UNO introspection
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)
1425 @classmethod
1426 def ExecuteBasicScript(cls, scope = '', script = '', *args):
1427 if scope is None or scope == '':
1428 scope = cls.SCRIPTISAPPLICATION
1429 if len(args) == 0:
1430 args = (scope,) + (script,) + (None,)
1431 else:
1432 args = (scope,) + (script,) + args
1433 # ExecuteBasicScript method has a ParamArray parameter in Basic
1434 return cls.SIMPLEEXEC('@SF_Session.ExecuteBasicScript', args)
1436 @classmethod
1437 def ExecuteCalcFunction(cls, calcfunction, *args):
1438 if len(args) == 0:
1439 # Arguments of Calc functions are strings or numbers. None == Empty is a good alias for no argument
1440 args = (calcfunction,) + (None,)
1441 else:
1442 args = (calcfunction,) + args
1443 # ExecuteCalcFunction method has a ParamArray parameter in Basic
1444 return cls.SIMPLEEXEC('@SF_Session.ExecuteCalcFunction', args)
1446 @classmethod
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)
1456 @classmethod
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 # #########################################################################
1480 # SF_String CLASS
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
1486 are not duplicated
1488 # Mandatory class properties for service registration
1489 serviceimplementation = 'basic'
1490 servicename = 'ScriptForge.String'
1491 servicesynonyms = ('string', 'scriptforge.string')
1492 serviceproperties = dict()
1494 @classmethod
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)
1544 @property
1545 def AtEndOfStream(self):
1546 return self.GetProperty('AtEndOfStream')
1548 atEndOfStream, atendofstream = AtEndOfStream, AtEndOfStream
1550 @property
1551 def Line(self):
1552 return self.GetProperty('Line')
1554 line = Line
1556 def CloseFile(self):
1557 return self.ExecMethod(self.vbMethod, 'CloseFile')
1559 def ReadAll(self):
1560 return self.ExecMethod(self.vbMethod, 'ReadAll')
1562 def ReadLine(self):
1563 return self.ExecMethod(self.vbMethod, 'ReadLine')
1565 def SkipLine(self):
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 # #########################################################################
1575 # SF_Timer CLASS
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
1590 @classmethod
1591 def ReviewServiceArgs(cls, start = False):
1593 Transform positional and keyword arguments into positional only
1595 return (start,)
1597 def Continue(self):
1598 return self.ExecMethod(self.vbMethod, 'Continue')
1600 def Restart(self):
1601 return self.ExecMethod(self.vbMethod, 'Restart')
1603 def Start(self):
1604 return self.ExecMethod(self.vbMethod, 'Start')
1606 def Suspend(self):
1607 return self.ExecMethod(self.vbMethod, 'Suspend')
1609 def Terminate(self):
1610 return self.ExecMethod(self.vbMethod, 'Terminate')
1612 # #########################################################################
1613 # SF_UI CLASS
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:
1619 - Windows selection
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)
1631 # Class constants
1632 MACROEXECALWAYS, MACROEXECNEVER, MACROEXECNORMAL = 2, 1, 0
1633 BASEDOCUMENT, CALCDOCUMENT, DRAWDOCUMENT, IMPRESSDOCUMENT, MATHDOCUMENT, WRITERDOCUMENT = \
1634 'Base', 'Calc', 'Draw', 'Impress', 'Math', 'Writer'
1636 @property
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,
1647 calcfilename)
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,)
1679 else:
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 # #####################################################################################################################
1698 class SFDatabases:
1700 The SFDatabases class manages databases embedded in or connected to Base documents
1702 pass
1704 # #########################################################################
1705 # SF_Database CLASS
1706 # #########################################################################
1707 class SF_Database(SFServices):
1709 Each instance of the current class represents a single database, with essentially its tables, queries
1710 and data
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)
1723 @classmethod
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 OpenQuery(self, queryname):
1755 return self.ExecMethod(self.vbMethod, 'OpenQuery', queryname)
1757 def OpenSql(self, sql, directsql = False):
1758 return self.ExecMethod(self.vbMethod, 'OpenSql', sql, directsql)
1760 def OpenTable(self, tablename):
1761 return self.ExecMethod(self.vbMethod, 'OpenTable', tablename)
1763 def RunSql(self, sqlcommand, directsql = False):
1764 return self.ExecMethod(self.vbMethod, 'RunSql', sqlcommand, directsql)
1766 # #########################################################################
1767 # SF_Datasheet CLASS
1768 # #########################################################################
1769 class SF_Datasheet(SFServices):
1771 A datasheet is the visual representation of tabular data produced by a database.
1772 A datasheet may be opened automatically by script code at any moment.
1773 The Base document owning the data may or may not be opened.
1774 Any SELECT SQL statement may trigger the datasheet display.
1776 # Mandatory class properties for service registration
1777 serviceimplementation = 'basic'
1778 servicename = 'SFDatabases.Datasheet'
1779 servicesynonyms = ('datasheet', 'sfdatabases.datasheet')
1780 serviceproperties = dict(ColumnHeaders = False, CurrentColumn = False, CurrentRow = False,
1781 DatabaseFileName = False, Filter = True, LastRow = False, OrderBy = True,
1782 ParentDatabase = False, Source = False, SourceType = False, XComponent = False,
1783 XControlModel = False, XTabControllerModel = False)
1785 def Activate(self):
1786 return self.ExecMethod(self.vbMethod, 'Activate')
1788 def CloseDatasheet(self):
1789 return self.ExecMethod(self.vbMethod, 'CloseDatasheet')
1791 def CreateMenu(self, menuheader, before = '', submenuchar = '>'):
1792 return self.ExecMethod(self.vbMethod, 'CreateMenu', menuheader, before, submenuchar)
1794 def GetText(self, column = 0):
1795 return self.ExecMethod(self.vbMethod, 'GetText', column)
1797 def GetValue(self, column = 0):
1798 return self.ExecMethod(self.vbMethod, 'GetValue', column)
1800 def GoToCell(self, row = 0, column = 0):
1801 return self.ExecMethod(self.vbMethod, 'GoToCell', row, column)
1803 def RemoveMenu(self, menuheader):
1804 return self.ExecMethod(self.vbMethod, 'RemoveMenu', menuheader)
1807 # #####################################################################################################################
1808 # SFDialogs CLASS (alias of SFDialogs Basic library) ###
1809 # #####################################################################################################################
1810 class SFDialogs:
1812 The SFDialogs class manages dialogs defined with the Basic IDE
1814 pass
1816 # #########################################################################
1817 # SF_Dialog CLASS
1818 # #########################################################################
1819 class SF_Dialog(SFServices):
1821 Each instance of the current class represents a single dialog box displayed to the user.
1822 The dialog box must have been designed and defined with the Basic IDE previously.
1823 From a Python script, a dialog box can be displayed in modal or in non-modal modes.
1825 In modal mode, the box is displayed and the execution of the macro process is suspended
1826 until one of the OK or Cancel buttons is pressed. In the meantime, other user actions
1827 executed on the box can trigger specific actions.
1829 In non-modal mode, the floating dialog remains displayed until the dialog is terminated
1830 by code (Terminate()) or until the LibreOffice application stops.
1832 # Mandatory class properties for service registration
1833 serviceimplementation = 'basic'
1834 servicename = 'SFDialogs.Dialog'
1835 servicesynonyms = ('dialog', 'sfdialogs.dialog')
1836 serviceproperties = dict(Caption = True, Height = True, Modal = False, Name = False,
1837 OnFocusGained = False, OnFocusLost = False, OnKeyPressed = False,
1838 OnKeyReleased = False, OnMouseDragged = False, OnMouseEntered = False,
1839 OnMouseExited = False, OnMouseMoved = False, OnMousePressed = False,
1840 OnMouseReleased = False,
1841 Page = True, Visible = True, Width = True, XDialogModel = False, XDialogView = False)
1842 # Class constants used together with the Execute() method
1843 OKBUTTON, CANCELBUTTON = 1, 0
1845 @classmethod
1846 def ReviewServiceArgs(cls, container = '', library = 'Standard', dialogname = ''):
1848 Transform positional and keyword arguments into positional only
1849 Add the XComponentContext as last argument
1851 return container, library, dialogname, ScriptForge.componentcontext
1853 # Methods potentially executed while the dialog is in execution require the flgHardCode flag
1854 def Activate(self):
1855 return self.ExecMethod(self.vbMethod + self.flgHardCode, 'Activate')
1857 def Center(self, parent = ScriptForge.cstSymMissing):
1858 parentclasses = (SFDocuments.SF_Document, SFDocuments.SF_Base, SFDocuments.SF_Calc, SFDocuments.SF_Writer,
1859 SFDialogs.SF_Dialog)
1860 parentobj = parent.objectreference if isinstance(parent, parentclasses) else parent
1861 return self.ExecMethod(self.vbMethod + self.flgObject + self.flgHardCode, 'Center', parentobj)
1863 def Controls(self, controlname = ''):
1864 return self.ExecMethod(self.vbMethod + self.flgArrayRet + self.flgHardCode, 'Controls', controlname)
1866 def EndExecute(self, returnvalue):
1867 return self.ExecMethod(self.vbMethod + self.flgHardCode, 'EndExecute', returnvalue)
1869 def Execute(self, modal = True):
1870 return self.ExecMethod(self.vbMethod + self.flgHardCode, 'Execute', modal)
1872 def GetTextsFromL10N(self, l10n):
1873 l10nobj = l10n.objectreference if isinstance(l10n, SFScriptForge.SF_L10N) else l10n
1874 return self.ExecMethod(self.vbMethod + self.flgObject, 'GetTextsFromL10N', l10nobj)
1876 def Resize(self, left = -1, top = -1, width = -1, height = -1):
1877 return self.ExecMethod(self.vbMethod + self.flgHardCode, 'Resize', left, top, width, height)
1879 def SetPageManager(self, pilotcontrols = '', tabcontrols = '', wizardcontrols = '', lastpage = 0):
1880 return self.ExecMethod(self.vbMethod, 'SetPageManager', pilotcontrols, tabcontrols, wizardcontrols,
1881 lastpage)
1883 def Terminate(self):
1884 return self.ExecMethod(self.vbMethod, 'Terminate')
1886 # #########################################################################
1887 # SF_DialogControl CLASS
1888 # #########################################################################
1889 class SF_DialogControl(SFServices):
1891 Each instance of the current class represents a single control within a dialog box.
1892 The focus is clearly set on getting and setting the values displayed by the controls of the dialog box,
1893 not on their formatting.
1894 A special attention is given to controls with type TreeControl.
1896 # Mandatory class properties for service registration
1897 serviceimplementation = 'basic'
1898 servicename = 'SFDialogs.DialogControl'
1899 servicesynonyms = ()
1900 serviceproperties = dict(Cancel = True, Caption = True, ControlType = False, CurrentNode = True,
1901 Default = True, Enabled = True, Format = True, ListCount = False,
1902 ListIndex = True, Locked = True, MultiSelect = True, Name = False,
1903 OnActionPerformed = False, OnAdjustmentValueChanged = False, OnFocusGained = False,
1904 OnFocusLost = False, OnItemStateChanged = False, OnKeyPressed = False,
1905 OnKeyReleased = False, OnMouseDragged = False, OnMouseEntered = False,
1906 OnMouseExited = False, OnMouseMoved = False, OnMousePressed = False,
1907 OnMouseReleased = False, OnNodeExpanded = True, OnNodeSelected = True,
1908 OnTextChanged = False, Page = True, Parent = False, Picture = True,
1909 RootNode = False, RowSource = True, Text = False, TipText = True,
1910 TripleState = True, Value = True, Visible = True,
1911 XControlModel = False, XControlView = False, XGridColumnModel = False,
1912 XGridDataModel = False, XTreeDataModel = False)
1914 # Root related properties do not start with X and, nevertheless, return a UNO object
1915 @property
1916 def CurrentNode(self):
1917 return self.EXEC(self.objectreference, self.vbGet + self.flgUno, 'CurrentNode')
1919 @property
1920 def RootNode(self):
1921 return self.EXEC(self.objectreference, self.vbGet + self.flgUno, 'RootNode')
1923 def AddSubNode(self, parentnode, displayvalue, datavalue = ScriptForge.cstSymEmpty):
1924 return self.ExecMethod(self.vbMethod + self.flgUno, 'AddSubNode', parentnode, displayvalue, datavalue)
1926 def AddSubTree(self, parentnode, flattree, withdatavalue = False):
1927 return self.ExecMethod(self.vbMethod, 'AddSubTree', parentnode, flattree, withdatavalue)
1929 def CreateRoot(self, displayvalue, datavalue = ScriptForge.cstSymEmpty):
1930 return self.ExecMethod(self.vbMethod + self.flgUno, 'CreateRoot', displayvalue, datavalue)
1932 def FindNode(self, displayvalue, datavalue = ScriptForge.cstSymEmpty, casesensitive = False):
1933 return self.ExecMethod(self.vbMethod + self.flgUno, 'FindNode', displayvalue, datavalue, casesensitive)
1935 def SetFocus(self):
1936 return self.ExecMethod(self.vbMethod, 'SetFocus')
1938 def SetTableData(self, dataarray, widths = (1,), alignments = ''):
1939 return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetTableData', dataarray, widths, alignments)
1941 def WriteLine(self, line = ''):
1942 return self.ExecMethod(self.vbMethod, 'WriteLine', line)
1945 # #####################################################################################################################
1946 # SFDocuments CLASS (alias of SFDocuments Basic library) ###
1947 # #####################################################################################################################
1948 class SFDocuments:
1950 The SFDocuments class gathers a number of classes, methods and properties making easy
1951 managing and manipulating LibreOffice documents
1953 pass
1955 # #########################################################################
1956 # SF_Document CLASS
1957 # #########################################################################
1958 class SF_Document(SFServices):
1960 The methods and properties are generic for all types of documents: they are combined in the
1961 current SF_Document class
1962 - saving, closing documents
1963 - accessing their standard or custom properties
1964 Specific properties and methods are implemented in the concerned subclass(es) SF_Calc, SF_Base, ...
1966 # Mandatory class properties for service registration
1967 serviceimplementation = 'basic'
1968 servicename = 'SFDocuments.Document'
1969 servicesynonyms = ('document', 'sfdocuments.document')
1970 serviceproperties = dict(Description = True, DocumentType = False, ExportFilters = False, ImportFilters = False,
1971 IsBase = False, IsCalc = False, IsDraw = False, IsImpress = False, IsMath = False,
1972 IsWriter = False, Keywords = True, Readonly = False, Subject = True, Title = True,
1973 XComponent = False)
1974 # Force for each property to get its value from Basic - due to intense interactivity with user
1975 forceGetProperty = True
1977 @classmethod
1978 def ReviewServiceArgs(cls, windowname = ''):
1980 Transform positional and keyword arguments into positional only
1982 return windowname,
1984 def Activate(self):
1985 return self.ExecMethod(self.vbMethod, 'Activate')
1987 def CloseDocument(self, saveask = True):
1988 return self.ExecMethod(self.vbMethod, 'CloseDocument', saveask)
1990 def CreateMenu(self, menuheader, before = '', submenuchar = '>'):
1991 return self.ExecMethod(self.vbMethod, 'CreateMenu', menuheader, before, submenuchar)
1993 def ExportAsPDF(self, filename, overwrite = False, pages = '', password = '', watermark = ''):
1994 return self.ExecMethod(self.vbMethod, 'ExportAsPDF', filename, overwrite, pages, password, watermark)
1996 def PrintOut(self, pages = '', copies = 1):
1997 return self.ExecMethod(self.vbMethod, 'PrintOut', pages, copies)
1999 def RemoveMenu(self, menuheader):
2000 return self.ExecMethod(self.vbMethod, 'RemoveMenu', menuheader)
2002 def RunCommand(self, command, *args, **kwargs):
2003 params = tuple([command] + list(args) + ScriptForge.unpack_args(kwargs))
2004 return self.ExecMethod(self.vbMethod, 'RunCommand', *params)
2006 def Save(self):
2007 return self.ExecMethod(self.vbMethod, 'Save')
2009 def SaveAs(self, filename, overwrite = False, password = '', filtername = '', filteroptions = ''):
2010 return self.ExecMethod(self.vbMethod, 'SaveAs', filename, overwrite, password, filtername, filteroptions)
2012 def SaveCopyAs(self, filename, overwrite = False, password = '', filtername = '', filteroptions = ''):
2013 return self.ExecMethod(self.vbMethod, 'SaveCopyAs', filename, overwrite,
2014 password, filtername, filteroptions)
2016 def SetPrinter(self, printer = '', orientation = '', paperformat = ''):
2017 return self.ExecMethod(self.vbMethod, 'SetPrinter', printer, orientation, paperformat)
2019 # #########################################################################
2020 # SF_Base CLASS
2021 # #########################################################################
2022 class SF_Base(SF_Document, SFServices):
2024 The SF_Base module is provided mainly to block parent properties that are NOT applicable to Base documents
2025 In addition, it provides methods to identify form documents and access their internal forms
2026 (read more elsewhere (the "SFDocuments.Form" service) about this subject)
2028 # Mandatory class properties for service registration
2029 serviceimplementation = 'basic'
2030 servicename = 'SFDocuments.Base'
2031 servicesynonyms = ('base', 'scriptforge.base')
2032 serviceproperties = dict(DocumentType = False, IsBase = False, IsCalc = False,
2033 IsDraw = False, IsImpress = False, IsMath = False, IsWriter = False,
2034 XComponent = False)
2036 @classmethod
2037 def ReviewServiceArgs(cls, windowname = ''):
2039 Transform positional and keyword arguments into positional only
2041 return windowname,
2043 def CloseDocument(self, saveask = True):
2044 return self.ExecMethod(self.vbMethod, 'CloseDocument', saveask)
2046 def CloseFormDocument(self, formdocument):
2047 return self.ExecMethod(self.vbMethod, 'CloseFormDocument', formdocument)
2049 def FormDocuments(self):
2050 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'FormDocuments')
2052 def Forms(self, formdocument, form = ''):
2053 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', formdocument, form)
2055 def GetDatabase(self, user = '', password = ''):
2056 return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password)
2058 def IsLoaded(self, formdocument):
2059 return self.ExecMethod(self.vbMethod, 'IsLoaded', formdocument)
2061 def OpenFormDocument(self, formdocument, designmode = False):
2062 return self.ExecMethod(self.vbMethod, 'OpenFormDocument', formdocument, designmode)
2064 def OpenQuery(self, queryname):
2065 return self.ExecMethod(self.vbMethod, 'OpenQuery', queryname)
2067 def OpenTable(self, tablename):
2068 return self.ExecMethod(self.vbMethod, 'OpenTable', tablename)
2070 def PrintOut(self, formdocument, pages = '', copies = 1):
2071 return self.ExecMethod(self.vbMethod, 'PrintOut', formdocument, pages, copies)
2073 def SetPrinter(self, formdocument = '', printer = '', orientation = '', paperformat = ''):
2074 return self.ExecMethod(self.vbMethod, 'SetPrinter', formdocument, printer, orientation, paperformat)
2076 # #########################################################################
2077 # SF_Calc CLASS
2078 # #########################################################################
2079 class SF_Calc(SF_Document, SFServices):
2081 The SF_Calc module is focused on :
2082 - management (copy, insert, move, ...) of sheets within a Calc document
2083 - exchange of data between Basic data structures and Calc ranges of values
2085 # Mandatory class properties for service registration
2086 serviceimplementation = 'basic'
2087 servicename = 'SFDocuments.Calc'
2088 servicesynonyms = ('calc', 'sfdocuments.calc')
2089 serviceproperties = dict(CurrentSelection = True, Sheets = False,
2090 Description = True, DocumentType = False, ExportFilters = False, ImportFilters = False,
2091 IsBase = False, IsCalc = False, IsDraw = False, IsImpress = False, IsMath = False,
2092 IsWriter = False, Keywords = True, Readonly = False, Subject = True, Title = True,
2093 XComponent = False)
2094 # Force for each property to get its value from Basic - due to intense interactivity with user
2095 forceGetProperty = True
2097 @classmethod
2098 def ReviewServiceArgs(cls, windowname = ''):
2100 Transform positional and keyword arguments into positional only
2102 return windowname,
2104 # Next functions are implemented in Basic as read-only properties with 1 argument
2105 def FirstCell(self, rangename):
2106 return self.GetProperty('FirstCell', rangename)
2108 def FirstColumn(self, rangename):
2109 return self.GetProperty('FirstColumn', rangename)
2111 def FirstRow(self, rangename):
2112 return self.GetProperty('FirstRow', rangename)
2114 def Height(self, rangename):
2115 return self.GetProperty('Height', rangename)
2117 def LastCell(self, rangename):
2118 return self.GetProperty('LastCell', rangename)
2120 def LastColumn(self, rangename):
2121 return self.GetProperty('LastColumn', rangename)
2123 def LastRow(self, rangename):
2124 return self.GetProperty('LastRow', rangename)
2126 def Range(self, rangename):
2127 return self.GetProperty('Range', rangename)
2129 def Region(self, rangename):
2130 return self.GetProperty('Region', rangename)
2132 def Sheet(self, sheetname):
2133 return self.GetProperty('Sheet', sheetname)
2135 def SheetName(self, rangename):
2136 return self.GetProperty('SheetName', rangename)
2138 def Width(self, rangename):
2139 return self.GetProperty('Width', rangename)
2141 def XCellRange(self, rangename):
2142 return self.ExecMethod(self.vbGet + self.flgUno, 'XCellRange', rangename)
2144 def XSheetCellCursor(self, rangename):
2145 return self.ExecMethod(self.vbGet + self.flgUno, 'XSheetCellCursor', rangename)
2147 def XSpreadsheet(self, sheetname):
2148 return self.ExecMethod(self.vbGet + self.flgUno, 'XSpreadsheet', sheetname)
2150 # Usual methods
2151 def A1Style(self, row1, column1, row2 = 0, column2 = 0, sheetname = '~'):
2152 return self.ExecMethod(self.vbMethod, 'A1Style', row1, column1, row2, column2, sheetname)
2154 def Activate(self, sheetname = ''):
2155 return self.ExecMethod(self.vbMethod, 'Activate', sheetname)
2157 def Charts(self, sheetname, chartname = ''):
2158 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Charts', sheetname, chartname)
2160 def ClearAll(self, range, filterformula = '', filterscope = ''):
2161 return self.ExecMethod(self.vbMethod, 'ClearAll', range, filterformula, filterscope)
2163 def ClearFormats(self, range, filterformula = '', filterscope = ''):
2164 return self.ExecMethod(self.vbMethod, 'ClearFormats', range, filterformula, filterscope)
2166 def ClearValues(self, range, filterformula = '', filterscope = ''):
2167 return self.ExecMethod(self.vbMethod, 'ClearValues', range, filterformula, filterscope)
2169 def CompactLeft(self, range, wholecolumn = False, filterformula = ''):
2170 return self.ExecMethod(self.vbMethod, 'CompactLeft', range, wholecolumn, filterformula)
2172 def CompactUp(self, range, wholerow = False, filterformula = ''):
2173 return self.ExecMethod(self.vbMethod, 'CompactUp', range, wholerow, filterformula)
2175 def CopySheet(self, sheetname, newname, beforesheet = 32768):
2176 sheet = (sheetname.objectreference if isinstance(sheetname, SFDocuments.SF_CalcReference) else sheetname)
2177 return self.ExecMethod(self.vbMethod + self.flgObject, 'CopySheet', sheet, newname, beforesheet)
2179 def CopySheetFromFile(self, filename, sheetname, newname, beforesheet = 32768):
2180 sheet = (sheetname.objectreference if isinstance(sheetname, SFDocuments.SF_CalcReference) else sheetname)
2181 return self.ExecMethod(self.vbMethod + self.flgObject, 'CopySheetFromFile',
2182 filename, sheet, newname, beforesheet)
2184 def CopyToCell(self, sourcerange, destinationcell):
2185 range = (sourcerange.objectreference if isinstance(sourcerange, SFDocuments.SF_CalcReference)
2186 else sourcerange)
2187 return self.ExecMethod(self.vbMethod + self.flgObject, 'CopyToCell', range, destinationcell)
2189 def CopyToRange(self, sourcerange, destinationrange):
2190 range = (sourcerange.objectreference if isinstance(sourcerange, SFDocuments.SF_CalcReference)
2191 else sourcerange)
2192 return self.ExecMethod(self.vbMethod + self.flgObject, 'CopyToRange', range, destinationrange)
2194 def CreateChart(self, chartname, sheetname, range, columnheader = False, rowheader = False):
2195 return self.ExecMethod(self.vbMethod, 'CreateChart', chartname, sheetname, range, columnheader, rowheader)
2197 def CreatePivotTable(self, pivottablename, sourcerange, targetcell, datafields = ScriptForge.cstSymEmpty,
2198 rowfields = ScriptForge.cstSymEmpty, columnfields = ScriptForge.cstSymEmpty,
2199 filterbutton = True, rowtotals = True, columntotals = True):
2200 return self.ExecMethod(self.vbMethod, 'CreatePivotTable', pivottablename, sourcerange, targetcell,
2201 datafields, rowfields, columnfields, filterbutton, rowtotals, columntotals)
2203 def DAvg(self, range):
2204 return self.ExecMethod(self.vbMethod, 'DAvg', range)
2206 def DCount(self, range):
2207 return self.ExecMethod(self.vbMethod, 'DCount', range)
2209 def DMax(self, range):
2210 return self.ExecMethod(self.vbMethod, 'DMax', range)
2212 def DMin(self, range):
2213 return self.ExecMethod(self.vbMethod, 'DMin', range)
2215 def DSum(self, range):
2216 return self.ExecMethod(self.vbMethod, 'DSum', range)
2218 def ExportRangeToFile(self, range, filename, imagetype = 'pdf', overwrite = False):
2219 return self.ExecMethod(self.vbMethod, 'ExportRangeToFile', range, filename, imagetype, overwrite)
2221 def Forms(self, sheetname, form = ''):
2222 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', sheetname, form)
2224 def GetColumnName(self, columnnumber):
2225 return self.ExecMethod(self.vbMethod, 'GetColumnName', columnnumber)
2227 def GetFormula(self, range):
2228 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetFormula', range)
2230 def GetValue(self, range):
2231 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetValue', range)
2233 def ImportFromCSVFile(self, filename, destinationcell, filteroptions = ScriptForge.cstSymEmpty):
2234 return self.ExecMethod(self.vbMethod, 'ImportFromCSVFile', filename, destinationcell, filteroptions)
2236 def ImportFromDatabase(self, filename = '', registrationname = '', destinationcell = '', sqlcommand = '',
2237 directsql = False):
2238 return self.ExecMethod(self.vbMethod, 'ImportFromDatabase', filename, registrationname,
2239 destinationcell, sqlcommand, directsql)
2241 def InsertSheet(self, sheetname, beforesheet = 32768):
2242 return self.ExecMethod(self.vbMethod, 'InsertSheet', sheetname, beforesheet)
2244 def MoveRange(self, source, destination):
2245 return self.ExecMethod(self.vbMethod, 'MoveRange', source, destination)
2247 def MoveSheet(self, sheetname, beforesheet = 32768):
2248 return self.ExecMethod(self.vbMethod, 'MoveSheet', sheetname, beforesheet)
2250 def Offset(self, range, rows = 0, columns = 0, height = ScriptForge.cstSymEmpty,
2251 width = ScriptForge.cstSymEmpty):
2252 return self.ExecMethod(self.vbMethod, 'Offset', range, rows, columns, height, width)
2254 def OpenRangeSelector(self, title = '', selection = '~', singlecell = False, closeafterselect = True):
2255 return self.ExecMethod(self.vbMethod, 'OpenRangeSelector', title, selection, singlecell, closeafterselect)
2257 def Printf(self, inputstr, range, tokencharacter = '%'):
2258 return self.ExecMethod(self.vbMethod, 'Printf', inputstr, range, tokencharacter)
2260 def PrintOut(self, sheetname = '~', pages = '', copies = 1):
2261 return self.ExecMethod(self.vbMethod, 'PrintOut', sheetname, pages, copies)
2263 def RemoveSheet(self, sheetname):
2264 return self.ExecMethod(self.vbMethod, 'RemoveSheet', sheetname)
2266 def RenameSheet(self, sheetname, newname):
2267 return self.ExecMethod(self.vbMethod, 'RenameSheet', sheetname, newname)
2269 def SetArray(self, targetcell, value):
2270 return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetArray', targetcell, value)
2272 def SetCellStyle(self, targetrange, style, filterformula = '', filterscope = ''):
2273 return self.ExecMethod(self.vbMethod, 'SetCellStyle', targetrange, style, filterformula, filterscope)
2275 def SetFormula(self, targetrange, formula):
2276 return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetFormula', targetrange, formula)
2278 def SetValue(self, targetrange, value):
2279 return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetValue', targetrange, value)
2281 def ShiftDown(self, range, wholerow = False, rows = 0):
2282 return self.ExecMethod(self.vbMethod, 'ShiftDown', range, wholerow, rows)
2284 def ShiftLeft(self, range, wholecolumn = False, columns = 0):
2285 return self.ExecMethod(self.vbMethod, 'ShiftLeft', range, wholecolumn, columns)
2287 def ShiftRight(self, range, wholecolumn = False, columns = 0):
2288 return self.ExecMethod(self.vbMethod, 'ShiftRight', range, wholecolumn, columns)
2290 def ShiftUp(self, range, wholerow = False, rows = 0):
2291 return self.ExecMethod(self.vbMethod, 'ShiftUp', range, wholerow, rows)
2293 def SortRange(self, range, sortkeys, sortorder = 'ASC', destinationcell = ScriptForge.cstSymEmpty,
2294 containsheader = False, casesensitive = False, sortcolumns = False):
2295 return self.ExecMethod(self.vbMethod, 'SortRange', range, sortkeys, sortorder, destinationcell,
2296 containsheader, casesensitive, sortcolumns)
2298 # #########################################################################
2299 # SF_CalcReference CLASS
2300 # #########################################################################
2301 class SF_CalcReference(SFServices):
2303 The SF_CalcReference class has as unique role to hold sheet and range references.
2304 They are implemented in Basic as Type ... End Type data structures
2306 # Mandatory class properties for service registration
2307 serviceimplementation = 'basic'
2308 servicename = 'SFDocuments.CalcReference'
2309 servicesynonyms = ()
2310 serviceproperties = dict()
2312 # #########################################################################
2313 # SF_Chart CLASS
2314 # #########################################################################
2315 class SF_Chart(SFServices):
2317 The SF_Chart module is focused on the description of chart documents
2318 stored in Calc sheets.
2319 With this service, many chart types and chart characteristics available
2320 in the user interface can be read or modified.
2322 # Mandatory class properties for service registration
2323 serviceimplementation = 'basic'
2324 servicename = 'SFDocuments.Chart'
2325 servicesynonyms = ()
2326 serviceproperties = dict(ChartType = True, Deep = True, Dim3D = True, Exploded = True, Filled = True,
2327 Legend = True, Percent = True, Stacked = True, Title = True,
2328 XChartObj = False, XDiagram = False, XShape = False, XTableChart = False,
2329 XTitle = True, YTitle = True)
2331 def Resize(self, xpos = -1, ypos = -1, width = -1, height = -1):
2332 return self.ExecMethod(self.vbMethod, 'Resize', xpos, ypos, width, height)
2334 def ExportToFile(self, filename, imagetype = 'png', overwrite = False):
2335 return self.ExecMethod(self.vbMethod, 'ExportToFile', filename, imagetype, overwrite)
2337 # #########################################################################
2338 # SF_Form CLASS
2339 # #########################################################################
2340 class SF_Form(SFServices):
2342 Management of forms defined in LibreOffice documents. Supported types are Base, Calc and Writer documents.
2343 It includes the management of subforms
2344 Each instance of the current class represents a single form or a single subform
2345 A form may optionally be (understand "is often") linked to a data source manageable with
2346 the SFDatabases.Database service. The current service offers a rapid access to that service.
2348 # Mandatory class properties for service registration
2349 serviceimplementation = 'basic'
2350 servicename = 'SFDocuments.Form'
2351 servicesynonyms = ()
2352 serviceproperties = dict(AllowDeletes = True, AllowInserts = True, AllowUpdates = True, BaseForm = False,
2353 Bookmark = True, CurrentRecord = True, Filter = True, LinkChildFields = False,
2354 LinkParentFields = False, Name = False,
2355 OnApproveCursorMove = True, OnApproveParameter = True, OnApproveReset = True,
2356 OnApproveRowChange = True, OnApproveSubmit = True, OnConfirmDelete = True,
2357 OnCursorMoved = True, OnErrorOccurred = True, OnLoaded = True, OnReloaded = True,
2358 OnReloading = True, OnResetted = True, OnRowChanged = True, OnUnloaded = True,
2359 OnUnloading = True,
2360 OrderBy = True, Parent = False, RecordSource = True, XForm = False)
2362 def Activate(self):
2363 return self.ExecMethod(self.vbMethod, 'Activate')
2365 def CloseFormDocument(self):
2366 return self.ExecMethod(self.vbMethod, 'CloseFormDocument')
2368 def Controls(self, controlname = ''):
2369 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
2371 def GetDatabase(self, user = '', password = ''):
2372 return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password)
2374 def MoveFirst(self):
2375 return self.ExecMethod(self.vbMethod, 'MoveFirst')
2377 def MoveLast(self):
2378 return self.ExecMethod(self.vbMethod, 'MoveLast')
2380 def MoveNew(self):
2381 return self.ExecMethod(self.vbMethod, 'MoveNew')
2383 def MoveNext(self, offset = 1):
2384 return self.ExecMethod(self.vbMethod, 'MoveNext', offset)
2386 def MovePrevious(self, offset = 1):
2387 return self.ExecMethod(self.vbMethod, 'MovePrevious', offset)
2389 def Requery(self):
2390 return self.ExecMethod(self.vbMethod, 'Requery')
2392 def Subforms(self, subform = ''):
2393 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Subforms', subform)
2395 # #########################################################################
2396 # SF_FormControl CLASS
2397 # #########################################################################
2398 class SF_FormControl(SFServices):
2400 Manage the controls belonging to a form or subform stored in a document.
2401 Each instance of the current class represents a single control within a form, a subform or a tablecontrol.
2402 A prerequisite is that all controls within the same form, subform or tablecontrol must have
2403 a unique name.
2405 # Mandatory class properties for service registration
2406 serviceimplementation = 'basic'
2407 servicename = 'SFDocuments.FormControl'
2408 servicesynonyms = ()
2409 serviceproperties = dict(Action = True, Caption = True, ControlSource = False, ControlType = False,
2410 Default = True, DefaultValue = True, Enabled = True, Format = True,
2411 ListCount = False, ListIndex = True, ListSource = True, ListSourceType = True,
2412 Locked = True, MultiSelect = True, Name = False,
2413 OnActionPerformed = True, OnAdjustmentValueChanged = True,
2414 OnApproveAction = True, OnApproveReset = True, OnApproveUpdate = True,
2415 OnChanged = True, OnErrorOccurred = True, OnFocusGained = True, OnFocusLost = True,
2416 OnItemStateChanged = True, OnKeyPressed = True, OnKeyReleased = True,
2417 OnMouseDragged = True, OnMouseEntered = True, OnMouseExited = True,
2418 OnMouseMoved = True, OnMousePressed = True, OnMouseReleased = True, OnResetted = True,
2419 OnTextChanged = True, OnUpdated = True, Parent = False, Picture = True,
2420 Required = True, Text = False, TipText = True, TripleState = True, Value = True,
2421 Visible = True, XControlModel = False, XControlView = False)
2423 def Controls(self, controlname = ''):
2424 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
2426 def SetFocus(self):
2427 return self.ExecMethod(self.vbMethod, 'SetFocus')
2429 # #########################################################################
2430 # SF_Writer CLASS
2431 # #########################################################################
2432 class SF_Writer(SF_Document, SFServices):
2434 The SF_Writer module is focused on :
2435 - TBD
2437 # Mandatory class properties for service registration
2438 serviceimplementation = 'basic'
2439 servicename = 'SFDocuments.Writer'
2440 servicesynonyms = ('writer', 'sfdocuments.writer')
2441 serviceproperties = dict(Description = True, DocumentType = False, ExportFilters = False, ImportFilters = False,
2442 IsBase = False, IsCalc = False, IsDraw = False, IsImpress = False, IsMath = False,
2443 IsWriter = False, Keywords = True, Readonly = False, Subject = True, Title = True,
2444 XComponent = False)
2445 # Force for each property to get its value from Basic - due to intense interactivity with user
2446 forceGetProperty = True
2448 @classmethod
2449 def ReviewServiceArgs(cls, windowname = ''):
2451 Transform positional and keyword arguments into positional only
2453 return windowname,
2455 def Forms(self, form = ''):
2456 return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', form)
2458 def PrintOut(self, pages = '', copies = 1, printbackground = True, printblankpages = False,
2459 printevenpages = True, printoddpages = True, printimages = True):
2460 return self.ExecMethod(self.vbMethod, 'PrintOut', pages, copies, printbackground, printblankpages,
2461 printevenpages, printoddpages, printimages)
2464 # #####################################################################################################################
2465 # SFWidgets CLASS (alias of SFWidgets Basic library) ###
2466 # #####################################################################################################################
2467 class SFWidgets:
2469 The SFWidgets class manages toolbars and popup menus
2471 pass
2473 # #########################################################################
2474 # SF_Menu CLASS
2475 # #########################################################################
2476 class SF_Menu(SFServices):
2478 Display a menu in the menubar of a document or a form document.
2479 After use, the menu will not be saved neither in the application settings, nor in the document.
2480 The menu will be displayed, as usual, when its header in the menubar is clicked.
2481 When one of its items is selected, there are 3 alternative options:
2482 - a UNO command (like ".uno:About") is triggered
2483 - a user script is run receiving a standard argument defined in this service
2484 - one of above combined with a toggle of the status of the item
2485 The menu is described from top to bottom. Each menu item receives a numeric and a string identifier.
2487 # Mandatory class properties for service registration
2488 serviceimplementation = 'basic'
2489 servicename = 'SFWidgets.Menu'
2490 servicesynonyms = ('menu', 'sfwidgets.menu')
2491 serviceproperties = dict(ShortcutCharacter = False, SubmenuCharacter = False)
2493 def AddCheckBox(self, menuitem, name = '', status = False, icon = '', tooltip = '',
2494 command = '', script = ''):
2495 return self.ExecMethod(self.vbMethod, 'AddCheckBox', menuitem, name, status, icon, tooltip,
2496 command, script)
2498 def AddItem(self, menuitem, name = '', icon = '', tooltip = '', command = '', script = ''):
2499 return self.ExecMethod(self.vbMethod, 'AddItem', menuitem, name, icon, tooltip, command, script)
2501 def AddRadioButton(self, menuitem, name = '', status = False, icon = '', tooltip = '',
2502 command = '', script = ''):
2503 return self.ExecMethod(self.vbMethod, 'AddRadioButton', menuitem, name, status, icon, tooltip,
2504 command, script)
2506 # #########################################################################
2507 # SF_PopupMenu CLASS
2508 # #########################################################################
2509 class SF_PopupMenu(SFServices):
2511 Display a popup menu anywhere and any time.
2512 A popup menu is usually triggered by a mouse action (typically a right-click) on a dialog, a form
2513 or one of their controls. In this case the menu will be displayed below the clicked area.
2514 When triggered by other events, including in the normal flow of a user script, the script should
2515 provide the coordinates of the topleft edge of the menu versus the actual component.
2516 The menu is described from top to bottom. Each menu item receives a numeric and a string identifier.
2517 The execute() method returns the item selected by the user.
2519 # Mandatory class properties for service registration
2520 serviceimplementation = 'basic'
2521 servicename = 'SFWidgets.PopupMenu'
2522 servicesynonyms = ('popupmenu', 'sfwidgets.popupmenu')
2523 serviceproperties = dict(ShortcutCharacter = False, SubmenuCharacter = False)
2525 @classmethod
2526 def ReviewServiceArgs(cls, event = None, x = 0, y = 0, submenuchar = ''):
2528 Transform positional and keyword arguments into positional only
2530 return event, x, y, submenuchar
2532 def AddCheckBox(self, menuitem, name = '', status = False, icon = '', tooltip = ''):
2533 return self.ExecMethod(self.vbMethod, 'AddCheckBox', menuitem, name, status, icon, tooltip)
2535 def AddItem(self, menuitem, name = '', icon = '', tooltip = ''):
2536 return self.ExecMethod(self.vbMethod, 'AddItem', menuitem, name, icon, tooltip)
2538 def AddRadioButton(self, menuitem, name = '', status = False, icon = '', tooltip = ''):
2539 return self.ExecMethod(self.vbMethod, 'AddRadioButton', menuitem, name, status, icon, tooltip)
2541 def Execute(self, returnid = True):
2542 return self.ExecMethod(self.vbMethod, 'Execute', returnid)
2545 # ##############################################False##################################################################
2546 # CreateScriptService() ###
2547 # #####################################################################################################################
2548 def CreateScriptService(service, *args, **kwargs):
2550 A service being the name of a collection of properties and methods,
2551 this method returns either
2552 - the Python object mirror of the Basic object implementing the requested service
2553 - the Python object implementing the service itself
2555 A service may be designated by its official name, stored in its class.servicename
2556 or by one of its synonyms stored in its class.servicesynonyms list
2557 If the service is not identified, the service creation is delegated to Basic, that might raise an error
2558 if still not identified there
2560 :param service: the name of the service as a string 'library.service' - cased exactly
2561 or one of its synonyms
2562 :param args: the arguments to pass to the service constructor
2563 :return: the service as a Python object
2565 # Init at each CreateScriptService() invocation
2566 # CreateScriptService is usually the first statement in user scripts requesting ScriptForge services
2567 # ScriptForge() is optional in user scripts when Python process inside LibreOffice process
2568 if ScriptForge.SCRIPTFORGEINITDONE is False:
2569 ScriptForge()
2571 def ResolveSynonyms(servicename):
2573 Synonyms within service names implemented in Python or predefined are resolved here
2574 :param servicename: The short name of the service
2575 :return: The official service name if found, the argument otherwise
2577 for cls in SFServices.__subclasses__():
2578 if servicename.lower() in cls.servicesynonyms:
2579 return cls.servicename
2580 return servicename
2583 # Check the list of available services
2584 scriptservice = ResolveSynonyms(service)
2585 if scriptservice in ScriptForge.serviceslist:
2586 serv = ScriptForge.serviceslist[scriptservice]
2587 # Check if the requested service is within the Python world
2588 if serv.serviceimplementation == 'python':
2589 return serv(*args)
2590 # Check if the service is a predefined standard Basic service
2591 elif scriptservice in ScriptForge.servicesmodules:
2592 return serv(ScriptForge.servicesmodules[scriptservice], classmodule = SFServices.moduleStandard)
2593 else:
2594 serv = None
2595 # The requested service is to be found in the Basic world
2596 # Check if the service must review the arguments
2597 if serv is not None:
2598 if hasattr(serv, 'ReviewServiceArgs'):
2599 # ReviewServiceArgs() must be a class method
2600 args = serv.ReviewServiceArgs(*args, **kwargs)
2601 # Get the service object back from Basic
2602 if len(args) == 0:
2603 serv = ScriptForge.InvokeBasicService('SF_Services', SFServices.vbMethod, 'CreateScriptService', service)
2604 else:
2605 serv = ScriptForge.InvokeBasicService('SF_Services', SFServices.vbMethod, 'CreateScriptService',
2606 service, *args)
2607 return serv
2610 createScriptService, createscriptservice = CreateScriptService, CreateScriptService
2612 # ######################################################################
2613 # Lists the scripts, that shall be visible inside the Basic/Python IDE
2614 # ######################################################################
2616 g_exportedScripts = ()