wizards/Package_sfdatabases.mk                   |    1 
 wizards/source/scriptforge/SF_Services.xba       |    2 
 wizards/source/scriptforge/SF_UI.xba             |   31 
 wizards/source/scriptforge/python/scriptforge.py |  117 ++-
 wizards/source/sfdatabases/SF_Database.xba       |  189 +++++
 wizards/source/sfdatabases/SF_Datasheet.xba      |  744 +++++++++++++++++++++++
 wizards/source/sfdatabases/SF_Register.xba       |   58 +
 wizards/source/sfdatabases/script.xlb            |    1 
 wizards/source/sfdialogs/SF_Dialog.xba           |    4 
 wizards/source/sfdocuments/SF_Base.xba           |  107 +++
 wizards/source/sfdocuments/SF_Calc.xba           |   50 -
 wizards/source/sfdocuments/SF_Document.xba       |    4 
 12 files changed, 1232 insertions(+), 76 deletions(-)

New commits:
commit 985c77b570807dcc558ccff4a51430fe489b68fd
Author:     Jean-Pierre Ledure <j...@ledure.be>
AuthorDate: Tue Nov 1 17:27:21 2022 +0100
Commit:     Jean-Pierre Ledure <j...@ledure.be>
CommitDate: Wed Nov 2 11:26:46 2022 +0100

    ScriptForge = (SFDatabases) New Datasheet service
    
    A datasheet is the visual representation
    of tabular data produced by a database.
    In the user interface of LibreOffice
    it is the result of the opening of a table or a query.
    In this case the concerned Base document must be open.
    
    In the context of ScriptForge, a datasheet
    may be opened automatically by script code :
    - either by reproducing the behaviour of the user interface
    - or at any moment.
      In this case the Base document does not need to be open.
    Additionally, any SELECT SQL statement
    may define the datasheet display.
    
    The proposed API allows for either datasheets
    (opened manually of by code) in particular
    to know which cell is selected and its content.
    
    Properties:
      ColumnHeaders
      CurrentColumn
      CurrentRow
      LastRow
      Source
      SourceType
      XComponent
      XControlModel
      XTabControllerModel
    
    Methods
      Activate
      ApplyFilter
      CloseDatasheet
      GetValue
      GetText
      GoToCell
      OrderBy
    
    The Base and Database services are enriched with the
      OpenTable
      OpenQuery
    methods. The Database service gets also a new
      OpenSql
    method.
    
    The whole set of properties and methods is available
    both for Basic and Python scripts.
    
    This new service requires a new help page dedicated
    to this service, as well as an update of the
    pages about the Base and Database services.
    
    Change-Id: Ib409ce74d95de78f2792ba53e7ae554eab0867ab
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142118
    Tested-by: Jenkins
    Reviewed-by: Jean-Pierre Ledure <j...@ledure.be>

