1# -*- coding: utf-8 -*-
2
3#     Copyright 2012-2020 Jean-Pierre LEDURE
4
5# =====================================================================================================================
6# ===                   The Access2Base library is a part of the LibreOffice project.                               ===
7# ===                   Full documentation is available on http://www.access2base.com                               ===
8# =====================================================================================================================
9
10# Access2Base 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.
13
14# Access2Base is free software; you can redistribute it and/or modify it under the terms of either (at your option):
15
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/ .
18
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/ .
23
24"""
25The access2base.py module implements an interface between Python (user) scripts and the Access2Base Basic library.
26
27Usage:
28    from access2base import *
29Additionally, if Python and LibreOffice are started in separate processes:
30    If LibreOffice started from console ... (example for Linux)
31        ./soffice --accept='socket,host=localhost,port=2019;urp;'
32    then insert next statement
33        A2BConnect(hostname = 'localhost', port = 2019)
34
35Specific documentation about Access2Base and Python:
36    http://www.access2base.com/access2base.html#%5B%5BAccess2Base%20and%20Python%5D%5D
37"""
38
39import uno
40XSCRIPTCONTEXT = uno
41
42from platform import system as _opsys
43import datetime, os, sys, traceback
44
45_LIBRARY = ''               # Should be 'Access2Base' or 'Access2BaseDev'
46_VERSION = '7.1'            # Actual version number
47_WRAPPERMODULE = 'Python'   # Module name in the Access2Base library containing Python interfaces
48
49# CallByName types
50_vbGet, _vbLet, _vbMethod, _vbSet, _vbUNO = 2, 4, 1, 8, 16
51
52
53class _Singleton(type):
54    """
55    A Singleton design pattern
56    Credits: « Python in a Nutshell » by Alex Martelli, O'Reilly
57    """
58    instances = {}
59    def __call__(cls, *args, **kwargs):
60        if cls not in cls.instances:
61            cls.instances[cls] = super(_Singleton, cls).__call__(*args, **kwargs)
62        return cls.instances[cls]
63
64
65class acConstants(object, metaclass = _Singleton):
66    """
67    VBA constants used in the Access2Base API.
68    Values derived from MSAccess, except when conflicts
69    """
70    # Python special constants (used in the protocol between Python and Basic)
71    # -----------------------------------------------------------------
72    Empty = '+++EMPTY+++'
73    Null = '+++NULL+++'
74    Missing = '+++MISSING+++'
75    FromIsoFormat = '%Y-%m-%d %H:%M:%S' # To be used with datetime.datetime.strptime()
76
77    # AcCloseSave
78    # -----------------------------------------------------------------
79    acSaveNo = 2
80    acSavePrompt = 0
81    acSaveYes = 1
82
83    # AcFormView
84    # -----------------------------------------------------------------
85    acDesign = 1
86    acNormal = 0
87    acPreview = 2
88
89    # AcFormOpenDataMode
90    # -----------------------------------------------------------------
91    acFormAdd = 0
92    acFormEdit = 1
93    acFormPropertySettings = -1
94    acFormReadOnly = 2
95
96    # acView
97    # -----------------------------------------------------------------
98    acViewDesign = 1
99    acViewNormal = 0
100    acViewPreview = 2
101
102    # acOpenDataMode
103    # -----------------------------------------------------------------
104    acAdd = 0
105    acEdit = 1
106    acReadOnly = 2
107
108    # AcObjectType
109    # -----------------------------------------------------------------
110    acDefault = -1
111    acDiagram = 8
112    acForm = 2
113    acQuery = 1
114    acReport = 3
115    acTable = 0
116    #   Unexisting in MS/Access
117    acBasicIDE = 101
118    acDatabaseWindow = 102
119    acDocument = 111
120    acWelcome = 112
121    #   Subtype if acDocument
122    docWriter = "Writer"
123    docCalc = "Calc"
124    docImpress = "Impress"
125    docDraw = "Draw"
126    docMath = "Math"
127
128    # AcWindowMode
129    # -----------------------------------------------------------------
130    acDialog = 3
131    acHidden = 1
132    acIcon = 2
133    acWindowNormal = 0
134
135    # VarType constants
136    # -----------------------------------------------------------------
137    vbEmpty = 0
138    vbNull = 1
139    vbInteger = 2
140    vbLong = 3
141    vbSingle = 4
142    vbDouble = 5
143    vbCurrency = 6
144    vbDate = 7
145    vbString = 8
146    vbObject = 9
147    vbBoolean = 11
148    vbVariant = 12
149    vbByte = 17
150    vbUShort = 18
151    vbULong = 19
152    vbBigint = 35
153    vbDecimal = 37
154    vbArray = 8192
155
156    # MsgBox constants
157    # -----------------------------------------------------------------
158    vbOKOnly = 0  # OK button only (default)
159    vbOKCancel = 1  # OK and Cancel buttons
160    vbAbortRetryIgnore = 2  # Abort, Retry, and Ignore buttons
161    vbYesNoCancel = 3  # Yes, No, and Cancel buttons
162    vbYesNo = 4  # Yes and No buttons
163    vbRetryCancel = 5  # Retry and Cancel buttons
164    vbCritical = 16  # Critical message
165    vbQuestion = 32  # Warning query
166    vbExclamation = 48  # Warning message
167    vbInformation = 64  # Information message
168    vbDefaultButton1 = 128  # First button is default (default) (VBA: 0)
169    vbDefaultButton2 = 256  # Second button is default
170    vbDefaultButton3 = 512  # Third button is default
171    vbApplicationModal = 0  # Application modal message box (default)
172    # MsgBox Return Values
173    # -----------------------------------------------------------------
174    vbOK = 1  # OK button pressed
175    vbCancel = 2  # Cancel button pressed
176    vbAbort = 3  # Abort button pressed
177    vbRetry = 4  # Retry button pressed
178    vbIgnore = 5  # Ignore button pressed
179    vbYes = 6  # Yes button pressed
180    vbNo = 7  # No button pressed
181
182    # Dialogs Return Values
183    # ------------------------------------------------------------------
184    dlgOK = 1  # OK button pressed
185    dlgCancel = 0  # Cancel button pressed
186
187    # Control Types
188    # -----------------------------------------------------------------
189    acCheckBox = 5
190    acComboBox = 7
191    acCommandButton = 2
192    acToggleButton = 122
193    acCurrencyField = 18
194    acDateField = 15
195    acFileControl = 12
196    acFixedLine = 24  # FREE ENTRY (USEFUL IN DIALOGS)
197    acFixedText = 10
198    acLabel = 10
199    acFormattedField = 1  # FREE ENTRY TAKEN TO NOT CONFUSE WITH acTextField
200    acGridControl = 11
201    acGroupBox = 8
202    acOptionGroup = 8
203    acHiddenControl = 13
204    acImageButton = 4
205    acImageControl = 14
206    acImage = 14
207    acListBox = 6
208    acNavigationBar = 22
209    acNumericField = 17
210    acPatternField = 19
211    acProgressBar = 23  # FREE ENTRY (USEFUL IN DIALOGS)
212    acRadioButton = 3
213    acOptionButton = 3
214    acScrollBar = 20
215    acSpinButton = 21
216    acSubform = 112
217    acTextField = 9
218    acTextBox = 9
219    acTimeField = 16
220
221    # AcRecord
222    # -----------------------------------------------------------------
223    acFirst = 2
224    acGoTo = 4
225    acLast = 3
226    acNewRec = 5
227    acNext = 1
228    acPrevious = 0
229
230    # FindRecord
231    # -----------------------------------------------------------------
232    acAnywhere = 0
233    acEntire = 1
234    acStart = 2
235    acDown = 1
236    acSearchAll = 2
237    acUp = 0
238    acAll = 0
239    acCurrent = -1
240
241    # AcDataObjectType
242    # -----------------------------------------------------------------
243    acActiveDataObject = -1
244    acDataForm = 2
245    acDataQuery = 1
246    acDataServerView = 7
247    acDataStoredProcedure = 9
248    acDataTable = 0
249
250    # AcQuitOption
251    # -----------------------------------------------------------------
252    acQuitPrompt = 0
253    acQuitSaveAll = 1
254    acQuitSaveNone = 2
255
256    # AcCommand
257    # -----------------------------------------------------------------
258    acCmdAboutMicrosoftAccess = 35
259    acCmdAboutOpenOffice = 35
260    acCmdAboutLibreOffice = 35
261    acCmdVisualBasicEditor = 525
262    acCmdBringToFront = 52
263    acCmdClose = 58
264    acCmdToolbarsCustomize = 165
265    acCmdChangeToCommandButton = 501
266    acCmdChangeToCheckBox = 231
267    acCmdChangeToComboBox = 230
268    acCmdChangeToTextBox = 227
269    acCmdChangeToLabel = 228
270    acCmdChangeToImage = 234
271    acCmdChangeToListBox = 229
272    acCmdChangeToOptionButton = 233
273    acCmdCopy = 190
274    acCmdCut = 189
275    acCmdCreateRelationship = 150
276    acCmdDelete = 337
277    acCmdDatabaseProperties = 256
278    acCmdSQLView = 184
279    acCmdRemove = 366
280    acCmdDesignView = 183
281    acCmdFormView = 281
282    acCmdNewObjectForm = 136
283    acCmdNewObjectTable = 134
284    acCmdNewObjectView = 350
285    acCmdOpenDatabase = 25
286    acCmdNewObjectQuery = 135
287    acCmdShowAllRelationships = 149
288    acCmdNewObjectReport = 137
289    acCmdSelectAll = 333
290    acCmdRemoveTable = 84
291    acCmdOpenTable = 221
292    acCmdRename = 143
293    acCmdDeleteRecord = 223
294    acCmdApplyFilterSort = 93
295    acCmdSnapToGrid = 62
296    acCmdViewGrid = 63
297    acCmdInsertHyperlink = 259
298    acCmdMaximumRecords = 508
299    acCmdObjectBrowser = 200
300    acCmdPaste = 191
301    acCmdPasteSpecial = 64
302    acCmdPrint = 340
303    acCmdPrintPreview = 54
304    acCmdSaveRecord = 97
305    acCmdFind = 30
306    acCmdUndo = 292
307    acCmdRefresh = 18
308    acCmdRemoveFilterSort = 144
309    acCmdRunMacro = 31
310    acCmdSave = 20
311    acCmdSaveAs = 21
312    acCmdSelectAllRecords = 109
313    acCmdSendToBack = 53
314    acCmdSortDescending = 164
315    acCmdSortAscending = 163
316    acCmdTabOrder = 41
317    acCmdDatasheetView = 282
318    acCmdZoomSelection = 371
319
320    # AcSendObjectType
321    # -----------------------------------------------------------------
322    acSendForm = 2
323    acSendNoObject = -1
324    acSendQuery = 1
325    acSendReport = 3
326    acSendTable = 0
327
328    # AcOutputObjectType
329    # -----------------------------------------------------------------
330    acOutputTable = 0
331    acOutputQuery = 1
332    acOutputForm = 2
333    acOutputArray = -1
334
335    # AcEncoding
336    # -----------------------------------------------------------------
337    acUTF8Encoding = 76
338
339    # AcFormat
340    # -----------------------------------------------------------------
341    acFormatPDF = "writer_pdf_Export"
342    acFormatODT = "writer8"
343    acFormatDOC = "MS Word 97"
344    acFormatHTML = "HTML"
345    acFormatODS = "calc8"
346    acFormatXLS = "MS Excel 97"
347    acFormatXLSX = "Calc MS Excel 2007 XML"
348    acFormatTXT = "Text - txt - csv (StarCalc)"
349
350    # AcExportQuality
351    # -----------------------------------------------------------------
352    acExportQualityPrint = 0
353    acExportQualityScreen = 1
354
355    # AcSysCmdAction
356    # -----------------------------------------------------------------
357    acSysCmdAccessDir = 9
358    acSysCmdAccessVer = 7
359    acSysCmdClearHelpTopic = 11
360    acSysCmdClearStatus = 5
361    acSysCmdGetObjectState = 10
362    acSysCmdGetWorkgroupFile = 13
363    acSysCmdIniFile = 8
364    acSysCmdInitMeter = 1
365    acSysCmdProfile = 12
366    acSysCmdRemoveMeter = 3
367    acSysCmdRuntime = 6
368    acSysCmdSetStatus = 4
369    acSysCmdUpdateMeter = 2
370
371    # Type property
372    # -----------------------------------------------------------------
373    dbBigInt = 16
374    dbBinary = 9
375    dbBoolean = 1
376    dbByte = 2
377    dbChar = 18
378    dbCurrency = 5
379    dbDate = 8
380    dbDecimal = 20
381    dbDouble = 7
382    dbFloat = 21
383    dbGUID = 15
384    dbInteger = 3
385    dbLong = 4
386    dbLongBinary = 11  # (OLE Object)
387    dbMemo = 12
388    dbNumeric = 19
389    dbSingle = 6
390    dbText = 10
391    dbTime = 22
392    dbTimeStamp = 23
393    dbVarBinary = 17
394    dbUndefined = -1
395
396    # Attributes property
397    # -----------------------------------------------------------------
398    dbAutoIncrField = 16
399    dbDescending = 1
400    dbFixedField = 1
401    dbHyperlinkField = 32768
402    dbSystemField = 8192
403    dbUpdatableField = 32
404    dbVariableField = 2
405
406    # OpenRecordset
407    # -----------------------------------------------------------------
408    dbOpenForwardOnly = 8
409    dbSQLPassThrough = 64
410    dbReadOnly = 4
411
412    # Query types
413    # -----------------------------------------------------------------
414    dbQAction = 240
415    dbQAppend = 64
416    dbQDDL = 4  # 96
417    dbQDelete = 32
418    dbQMakeTable = 128  # 80
419    dbQSelect = 0
420    dbQSetOperation = 8  # 128
421    dbQSQLPassThrough = 1  # 112
422    dbQUpdate = 16  # 48
423
424    # Edit mode
425    # -----------------------------------------------------------------
426    dbEditNone = 0
427    dbEditInProgress = 1
428    dbEditAdd = 2
429
430    # Toolbars
431    # -----------------------------------------------------------------
432    msoBarTypeNormal = 0  # Usual toolbar
433    msoBarTypeMenuBar = 1  # Menu bar
434    msoBarTypePopup = 2  # Shortcut menu
435    msoBarTypeStatusBar = 11  # Status bar
436    msoBarTypeFloater = 12  # Floating window
437
438    msoControlButton = 1  # Command button
439    msoControlPopup = 10  # Popup, submenu
440
441    # New Lines
442    # -----------------------------------------------------------------
443    vbCr = chr(13)
444    vbLf = chr(10)
445
446    def _NewLine():
447        if _opsys == 'Windows': return chr(13) + chr(10)
448        return chr(10)
449
450    vbNewLine = _NewLine()
451    vbTab = chr(9)
452
453    # Module types
454    # -----------------------------------------------------------------
455    acClassModule = 1
456    acStandardModule = 0
457
458    # (Module) procedure types
459    # -----------------------------------------------------------------
460    vbext_pk_Get = 1  # A Property Get procedure
461    vbext_pk_Let = 2  # A Property Let procedure
462    vbext_pk_Proc = 0  # A Sub or Function procedure
463    vbext_pk_Set = 3  # A Property Set procedure
464
465
466COMPONENTCONTEXT, DESKTOP, SCRIPTPROVIDER, THISDATABASEDOCUMENT = None, None, None, None
467
468def _ErrorHandler(type, value, tb):
469    '''
470    Is the function to be set as new sys.excepthook to bypass the standard error handler
471        Derived from https://stackoverflow.com/questions/31949760/how-to-limit-python-traceback-to-specific-files
472    Handler removes traces pointing to methods located in access2base.py when error is due to a user programming error
473        sys.excepthook = _ErrorHandler
474    NOT APPLIED YET
475    '''
476
477    def check_file(name):
478        return 'access2base.py' not in name
479
480    show = (fs for fs in traceback.extract_tb(tb) if check_file(fs.filename))
481    fmt = traceback.format_list(show) + traceback.format_exception_only(type, value)
482    print(''.join(fmt), end = '', file = sys.stderr)
483    # Reset to standard handler
484    sys.excepthook = sys.__excepthook__
485
486
487def A2BConnect(hostname = '', port = 0):
488    """
489    To be called explicitly by user scripts when Python process runs outside the LibreOffice process.
490        LibreOffice started as (Linux):
491            ./soffice --accept='socket,host=localhost,port=xxxx;urp;'
492    Otherwise called implicitly by the current module without arguments
493    Initializes COMPONENTCONTEXT, SCRIPTPROVIDER and DESKTOP
494    :param hostname: probably 'localhost' or ''
495    :param port: port number or 0
496    :return: None
497    """
498    global XSCRIPTCONTEXT, COMPONENTCONTEXT, DESKTOP, SCRIPTPROVIDER
499    # Determine COMPONENTCONTEXT, via socket or inside LibreOffice
500    if len(hostname) > 0 and port > 0:      # Explicit connection request via socket
501        # Code derived from Bridge.py by Alain H. Romedenne
502        local_context = XSCRIPTCONTEXT.getComponentContext()
503        resolver = local_context.ServiceManager.createInstanceWithContext(
504            'com.sun.star.bridge.UnoUrlResolver', local_context)
505        try:
506            conn = 'socket,host=%s,port=%d' % (hostname, port)
507            connection_url = 'uno:%s;urp;StarOffice.ComponentContext' % conn
508            established_context = resolver.resolve(connection_url)
509        except Exception:  # thrown when LibreOffice specified instance isn't started
510            raise ConnectionError('Connection to LibreOffice failed (host = ' + hostname + ', port = ' + str(port) + ')')
511        COMPONENTCONTEXT = established_context
512        DESKTOP = None
513    elif len(hostname) == 0 and port == 0:       # Usual interactive mode
514        COMPONENTCONTEXT = XSCRIPTCONTEXT.getComponentContext()
515        DESKTOP = COMPONENTCONTEXT.ServiceManager.createInstanceWithContext( 'com.sun.star.frame.Desktop', COMPONENTCONTEXT)
516    else:
517        raise SystemExit('The invocation of A2BConnect() has invalid arguments')
518    # Determine SCRIPTPROVIDER
519    servicemanager = COMPONENTCONTEXT.ServiceManager
520    masterscript = servicemanager.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", COMPONENTCONTEXT)
521    SCRIPTPROVIDER = masterscript.createScriptProvider("")
522    Script = _A2B.xScript('TraceLog', 'Trace')  # Don't use invokeMethod() to force reset of error stack
523    Script.invoke(('===>', 'Python wrapper loaded V.' + _VERSION, False), (), ())
524    return None
525
526
527class _A2B(object, metaclass = _Singleton):
528    """
529    Collection of helper functions implementing the protocol between Python and Basic
530        Read comments in PythonWrapper Basic function
531    """
532
533    @classmethod
534    def BasicObject(cls, objectname):
535        objs = {'COLLECTION': _Collection
536            , 'COMMANDBAR': _CommandBar
537            , 'COMMANDBARCONTROL': _CommandBarControl
538            , 'CONTROL': _Control
539            , 'DATABASE': _Database
540            , 'DIALOG': _Dialog
541            , 'EVENT': _Event
542            , 'FIELD': _Field
543            , 'FORM': _Form
544            , 'MODULE': _Module
545            , 'OPTIONGROUP': _OptionGroup
546            , 'PROPERTY': _Property
547            , 'QUERYDEF': _QueryDef
548            , 'RECORDSET': _Recordset
549            , 'SUBFORM': _SubForm
550            , 'TABLEDEF': _TableDef
551            , 'TEMPVAR': _TempVar
552                }
553        return objs[objectname]
554
555    @classmethod
556    def xScript(cls, script, module):
557        """
558        At first call checks the existence of the Access2Base library
559        Initializes _LIBRARY with the found library name
560        First and next calls execute the given script in the given module of the _LIBRARY library
561        The script and module are presumed to exist
562        :param script: name of script
563        :param module: name of module
564        :return: the script object. NB: the execution is done with the invoke() method applied on the returned object
565        """
566        global _LIBRARY
567        Script = None
568        def sScript(lib):
569            return 'vnd.sun.star.script:' + lib + '.' + module + '.' + script + '?language=Basic&location=application'
570        if _LIBRARY == '':
571            # Check the availability of the Access2Base library
572            for lib in ('Access2BaseDev', 'Access2Base'):
573                try:
574                    if Script == None:
575                        Script = SCRIPTPROVIDER.getScript(sScript(lib))
576                        _LIBRARY = lib
577                except Exception:
578                    pass
579            if Script == None:
580                raise SystemExit('Access2Base basic library not found')
581        else:
582            Script = SCRIPTPROVIDER.getScript(sScript(_LIBRARY))
583        return Script
584
585    @classmethod
586    def A2BErrorCode(cls):
587        """
588        Return the Access2Base error stack as a tuple
589            0 => error code
590            1 => severity level
591            2 => short error message
592            3 => long error message
593        """
594        Script = cls.xScript('TraceErrorCode', 'Trace')
595        return Script.invoke((), (), ())[0]
596
597    @classmethod
598    def invokeMethod(cls, script, module, *args):
599        """
600        Direct call to a named script/module pair with their arguments
601        If the arguments do not match their definition at the Basic side, a TypeError is raised
602        :param script: name of script
603        :param module: name of module
604        :param args: list of arguments to be passed to the script
605        :return: the value returned by the script execution
606        """
607        if COMPONENTCONTEXT == None: A2BConnect()     #   Connection from inside LibreOffice is done at first API invocation
608        Script = cls.xScript(script, module)
609        try:
610            Returned = Script.invoke((args), (), ())[0]
611        except:
612            raise TypeError("Access2Base error: method '" + script + "' in Basic module '" + module + "' call error. Check its arguments.")
613        else:
614            if Returned == None:
615                if cls.VerifyNoError(): return None
616            return Returned
617
618    @classmethod
619    def invokeWrapper(cls, action, basic, script, *args):
620        """
621        Call the Basic wrapper to invite it to execute the proposed action on a Basic object
622        If the arguments do not match their definition at the Basic side, a TypeError is raised
623        After execution, a check is done if the execution has raised an error within Basic
624            If yes, a TypeError is raised
625        :param action: Property Get, Property Let, Property Set, invoke Method or return UNO object
626        :param basic: the reference of the Basic object, i.e. the index in the array caching the addresses of the objects
627                        conventionally Application = -1 and DoCmd = -2
628        :param script: the property or method name
629        :param args: the arguments of the method, if any
630        :return: the value returned by the execution of the Basic routine
631        """
632        if COMPONENTCONTEXT == None: A2BConnect()     #   Connection from inside LibreOffice is done at first API invocation
633        # Intercept special call to Application.Events()
634        if basic == Application.basicmodule and script == 'Events':
635            Script = cls.xScript('PythonEventsWrapper', _WRAPPERMODULE)
636            Returned = Script.invoke((args[0],), (), ())
637        else:
638            Script = cls.xScript('PythonWrapper', _WRAPPERMODULE)
639            NoArgs = '+++NOARGS+++'     # Conventional notation for properties/methods without arguments
640            if len(args) == 0:
641                args = (action,) + (basic,) + (script,) + (NoArgs,)
642            else:
643                args = (action,) + (basic,) + (script,) + args
644            try:
645                Returned = Script.invoke((args), (), ())
646            except:
647                raise TypeError("Access2Base error: method '" + script + "' call error. Check its arguments.")
648
649        if isinstance(Returned[0], tuple):
650            # Is returned value a reference to a basic object, a scalar or a UNO object ?
651            if len(Returned[0]) in (3, 4):
652                if Returned[0][0] == 0:         # scalar
653                    return Returned[0][1]
654                elif Returned[0][0] == 1:       # reference to objects cache
655                    basicobject = cls.BasicObject(Returned[0][2])
656                    if len(Returned[0]) == 3:
657                        return basicobject(Returned[0][1], Returned[0][2])
658                    else:
659                        return basicobject(Returned[0][1], Returned[0][2], Returned[0][3])
660                elif Returned[0][0] == 2:       # Null value
661                    return None
662                else:       # Should not happen
663                    return None
664            else:                               # UNO object
665                return Returned[0]
666        elif Returned[0] == None:
667            if cls.VerifyNoError(): return None
668        else: # Should not happen
669            return Returned[0]
670
671    @classmethod
672    def VerifyNoError(cls):
673        # has Access2Base generated an error ?
674        errorstack = cls.A2BErrorCode()  # 0 = code, 1 = severity, 2 = short text, 3 = long text
675        if errorstack[1] in ('ERROR', 'FATAL', 'ABORT'):
676            raise TypeError('Access2Base error: ' + errorstack[3])
677        return True
678
679
680class Application(object, metaclass = _Singleton):
681    """ Collection of methods located in the Application (Basic) module """
682    W = _A2B.invokeWrapper
683    basicmodule = -1
684
685    @classmethod
686    def AllDialogs(cls, dialog = acConstants.Missing):
687        return cls.W(_vbMethod, cls.basicmodule, 'AllDialogs', dialog)
688    @classmethod
689    def AllForms(cls, form = acConstants.Missing):
690        return cls.W(_vbMethod, cls.basicmodule, 'AllForms', form)
691    @classmethod
692    def AllModules(cls, module = acConstants.Missing):
693        return cls.W(_vbMethod, cls.basicmodule, 'AllModules', module)
694    @classmethod
695    def CloseConnection(cls):
696        return cls.W(_vbMethod, cls.basicmodule, 'CloseConnection')
697    @classmethod
698    def CommandBars(cls, bar = acConstants.Missing):
699        return cls.W(_vbMethod, cls.basicmodule, 'CommandBars', bar)
700    @classmethod
701    def CurrentDb(cls):
702        return cls.W(_vbMethod, cls.basicmodule, 'CurrentDb')
703    @classmethod
704    def CurrentUser(cls):
705        return cls.W(_vbMethod, cls.basicmodule, 'CurrentUser')
706    @classmethod
707    def DAvg(cls, expression, domain, criteria = ''):
708        return cls.W(_vbMethod, cls.basicmodule, 'DAvg', expression, domain, criteria)
709    @classmethod
710    def DCount(cls, expression, domain, criteria = ''):
711        return cls.W(_vbMethod, cls.basicmodule, 'DCount', expression, domain, criteria)
712    @classmethod
713    def DLookup(cls, expression, domain, criteria = '', orderclause = ''):
714        return cls.W(_vbMethod, cls.basicmodule, 'DLookup', expression, domain, criteria, orderclause)
715    @classmethod
716    def DMax(cls, expression, domain, criteria = ''):
717        return cls.W(_vbMethod, cls.basicmodule, 'DMax', expression, domain, criteria)
718    @classmethod
719    def DMin(cls, expression, domain, criteria = ''):
720        return cls.W(_vbMethod, cls.basicmodule, 'DMin', expression, domain, criteria)
721    @classmethod
722    def DStDev(cls, expression, domain, criteria = ''):
723        return cls.W(_vbMethod, cls.basicmodule, 'DStDev', expression, domain, criteria)
724    @classmethod
725    def DStDevP(cls, expression, domain, criteria = ''):
726        return cls.W(_vbMethod, cls.basicmodule, 'DStDevP', expression, domain, criteria)
727    @classmethod
728    def DSum(cls, expression, domain, criteria = ''):
729        return cls.W(_vbMethod, cls.basicmodule, 'DSum', expression, domain, criteria)
730    @classmethod
731    def DVar(cls, expression, domain, criteria = ''):
732        return cls.W(_vbMethod, cls.basicmodule, 'DVar', expression, domain, criteria)
733    @classmethod
734    def DVarP(cls, expression, domain, criteria = ''):
735        return cls.W(_vbMethod, cls.basicmodule, 'DVarP', expression, domain, criteria)
736    @classmethod
737    def Events(cls, event):
738        return cls.W(_vbMethod, cls.basicmodule, 'Events', event)
739    @classmethod
740    def Forms(cls, form = acConstants.Missing):
741        return cls.W(_vbMethod, cls.basicmodule, 'Forms', form)
742    @classmethod
743    def getObject(cls, shortcut):
744        return cls.W(_vbMethod, cls.basicmodule, 'getObject', shortcut)
745    GetObject = getObject
746    @classmethod
747    def getValue(cls, shortcut):
748        return cls.W(_vbMethod, cls.basicmodule, 'getValue', shortcut)
749    GetValue = getValue
750    @classmethod
751    def HtmlEncode(cls, string, length = 0):
752        return cls.W(_vbMethod, cls.basicmodule, 'HtmlEncode', string, length)
753    @classmethod
754    def OpenConnection(cls, thisdatabasedocument = acConstants.Missing):
755        global THISDATABASEDOCUMENT
756        if COMPONENTCONTEXT == None: A2BConnect()     #   Connection from inside LibreOffice is done at first API invocation
757        if DESKTOP != None:
758            THISDATABASEDOCUMENT = DESKTOP.getCurrentComponent()
759            return _A2B.invokeMethod('OpenConnection', 'Application', THISDATABASEDOCUMENT)
760    @classmethod
761    def OpenDatabase(cls, connectionstring, username = '', password = '', readonly = False):
762        return cls.W(_vbMethod, cls.basicmodule, 'OpenDatabase', connectionstring, username
763                           , password, readonly)
764    @classmethod
765    def ProductCode(cls):
766        return cls.W(_vbMethod, cls.basicmodule, 'ProductCode')
767    @classmethod
768    def setValue(cls, shortcut, value):
769        return cls.W(_vbMethod, cls.basicmodule, 'setValue', shortcut, value)
770    SetValue = setValue
771    @classmethod
772    def SysCmd(cls, action, text = '', value = -1):
773        return cls.W(_vbMethod, cls.basicmodule, 'SysCmd', action, text, value)
774    @classmethod
775    def TempVars(cls, var = acConstants.Missing):
776        return cls.W(_vbMethod, cls.basicmodule, 'TempVars', var)
777    @classmethod
778    def Version(cls):
779        return cls.W(_vbMethod, cls.basicmodule, 'Version')
780
781
782class DoCmd(object, metaclass = _Singleton):
783    """ Collection of methods located in the DoCmd (Basic) module """
784    W = _A2B.invokeWrapper
785    basicmodule = -2
786
787    @classmethod
788    def ApplyFilter(cls, filter = '', sqlwhere = '', controlname = ''):
789        return cls.W(_vbMethod, cls.basicmodule, 'ApplyFilter', filter, sqlwhere, controlname)
790    @classmethod
791    def Close(cls, objecttype, objectname, save = acConstants.acSavePrompt):
792        return cls.W(_vbMethod, cls.basicmodule, 'Close', objecttype, objectname, save)
793    @classmethod
794    def CopyObject(cls, sourcedatabase, newname, sourceobjecttype, sourceobjectname):    # 1st argument must be set
795        return cls.W(_vbMethod, cls.basicmodule, 'CopyObject', sourcedatabase, newname, sourceobjecttype
796                           , sourceobjectname)
797    @classmethod
798    def FindNext(cls):
799        return cls.W(_vbMethod, cls.basicmodule, 'FindNext')
800    @classmethod
801    def FindRecord(cls, findwhat, match = acConstants.acEntire, matchcase = False, search = acConstants.acSearchAll
802        , searchasformatted = False, onlycurrentfield = acConstants.acCurrent, findfirst = True):
803        return cls.W(_vbMethod, cls.basicmodule, 'FindRecord', findwhat, match, matchcase, search
804        , searchasformatted, onlycurrentfield, findfirst)
805    @classmethod
806    def GetHiddenAttribute(cls, objecttype, objectname = ''):
807        return cls.W(_vbMethod, cls.basicmodule, 'GetHiddenAttribute', objecttype, objectname)
808    @classmethod
809    def GoToControl(cls, controlname):
810        return cls.W(_vbMethod, cls.basicmodule, 'GoToControl', controlname)
811    @classmethod
812    def GoToRecord(cls, objecttype = acConstants.acActiveDataObject, objectname = '', record = acConstants.acNext
813                   , offset = 1):
814        return cls.W(_vbMethod, cls.basicmodule, 'GoToRecord', objecttype, objectname, record, offset)
815    @classmethod
816    def Maximize(cls):
817        return cls.W(_vbMethod, cls.basicmodule, 'Maximize')
818    @classmethod
819    def Minimize(cls):
820        return cls.W(_vbMethod, cls.basicmodule, 'Minimize')
821    @classmethod
822    def MoveSize(cls, left = -1, top = -1, width = -1, height = -1):
823        return cls.W(_vbMethod, cls.basicmodule, 'MoveSize', left, top, width, height)
824    @classmethod
825    def OpenForm(cls, formname, view = acConstants.acNormal, filter = '', wherecondition = ''
826        , datamode = acConstants.acFormEdit, windowmode = acConstants.acWindowNormal, openargs = ''):
827        return cls.W(_vbMethod, cls.basicmodule, 'OpenForm', formname, view, filter, wherecondition
828        , datamode, windowmode, openargs)
829    @classmethod
830    def OpenQuery(cls, queryname, view = acConstants.acNormal, datamode = acConstants.acEdit):
831        return cls.W(_vbMethod, cls.basicmodule, 'OpenQuery', queryname, view, datamode)
832    @classmethod
833    def OpenReport(cls, queryname, view = acConstants.acNormal):
834        return cls.W(_vbMethod, cls.basicmodule, 'OpenReport', queryname, view)
835    @classmethod
836    def OpenSQL(cls, sql, option = -1):
837        return cls.W(_vbMethod, cls.basicmodule, 'OpenSQL', sql, option)
838    @classmethod
839    def OpenTable(cls, tablename, view = acConstants.acNormal, datamode = acConstants.acEdit):
840        return cls.W(_vbMethod, cls.basicmodule, 'OpenTable', tablename, view, datamode)
841    @classmethod
842    def OutputTo(cls, objecttype, objectname = '', outputformat = '', outputfile = '', autostart = False, templatefile = ''
843        , encoding = acConstants.acUTF8Encoding, quality = acConstants.acExportQualityPrint):
844        if objecttype == acConstants.acOutputForm: encoding = 0
845        return cls.W(_vbMethod, cls.basicmodule, 'OutputTo', objecttype, objectname, outputformat
846                           , outputfile, autostart, templatefile, encoding, quality)
847    @classmethod
848    def Quit(cls):
849        return cls.W(_vbMethod, cls.basicmodule, 'Quit')
850    @classmethod
851    def RunApp(cls, commandline):
852        return cls.W(_vbMethod, cls.basicmodule, 'RunApp', commandline)
853    @classmethod
854    def RunCommand(cls, command):
855        return cls.W(_vbMethod, cls.basicmodule, 'RunCommand', command)
856    @classmethod
857    def RunSQL(cls, SQL, option = -1):
858        return cls.W(_vbMethod, cls.basicmodule, 'RunSQL', SQL, option)
859    @classmethod
860    def SelectObject(cls, objecttype, objectname = '', indatabasewindow = False):
861        return cls.W(_vbMethod, cls.basicmodule, 'SelectObject', objecttype, objectname, indatabasewindow)
862    @classmethod
863    def SendObject(cls, objecttype = acConstants.acSendNoObject, objectname = '', outputformat = '', to = '', cc = ''
864        , bcc = '', subject = '', messagetext = '', editmessage = True, templatefile = ''):
865        return cls.W(_vbMethod, cls.basicmodule, 'SendObject', objecttype, objectname, outputformat, to, cc
866        , bcc, subject, messagetext, editmessage, templatefile)
867    @classmethod
868    def SetHiddenAttribute(cls, objecttype, objectname = '', hidden = True):
869        return cls.W(_vbMethod, cls.basicmodule, 'SetHiddenAttribute', objecttype, objectname, hidden)
870    @classmethod
871    def SetOrderBy(cls, orderby = '', controlname = ''):
872        return cls.W(_vbMethod, cls.basicmodule, 'SetOrderBy', orderby, controlname)
873    @classmethod
874    def ShowAllRecords(cls):
875        return cls.W(_vbMethod, cls.basicmodule, 'ShowAllRecords')
876
877
878class Basic(object, metaclass = _Singleton):
879    """ Collection of helper functions having the same behaviour as their Basic counterparts """
880    M = _A2B.invokeMethod
881
882    @classmethod
883    def ConvertFromUrl(cls, url):
884        return cls.M('PyConvertFromUrl', _WRAPPERMODULE, url)
885
886    @classmethod
887    def ConvertToUrl(cls, file):
888        return cls.M('PyConvertToUrl', _WRAPPERMODULE, file)
889
890    @classmethod
891    def CreateUnoService(cls, servicename):
892        return cls.M('PyCreateUnoService', _WRAPPERMODULE, servicename)
893
894    @classmethod
895    def DateAdd(cls, add, count, datearg):
896        if isinstance(datearg, datetime.datetime): datearg = datearg.isoformat()
897        dateadd = cls.M('PyDateAdd', _WRAPPERMODULE, add, count, datearg)
898        return datetime.datetime.strptime(dateadd, acConstants.FromIsoFormat)
899
900    @classmethod
901    def DateDiff(cls, add, date1, date2, weekstart = 1, yearstart = 1):
902        if isinstance(date1, datetime.datetime): date1 = date1.isoformat()
903        if isinstance(date2, datetime.datetime): date2 = date2.isoformat()
904        return cls.M('PyDateDiff', _WRAPPERMODULE, add, date1, date2, weekstart, yearstart)
905
906    @classmethod
907    def DatePart(cls, add, datearg, weekstart = 1, yearstart = 1):
908        if isinstance(datearg, datetime.datetime): datearg = datearg.isoformat()
909        return cls.M('PyDatePart', _WRAPPERMODULE, add, datearg, weekstart, yearstart)
910
911    @classmethod
912    def DateValue(cls, datestring):
913        datevalue = cls.M('PyDateValue', _WRAPPERMODULE, datestring)
914        return datetime.datetime.strptime(datevalue, acConstants.FromIsoFormat)
915
916    @classmethod
917    def Format(cls, value, format = None):
918        if isinstance(value, (datetime.datetime, datetime.date, datetime.time, )):
919            value = value.isoformat()
920        return cls.M('PyFormat', _WRAPPERMODULE, value, format)
921
922    @classmethod
923    def GetGUIType(cls):
924        return cls.M('PyGetGUIType', _WRAPPERMODULE)
925
926    @staticmethod
927    def GetPathSeparator():
928        return os.sep
929
930    @classmethod
931    def GetSystemTicks(cls):
932        return cls.M('PyGetSystemTicks', _WRAPPERMODULE)
933
934    @classmethod
935    def MsgBox(cls, text, type = None, dialogtitle = None):
936        return cls.M('PyMsgBox', _WRAPPERMODULE, text, type, dialogtitle)
937
938    class GlobalScope(object, metaclass = _Singleton):
939        @classmethod
940        def BasicLibraries(cls):
941            return Basic.M('PyGlobalScope', _WRAPPERMODULE, 'Basic')
942        @classmethod
943        def DialogLibraries(self):
944            return Basic.M('PyGlobalScope', _WRAPPERMODULE, 'Dialog')
945
946    @classmethod
947    def InputBox(cls, text, title = None, default = None, xpos = None, ypos = None):
948        return cls.M('PyInputBox', _WRAPPERMODULE, text, title, default, xpos, ypos)
949
950    @staticmethod
951    def Now():
952        return datetime.datetime.now()
953
954    @staticmethod
955    def RGB(red, green, blue):
956        return int('%02x%02x%02x' % (red, green, blue), 16)
957
958    @classmethod
959    def Timer(cls):
960        return cls.M('PyTimer', _WRAPPERMODULE)
961
962    @staticmethod
963    def Xray(myObject):
964        xrayscript = 'vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application'
965        xScript = SCRIPTPROVIDER.getScript(xrayscript)
966        xScript.invoke((myObject,), (), ())
967        return
968
969
970class _BasicObject(object):
971    """
972    Parent class of Basic objects
973    Each subclass is identified by its classProperties:
974         dictionary with keys = allowed properties, value = True if editable or False
975    Each instance is identified by its
976        - reference in the cache managed by Basic
977        - type ('DATABASE', 'COLLECTION', ...)
978        - name (form, control, ... name) - may be blank
979    Properties are got and set following next strategy:
980        1. Property names are controlled strictly ('Value' and not 'value')
981        2. Getting a property value for the first time is always done via a Basic call
982        3. Next occurrences are fetched from the Python dictionary of the instance if the property is read-only, otherwise via a Basic call
983        4. Methods output might force the deletion of a property from the dictionary ('MoveNext' changes 'BOF' and 'EOF' properties)
984        5. Setting a property value is done via a Basic call, except if self.internal == True
985    """
986    W = _A2B.invokeWrapper
987    internal_attributes = ('objectreference', 'objecttype', 'name', 'internal')
988
989    def __init__(self, reference = -1, objtype = None, name = ''):
990        self.objectreference = reference    # reference in the cache managed by Basic
991        self.objecttype = objtype           # ('DATABASE', 'COLLECTION', ...)
992        self.name = name                    # '' when no name
993        self.internal = False               # True to exceptionally allow assigning a new value to a read-only property
994        self.localProperties = ()
995
996    def __getattr__(self, name):
997        if name in ('classProperties', 'localProperties'):
998            pass
999        elif name in self.classProperties:
1000            # Get Property from Basic
1001            return self.W(_vbGet, self.objectreference, name)
1002        # Usual attributes getter
1003        return super(_BasicObject, self).__getattribute__(name)
1004
1005    def __setattr__(self, name, value):
1006        if name in ('classProperties', 'localProperties'):
1007            pass
1008        elif name in self.classProperties:
1009            if self.internal:       # internal = True forces property setting even if property is read-only
1010                pass
1011            elif self.classProperties[name] == True: # True == Editable
1012                self.W(_vbLet, self.objectreference, name, value)
1013            else:
1014                raise AttributeError("type object '" + self.objecttype + "' has no editable attribute '" + name + "'")
1015        elif name[0:2] == '__' or name in self.internal_attributes or name in self.localProperties:
1016            pass
1017        else:
1018            raise AttributeError("type object '" + self.objecttype + "' has no attribute '" + name + "'")
1019        object.__setattr__(self, name, value)
1020        return
1021
1022    def __repr__(self):
1023        repr = "Basic object (type='" + self.objecttype + "', index=" + str(self.objectreference)
1024        if len(self.name) > 0: repr += ", name='" + self.name + "'"
1025        return repr + ")"
1026
1027    def _Reset(self, propertyname, basicreturn = None):
1028        """ force new value or erase properties from dictionary (done to optimize calls to Basic scripts) """
1029        if propertyname in ('BOF', 'EOF'):
1030            # After a Move method invocation on a Recordset object, BOF or EOF likely to be got soon
1031            if isinstance(basicreturn, int):
1032                self.internal = True
1033                # f.i. basicreturn = 0b10 means: BOF = True, EOF = False
1034                self.BOF = basicreturn in (2, 3, -2, -3)
1035                self.EOF = basicreturn in (1, 3, -1, -3)
1036                self.internal = False
1037                return ( basicreturn >= 0 )
1038        else:
1039            # Suppress possibly invalid property values: e.g. RecordCount after Delete applied on Recordset object
1040            if property in self.__dict__:
1041                del(self.propertyname)
1042        return basicreturn
1043
1044    @property
1045    def Name(self): return self.name
1046    @property
1047    def ObjectType(self): return self.objecttype
1048
1049    def Dispose(self):
1050        return self.W(_vbMethod, self.objectreference, 'Dispose')
1051    def getProperty(self, propertyname, index = acConstants.Missing):
1052        return self.W(_vbMethod, self.objectreference, 'getProperty', propertyname, index)
1053    GetProperty = getProperty
1054    def hasProperty(self, propertyname):
1055        return propertyname in tuple(self.classProperties.keys())
1056    HasProperty = hasProperty
1057    def Properties(self, index = acConstants.Missing):
1058        return self.W(_vbMethod, self.objectreference, 'Properties', index)
1059    def setProperty(self, propertyname, value, index = acConstants.Missing):
1060        if self.hasProperty(propertyname):
1061            if self.W(_vbMethod, self.objectreference, 'setProperty', propertyname, value, index):
1062                return self.__setattr__(propertyname, value)
1063        raise AttributeError("type object '" + self.objecttype + "' has no editable attribute '" + propertyname + "'")
1064    SetProperty = setProperty
1065
1066
1067class _Collection(_BasicObject):
1068    """ Collection object built as a Python iterator """
1069    classProperties = dict(Count = False)
1070    def __init__(self, reference = -1, objtype = None):
1071        super().__init__(reference, objtype)
1072        self.localProperties = ('count', 'index')
1073        self.count = self.Count
1074        self.index = 0
1075    def __iter__(self):
1076        self.index = 0
1077        return self
1078    def __next__(self):
1079        if self.index >= self.count:
1080            raise StopIteration
1081        next = self.Item(self.index)
1082        self.index = self.index + 1
1083        return next
1084    def __len__(self):
1085        return self.count
1086
1087    def Add(self, table, value = acConstants.Missing):
1088        if isinstance(table, _BasicObject):     # Add method applied to a TABLEDEFS collection
1089            return self.W(_vbMethod, self.objectreference, 'Add', table.objectreference)
1090        else:                                   # Add method applied to a TEMPVARS collection
1091            add = self.W(_vbMethod, self.objectreference, 'Add', table, value)
1092            self.count = self.Count
1093            return add
1094    def Delete(self, name):
1095        return self.W(_vbMethod, self.objectreference, 'Delete', name)
1096    def Item(self, index):
1097        return self.W(_vbMethod, self.objectreference, 'Item', index)
1098    def Remove(self, tempvarname):
1099        remove = self.W(_vbMethod, self.objectreference, 'Remove', tempvarname)
1100        self.count = self.Count
1101        return remove
1102    def RemoveAll(self):
1103        remove = self.W(_vbMethod, self.objectreference, 'RemoveAll')
1104        self.count = self.Count
1105        return remove
1106
1107
1108class _CommandBar(_BasicObject):
1109    classProperties = dict(BuiltIn = False, Parent = False, Visible = True)
1110
1111    def CommandBarControls(self, index = acConstants.Missing):
1112        return self.W(_vbMethod, self.objectreference, 'CommandBarControls', index)
1113    def Reset(self):
1114        return self.W(_vbMethod, self.objectreference, 'Reset')
1115
1116
1117class _CommandBarControl(_BasicObject):
1118    classProperties = dict(BeginGroup = False, BuiltIn = False, Caption = True, Index = False, OnAction = True
1119                        , Parent = False, TooltipText = True, Type = False, Visible = True)
1120
1121    def Execute(self):
1122        return self.W(_vbMethod, self.objectreference, 'Execute')
1123
1124
1125class _Control(_BasicObject):
1126    classProperties = dict(BackColor = True, BorderColor = True, BorderStyle = True, Cancel = True, Caption = True
1127                        , ControlSource = False, ControlTipText = True, ControlType = False, Default = True
1128                        , DefaultValue = True, Enabled = True, FontBold = True, FontItalic = True, FontName = True
1129                        , FontSize = True, FontUnderline = True, FontWeight = True, ForeColor = True, Form = False
1130                        , Format = True, ItemData = False, ListCount = False, ListIndex = True, Locked = True, MultiSelect = True
1131                        , OnActionPerformed = True, OnAdjustmentValueChanged = True, OnApproveAction = True
1132                        , OnApproveReset = True, OnApproveUpdate = True, OnChanged = True, OnErrorOccurred = True
1133                        , OnFocusGained = True, OnFocusLost = True, OnItemStateChanged = True, OnKeyPressed = True
1134                        , OnKeyReleased = True, OnMouseDragged = True, OnMouseEntered = True, OnMouseExited = True
1135                        , OnMouseMoved = True, OnMousePressed = True, OnMouseReleased = True, OnResetted = True, OnTextChanged = True
1136                        , OnUpdated = True, OptionValue = False, Page = False, Parent = False, Picture = True, Required = True
1137                        , RowSource = True, RowSourceType = True, Selected = True, SelLength = True, SelStart = True, SelText = True
1138                        , SubType = False, TabIndex = True, TabStop = True, Tag = True, Text = False, TextAlign = True
1139                        , TripleState = True, Value = True, Visible = True
1140                        )
1141
1142    @property
1143    def BoundField(self): return self.W(_vbUNO, self.objectreference, 'BoundField')
1144    @property
1145    def ControlModel(self): return self.W(_vbUNO, self.objectreference, 'ControlModel')
1146    @property
1147    def ControlView(self): return self.W(_vbUNO, self.objectreference, 'ControlView')
1148    @property
1149    def LabelControl(self): return self.W(_vbUNO, self.objectreference, 'LabelControl')
1150
1151    def AddItem(self, value, index = -1):
1152        basicreturn = self.W(_vbMethod, self.objectreference, 'AddItem', value, index)
1153        self._Reset('ItemData')
1154        self._Reset('ListCount')
1155        return basicreturn
1156    def Controls(self, index = acConstants.Missing):
1157        return self.W(_vbMethod, self.objectreference, 'Controls', index)
1158    # Overrides method in parent class: list of properties is strongly control type dependent
1159    def hasProperty(self, propertyname):
1160        return self.W(_vbMethod, self.objectreference, 'hasProperty', propertyname)
1161    HasProperty = hasProperty
1162    def RemoveItem(self, index):
1163        basicreturn = self.W(_vbMethod, self.objectreference, 'RemoveItem', index)
1164        self._Reset('ItemData')
1165        self._Reset('ListCount')
1166        return basicreturn
1167    def Requery(self):
1168        return self.W(_vbMethod, self.objectreference, 'Requery')
1169    def SetSelected(self, value, index):
1170        return self.W(_vbMethod, self.objectreference, 'SetSelected', value, index)
1171    def SetFocus(self):
1172        return self.W(_vbMethod, self.objectreference, 'SetFocus')
1173
1174
1175class _Database(_BasicObject):
1176    classProperties = dict(Connect = False, OnCreate = True
1177                        , OnFocus = True, OnLoad = True, OnLoadFinished = True, OnModifyChanged = True, OnNew = True
1178                        , OnPrepareUnload = True, OnPrepareViewClosing = True, OnSave = True, OnSaveAs = True
1179                        , OnSaveAsDone = True, OnSaveAsFailed = True, OnSaveDone = True, OnSaveFailed = True
1180                        , OnSubComponentClosed = True, OnSubComponentOpened = True, OnTitleChanged = True, OnUnfocus = True
1181                        , OnUnload = True, OnViewClosed = True, OnViewCreated = True, Version = False
1182                        )
1183
1184    @property
1185    def Connection(self): return self.W(_vbUNO, self.objectreference, 'Connection')
1186    @property
1187    def Document(self): return self.W(_vbUNO, self.objectreference, 'Document')
1188    @property
1189    def MetaData(self): return self.W(_vbUNO, self.objectreference, 'MetaData')
1190
1191    def Close(self):
1192        return self.W(_vbMethod, self.objectreference, 'Close')
1193    def CloseAllRecordsets(self):
1194        return self.W(_vbMethod, self.objectreference, 'CloseAllRecordsets')
1195    def CreateQueryDef(self, name, sqltext, option = -1):
1196        return self.W(_vbMethod, self.objectreference, 'CreateQueryDef', name, sqltext, option)
1197    def CreateTableDef(self, name):
1198        return self.W(_vbMethod, self.objectreference, 'CreateTableDef', name)
1199    def DAvg(self, expression, domain, criteria = ''):
1200        return self.W(_vbMethod, self.objectreference, 'DAvg', expression, domain, criteria)
1201    def DCount(self, expression, domain, criteria = ''):
1202        return self.W(_vbMethod, self.objectreference, 'DCount', expression, domain, criteria)
1203    def DLookup(self, expression, domain, criteria = '', orderclause = ''):
1204        return self.W(_vbMethod, self.objectreference, 'DLookup', expression, domain, criteria, orderclause)
1205    def DMax(self, expression, domain, criteria = ''):
1206        return self.W(_vbMethod, self.objectreference, 'DMax', expression, domain, criteria)
1207    def DMin(self, expression, domain, criteria = ''):
1208        return self.W(_vbMethod, self.objectreference, 'DMin', expression, domain, criteria)
1209    def DStDev(self, expression, domain, criteria = ''):
1210        return self.W(_vbMethod, self.objectreference, 'DStDev', expression, domain, criteria)
1211    def DStDevP(self, expression, domain, criteria = ''):
1212        return self.W(_vbMethod, self.objectreference, 'DStDevP', expression, domain, criteria)
1213    def DVar(self, expression, domain, criteria = ''):
1214        return self.W(_vbMethod, self.objectreference, 'DVar', expression, domain, criteria)
1215    def DVarP(self, expression, domain, criteria = ''):
1216        return self.W(_vbMethod, self.objectreference, 'DVarP', expression, domain, criteria)
1217    def OpenRecordset(self, source, type = -1, option = -1, lockedit = -1):
1218        return self.W(_vbMethod, self.objectreference, 'OpenRecordset', source, type, option, lockedit)
1219    def OpenSQL(self, SQL, option = -1):
1220        return self.W(_vbMethod, self.objectreference, 'OpenSQL', SQL, option)
1221    def OutputTo(self, objecttype, objectname = '', outputformat = '', outputfile = '', autostart = False, templatefile = ''
1222        , encoding = acConstants.acUTF8Encoding, quality = acConstants.acExportQualityPrint):
1223        if objecttype == acConstants.acOutputForm: encoding = 0
1224        return self.W(_vbMethod, self.objectreference, 'OutputTo', objecttype, objectname, outputformat, outputfile
1225                      , autostart, templatefile, encoding, quality)
1226    def QueryDefs(self, index = acConstants.Missing):
1227        return self.W(_vbMethod, self.objectreference, 'QueryDefs', index)
1228    def Recordsets(self, index = acConstants.Missing):
1229        return self.W(_vbMethod, self.objectreference, 'Recordsets', index)
1230    def RunSQL(self, SQL, option = -1):
1231        return self.W(_vbMethod, self.objectreference, 'RunSQL', SQL, option)
1232    def TableDefs(self, index = acConstants.Missing):
1233        return self.W(_vbMethod, self.objectreference, 'TableDefs', index)
1234
1235
1236class _Dialog(_BasicObject):
1237    classProperties = dict(Caption = True, Height = True, IsLoaded = False, OnFocusGained = True
1238                        , OnFocusLost = True, OnKeyPressed = True, OnKeyReleased = True, OnMouseDragged = True
1239                        , OnMouseEntered = True, OnMouseExited = True, OnMouseMoved = True, OnMousePressed = True
1240                        , OnMouseReleased = True, Page = True, Parent = False, Visible = True, Width = True
1241                        )
1242
1243    @property
1244    def UnoDialog(self): return self.W(_vbUNO, self.objectreference, 'UnoDialog')
1245
1246    def EndExecute(self, returnvalue):
1247        return self.W(_vbMethod, self.objectreference, 'EndExecute', returnvalue)
1248    def Execute(self):
1249        return self.W(_vbMethod, self.objectreference, 'Execute')
1250    def Move(self, left = -1, top = -1, width = -1, height = -1):
1251        return self.W(_vbMethod, self.objectreference, 'Move', left, top, width, height)
1252    def OptionGroup(self, groupname):
1253        return self.W(_vbMethod, self.objectreference, 'OptionGroup', groupname)
1254    def Start(self):
1255        return self.W(_vbMethod, self.objectreference, 'Start')
1256    def Terminate(self):
1257        return self.W(_vbMethod, self.objectreference, 'Terminate')
1258
1259class _Event(_BasicObject):
1260    classProperties = dict(ButtonLeft = False, ButtonMiddle = False, ButtonRight = False, ClickCount = False
1261                    , ContextShortcut = False, EventName = False, EventType = False, FocusChangeTemporary = False
1262                    , KeyAlt = False, KeyChar = False, KeyCode = False, KeyCtrl = False, KeyFunction = False, KeyShift = False
1263                    , Recommendation = False, RowChangeAction = False, Source = False, SubComponentName = False
1264                    , SubComponentType = False, XPos = False, YPos = False
1265                    )
1266
1267
1268class _Field(_BasicObject):
1269    classProperties = dict(DataType = False, DataUpdatable = False, DbType = False, DefaultValue = True
1270                        , Description = True, FieldSize = False, Size = False, Source = False
1271                        , SourceField = False, SourceTable = False, TypeName = False, Value = True
1272                        )
1273
1274    @property
1275    def Column(self): return self.W(_vbUNO, self.objectreference, 'Column')
1276
1277    def AppendChunk(self, value):
1278        return self.W(_vbMethod, self.objectreference, 'AppendChunk', value)
1279    def GetChunk(self, offset, numbytes):
1280        return self.W(_vbMethod, self.objectreference, 'GetChunk', offset, numbytes)
1281    def ReadAllBytes(self, file):
1282        return self.W(_vbMethod, self.objectreference, 'ReadAllBytes', file)
1283    def ReadAllText(self, file):
1284        return self.W(_vbMethod, self.objectreference, 'ReadAllText', file)
1285    def WriteAllBytes(self, file):
1286        return self.W(_vbMethod, self.objectreference, 'WriteAllBytes', file)
1287    def WriteAllText(self, file):
1288        return self.W(_vbMethod, self.objectreference, 'WriteAllText', file)
1289
1290
1291class _Form(_BasicObject):
1292    classProperties = dict(AllowAdditions = True, AllowDeletions = True, AllowEdits = True, Bookmark = True
1293                        , Caption = True, CurrentRecord = True, Filter = True, FilterOn = True, Height = True
1294                        , IsLoaded = False, OnApproveCursorMove = True, OnApproveParameter = True, OnApproveReset = True
1295                        , OnApproveRowChange = True, OnApproveSubmit = True, OnConfirmDelete = True, OnCursorMoved = True
1296                        , OnErrorOccurred = True, OnLoaded = True, OnReloaded = True, OnReloading = True, OnResetted = True
1297                        , OnRowChanged = True, OnUnloaded = True, OnUnloading = True, OpenArgs = False, OrderBy = True
1298                        , OrderByOn = True, Parent = False, Recordset = False, RecordSource = True, Visible = True
1299                        , Width = True
1300                        )
1301
1302    @property
1303    def Component(self): return self.W(_vbUNO, self.objectreference, 'Component')
1304    @property
1305    def ContainerWindow(self): return self.W(_vbUNO, self.objectreference, 'ContainerWindow')
1306    @property
1307    def DatabaseForm(self): return self.W(_vbUNO, self.objectreference, 'DatabaseForm')
1308
1309    def Close(self):
1310        return self.W(_vbMethod, self.objectreference, 'Close')
1311    def Controls(self, index = acConstants.Missing):
1312        return self.W(_vbMethod, self.objectreference, 'Controls', index)
1313    def Move(self, left = -1, top = -1, width = -1, height = -1):
1314        return self.W(_vbMethod, self.objectreference, 'Move', left, top, width, height)
1315    def OptionGroup(self, groupname):
1316        return self.W(_vbMethod, self.objectreference, 'OptionGroup', groupname)
1317    def Refresh(self):
1318        return self.W(_vbMethod, self.objectreference, 'Refresh')
1319    def Requery(self):
1320        return self.W(_vbMethod, self.objectreference, 'Requery')
1321    def SetFocus(self):
1322        return self.W(_vbMethod, self.objectreference, 'SetFocus')
1323
1324
1325class _Module(_BasicObject):
1326    classProperties = dict(CountOfDeclarationLines = False, CountOfLines = False
1327                        , ProcStartLine = False, Type = False
1328                        )
1329    def __init__(self, reference = -1, objtype = None, name = ''):
1330        super().__init__(reference, objtype, name)
1331        self.localProperties = ('startline', 'startcolumn', 'endline', 'endcolumn', 'prockind')
1332
1333    def Find(self, target, startline, startcolumn, endline, endcolumn, wholeword = False
1334        , matchcase = False, patternsearch = False):
1335        Returned = self.W(_vbMethod, self.objectreference, 'Find', target, startline, startcolumn, endline
1336                      , endcolumn, wholeword, matchcase, patternsearch)
1337        if isinstance(Returned, tuple):
1338            if Returned[0] == True and len(Returned) == 5:
1339                self.startline = Returned[1]
1340                self.startcolumn = Returned[2]
1341                self.endline = Returned[3]
1342                self.endcolumn = Returned[4]
1343            return Returned[0]
1344        return Returned
1345    def Lines(self, line, numlines):
1346        return self.W(_vbMethod, self.objectreference, 'Lines', line, numlines)
1347    def ProcBodyLine(self, procname, prockind):
1348        return self.W(_vbMethod, self.objectreference, 'ProcBodyLine', procname, prockind)
1349    def ProcCountLines(self, procname, prockind):
1350        return self.W(_vbMethod, self.objectreference, 'ProcCountLines', procname, prockind)
1351    def ProcOfLine(self, line, prockind):
1352        Returned = self.W(_vbMethod, self.objectreference, 'ProcOfLine', line, prockind)
1353        if isinstance(Returned, tuple):
1354            if len(Returned) == 2:
1355                self.prockind = Returned[1]
1356                return Returned[0]
1357        return Returned
1358    def ProcStartLine(self, procname, prockind):
1359        return self.W(_vbMethod, self.objectreference, 'ProcStartLine', procname, prockind)
1360
1361
1362class _OptionGroup(_BasicObject):
1363    classProperties = dict(Count = False, Value = True)
1364
1365    def Controls(self, index = acConstants.Missing):
1366        return self.W(_vbMethod, self.objectreference, 'Controls', index)
1367
1368
1369class _Property(_BasicObject):
1370    classProperties = dict(Value = True)
1371
1372
1373class _QueryDef(_BasicObject):
1374    classProperties = dict(SQL = True, Type = False)
1375
1376    @property
1377    def Query(self): return self.W(_vbUNO, self.objectreference, 'Query')
1378
1379    def Execute(self, options = acConstants.Missing):
1380        return self.W(_vbMethod, self.objectreference, 'Execute', options)
1381    def Fields(self, index = acConstants.Missing):
1382        return self.W(_vbMethod, self.objectreference, 'Fields', index)
1383    def OpenRecordset(self, type = -1, option = -1, lockedit = -1):
1384        return self.W(_vbMethod, self.objectreference, 'OpenRecordset', type, option, lockedit)
1385
1386
1387class _Recordset(_BasicObject):
1388    classProperties = dict(AbsolutePosition = True, BOF = False, Bookmark = True, Bookmarkable = False
1389                        , EditMode = False, EOF = False, Filter = True, RecordCount = False
1390                        )
1391
1392    @property
1393    def RowSet(self): return self.W(_vbUNO, self.objectreference, 'RowSet')
1394
1395    def AddNew(self):
1396        return self.W(_vbMethod, self.objectreference, 'AddNew')
1397    def CancelUpdate(self):
1398        return self.W(_vbMethod, self.objectreference, 'CancelUpdate')
1399    def Clone(self):
1400        return self.W(_vbMethod, self.objectreference, 'Clone')
1401    def Close(self):
1402        return self.W(_vbMethod, self.objectreference, 'Close')
1403    def Delete(self):
1404        return self._Reset('RecordCount',self.W(_vbMethod, self.objectreference, 'Delete'))
1405    def Edit(self):
1406        return self.W(_vbMethod, self.objectreference, 'Edit')
1407    def Fields(self, index = acConstants.Missing):
1408        return self.W(_vbMethod, self.objectreference, 'Fields', index)
1409    def GetRows(self, numrows):
1410        return self.W(_vbMethod, self.objectreference, 'GetRows', numrows)
1411    def Move(self, rows, startbookmark = acConstants.Missing):
1412        return self._Reset('BOF', self.W(_vbMethod, self.objectreference, 'Move', rows, startbookmark))
1413    def MoveFirst(self):
1414        return self._Reset('BOF', self.W(_vbMethod, self.objectreference, 'MoveFirst'))
1415    def MoveLast(self):
1416        return self._Reset('BOF', self.W(_vbMethod, self.objectreference, 'MoveLast'))
1417    def MoveNext(self):
1418        return self._Reset('BOF', self.W(_vbMethod, self.objectreference, 'MoveNext'))
1419    def MovePrevious(self):
1420        return self._Reset('BOF', self.W(_vbMethod, self.objectreference, 'MovePrevious'))
1421    def OpenRecordset(self, type = -1, option = -1, lockedit = -1):
1422        return self.W(_vbMethod, self.objectreference, 'OpenRecordset', type, option, lockedit)
1423    def Update(self):
1424        return self._Reset('RecordCount',self.W(_vbMethod, self.objectreference, 'Update'))
1425
1426
1427class _SubForm(_Form):
1428    classProperties = dict(AllowAdditions = True, AllowDeletions = True, AllowEdits = True, CurrentRecord = True
1429                        , Filter = True, FilterOn = True, LinkChildFields = False, LinkMasterFields = False
1430                        , OnApproveCursorMove = True, OnApproveParameter = True, OnApproveReset = True
1431                        , OnApproveRowChange = True, OnApproveSubmit = True, OnConfirmDelete = True, OnCursorMoved = True
1432                        , OnErrorOccurred = True, OnLoaded = True, OnReloaded = True, OnReloading = True, OnResetted = True
1433                        , OnRowChanged = True, OnUnloaded = True, OnUnloading = True, OrderBy = True
1434                        , OrderByOn = True, Parent = False, Recordset = False, RecordSource = True, Visible = True
1435                        )
1436
1437    def SetFocus(self):
1438        raise AttributeError("type object 'SubForm' has no method 'SetFocus'")
1439
1440
1441class _TableDef(_BasicObject):
1442    classProperties = dict()
1443
1444    @property
1445    def Table(self): return self.W(_vbUNO, self.objectreference, 'Table')
1446
1447    def CreateField(self, name, type, size = 0, attributes = 0):
1448        return self.W(_vbMethod, self.objectreference, 'CreateField', name, type, size, attributes)
1449    def Fields(self, index = acConstants.Missing):
1450        return self.W(_vbMethod, self.objectreference, 'Fields', index)
1451    def OpenRecordset(self, type = -1, option = -1, lockedit = -1):
1452        return self.W(_vbMethod, self.objectreference, 'OpenRecordset', type, option, lockedit)
1453
1454
1455class _TempVar(_BasicObject):
1456    classProperties = dict(Value = True)
1457
1458"""
1459Set of directly callable error handling methods
1460"""
1461def DebugPrint(*args):
1462    dargs = ()
1463    for arg in args:
1464        if isinstance(arg, _BasicObject):
1465            arg = ('[' + arg.objecttype + '] ' + arg.name).rstrip()
1466        dargs = dargs + (arg,)
1467    return _A2B.invokeMethod('DebugPrint', _WRAPPERMODULE, *dargs)
1468def TraceConsole(): return _A2B.invokeMethod('TraceConsole', 'Trace')
1469def TraceError(tracelevel, errorcode, errorprocedure, errorline):
1470    return _A2B.invokeMethod('TraceError', 'Trace', tracelevel, errorcode, errorprocedure, errorline)
1471def TraceLevel(newtracelevel = 'ERROR'): return _A2B.invokeMethod('TraceLevel', 'Trace', newtracelevel)
1472def TraceLog(tracelevel, text, messagebox = True):
1473    return _A2B.invokeMethod('TraceLog', 'Trace', tracelevel, text, messagebox)
1474
1475