diff --git a/wizards/Package_sfdatabases.mk b/wizards/Package_sfdatabases.mk
index 81fc55750291..bc5636fa1b2f 100644
--- a/wizards/Package_sfdatabases.mk
+++ b/wizards/Package_sfdatabases.mk
@@ -21,6 +21,7 @@ $(eval $(call 
gb_Package_Package,wizards_basicsrvsfdatabases,$(SRCDIR)/wizards/s
 
 $(eval $(call 
gb_Package_add_files,wizards_basicsrvsfdatabases,$(LIBO_SHARE_FOLDER)/basic/SFDatabases,\
        SF_Database.xba \
+       SF_Datasheet.xba \
        SF_Register.xba \
        __License.xba \
        dialog.xlb \
diff --git a/wizards/source/scriptforge/SF_Services.xba 
b/wizards/source/scriptforge/SF_Services.xba
index 627dc4d2e8fe..b72298ea3046 100644
--- a/wizards/source/scriptforge/SF_Services.xba
+++ b/wizards/source/scriptforge/SF_Services.xba
@@ -129,7 +129,7 @@ Try:
                        Case &quot;document&quot;, &quot;calc&quot;, 
&quot;writer&quot;, &quot;base&quot;, &quot;documentevent&quot;, 
&quot;formevent&quot;
                                                                                
                                sLibrary = &quot;SFDocuments&quot;
                        Case &quot;dialog&quot;, &quot;dialogevent&quot;        
                :       sLibrary = &quot;SFDialogs&quot;
-                       Case &quot;database&quot;                               
                        :       sLibrary = &quot;SFDatabases&quot;
+                       Case &quot;database&quot;, &quot;datasheet&quot;        
                :       sLibrary = &quot;SFDatabases&quot;
                        Case &quot;unittest&quot;                               
                        :       sLibrary = &quot;SFUnitTests&quot;
                        Case &quot;menu&quot;, &quot;popupmenu&quot;            
                :       sLibrary = &quot;SFWidgets&quot;
                        Case Else
diff --git a/wizards/source/scriptforge/SF_UI.xba 
b/wizards/source/scriptforge/SF_UI.xba
index c8a7f9a8f861..e64011b9ed78 100644
--- a/wizards/source/scriptforge/SF_UI.xba
+++ b/wizards/source/scriptforge/SF_UI.xba
@@ -53,6 +53,7 @@ Type Window
        WindowTitle                             As String               &apos;  
Only mean to identify new documents
        WindowFileName                  As String               &apos;  URL of 
file name
        DocumentType                    As String               &apos;  Writer, 
Calc, ...
+       ParentName                              As String               &apos;  
Identifier of the parent Base file when Window is a subcomponent
 End Type
 
 &apos; The progress/status bar of the active window
@@ -72,11 +73,12 @@ Const IMPRESSDOCUMENT                       = 
&quot;Impress&quot;
 Const MATHDOCUMENT                             = &quot;Math&quot;
 Const WRITERDOCUMENT                   = &quot;Writer&quot;
 
-&apos; Window subtypes - Not supported yet
-Const BASETABLE                                        = &quot;BASETABLE&quot;
-Const BASEQUERY                                        = &quot;BASEQUERY&quot;
-Const BASEREPORT                               = &quot;BASEREPORT&quot;
-Const BASEDIAGRAM                              = &quot;BASEDIAGRAM&quot;
+&apos; Window subtypes
+Const TABLEDATA                                        = &quot;TableData&quot;
+Const QUERYDATA                                        = &quot;QueryData&quot;
+Const SQLDATA                                  = &quot;SqlData&quot;
+Const BASEREPORT                               = &quot;BaseReport&quot;
+Const BASEDIAGRAM                              = &quot;BaseDiaram&quot;
 
 &apos; Macro execution modes
 Const cstMACROEXECNORMAL               = 0             &apos;  Default, 
execution depends on user configuration and choice
@@ -1246,7 +1248,8 @@ Public Function _IdentifyWindow(ByRef poComponent As 
Object) As Object
 Dim oWindow As Window                          &apos;  Return value
 Dim sImplementation As String          &apos;  Component&apos;s 
implementationname
 Dim sIdentifier As String                      &apos;  Component&apos;s 
identifier
-Dim vArg As Variant                                    &apos;  One single item 
of the Args UNO property
+Dim vSelection As Variant                      &apos;  Array of 
poCOmponent.Selection property values
+Dim iCommandType As Integer                    &apos;  Datasheet type
 Dim FSO As Object                                      &apos;  Alias for 
SF_FileSystem
 
        If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
@@ -1261,6 +1264,7 @@ Dim FSO As Object                                 &apos;  
Alias for SF_FileSystem
                .WindowTitle = &quot;&quot;
                .WindowFileName = &quot;&quot;
                .DocumentType = &quot;&quot;
+               .ParentName = &quot;&quot;
                If IsNull(poComponent) Then GoTo Finally
                If SF_Session.HasUnoProperty(poComponent, 
&quot;ImplementationName&quot;) Then sImplementation = 
poComponent.ImplementationName
                If SF_Session.HasUnoProperty(poComponent, 
&quot;Identifier&quot;) Then sIdentifier = poComponent.Identifier
@@ -1272,7 +1276,20 @@ Dim FSO As Object                                        
&apos;  Alias for SF_FileSystem
                                .WindowFileName = 
SF_Utils._GetPropertyValue(poComponent.Args, &quot;URL&quot;)
                                If Len(.WindowFileName) &gt; 0 Then .WindowName 
= FSO.GetName(FSO._ConvertFromUrl(.WindowFileName))
                                .DocumentType = BASEDOCUMENT
-                       Case 
&quot;org.openoffice.comp.dbu.ODatasourceBrowser&quot;
+                       Case 
&quot;org.openoffice.comp.dbu.ODatasourceBrowser&quot;             &apos;  Base 
datasheet (table, query or sql in read mode
+                               Set .Frame = poComponent.Frame
+                               If Not IsEmpty(poComponent.Selection) Then      
        &apos;  Empty for (F4) DatasourceBrowser !!
+                                       vSelection = poComponent.Selection
+                                       .WindowName = 
SF_Utils._GetPropertyValue(vSelection, &quot;Command&quot;)
+                                       iCommandType = 
SF_Utils._GetPropertyValue(vSelection, &quot;CommandType&quot;)
+                                       Select Case iCommandType
+                                               Case 
com.sun.star.sdb.CommandType.TABLE         :       .DocumentType = TABLEDATA
+                                               Case 
com.sun.star.sdb.CommandType.QUERY         :       .DocumentType = QUERYDATA
+                                               Case 
com.sun.star.sdb.CommandType.COMMAND       :       .DocumentType = SQLDATA
+                                       End Select
+                                       .ParentName = 
SF_Utils._GetPropertyValue(vSelection, &quot;DataSourceName&quot;)
+                                       .WindowTitle = .WindowName
+                               End If
                        Case &quot;org.openoffice.comp.dbu.OTableDesign&quot;, 
&quot;org.openoffice.comp.dbu.OQueryDesign&quot;                 &apos;  Table 
or Query in Edit mode
                        Case &quot;org.openoffice.comp.dbu.ORelationDesign&quot;
                        Case &quot;com.sun.star.comp.sfx2.BackingComp&quot;     
                        &apos;          Welcome screen
diff --git a/wizards/source/scriptforge/python/scriptforge.py 
b/wizards/source/scriptforge/python/scriptforge.py
index c05d5349f0b4..940c355f1e44 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -224,7 +224,7 @@ class ScriptForge(object, metaclass = _Singleton):
                 scope, script = script.split('#')
             if '.py$' in script.lower():  # Python
                 if len(scope) == 0:
-                    scope = 'share'     # Default for Python
+                    scope = 'share'  # Default for Python
                 # Provide an alternate helper script depending on test context
                 if script.startswith(cls.pythonhelpermodule) and hasattr(cls, 
'pythonhelpermodule2'):
                     script = cls.pythonhelpermodule2 + 
script[len(cls.pythonhelpermodule):]
@@ -233,10 +233,10 @@ class ScriptForge(object, metaclass = _Singleton):
                 uri = 
'vnd.sun.star.script:{0}?language=Python&location={1}'.format(script, scope)
             else:  # Basic
                 if len(scope) == 0:
-                    scope = 'application'     # Default for Basic
+                    scope = 'application'  # Default for Basic
                 lib = ''
                 if len(script.split('.')) < 3:
-                    lib = cls.library + '.'     # Default library = ScriptForge
+                    lib = cls.library + '.'  # Default library = ScriptForge
                 uri = 
'vnd.sun.star.script:{0}{1}?language=Basic&location={2}'.format(lib, script, 
scope)
             # Get the script object
             fullscript = ('@' if paramarray else '') + scope + ':' + script
@@ -327,7 +327,7 @@ class ScriptForge(object, metaclass = _Singleton):
         elif returntuple[cstVarType] == ScriptForge.V_DATE:
             dat = 
SFScriptForge.SF_Basic.CDateFromUnoDateTime(returntuple[cstValue])
             return dat
-        else:         # All other scalar values
+        else:  # All other scalar values
             pass
         return returntuple[cstValue]
 
@@ -347,6 +347,7 @@ class ScriptForge(object, metaclass = _Singleton):
                         # etc ...
                     copyFile, copyfile = CopyFile, CopyFile
             """
+
         def camelCase(key):
             return key[0].lower() + key[1:]
 
@@ -354,8 +355,8 @@ class ScriptForge(object, metaclass = _Singleton):
             # Synonyms of properties
             if hasattr(cls, 'serviceproperties'):
                 dico = cls.serviceproperties
-                dicosyn = dict(zip(map(str.lower, dico.keys()), dico.keys()))  
 # lower case
-                cc = dict(zip(map(camelCase, dico.keys()), dico.keys()))       
 # camel Case
+                dicosyn = dict(zip(map(str.lower, dico.keys()), dico.keys()))  
# lower case
+                cc = dict(zip(map(camelCase, dico.keys()), dico.keys()))  # 
camel Case
                 dicosyn.update(cc)
                 setattr(cls, 'propertysynonyms', dicosyn)
             # Synonyms of methods. A method is a public callable attribute
@@ -448,7 +449,7 @@ class SFServices(object):
         """
     # Python-Basic protocol constants and flags
     vbGet, vbLet, vbMethod, vbSet = 2, 4, 1, 8  # CallByName constants
-    flgPost = 32    # The method or the property implies a hardcoded 
post-processing
+    flgPost = 32  # The method or the property implies a hardcoded 
post-processing
     flgDateArg = 64  # Invoked service method may contain a date argument
     flgDateRet = 128  # Invoked service method can return a date
     flgArrayArg = 512  # 1st argument can be a 2D array
@@ -506,7 +507,7 @@ class SFServices(object):
                         prop = self.GetProperty(name)
                         self.__dict__[name] = prop
                         return prop
-                else:   # Get Property from Basic and do not store it
+                else:  # Get Property from Basic and do not store it
                     return self.GetProperty(name)
         # Execute the usual attributes getter
         return super(SFServices, self).__getattribute__(name)
@@ -545,7 +546,7 @@ class SFServices(object):
 
     def Dispose(self):
         if self.serviceimplementation == 'basic':
-            if self.objectreference >= len(ScriptForge.servicesmodules):    # 
Do not dispose predefined module objects
+            if self.objectreference >= len(ScriptForge.servicesmodules):  # Do 
not dispose predefined module objects
                 self.ExecMethod(self.vbMethod, 'Dispose')
                 self.objectreference = -1
 
@@ -564,7 +565,7 @@ class SFServices(object):
             calltype = self.vbGet + (self.flgUno if propertyname[0] == 'X' 
else 0)
             if arg is None:
                 return self.EXEC(self.objectreference, calltype, propertyname)
-            else:   # There are a few cases (Calc ...) where GetProperty 
accepts an argument
+            else:  # There are a few cases (Calc ...) where GetProperty 
accepts an argument
                 return self.EXEC(self.objectreference, calltype, propertyname, 
arg)
         return None
 
@@ -667,7 +668,7 @@ class SFScriptForge:
                 :param unodate: com.sun.star.util.DateTime, 
com.sun.star.util.Date or com.sun.star.util.Time
                 :return: the equivalent datetime.datetime
                 """
-            date = datetime.datetime(1899, 12, 30, 0, 0, 0, 0)      # Idem as 
Basic builtin TimeSeria() function
+            date = datetime.datetime(1899, 12, 30, 0, 0, 0, 0)  # Idem as 
Basic builtin TimeSeria() function
             datetype = repr(type(unodate))
             if 'com.sun.star.util.DateTime' in datetype:
                 if 1900 <= unodate.Year <= datetime.MAXYEAR:
@@ -693,16 +694,16 @@ class SFScriptForge:
                 """
             unodate = uno.createUnoStruct('com.sun.star.util.DateTime')
             unodate.Year, unodate.Month, unodate.Day, unodate.Hours, 
unodate.Minutes, unodate.Seconds, \
-                unodate.NanoSeconds, unodate.IsUTC = \
-                1899, 12, 30, 0, 0, 0, 0, False    # Identical to Basic 
TimeSerial() function
+            unodate.NanoSeconds, unodate.IsUTC = \
+                1899, 12, 30, 0, 0, 0, 0, False  # Identical to Basic 
TimeSerial() function
 
             if isinstance(date, float):
                 date = time.localtime(date)
             if isinstance(date, time.struct_time):
                 if 1900 <= date[0] <= 32767:
-                    unodate.Year, unodate.Month, unodate.Day, unodate.Hours, 
unodate.Minutes, unodate.Seconds =\
+                    unodate.Year, unodate.Month, unodate.Day, unodate.Hours, 
unodate.Minutes, unodate.Seconds = \
                         date[0:6]
-                else:   # Copy only the time related part
+                else:  # Copy only the time related part
                     unodate.Hours, unodate.Minutes, unodate.Seconds = date[3:3]
             elif isinstance(date, (datetime.datetime, datetime.date, 
datetime.time)):
                 if isinstance(date, (datetime.datetime, datetime.date)):
@@ -712,7 +713,7 @@ class SFScriptForge:
                     unodate.Hours, unodate.Minutes, unodate.Seconds, 
unodate.NanoSeconds = \
                         date.hour, date.minute, date.second, date.microsecond 
* 1000
             else:
-                return date     # Not recognized as a date
+                return date  # Not recognized as a date
             return unodate
 
         @classmethod
@@ -817,6 +818,7 @@ class SFScriptForge:
             DESK = 'com.sun.star.frame.Desktop'
             desktop = smgr.createInstanceWithContext(DESK, ctx)
             return desktop
+
         starDesktop, stardesktop = StarDesktop, StarDesktop
 
         @property
@@ -832,8 +834,9 @@ class SFScriptForge:
                 return None
             impl = comp.ImplementationName
             if impl in ('com.sun.star.comp.basic.BasicIDE', 
'com.sun.star.comp.sfx2.BackingComp'):
-                return None     # None when Basic IDE or welcome screen
+                return None  # None when Basic IDE or welcome screen
             return comp
+
         thisComponent, thiscomponent = ThisComponent, ThisComponent
 
         @property
@@ -844,7 +847,7 @@ class SFScriptForge:
                 Above behaviour cannot be reproduced in Python.
                 :return: the current Base (main) component or None when not a 
Base document or one of its subcomponents
             """
-            comp = self.ThisComponent   # Get the current component
+            comp = self.ThisComponent  # Get the current component
             if comp is None:
                 return None
             #
@@ -869,6 +872,7 @@ class SFScriptForge:
                     if db.ImplementationName == targetimpl:
                         return db
             return None
+
         thisDatabaseDocument, thisdatabasedocument = ThisDatabaseDocument, 
ThisDatabaseDocument
 
         @classmethod
@@ -1055,7 +1059,7 @@ class SFScriptForge:
             # Direct call because RaiseFatal forces an execution stop in Basic
             if len(args) == 0:
                 args = (None,)
-            return cls.SIMPLEEXEC('@SF_Exception.RaiseFatal', (errorcode, 
*args))   # With ParamArray
+            return cls.SIMPLEEXEC('@SF_Exception.RaiseFatal', (errorcode, 
*args))  # With ParamArray
 
         @classmethod
         def _RaiseFatal(cls, sub, subargs, errorcode, *args):
@@ -1221,11 +1225,12 @@ class SFScriptForge:
             dialogobj = dialog.objectreference if isinstance(dialog, 
SFDialogs.SF_Dialog) else dialog
             return self.ExecMethod(self.vbMethod + self.flgObject, 
'AddTextsFromDialog', dialogobj)
 
-        def ExportToPOTFile(self, filename, header = '', encoding= 'UTF-8'):
+        def ExportToPOTFile(self, filename, header = '', encoding = 'UTF-8'):
             return self.ExecMethod(self.vbMethod, 'ExportToPOTFile', filename, 
header, encoding)
 
         def GetText(self, msgid, *args):
             return self.ExecMethod(self.vbMethod, 'GetText', msgid, *args)
+
         _ = GetText
 
     # #########################################################################
@@ -1409,13 +1414,13 @@ class SFScriptForge:
         serviceproperties = dict()
 
         # Class constants                       Where to find an invoked 
library ?
-        SCRIPTISEMBEDDED = 'document'           # in the document
-        SCRIPTISAPPLICATION = 'application'     # in any shared library (Basic)
-        SCRIPTISPERSONAL = 'user'               # in My Macros (Python)
-        SCRIPTISPERSOXT = 'user:uno_packages'   # in an extension installed 
for the current user (Python)
-        SCRIPTISSHARED = 'share'                # in LibreOffice macros 
(Python)
+        SCRIPTISEMBEDDED = 'document'  # in the document
+        SCRIPTISAPPLICATION = 'application'  # in any shared library (Basic)
+        SCRIPTISPERSONAL = 'user'  # in My Macros (Python)
+        SCRIPTISPERSOXT = 'user:uno_packages'  # in an extension installed for 
the current user (Python)
+        SCRIPTISSHARED = 'share'  # in LibreOffice macros (Python)
         SCRIPTISSHAROXT = 'share:uno_packages'  # in an extension installed 
for all users (Python)
-        SCRIPTISOXT = 'uno_packages'            # in an extension but the 
installation parameters are unknown (Python)
+        SCRIPTISOXT = 'uno_packages'  # in an extension but the installation 
parameters are unknown (Python)
 
         @classmethod
         def ExecuteBasicScript(cls, scope = '', script = '', *args):
@@ -1539,11 +1544,13 @@ class SFScriptForge:
         @property
         def AtEndOfStream(self):
             return self.GetProperty('AtEndOfStream')
+
         atEndOfStream, atendofstream = AtEndOfStream, AtEndOfStream
 
         @property
         def Line(self):
             return self.GetProperty('Line')
+
         line = Line
 
         def CloseFile(self):
@@ -1629,6 +1636,7 @@ class SFScriptForge:
         @property
         def ActiveWindow(self):
             return self.ExecMethod(self.vbMethod, 'ActiveWindow')
+
         activeWindow, activewindow = ActiveWindow, ActiveWindow
 
         def Activate(self, windowname = ''):
@@ -1743,9 +1751,57 @@ class SFDatabases:
         def GetRows(self, sqlcommand, directsql = False, header = False, 
maxrows = 0):
             return self.ExecMethod(self.vbMethod + self.flgArrayRet, 
'GetRows', sqlcommand, directsql, header, maxrows)
 
+        def OpenQuery(self, queryname):
+            return self.ExecMethod(self.vbMethod, 'OpenQuery', queryname)
+
+        def OpenSql(self, sql, directsql = False):
+            return self.ExecMethod(self.vbMethod, 'OpenSql', sql, directsql)
+
+        def OpenTable(self, tablename):
+            return self.ExecMethod(self.vbMethod, 'OpenTable', tablename)
+
         def RunSql(self, sqlcommand, directsql = False):
             return self.ExecMethod(self.vbMethod, 'RunSql', sqlcommand, 
directsql)
 
+    # #########################################################################
+    # SF_Datasheet CLASS
+    # #########################################################################
+    class SF_Datasheet(SFServices):
+        """
+            A datasheet is the visual representation of tabular data produced 
by a database.
+            A datasheet may be opened automatically by script code at any 
moment.
+            The Base document owning the data may or may not be opened.
+            Any SELECT SQL statement may trigger the datasheet display.
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDatabases.Datasheet'
+        servicesynonyms = ('datasheet', 'sfdatabases.datasheet')
+        serviceproperties = dict(ColumnHeaders = False, CurrentColumn = False, 
CurrentRow = False, LastRow = False,
+                                 SOurce = False, SourceType = False, 
XComponent = False, XControlModel = False,
+                                 XTabControllerModel = False)
+
+        def Activate(self):
+            return self.ExecMethod(self.vbMethod, 'Activate')
+
+        def ApplyFilter(self, filter = ''):
+            return self.ExecMethod(self.vbMethod, 'ApplyFilter', filter)
+
+        def CloseDatasheet(self):
+            return self.ExecMethod(self.vbMethod, 'CloseDatasheet')
+
+        def GetText(self, column = 0):
+            return self.ExecMethod(self.vbMethod, 'GetText', column)
+
+        def GetValue(self, column = 0):
+            return self.ExecMethod(self.vbMethod, 'GetValue', column)
+
+        def GoToCell(self, row = 0, column = 0):
+            return self.ExecMethod(self.vbMethod, 'GoToCell', row, column)
+
+        def OrderBy(self, order = ''):
+            return self.ExecMethod(self.vbMethod, 'OrderBy', order)
+
 
 # 
#####################################################################################################################
 #                       SFDialogs CLASS    (alias of SFDialogs Basic library)  
                                     ###
@@ -1799,7 +1855,7 @@ class SFDialogs:
 
         def Center(self, parent = ScriptForge.cstSymMissing):
             parentclasses = (SFDocuments.SF_Document, SFDocuments.SF_Base, 
SFDocuments.SF_Calc, SFDocuments.SF_Writer,
-                                                          SFDialogs.SF_Dialog)
+                             SFDialogs.SF_Dialog)
             parentobj = parent.objectreference if isinstance(parent, 
parentclasses) else parent
             return self.ExecMethod(self.vbMethod + self.flgObject + 
self.flgHardCode, 'Center', parentobj)
 
@@ -2004,6 +2060,12 @@ class SFDocuments:
         def OpenFormDocument(self, formdocument, designmode = False):
             return self.ExecMethod(self.vbMethod, 'OpenFormDocument', 
formdocument, designmode)
 
+        def OpenQuery(self, queryname):
+            return self.ExecMethod(self.vbMethod, 'OpenQuery', queryname)
+
+        def OpenTable(self, tablename):
+            return self.ExecMethod(self.vbMethod, 'OpenTable', tablename)
+
         def PrintOut(self, formdocument, pages = '', copies = 1):
             return self.ExecMethod(self.vbMethod, 'PrintOut', formdocument, 
pages, copies)
 
@@ -2546,7 +2608,6 @@ def CreateScriptService(service, *args, **kwargs):
 
 createScriptService, createscriptservice = CreateScriptService, 
CreateScriptService
 
-
 # ######################################################################
 # Lists the scripts, that shall be visible inside the Basic/Python IDE
 # ######################################################################
diff --git a/wizards/source/sfdatabases/SF_Database.xba 
b/wizards/source/sfdatabases/SF_Database.xba
index 804084aff28e..6994f791a433 100644
--- a/wizards/source/sfdatabases/SF_Database.xba
+++ b/wizards/source/sfdatabases/SF_Database.xba
@@ -13,7 +13,7 @@ Option Explicit
 
 
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
 &apos;&apos;&apos;     SF_Database
-&apos;&apos;&apos;     =========
+&apos;&apos;&apos;     ===========
 &apos;&apos;&apos;             Management of databases embedded in or related 
to Base documents
 &apos;&apos;&apos;             Each instance of the current class represents a 
single database, with essentially its tables, queries and data
 &apos;&apos;&apos;
@@ -27,7 +27,7 @@ Option Explicit
 &apos;&apos;&apos;
 &apos;&apos;&apos;             Service invocation and usage:
 &apos;&apos;&apos;             1) To access any database at anytime
-&apos;&apos;&apos;                     Dim myDatabase As Object
+&apos;&apos;&apos;                             Dim myDatabase As Object
 &apos;&apos;&apos;                             Set myDatabase = 
CreateScriptService(&quot;SFDatabases.Database&quot;, FileName, , [ReadOnly], 
[User, [Password]])
 &apos;&apos;&apos;                                     &apos;  Args:
 &apos;&apos;&apos;                                     &apos;          
FileName:       the name of the Base file compliant with the 
SF_FileSystem.FileNaming notation
@@ -38,7 +38,7 @@ Option Explicit
 &apos;&apos;&apos;                             myDatabase.CloseDatabase()
 &apos;&apos;&apos;
 &apos;&apos;&apos;             2) To access the database related to the 
current Base document
-&apos;&apos;&apos;                     Dim myDoc As Object, myDatabase As 
Object, ui As Object
+&apos;&apos;&apos;                             Dim myDoc As Object, myDatabase 
As Object, ui As Object
 &apos;&apos;&apos;                             Set ui = 
CreateScriptService(&quot;UI&quot;)
 &apos;&apos;&apos;                             Set myDoc = 
ui.OpenBaseDocument(&quot;myDb.odb&quot;)
 &apos;&apos;&apos;                             Set myDatabase = 
myDoc.GetDatabase()    &apos;  user and password are supplied here, if needed
@@ -401,11 +401,127 @@ Public Function Methods() As Variant
                                        , &quot;DMin&quot; _
                                        , &quot;DSum&quot; _
                                        , &quot;GetRows&quot; _
+                                       , &quot;OpenQuery&quot; _
+                                       , &quot;OpenSql&quot; _
+                                       , &quot;OpenTable&quot; _
                                        , &quot;RunSql&quot; _
                                        )
 
 End Function   &apos;  SFDatabases.SF_Database.Methods
 
+REM 
-----------------------------------------------------------------------------
+Public Function OpenQuery(Optional ByVal QueryName As Variant) As Object
+&apos;&apos;&apos;     Open the query given by its name
+&apos;&apos;&apos;     The datasheet will live independently from any other 
(typically Base) component
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             QueryName: a valid query name as a 
case-sensitive string
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A Datasheet class instance if the query could 
be opened, otherwise Nothing
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             Query name is invalid
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             oDb.OpenQuery(&quot;myQuery&quot;)
+
+Dim oOpen As Object                            &apos;  Return value
+Const cstThisSub = &quot;SFDatabases.Database.OpenQuery&quot;
+Const cstSubArgs = &quot;QueryName&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oOpen = Nothing
+
+Check:
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(QueryName, 
&quot;QueryName&quot;, V_STRING, Queries) Then GoTo Finally
+       End If
+
+Try:
+       Set oOpen = _OpenDatasheet(QueryName, 
com.sun.star.sdb.CommandType.QUERY _
+                                               , 
_Connection.Queries.getByName(QueryName).EscapeProcessing)
+
+Finally:
+       Set OpenQuery = oOpen
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDocuments.SF_Base.OpenQuery
+
+REM 
-----------------------------------------------------------------------------
+Public Function OpenSql(Optional ByRef Sql As Variant _
+                                                       , Optional ByVal 
DirectSql As Variant _
+                                                       ) As Object
+&apos;&apos;&apos;     Open the datasheet based on a SQL SELECT statement.
+&apos;&apos;&apos;     The datasheet will live independently from any other 
(typically Base) component
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Sql:    a valid Sql statement as a 
case-sensitive string.
+&apos;&apos;&apos;                             Identifiers may be surrounded 
by square brackets
+&apos;&apos;&apos;             DirectSql: when True, the statement is 
processed by the targeted RDBMS
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A Datasheet class instance if it could be 
opened, otherwise Nothing
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             oDb.OpenSql(&quot;SELECT * FROM [Customers] 
ORDER BY [CITY]&quot;)
+
+Dim oOpen As Object                            &apos;  Return value
+Const cstThisSub = &quot;SFDatabases.Database.OpenSql&quot;
+Const cstSubArgs = &quot;Sql, [DirectSql=False]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oOpen = Nothing
+
+Check:
+       If IsMissing(DirectSql) Or IsEmpty(DirectSql) Then DirectSql = False
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(Sql, &quot;Sql&quot;, 
V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(DirectSql, 
&quot;DirectSql&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+       End If
+
+Try:
+       Set oOpen = _OpenDatasheet(_ReplaceSquareBrackets(Sql), 
com.sun.star.sdb.CommandType.COMMAND, Not DirectSql)
+
+Finally:
+       Set OpenSql = oOpen
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDocuments.SF_Base.OpenSql
+
+REM 
-----------------------------------------------------------------------------
+Public Function OpenTable(Optional ByVal TableName As Variant) As Object
+&apos;&apos;&apos;     Open the table given by its name
+&apos;&apos;&apos;     The datasheet will live independently from any other 
(typically Base) component
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             TableName: a valid table name as a 
case-sensitive string
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A Datasheet class instance if the table could 
be opened, otherwise Nothing
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             Table name is invalid
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             oDb.OpenTable(&quot;myTable&quot;)
+
+Dim oOpen As Object                            &apos;  Return value
+Const cstThisSub = &quot;SFDatabases.Database.OpenTable&quot;
+Const cstSubArgs = &quot;TableName&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oOpen = Nothing
+
+Check:
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(TableName, 
&quot;TableName&quot;, V_STRING, Tables) Then GoTo Finally
+       End If
+
+Try:
+       Set oOpen = _OpenDatasheet(TableName, 
com.sun.star.sdb.CommandType.TABLE, True)
+
+Finally:
+       Set OpenTable = oOpen
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDocuments.SF_Base.OpenTable
+
 REM 
-----------------------------------------------------------------------------
 Public Function Properties() As Variant
 &apos;&apos;&apos;     Return the list or properties of the Database class as 
an array
@@ -664,8 +780,8 @@ Private Function _GetColumnValue(ByRef poResultSet As 
Object _
 &apos;&apos;&apos;     Get the data stored in the current record of a result 
set in a given column
 &apos;&apos;&apos;     The type of the column is found in the resultset&apos;s 
metadata
 &apos;&apos;&apos;     Args:
-&apos;&apos;&apos;             poResultSet: com.sun.star.sdbc.XResultSet
-&apos;&apos;&apos;             plColIndex: the index of the column to extract 
the value from
+&apos;&apos;&apos;             poResultSet: com.sun.star.sdbc.XResultSet or 
com.sun.star.awt.XTabControllerModel
+&apos;&apos;&apos;             plColIndex: the index of the column to extract 
the value from. Starts at 1
 &apos;&apos;&apos;             pbReturnBinary: when True, the method returns 
the content of a binary field,
 &apos;&apos;&apos;                     as long as its length does not exceed a 
maximum length.
 &apos;&apos;&apos;                     Default = False: binary fields are not 
returned, only their length
@@ -685,7 +801,7 @@ Dim lSize As Long                           &apos;  Binary 
field length
 Const cstMaxBinlength = 2 * 65535
 
        On Local Error Goto 0                   &apos;  Disable error handler
-       vValue = Null                                   &apos;  Default value 
if error
+       vValue = Empty                                  &apos;  Default value 
if error
        If IsMissing(pbReturnBinary) Then pbReturnBinary = False
 
        With com.sun.star.sdbc.DataType
@@ -701,17 +817,17 @@ Const cstMaxBinlength = 2 * 65535
                                                If Not 
ScriptForge.SF_Session.HasUNOMethod(oStream, &quot;getLength&quot;) Then &apos; 
 When no recordset
                                                        lSize = cstMaxBinLength
                                                Else
-                                                       lSize = 
CLng(oValue.getLength())
+                                                       lSize = 
CLng(oStream.getLength())
                                                End If
                                                If lSize &lt;= cstMaxBinLength 
And pbReturnBinary Then
                                                        vValue = Array()
-                                                       
oValue.readBytes(vValue, lSize)
+                                                       
oStream.readBytes(vValue, lSize)
                                                Else    &apos;  Return length 
of field, not content
                                                        vValue = lSize
                                                End If
                                        End If
                                End If
-                               oValue.closeInput()
+                               If Not IsNull(oStream) Then oStream.closeInput()
                        Case .BIT, .BOOLEAN                             :       
vValue = poResultSet.getBoolean(plColIndex)
                        Case .DATE
                                vDateTime = poResultSet.getDate(plColIndex)
@@ -754,6 +870,61 @@ Const cstMaxBinlength = 2 * 65535
        
 End Function   &apos;  SFDatabases.SF_Database.GetColumnValue
 
+REM 
-----------------------------------------------------------------------------
+Public Function _OpenDatasheet(Optional ByVal psCommand As Variant _
+                                                               , 
piDatasheetType As Integer _
+                                                               , 
pbEscapeProcessing As Boolean _
+                                                               ) As Object
+&apos;&apos;&apos;     Open the datasheet given by its name and its type
+&apos;&apos;&apos;     The datasheet will live independently from any other 
component
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             psCommand: a valid table or query name or an 
SQL statement as a case-sensitive string
+&apos;&apos;&apos;             piDatasheetType: one of the 
com.sun.star.sdb.CommandType constants
+&apos;&apos;&apos;             pbEscapeProcessing: == Not DirectSql
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A Datasheet class instance if the datasheet 
could be opened, otherwise Nothing
+
+Dim oOpen As Object                            &apos;  Return value
+Dim oNewDatasheet As Object            &apos;  com.sun.star.lang.XComponent
+Dim oURL As Object                             &apos;  com.sun.star.util.URL
+Dim oDispatch As Object                        &apos;  
com.sun.star.frame.XDispatch
+Dim vArgs As Variant                   &apos;  Array of property values
+
+       On Local Error GoTo Catch
+       Set oOpen = Nothing
+
+Try:
+       &apos;  Setup the dispatcher
+       Set oURL = New com.sun.star.util.URL
+       oURL.Complete = &quot;.component:DB/DataSourceBrowser&quot;
+       Set oDispatch = StarDesktop.queryDispatch(oURL, &quot;_Blank&quot;, 8)
+
+       &apos;  Setup the arguments of the component to create
+       With ScriptForge.SF_Utils
+               vArgs = Array( _
+                       ._MakePropertyValue(&quot;ActiveConnection&quot;,       
        _Connection) _
+                       , ._MakePropertyValue(&quot;CommandType&quot;,          
piDatasheetType) _
+                       , ._MakePropertyValue(&quot;Command&quot;,              
        psCommand) _
+                       , ._MakePropertyValue(&quot;ShowMenu&quot;,             
        True) _
+                       , ._MakePropertyValue(&quot;ShowTreeView&quot;,         
False) _
+                       , ._MakePropertyValue(&quot;ShowTreeViewButton&quot;,   
False) _
+                       , ._MakePropertyValue(&quot;Filter&quot;,               
                &quot;&quot;) _
+                       , ._MakePropertyValue(&quot;ApplyFilter&quot;,          
False) _
+                       , ._MakePropertyValue(&quot;EscapeProcessing&quot;,     
pbEscapeProcessing) _
+                       )
+       End With
+
+       &apos;  Open the targeted datasheet
+       Set oNewDatasheet = oDispatch.dispatchWithReturnValue(oURL, vArgs)
+       If Not IsNull(oNewDatasheet) Then Set oOpen = 
ScriptForge.SF_Services.CreateScriptService(&quot;SFDatabases.Datasheet&quot;, 
[Me], oNewDatasheet)
+
+Finally:
+       Set _OpenDatasheet = oOpen
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDocuments.SF_Base._OpenDatasheet
+
 REM 
-----------------------------------------------------------------------------
 Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
 &apos;&apos;&apos;     Return the value of the named property
diff --git a/wizards/source/sfdatabases/SF_Datasheet.xba 
b/wizards/source/sfdatabases/SF_Datasheet.xba
new file mode 100644
index 000000000000..5550e35df30c
--- /dev/null
+++ b/wizards/source/sfdatabases/SF_Datasheet.xba
@@ -0,0 +1,744 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" 
"module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script"; 
script:name="SF_Datasheet" script:language="StarBasic" 
script:moduleType="normal">REM 
=======================================================================================================================
+REM ===                        The ScriptForge library and its associated 
libraries are part of the LibreOffice project.                               ===
+REM    ===                                             The SFDatabases library 
is one of the associated libraries.                                             
                        ===
+REM ===                                        Full documentation is available 
on https://help.libreoffice.org/                                                
                ===
+REM 
=======================================================================================================================
+
+Option Compatible
+Option ClassModule
+
+Option Explicit
+
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+&apos;&apos;&apos;     SF_Datasheet
+&apos;&apos;&apos;     ============
+&apos;&apos;&apos;             A datasheet is the visual representation of 
tabular data produced by a database.
+&apos;&apos;&apos;             In the user interface of LibreOffice it is the 
result of the opening of
+&apos;&apos;&apos;             a table or a query. In this case the concerned 
Base document must be open.
+&apos;&apos;&apos;
+&apos;&apos;&apos;             In the context of ScriptForge, a datasheet may 
be opened automatically by script code :
+&apos;&apos;&apos;                     - either by reproducing the behaviour 
of the user interface
+&apos;&apos;&apos;                     - or at any moment. In this case the 
Base document may or may not be opened.
+&apos;&apos;&apos;                       Additionally, any SELECT SQL 
statement may trigger the datasheet display.
+&apos;&apos;&apos;
+&apos;&apos;&apos;             The proposed API allows for either datasheets 
(opened manually of by code) in particular
+&apos;&apos;&apos;             to know which cell is selected and its content.
+&apos;&apos;&apos;
+&apos;&apos;&apos;             Service invocation:
+&apos;&apos;&apos;                     1) From an open Base document
+&apos;&apos;&apos;                             Set ui = 
CreateScriptService(&quot;UI&quot;)
+&apos;&apos;&apos;                             Set oBase = 
ui.getDocument(&quot;/home/user/Documents/myDb.odb&quot;)
+&apos;&apos;&apos;                             Set oSheet1 = 
oBase.OpenTable(&quot;Customers&quot;)    &apos;  or OpenQuery(...)
+&apos;&apos;&apos;                             Set oSheet2 = 
oBase.Datasheets(&quot;Products&quot;)    &apos;  when the datasheet has been 
opened manually
+&apos;&apos;&apos;                     2) Independently from a Base document
+&apos;&apos;&apos;                             Set oDatabase = 
CreateScriptService(&quot;Database&quot;, 
&quot;/home/user/Documents/myDb.odb&quot;)
+&apos;&apos;&apos;                             Set oSheet = 
oDatabase.OpenTable(&quot;Customers&quot;)
+&apos;&apos;&apos;
+&apos;&apos;&apos;             Detailed user documentation:
+&apos;&apos;&apos;                     
https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_datasheet.html?DbPAR=BASIC
+&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
+
+REM ================================================================== 
EXCEPTIONS
+
+Private Const DOCUMENTDEADERROR                =       
&quot;DOCUMENTDEADERROR&quot;
+
+REM ============================================================= PRIVATE 
MEMBERS
+
+Private [Me]                           As Object
+Private [_Parent]                      As Object               &apos; Base 
instance when opened from a Base document by code
+                                                                               
        &apos; or Database instance when opened without Base document
+Private ObjectType                     As String               &apos; Must be 
DATASHEET
+Private ServiceName                    As String
+
+Private _Component                     As Object               &apos; 
com.sun.star.lang.XComponent - org.openoffice.comp.dbu.ODatasourceBrowser
+Private _Frame                         As Object               &apos; 
com.sun.star.frame.XFrame
+Private _ParentBase                    As Object               &apos; The 
parent SF_Base instance (may be void)
+Private _ParentDatabase                As Object               &apos; The 
parent SF_Database instance (must not be void)
+Private _SheetType                     As String               &apos; TABLE, 
QUERY or SQL
+Private _ParentType                    As String               &apos; BASE or 
DATABASE
+Private _BaseFileName          As String               &apos; URL format of 
parent Base file
+Private _Command                       As String               &apos; Table 
name, query name or SQL statement
+Private _DirectSql                     As Boolean              &apos; When 
True, SQL processed by RDBMS
+Private _TabControllerModel    As Object               &apos; 
com.sun.star.awt.XTabControllerModel - com.sun.star.comp.forms.ODatabaseForm
+Private _ControlModel          As Object               &apos; 
com.sun.star.awt.XControlModel - com.sun.star.form.OGridControlModel
+Private _ControlView           As Object               &apos; 
com.sun.star.awt.XControl - org.openoffice.comp.dbu.ODatasourceBrowser
+Private _ColumnHeaders         As Variant              &apos; List of column 
headers as an array of strings
+
+REM ============================================================ MODULE 
CONSTANTS
+
+REM ====================================================== 
CONSTRUCTOR/DESTRUCTOR
+
+REM 
-----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+       Set [Me] = Nothing
+       Set [_Parent] = Nothing
+       ObjectType = &quot;DATASHEET&quot;
+       ServiceName = &quot;SFDatabases.Datasheet&quot;
+       Set _Component = Nothing
+       Set _Frame = Nothing
+       Set _ParentBase = Nothing
+       Set _ParentDatabase = Nothing
+       _SheetType = &quot;&quot;
+       _ParentType = &quot;&quot;
+       _BaseFileName = &quot;&quot;
+       _Command = &quot;&quot;
+       _DirectSql = False
+       Set _TabControllerModel = Nothing
+       Set _ControlModel = Nothing
+       Set _ControlView = Nothing
+       _ColumnHeaders = Array()
+End Sub                &apos;  SFDatabases.SF_Datasheet Constructor
+
+REM 
-----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+       Call Class_Initialize()
+End Sub                &apos;  SFDatabases.SF_Datasheet Destructor
+
+REM 
-----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+       Call Class_Terminate()
+       Set Dispose = Nothing
+End Function   &apos;  SFDatabases.SF_Datasheet Explicit Destructor
+
+REM ================================================================== 
PROPERTIES
+
+REM 
-----------------------------------------------------------------------------
+Property Get ColumnHeaders() As Variant
+&apos;&apos;&apos;     Returns the list of column headers of the datasheet as 
an array of strings
+       ColumnHeaders = _PropertyGet(&quot;ColumnHeaders&quot;)
+End Property   &apos;  SFDatabases.SF_Datasheet.ColumnHeaders
+
+REM 
-----------------------------------------------------------------------------
+Property Get CurrentColumn() As String
+&apos;&apos;&apos;     Returns the currently selected column by its name
+       CurrentColumn = _PropertyGet(&quot;CurrentColumn&quot;)
+End Property   &apos;  SFDatabases.SF_Datasheet.CurrentColumn
+
+REM 
-----------------------------------------------------------------------------
+Property Get CurrentRow() As Long
+&apos;&apos;&apos;     Returns the currently selected row by its number &gt;= 1
+       CurrentRow = _PropertyGet(&quot;CurrentRow&quot;)
+End Property   &apos;  SFDatabases.SF_Datasheet.CurrentRow
+
+REM 
-----------------------------------------------------------------------------
+Property Get LastRow() As Long
+&apos;&apos;&apos;     Returns the total number of rows
+&apos;&apos;&apos;     The process may imply to move the cursor to the last 
available row.
+&apos;&apos;&apos;     Afterwards the cursor is reset to the current row.
+       LastRow = _PropertyGet(&quot;LastRow&quot;)
+End Property   &apos;  SFDatabases.SF_Datasheet.LastRow
+
+REM 
-----------------------------------------------------------------------------
+Property Get Source() As String
+&apos;&apos;&apos;     Returns the source of the data: table name, query name 
or sql statement
+       Source = _PropertyGet(&quot;Source&quot;)
+End Property   &apos;  SFDatabases.SF_Datasheet.Source
+
+REM 
-----------------------------------------------------------------------------
+Property Get SourceType() As String
+&apos;&apos;&apos;     Returns thetype of source of the data: TABLE, QUERY or 
SQL
+       SourceType = _PropertyGet(&quot;SourceType&quot;)
+End Property   &apos;  SFDatabases.SF_Datasheet.SourceType
+
+REM 
-----------------------------------------------------------------------------
+Property Get XComponent() As Object
+&apos;&apos;&apos;     Returns the com.sun.star.lang.XComponent UNO object 
representing the datasheet
+       XComponent = _PropertyGet(&quot;XComponent&quot;)
+End Property   &apos;  SFDocuments.SF_Document.XComponent
+
+REM 
-----------------------------------------------------------------------------
+Property Get XControlModel() As Object
+&apos;&apos;&apos;     Returns the com.sun.star.lang.XControl UNO object 
representing the datasheet
+       XControlModel = _PropertyGet(&quot;XControlModel&quot;)
+End Property   &apos;  SFDocuments.SF_Document.XControlModel
+
+REM 
-----------------------------------------------------------------------------
+Property Get XTabControllerModel() As Object
+&apos;&apos;&apos;     Returns the com.sun.star.lang.XTabControllerModel UNO 
object representing the datasheet
+       XTabControllerModel = _PropertyGet(&quot;XTabControllerModel&quot;)
+End Property   &apos;  SFDocuments.SF_Document.XTabControllerModel
+
+REM ===================================================================== 
METHODS
+
+REM 
-----------------------------------------------------------------------------
+Public Sub Activate()
+&apos;&apos;&apos; Make the actual datasheet active
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             oSheet.Activate()
+
+Dim oContainer As Object                       &apos;  com.sun.star.awt.XWindow
+Const cstThisSub = &quot;SFDatabases.Datasheet.Activate&quot;
+Const cstSubArgs = &quot;&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+Check:
+       SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+       If Not _IsStillAlive() Then GoTo Finally
+
+Try:
+       Set oContainer = _Component.Frame.ContainerWindow
+       With oContainer
+               If .isVisible() = False Then .setVisible(True)
+               .IsMinimized = False
+               .setFocus()
+               .toFront()                              &apos;  Force window 
change in Linux
+               Wait 1                                  &apos;  Bypass 
desynchro issue in Linux
+       End With
+
+Finally:
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Sub
+Catch:
+       GoTo Finally
+End Sub                        &apos;   SFDatabases.SF_Datasheet.Activate
+
+REM 
-----------------------------------------------------------------------------
+Public Function ApplyFilter(Optional ByVal Filter As Variant) As Boolean
+&apos;&apos;&apos; Apply the given filter to the actual datasheet
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Filter: a SQL WHERE clause without the WHERE 
keyword
+&apos;&apos;&apos;                     Table and field names may be surrounded 
by square brackets
+&apos;&apos;&apos;                     When the argument is the zero-length 
string or absent, the actual filter is removed
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             
oSheet.ApplyFilter(&quot;[ShipCountry]=&apos;USA&apos;&quot;)
+
+Dim bApply As Boolean                          &apos;  Return value
+Dim sFilter As String                          &apos;  Filter after 
replacement of square brackets by real delimiter
+Const cstThisSub = &quot;SFDatabases.Datasheet.ApplyFilter&quot;
+Const cstSubArgs = &quot;[Filter=&quot;&quot;&quot;&quot;]&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bApply = False
+
+Check:
+       If IsMissing(Filter) Or IsEmpty(Filter) Then Filter = &quot;&quot;
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not _IsStillAlive() Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(Filter, 
&quot;Filter&quot;, V_STRING) Then GoTo Catch
+       End If
+
+Try:
+       With _TabControllerModel
+               If Len(Filter) &gt; 0 Then
+                       .Filter = _ParentDatabase._ReplaceSquareBrackets(Filter)
+                       .ApplyFilter = True
+                       .reload()
+               Else
+                       .Filter = &quot;&quot;
+                       .ApplyFilter = False
+                       .reload()
+               End If
+       End With
+
+       bApply = True
+
+Finally:
+       ApplyFilter = bApply
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDatabases.SF_Datasheet.ApplyFilter
+
+REM 
-----------------------------------------------------------------------------
+Public Function CloseDatasheet() As Boolean
+&apos;&apos;&apos; Close the actual datasheet
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             oSheet.CloseDatasheet()
+
+Dim bClose As Boolean          &apos;  Return value
+Const cstThisSub = &quot;SFDatabases.Datasheet.CloseDatasheet&quot;
+Const cstSubArgs = &quot;&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bClose = False
+
+Check:
+       SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+       If Not _IsStillAlive() Then GoTo Finally
+
+Try:
+       _TabControllerModel.close()
+       _Frame.close(True)
+       _Frame.dispose()
+       Dispose()
+       bClose = True
+
+Finally:
+       CloseDatasheet = bClose
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDatabases.SF_Datasheet.CloseDatasheet
+
+REM 
-----------------------------------------------------------------------------
+Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
+&apos;&apos;&apos;     Return the actual value of the given property
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             PropertyName: the name of the property as a 
string
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             The actual value of the propRATTCerty
+&apos;&apos;&apos;             If the property does not exist, returns Null
+
+Const cstThisSub = &quot;SFDatabases.Datasheet.GetProperty&quot;
+Const cstSubArgs = &quot;&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       GetProperty = Null
+
+Check:
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(PropertyName, 
&quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
+       End If
+
+Try:
+       GetProperty = _PropertyGet(PropertyName)
+
+Finally:
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Datasheet.GetProperty
+
+REM 
-----------------------------------------------------------------------------
+Public Function GetText(Optional ByVal Column As Variant) As String
+&apos;&apos;&apos; Get the text in the given column of the current row.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Column: the name of the column as a string or 
its position (&gt;= 1). Default = the current column
+&apos;&apos;&apos;                             If the argument exceeds the 
number of columns, the last column is selected.
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             The text in the cell as a string as how it is 
displayed
+&apos;&apos;&apos;             Note that the position of the cursor is left 
unchanged.
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             oSheet.GeText(&quot;ShipCity&quot;))    &apos;  
Extract the text on the current row from the column &quot;ShipCity&quot;
+
+Dim sText As String                            &apos;  Return Text
+Dim lCol As Long                                       &apos;  Numeric index 
of Column in lists of columns
+Dim lMaxCol As Long                            &apos;  Index of last column
+Const cstThisSub = &quot;SFDatabases.Datasheet.GetText&quot;
+Const cstSubArgs = &quot;[Column=0]&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       sText = &quot;&quot;
+
+Check:
+       If IsMissing(Column) Or IsEmpty(Column) Then Column = 0
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not _IsStillAlive() Then GoTo Finally
+               If VarType(Column) &lt;&gt; V_STRING Then
+                       If Not ScriptForge.SF_Utils._Validate(Column, 
&quot;Column&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
+               Else
+                       If Not ScriptForge.SF_Utils._Validate(Column, 
&quot;Column&quot;, V_STRING, _ColumnHeaders) Then GoTo Catch
+               End If
+       End If
+
+Try:
+       &apos;  Position the column - The index to be passed starts at 0
+       With _ControlView
+               If VarType(Column) = V_STRING Then
+                       lCol = ScriptForge.SF_Array.IndexOf(_ColumnHeaders, 
Column, CaseSensitive := False)
+               Else
+                       lCol = -1
+                       If Column &gt;= 1 Then
+                               lMaxCol = .Count - 1
+                               If Column &gt; lMaxCol + 1 Then lCol = lMaxCol 
Else lCol = Column - 1
+                       End If
+               End If
+
+               If lCol &gt;= 0 Then sText = .getByIndex(lCol).Text
+       End With
+
+Finally:
+       GetText = sText
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDatabases.SF_Datasheet.GetText
+
+REM 
-----------------------------------------------------------------------------
+Public Function GetValue(Optional ByVal Column As Variant) As Variant
+&apos;&apos;&apos; Get the value in the given column of the current row.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Column: the name of the column as a string or 
its position (&gt;= 1). Default = the current column
+&apos;&apos;&apos;                             If the argument exceeds the 
number of columns, the last column is selected.
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             The value in the cell as a valid Basic type
+&apos;&apos;&apos;             Typical types are: STRING, INTEGER, LONG, 
FLOAT, DOUBLE, DATE, NULL
+&apos;&apos;&apos;             Binary types are returned as a LONG giving 
their length, not their content
+&apos;&apos;&apos;             An EMPTY return value means that the value 
could not be retrieved.
+&apos;&apos;&apos;             Note that the position of the cursor is left 
unchanged.
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             oSheet.GeValue(&quot;ShipCity&quot;))   &apos;  
Extract the value on the current row from the column &quot;ShipCity&quot;
+
+Dim vValue As Variant                          &apos;  Return value
+Dim lCol As Long                                       &apos;  Numeric index 
of Column in lists of columns
+Dim lMaxCol As Long                            &apos;  Index of last column
+Const cstThisSub = &quot;SFDatabases.Datasheet.GetValue&quot;
+Const cstSubArgs = &quot;[Column=0]&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       vValue = Empty
+
+Check:
+       If IsMissing(Column) Or IsEmpty(Column) Then Column = 0
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not _IsStillAlive() Then GoTo Finally
+               If VarType(Column) &lt;&gt; V_STRING Then
+                       If Not ScriptForge.SF_Utils._Validate(Column, 
&quot;Column&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
+               Else
+                       If Not ScriptForge.SF_Utils._Validate(Column, 
&quot;Column&quot;, V_STRING, _ColumnHeaders) Then GoTo Catch
+               End If
+       End If
+
+Try:
+       &apos;  Position the column - The index to be passed starts at 1
+       If VarType(Column) = V_STRING Then
+               lCol = ScriptForge.SF_Array.IndexOf(_ColumnHeaders, Column, 
CaseSensitive := False) + 1
+       Else
+               lCol = 0
+               If Column &gt;= 1 Then
+                       lMaxCol = _ControlView.Count
+                       If Column &gt; lMaxCol Then lCol = lMaxCol Else lCol = 
Column
+               End If
+       End If
+
+       &apos;  The _TabControllerModel acts exactly as a result set, from 
which the generic _GetColumnValue can extract the searched value
+       If lCol &gt;= 1 Then vValue = 
_ParentDatabase._GetColumnValue(_TabControllerModel, lCol)
+
+Finally:
+       GetValue = vValue
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDatabases.SF_Datasheet.GetValue
+
+REM 
-----------------------------------------------------------------------------
+Public Function GoToCell(Optional ByVal Row As Variant _
+                                                       , Optional ByVal Column 
As Variant _
+                                                       ) As Boolean
+&apos;&apos;&apos; Set the cursor on the given row and the given column.
+&apos;&apos;&apos;     If the requested row exceeds the number of available 
rows, the cursor is set on the last row.
+&apos;&apos;&apos;     If the requested column exceeds the number of available 
columns, the selected column is the last one.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Row: the row number (&gt;= 1) as a numeric 
value. Default= no change
+&apos;&apos;&apos;             Column: the name of the column as a string or 
its position (&gt;= 1). Default = the current column
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             oSheet.GoToCell(1000000, &quot;ShipCity&quot;)) 
&apos;  Set the cursor on he last row, column &quot;ShipCity&quot;
+
+Dim bGoTo As Boolean                           &apos;  Return value
+Dim lCol As Long                                       &apos;  Numercic index 
of Column in lists of columns
+Dim lMaxCol As Long                            &apos;  Index of last column
+Const cstThisSub = &quot;SFDatabases.Datasheet.GoToCell&quot;
+Const cstSubArgs = &quot;[Row=0], [Column=0]&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bGoTo = False
+
+Check:
+       If IsMissing(Row) Or IsEmpty(Row) Then Row = 0
+       If IsMissing(Column) Or IsEmpty(Column) Then Column = 0
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not _IsStillAlive() Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(Row, &quot;Row&quot;, 
ScriptForge.V_NUMERIC) Then GoTo Catch
+               If VarType(Column) &lt;&gt; V_STRING Then
+                       If Not ScriptForge.SF_Utils._Validate(Column, 
&quot;Column&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
+               Else
+                       If Not ScriptForge.SF_Utils._Validate(Column, 
&quot;Column&quot;, V_STRING, _ColumnHeaders) Then GoTo Catch
+               End If
+       End If
+
+Try:
+       &apos;  Position the row
+       With _TabControllerModel
+               If Row &lt;= 0 Then Row = .Row Else .absolute(Row)
+               &apos;  Does Row exceed the total number of rows ?
+               If .IsRowCountFinal And Row &gt; .RowCount Then 
.absolute(.RowCount)
+       End With
+
+       &apos;  Position the column
+       With _ControlView
+               If VarType(Column) = V_STRING Then
+                       lCol = ScriptForge.SF_Array.IndexOf(_ColumnHeaders, 
Column, CaseSensitive := False)
+               Else
+                       lCol = -1
+                       If Column &gt;= 1 Then
+                               lMaxCol = .Count - 1
+                               If Column &gt; lMaxCol + 1 Then lCol = lMaxCol 
Else lCol = Column - 1
+                       End If
+               End If
+               If lCol &gt;= 0 Then .setCurrentColumnPosition(lCol)
+       End With
+
+       bGoTo = True
+
+Finally:
+       GoToCell = bGoTo
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDatabases.SF_Datasheet.GoToCell
+
+REM 
-----------------------------------------------------------------------------
+Public Function Methods() As Variant
+&apos;&apos;&apos;     Return the list of public methods of the Model service 
as an array
+
+       Methods = Array( _
+                                       &quot;Activate&quot; _
+                                       , &quot;ApplyFilter&quot; _
+                                       , &quot;CloseDatasheet&quot; _
+                                       , &quot;GetText&quot; _
+                                       , &quot;GetValue&quot; _
+                                       , &quot;GoToCell&quot; _
+                                       , &quot;OrderBy&quot; _
+                                       )
+
+End Function   &apos;  SFDatabases.SF_Datasheet.Methods
+
+REM 
-----------------------------------------------------------------------------
+Public Function OrderBy(Optional ByVal Order As Variant) As Boolean
+&apos;&apos;&apos; Sort the actual datasheet based on the given ordering 
instructions
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Order: a SQL ORDER BY clause without the ORDER 
BY keywords
+&apos;&apos;&apos;                     Table and field names may be surrounded 
by square brackets
+&apos;&apos;&apos;                     When the argument is the zero-length 
string or absent, the actual sort is removed
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             oSheet.OrderBy(&quot;[ShipCountry] DESC, 
[EmployeeID]&quot;)
+
+Dim bOrder As Boolean                          &apos;  Return value
+Dim sOrder As String                           &apos;  Order after replacement 
of square brackets by real delimiter
+Const cstThisSub = &quot;SFDatabases.Datasheet.OrderBy&quot;
+Const cstSubArgs = &quot;[Order=&quot;&quot;&quot;&quot;]&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bOrder = False
+
+Check:
+       If IsMissing(Order) Or IsEmpty(Order) Then Order = &quot;&quot;
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not _IsStillAlive() Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(Order, &quot;Order&quot;, 
V_STRING) Then GoTo Catch
+       End If
+
+Try:
+       With _TabControllerModel
+               If Len(Order) &gt; 0 Then
+                       .Order = _ParentDatabase._ReplaceSquareBrackets(Order)
+                       .ApplyFilter = True
+                       .reload()
+               Else
+                       .Order = &quot;&quot;
+                       .ApplyFilter = False
+                       .reload()
+               End If
+       End With
+
+       bOrder = True
+
+Finally:
+       OrderBy = bOrder
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDatabases.SF_Datasheet.OrderBy
+
+REM 
-----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos;     Return the list or properties of the Model class as an 
array
+
+       Properties = Array( _
+                                       &quot;ColumnHeaders&quot; _
+                                       , &quot;CurrentColumn&quot; _
+                                       , &quot;CurrentRow&quot; _
+                                       , &quot;LastRow&quot; _
+                                       , &quot;Source&quot; _
+                                       , &quot;SourceType&quot; _
+                                       , &quot;XComponent&quot; _
+                                       , &quot;XControlModel&quot; _
+                                       , &quot;XTabControllerModel&quot; _
+                                       )
+
+End Function   &apos;  SFDatabases.SF_Datasheet.Properties
+
+REM =========================================================== PRIVATE 
FUNCTIONS
+
+REM 
-----------------------------------------------------------------------------
+Public Sub _Initialize()
+&apos;&apos;&apos;     Called immediately after instance creation to complete 
the initial values
+&apos;&apos;&apos;     An eventual error must be trapped in the calling 
routine to cancel the instance creation
+
+Dim iType As Integer                   &apos;  One of the 
com.sun.star.sdb.CommandType constants
+Dim oColumn As Object                  &apos;  A single column
+Dim oColumnDescriptor As Object        &apos;  A single column descriptor
+Dim i As Long
+
+Try:
+       _ParentType = [_Parent].ObjectType
+
+       With _Component
+               &apos;  The existence of _Component.Selection must be checked 
upfront
+               _Command = ScriptForge.SF_Utils._GetPropertyValue(.Selection, 
&quot;Command&quot;)
+
+               iType = ScriptForge.SF_Utils._GetPropertyValue(.Selection, 
&quot;CommandType&quot;)
+               Select Case iType
+                       Case com.sun.star.sdb.CommandType.TABLE         :       
_SheetType = &quot;TABLE&quot;
+                       Case com.sun.star.sdb.CommandType.QUERY         :       
_SheetType = &quot;QUERY&quot;
+                       Case com.sun.star.sdb.CommandType.COMMAND       :       
_SheetType = &quot;SQL&quot;
+               End Select
+
+               _BaseFileName = 
ScriptForge.SF_Utils._GetPropertyValue(.Selection, &quot;DataSourceName&quot;)
+               _DirectSql = Not 
ScriptForge.SF_Utils._GetPropertyValue(.Selection, &quot;EscapeProcessing&quot;)
+
+               &apos;  Useful UNO objects
+               Set _Frame = .Frame
+               Set _ControlView = .CurrentControl
+               Set _TabControllerModel = 
.com_sun_star_awt_XTabController_getModel
+               Set _ControlModel = _ControlView.getModel()
+
+               &apos;  Retrieve the parent database instance
+               Select Case [_Parent].ObjectType
+                       Case &quot;BASE&quot;
+                               With _TabControllerModel
+                                       Set _ParentDatabase = 
[_Parent].GetDatabase(.User, .Password)
+                               End With
+                               Set _ParentBase = [_Parent]
+                       Case &quot;DATABASE&quot;
+                               Set _ParentDatabase = [_Parent]
+                               Set _ParentBase = Nothing
+               End Select
+
+               &apos;  Load column headers
+               _ColumnHeaders  = 
_TabControllerModel.getColumns().getElementNames()
+
+       End With
+
+Finally:
+       Exit Sub
+End Sub                        &apos;  SFDatabases.SF_Datasheet._Initialize
+
+                                                                               
        &apos; or Nothing when opened manually from the user interface
+REM 
-----------------------------------------------------------------------------
+Private Function _IsStillAlive(Optional ByVal pbError As Boolean) As Boolean
+&apos;&apos;&apos;     Returns True if the datasheet has not been closed 
manually or incidentally since the last use
+&apos;&apos;&apos;     If dead the actual instance is disposed. The execution 
is cancelled when pbError = True (default)
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             pbError: if True (default), raise a fatal error
+
+Dim bAlive As Boolean                  &apos;  Return value
+Dim sName As String                            &apos;  Used in error message
+
+       On Local Error GoTo Catch               &apos;  Anticipate 
DisposedException errors or alike
+       If IsMissing(pbError) Then pbError = True
+
+Try:
+       &apos;  Check existence of datasheet
+       bAlive = Not IsNull(_Component.ComponentWindow)
+
+Finally:
+       If pbError And Not bAlive Then
+               sName = _Command
+               Dispose()
+               If pbError Then 
ScriptForge.SF_Exception.RaiseFatal(DOCUMENTDEADERROR, sName)
+       End If
+       _IsStillAlive = bAlive
+       Exit Function
+Catch:
+       bAlive = False
+       On Error GoTo 0
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Datasheet._IsStillAlive
+
+REM 
-----------------------------------------------------------------------------
+Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
+&apos;&apos;&apos;     Return the value of the named property
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             psProperty: the name of the property
+
+Dim lRow As Long                               &apos;  Actual row number
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+       cstThisSub = &quot;SFDatabases.Datasheet.get&quot; &amp; psProperty
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+       ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+       If Not _IsStillAlive(False) Then GoTo Finally
+
+       Select Case psProperty
+               Case &quot;ColumnHeaders&quot;
+                                                                               
        &apos; or Nothing when opened manually from the user interface
+
+                                                                               
        &apos; or Nothing when opened manually from the user interface
+                       _PropertyGet = _ColumnHeaders
+               Case &quot;CurrentColumn&quot;
+                       _PropertyGet = 
_ColumnHeaders(_ControlView.getCurrentColumnPosition())
+               Case &quot;CurrentRow&quot;
+                       _PropertyGet = _TabControllerModel.Row
+               Case &quot;LastRow&quot;
+                       With _TabControllerModel
+                               If .IsRowCountFinal Then
+                                       _PropertyGet = .RowCount
+                               Else
+                                       lRow = .Row
+                                       If lRow &gt; 0 Then
+                                               .last()
+                                               _PropertyGet = .RowCount
+                                               .absolute(lRow)
+                                       Else
+                                               _PropertyGet = 0
+                                       End If
+                               End If
+                       End With
+               Case &quot;Source&quot;
+                       _PropertyGet = _Command
+               Case &quot;SourceType&quot;
+                       _PropertyGet = _SheetType
+               Case &quot;XComponent&quot;
+                       Set _PropertyGet = _Component
+               Case &quot;XControlModel&quot;
+                       Set _PropertyGet = _ControlModel
+               Case &quot;XTabControllerModel&quot;
+                       Set _PropertyGet = _TabControllerModel
+               Case Else
+                       _PropertyGet = Null
+       End Select
+
+Finally:
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Datasheet._PropertyGet
+
+REM 
-----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos;     Convert the Datasheet instance to a readable string, 
typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Return:
+&apos;&apos;&apos;             &quot;[DATASHEET]: A readable string&quot;
+
+       _Repr = &quot;[DATASHEET]: A readable string&quot;
+
+End Function   &apos;  SFDatabases.SF_Datasheet._Repr
+
+REM ============================================ END OF 
SFDATABASES.SF_DATASHEET
+</script:module>
\ No newline at end of file
diff --git a/wizards/source/sfdatabases/SF_Register.xba 
b/wizards/source/sfdatabases/SF_Register.xba
index c9b3f03d7334..25d41e99718a 100644
--- a/wizards/source/sfdatabases/SF_Register.xba
+++ b/wizards/source/sfdatabases/SF_Register.xba
@@ -46,6 +46,7 @@ Public Sub RegisterScriptServices() As Variant
        With GlobalScope.ScriptForge.SF_Services
                .RegisterService(&quot;Database&quot;,                          
&quot;SFDatabases.SF_Register._NewDatabase&quot;)               &apos;  
Reference to the function initializing the service
                .RegisterService(&quot;DatabaseFromDocument&quot;,      
&quot;SFDatabases.SF_Register._NewDatabaseFromSource&quot;)
+               .RegisterService(&quot;Datasheet&quot;,                         
&quot;SFDatabases.SF_Register._NewDatasheet&quot;)
        End With
 
 End Sub                        &apos;  
SFDatabases.SF_Register.RegisterScriptServices
@@ -55,7 +56,7 @@ REM 
=========================================================== PRIVATE FUNCTION
 REM 
-----------------------------------------------------------------------------
 Public Function _NewDatabase(Optional ByVal pvArgs As Variant) As Object
 &apos;&apos;&apos;     Create a new instance of the SF_Database class
-&apos; Args:
+&apos;&apos;&apos;     Args:
 &apos;&apos;&apos;             FileName : the name of the file (compliant with 
the SF_FileSystem.FileNaming notation)
 &apos;&apos;&apos;             RegistrationName: mutually exclusive with 
FileName. Used when database is registered
 &apos;&apos;&apos;             ReadOnly : (boolean). Default = True
@@ -140,7 +141,7 @@ Public Function _NewDatabaseFromSource(Optional ByVal 
pvArgs As Variant) As Obje
 &apos;&apos;&apos;     Create a new instance of the SF_Database class from the 
given datasource
 &apos;&apos;&apos;     established in the SFDocuments.Base service
 &apos;&apos;&apos;     THIS SERVICE MUST NOT BE CALLED FROM A USER SCRIPT
-&apos; Args:
+&apos;&apos;&apos;     Args:
 &apos;&apos;&apos;             DataSource:     com.sun.star.sdbc.XDataSource
 &apos;&apos;&apos;             User, Password : connection parameters
 &apos;&apos;&apos;     Returns:
@@ -191,5 +192,58 @@ Catch:
        GoTo Finally
 End Function   &apos;  SFDatabases.SF_Register._NewDatabaseFromSource
 
+REM 
-----------------------------------------------------------------------------
+Public Function _NewDatasheet(Optional ByVal pvArgs As Variant) As Object
+&apos;                                                   Optional ByRef 
poParent As Object _
+&apos;                                                         , Optional 
ByRef poComponent As Object _
+&apos;                                                         ) As Object
+&apos;&apos;&apos;     Create a new instance of the SF_Datasheet class
+&apos;&apos;&apos;     Called from (internal calls only)
+&apos;&apos;&apos;             base.Datasheets()
+&apos;&apos;&apos;             base.OpenTable()
+&apos;&apos;&apos;             base.OpenQuery()
+&apos;&apos;&apos;             database.OpenTable()
+&apos;&apos;&apos;             database.OpenQuery()
+&apos;&apos;&apos;             database.OpenSql()
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Parent: the parent SF_Database or SF_Base 
instance having produced the new datasheet
+&apos;&apos;&apos;             Component:      the component of the new 
datasheet
+&apos;&apos;&apos;                                             
com.sun.star.lang.XComponent - org.openoffice.comp.dbu.ODatasourceBrowser
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             The instance or Nothing
+
+Dim oDatasheet As Object               &apos;  Return value
+Dim oParent As Object                  &apos;  The parent SF_Database or 
SF_Base instance having produced the new datasheet
+Dim oComponent As Object               &apos;  The component of the new 
datasheet
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oDatasheet = Nothing
+
+Check:
+       &apos;  Get arguments
+       If UBound(pvArgs) &lt;&gt; 1 Then GoTo Catch
+       Set oParent = pvArgs(0)
+       Set oComponent = pvArgs(1)
+       If IsNull(oParent) Or IsNull(oComponent) Then GoTo Catch
+       If IsEmpty(oComponent.Selection) Then GoTo Catch
+
+Try:
+               Set oDatasheet = New SF_Datasheet
+               With oDatasheet
+                       Set .[Me] = oDatasheet
+                       Set .[_Parent] = oParent
+                       Set ._Component = oComponent
+                       &apos;  Achieve the initialization
+                       ._Initialize()
+               End With
+
+Finally:
+       Set _NewDatasheet = oDatasheet
+       Exit Function
+Catch:
+       Set oDatasheet = Nothing
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Register._NewDatasheet
+
 REM ============================================== END OF 
SFDATABASES.SF_REGISTER
 </script:module>
\ No newline at end of file
diff --git a/wizards/source/sfdatabases/script.xlb 
b/wizards/source/sfdatabases/script.xlb
index 6cea80d2a912..15d7cbdbe978 100644
--- a/wizards/source/sfdatabases/script.xlb
+++ b/wizards/source/sfdatabases/script.xlb
@@ -4,4 +4,5 @@
  <library:element library:name="SF_Register"/>
  <library:element library:name="__License"/>
  <library:element library:name="SF_Database"/>
+ <library:element library:name="SF_Datasheet"/>
 </library:library>
\ No newline at end of file
diff --git a/wizards/source/sfdialogs/SF_Dialog.xba 
b/wizards/source/sfdialogs/SF_Dialog.xba
index 486e90ef71dd..507e5ac72c00 100644
--- a/wizards/source/sfdialogs/SF_Dialog.xba
+++ b/wizards/source/sfdialogs/SF_Dialog.xba
@@ -1083,7 +1083,7 @@ Try:
        Next sControlName
 
        vRadioList = ScriptForge.SF_Array.SortRows(vRadioList, 1)
-       &apos;  Retain continuous tav indexes
+       &apos;  Retain contiguous tab indexes
        For i = 1 To UBound(vRadioList, 1)      &apos;  First row = argument
                If vRadioList(i, 1) = iRadioTabIndex + i Then sList = sList 
&amp; cstComma &amp; vRadioList(i, 0)
        Next i
@@ -1481,4 +1481,4 @@ Private Function _Repr() As String
 End Function   &apos;  SFDialogs.SF_Dialog._Repr
 
 REM ============================================ END OF SFDIALOGS.SF_DIALOG
-</script:module>
+</script:module>
\ No newline at end of file
diff --git a/wizards/source/sfdocuments/SF_Base.xba 
b/wizards/source/sfdocuments/SF_Base.xba
index 1e6395dbfa2c..81afacc7bbda 100644
--- a/wizards/source/sfdocuments/SF_Base.xba
+++ b/wizards/source/sfdocuments/SF_Base.xba
@@ -459,7 +459,7 @@ Public Function OpenFormDocument(Optional ByVal 
FormDocument As Variant _
 &apos;&apos;&apos;     Open the FormDocument given by its hierarchical name 
either in normal or in design mode
 &apos;&apos;&apos;     If the form document is already open, the form document 
is made active without changing its mode
 &apos;&apos;&apos;     Args:
-&apos;&apos;&apos;             FormDocument: a valid document form name as a 
case-sensitive string
+&apos;&apos;&apos;             FormDocument: a valid form document name as a 
case-sensitive string
 &apos;&apos;&apos;             DesignMode: when True the form document is 
opened in design mode (Default = False)
 &apos;&apos;&apos;     Returns:
 &apos;&apos;&apos;             True if the form document could be opened, 
otherwise False
@@ -509,6 +509,111 @@ Catch:
        GoTo Finally
 End Function   &apos;  SFDocuments.SF_Base.OpenFormDocument
 
+REM 
-----------------------------------------------------------------------------
+Public Function OpenQuery(Optional ByVal QueryName As Variant _
+                                                                       , 
Optional ByVal DesignMode As Variant _
+                                                                       ) As 
Object
+&apos;&apos;&apos;     Open the query given by its name either in normal or in 
design mode
+&apos;&apos;&apos;     If the query is already open, the query datasheet is 
made active without changing its mode
+&apos;&apos;&apos;     If still open, the datasheet will be closed together 
with the actual Base document.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             QueryName: a valid Query name as a 
case-sensitive string
+&apos;&apos;&apos;             DesignMode: when True the query is opened in 
design mode (Default = False)
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A Datasheet class instance if the query could 
be opened and DesignMode = False, otherwise False
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             Query name is invalid
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             oDoc.OpenQuery(&quot;myQuery&quot;, DesignMode 
:= False)
+
+Dim oOpen As Object                                    &apos;  Return value
+Dim vQueries As Variant                                &apos;  Array of query 
names
+Dim oNewQuery As Object                                &apos;  Output of 
loadComponent()
+Const cstThisSub = &quot;SFDocuments.Base.OpenQuery&quot;
+Const cstSubArgs = &quot;QueryName, [DesignMode=False]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oOpen = Nothing
+
+Check:
+       If IsMissing(DesignMode) Or IsEmpty(DesignMode) Then DesignMode = False
+       vQueries = GetDatabase().Queries        &apos;  Includes _IsStillAlive()
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(QueryName, 
&quot;QueryName&quot;, V_STRING, vQueries) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(DesignMode, 
&quot;DesignMode&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+       End If
+
+Try:
+       With _Component.CurrentController
+               &apos;  The connection may have been done previously by a user 
commmand. If not, do it now.
+               If Not .IsConnected Then .connect()
+               &apos;  loadComponent activates the query component when 
already loaded
+               Set oNewQuery = 
.loadComponent(com.sun.star.sdb.application.DatabaseObject.QUERY, QueryName, 
DesignMode)
+       End With
+       &apos;  When design mode, the method returns Nothing
+       If Not DesignMode Then Set oOpen = 
ScriptForge.SF_Services.CreateScriptService(&quot;SFDatabases.Datasheet&quot;, 
[Me], oNewQuery)
+
+Finally:
+       Set OpenQuery = oOpen
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDocuments.SF_Base.OpenQuery
+
+REM 
-----------------------------------------------------------------------------
+Public Function OpenTable(Optional ByVal TableName As Variant _
+                                                                       , 
Optional ByVal DesignMode As Variant _
+                                                                       ) As 
Object
+&apos;&apos;&apos;     Open the table given by its name either in normal or in 
design mode
+&apos;&apos;&apos;     If the table is already open, the table datasheet is 
made active without changing its mode
+&apos;&apos;&apos;     If still open, the datasheet will be closed together 
with the actual Base document.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             TableName: a valid table name as a 
case-sensitive string
+&apos;&apos;&apos;             DesignMode: when True the table is opened in 
design mode (Default = False)
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A Datasheet class instance if the table could 
be opened or was already open, and DesignMode = False.
+&apos;&apos;&apos;             Otherwise Nothing
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             Table name is invalid
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             oDoc.OpenTable(&quot;myTable&quot;, DesignMode 
:= False)
+
+Dim oOpen As Object                                    &apos;  Return value
+Dim vTables As Variant                         &apos;  Array of table names
+Dim oNewTable As Object                                &apos;  Output of 
loadComponent()
+Const cstThisSub = &quot;SFDocuments.Base.OpenTable&quot;
+Const cstSubArgs = &quot;TableName, [DesignMode=False]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oOpen = Nothing
+
+Check:
+       If IsMissing(DesignMode) Or IsEmpty(DesignMode) Then DesignMode = False
+       vTables = GetDatabase().Tables
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(TableName, 
&quot;TableName&quot;, V_STRING, vTables) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(DesignMode, 
&quot;DesignMode&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+       End If
+
+Try:
+       With _Component.CurrentController
+               &apos;  The connection may have been done previously by a user 
commmand. If not, do it now.
+               If Not .IsConnected Then .connect()
+               &apos;  loadComponent activates the table component when 
already loaded
+               Set oNewTable = 
.loadComponent(com.sun.star.sdb.application.DatabaseObject.TABLE, TableName, 
DesignMode)
+       End With
+       &apos;  When design mode, the method returns Nothing
+       If Not DesignMode Then Set oOpen = 
ScriptForge.SF_Services.CreateScriptService(&quot;SFDatabases.Datasheet&quot;, 
[Me], oNewTable)
+
+Finally:
+       Set OpenTable = oOpen
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDocuments.SF_Base.OpenTable
+
 REM 
-----------------------------------------------------------------------------
 Public Function PrintOut(Optional ByVal FormDocument As Variant _
                                                        , Optional ByVal Pages 
As Variant _
diff --git a/wizards/source/sfdocuments/SF_Calc.xba 
b/wizards/source/sfdocuments/SF_Calc.xba
index e32dab652166..0733be07eb6a 100644
--- a/wizards/source/sfdocuments/SF_Calc.xba
+++ b/wizards/source/sfdocuments/SF_Calc.xba
@@ -401,7 +401,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.A1Style
+End Function   &apos;  SFDocuments.SF_Calc.A1Style
 
 REM 
-----------------------------------------------------------------------------
 Public Function Activate(Optional ByVal SheetName As Variant) As Boolean
@@ -560,7 +560,7 @@ Public Sub ClearAll(Optional ByVal Range As Variant _
 
        _ClearRange(&quot;All&quot;, Range, FilterFormula, FilterScope)
 
-End Sub        &apos;  SF_Documents.SF_Calc.ClearAll
+End Sub        &apos;  SFDocuments.SF_Calc.ClearAll
 
 REM 
-----------------------------------------------------------------------------
 Public Sub ClearFormats(Optional ByVal Range As Variant _
@@ -580,7 +580,7 @@ Public Sub ClearFormats(Optional ByVal Range As Variant _
 
        _ClearRange(&quot;Formats&quot;, Range, FilterFormula, FilterScope)
 
-End Sub        &apos;  SF_Documents.SF_Calc.ClearFormats
+End Sub        &apos;  SFDocuments.SF_Calc.ClearFormats
 
 REM 
-----------------------------------------------------------------------------
 Public Sub ClearValues(Optional ByVal Range As Variant _
@@ -600,7 +600,7 @@ Public Sub ClearValues(Optional ByVal Range As Variant _
 
        _ClearRange(&quot;Values&quot;, Range, FilterFormula, FilterScope)
 
-End Sub        &apos;  SF_Documents.SF_Calc.ClearValues
+End Sub        &apos;  SFDocuments.SF_Calc.ClearValues
 
 REM 
-----------------------------------------------------------------------------
 Public Function CompactLeft(Optional ByVal Range As Variant _
@@ -1424,7 +1424,7 @@ Try:
 
 Finally:
        Exit Function
-End Function   &apos;  SF_Documents.SF_Calc.DAvg
+End Function   &apos;  SFDocuments.SF_Calc.DAvg
 
 REM 
-----------------------------------------------------------------------------
 Public Function DCount(Optional ByVal Range As Variant) As Long
@@ -1441,7 +1441,7 @@ Try:
 
 Finally:
        Exit Function
-End Function   &apos;  SF_Documents.SF_Calc.DCount
+End Function   &apos;  SFDocuments.SF_Calc.DCount
 
 REM 
-----------------------------------------------------------------------------
 Public Function DMax(Optional ByVal Range As Variant) As Double
@@ -1458,7 +1458,7 @@ Try:
 
 Finally:
        Exit Function
-End Function   &apos;  SF_Documents.SF_Calc.DMax
+End Function   &apos;  SFDocuments.SF_Calc.DMax
 
 REM 
-----------------------------------------------------------------------------
 Public Function DMin(Optional ByVal Range As Variant) As Double
@@ -1475,7 +1475,7 @@ Try:
 
 Finally:
        Exit Function
-End Function   &apos;  SF_Documents.SF_Calc.DMin
+End Function   &apos;  SFDocuments.SF_Calc.DMin
 
 REM 
-----------------------------------------------------------------------------
 Public Function DSum(Optional ByVal Range As Variant) As Double
@@ -1492,7 +1492,7 @@ Try:
 
 Finally:
        Exit Function
-End Function   &apos;  SF_Documents.SF_Calc.DSum
+End Function   &apos;  SFDocuments.SF_Calc.DSum
 
 REM 
-----------------------------------------------------------------------------
 Public Function ExportRangeToFile(Optional ByVal Range As Variant _
@@ -1754,7 +1754,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.GetFormula
+End Function   &apos;  SFDocuments.SF_Calc.GetFormula
 
 REM 
-----------------------------------------------------------------------------
 Public Function GetProperty(Optional ByVal PropertyName As Variant _
@@ -1839,7 +1839,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.GetValue
+End Function   &apos;  SFDocuments.SF_Calc.GetValue
 
 REM 
-----------------------------------------------------------------------------
 Public Function ImportFromCSVFile(Optional ByVal FileName As Variant _
@@ -2300,7 +2300,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.Offset
+End Function   &apos;  SFDocuments.SF_Calc.Offset
 
 REM 
-----------------------------------------------------------------------------
 Public Function OpenRangeSelector(Optional ByVal Title As Variant _
@@ -2381,7 +2381,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.OpenRangeSelector
+End Function   &apos;  SFDocuments.SF_Calc.OpenRangeSelector
 
 REM 
-----------------------------------------------------------------------------
 Public Function Printf(Optional ByVal InputStr As Variant _
@@ -2478,7 +2478,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.Printf
+End Function   &apos;  SFDocuments.SF_Calc.Printf
 
 REM 
-----------------------------------------------------------------------------
 Public Function PrintOut(Optional ByVal SheetName As Variant _
@@ -2711,7 +2711,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.SetArray
+End Function   &apos;  SFDocuments.SF_Calc.SetArray
 
 REM 
-----------------------------------------------------------------------------
 Public Function SetCellStyle(Optional ByVal TargetRange As Variant _
@@ -2789,7 +2789,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.SetCellStyle
+End Function   &apos;  SFDocuments.SF_Calc.SetCellStyle
 
 REM 
-----------------------------------------------------------------------------
 Public Function SetFormula(Optional ByVal TargetRange As Variant _
@@ -2858,7 +2858,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.SetFormula
+End Function   &apos;  SFDocuments.SF_Calc.SetFormula
 
 REM 
-----------------------------------------------------------------------------
 Private Function SetProperty(Optional ByVal psProperty As String _
@@ -2966,7 +2966,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.SetValue
+End Function   &apos;  SFDocuments.SF_Calc.SetValue
 
 REM 
-----------------------------------------------------------------------------
 Public Function ShiftDown(Optional ByVal Range As Variant _
@@ -3423,7 +3423,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc.SortRange
+End Function   &apos;  SFDocuments.SF_Calc.SortRange
 
 REM ======================================================= SUPERCLASS 
PROPERTIES
 
@@ -3685,7 +3685,7 @@ Finally:
        Exit Sub
 Catch:
        GoTo Finally
-End Sub        &apos;  SF_Documents.SF_Calc._ClearRange
+End Sub        &apos;  SFDocuments.SF_Calc._ClearRange
 
 REM 
-----------------------------------------------------------------------------
 Private Function _ComputeFilter(ByRef poRange As Object _
@@ -3853,7 +3853,7 @@ Try:
 
 Finally:
        _ConvertFromDataArray = vArray
-End Function   &apos;  SF_Documents.SF_Calc._ConvertFromDataArray
+End Function   &apos;  SFDocuments.SF_Calc._ConvertFromDataArray
 
 REM 
-----------------------------------------------------------------------------
 Private Function _ConvertToCellValue(ByVal pvItem As Variant) As Variant
@@ -3873,7 +3873,7 @@ Try:
 Finally:
        _ConvertToCellValue = vCell
        Exit Function
-End Function   &apos;  SF_Documents.SF_Calc._ConvertToCellValue
+End Function   &apos;  SFDocuments.SF_Calc._ConvertToCellValue
 
 REM 
-----------------------------------------------------------------------------
 Private Function _ConvertToDataArray(ByRef pvArray As Variant _
@@ -3997,7 +3997,7 @@ Try:
 Finally:
        _ConvertToDataArray = vDataArray
        Exit Function
-End Function   &apos;  SF_Documents.SF_Calc._ConvertToDataArray
+End Function   &apos;  SFDocuments.SF_Calc._ConvertToDataArray
 
 REM 
-----------------------------------------------------------------------------
 Private Function _DFunction(ByVal psFunction As String _
@@ -4043,7 +4043,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc._DFunction
+End Function   &apos;  SFDocuments.SF_Calc._DFunction
 
 REM 
-----------------------------------------------------------------------------
 Private Function _FileIdent() As String
@@ -4205,7 +4205,7 @@ CatchAddress:
                                , &quot;Rows&quot;, plRows, 
&quot;Columns&quot;, plColumns, &quot;Height&quot;, plHeight, 
&quot;Width&quot;, plWidth _
                                , &quot;Document&quot;, [_Super]._FileIdent())
        GoTo Finally
-End Function   &apos;  SF_Documents.SF_Calc._Offset
+End Function   &apos;  SFDocuments.SF_Calc._Offset
 
 REM 
-----------------------------------------------------------------------------
 Private Function _ParseAddress(ByVal psAddress As String) As Object
diff --git a/wizards/source/sfdocuments/SF_Document.xba 
b/wizards/source/sfdocuments/SF_Document.xba
index 30508f2e87b1..e537b90e5da1 100644
--- a/wizards/source/sfdocuments/SF_Document.xba
+++ b/wizards/source/sfdocuments/SF_Document.xba
@@ -864,7 +864,9 @@ Check:
        &apos;  When called from a subclass (Calc, Writer, ..) the arguments 
are gathered into one single array item
        vArgs = Args
        If IsArray(Args) Then
-               If UBound(Args) &gt;= 0 And IsArray(Args(0)) Then vArgs = 
Args(0)
+               If UBound(Args) &gt;= 0 Then
+                       If IsArray(Args(0)) Then vArgs = Args(0)
+               End If
        End If
        If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
                If Not _IsStillAlive() Then GoTo Finally

Reply via email to