wizards/Package_sfdatabases.mk                   |    1 
 wizards/source/scriptforge/SF_Exception.xba      |   19 
 wizards/source/scriptforge/SF_PythonHelper.xba   |    4 
 wizards/source/scriptforge/SF_Root.xba           |   49 
 wizards/source/scriptforge/po/ScriptForge.pot    |   65 
 wizards/source/scriptforge/po/en.po              |   65 
 wizards/source/scriptforge/python/scriptforge.py |   88 +
 wizards/source/sfdatabases/SF_Database.xba       |  146 +-
 wizards/source/sfdatabases/SF_Dataset.xba        | 1664 +++++++++++++++++++++++
 wizards/source/sfdatabases/SF_Datasheet.xba      |    8 
 wizards/source/sfdatabases/script.xlb            |    1 
 11 files changed, 2066 insertions(+), 44 deletions(-)

New commits:
commit 7b2a6f04443c5d80ce681e5f1c89bf140fdb5c3a
Author:     Jean-Pierre Ledure <j...@ledure.be>
AuthorDate: Sat Nov 11 17:02:38 2023 +0100
Commit:     Jean-Pierre Ledure <j...@ledure.be>
CommitDate: Sat Nov 11 18:20:15 2023 +0100

    ScriptForge (SFDatabases) new Dataset service
    
    A dataset represents a set of tabular data
    stored/produced by a database.
    To use datasets, the database instance must exist
    but the Base document may not be open.
    
    A Dataset instance is create either with
    - the (new) database.CreateDataset() method
    - from an existing dataset with the (new)
      dataset.CreateDataset() method.
    
    The proposed API supports next main purposes:
    - browse for- and backward thru the dataset to get its content
    - update any record with new values
    - create new records or delete some.
    In summary, the AKA "CRUD" operations
    (create, read, update, delete).
    
    The originality of the proposed API is the use
    of a dense syntax to make insertions and updates
    easy and readable:
    Example:
    (BASIC)
      Dim newID As Long
      newID = dataset.Insert("LastName", "Doe", "FirstName", "John")
      '     ... is equivalent to:
      Dim dict As Object, newID As Long
      Set dict = CreateScriptService("ScriptForge.Dictionary")
      dict.Add("LastName", "Doe")
      dict.Add("FirstName", "John")
      newID = dataset.Insert(dict)
    (PYTHON) - next statements are equivalent
      newid = dataset.Insert('LastName', 'Doe', 'FirstName', 'John')
      newid = dataset.Insert({'LastName': 'Doe', 'FirstName': 'John'})
      newid = dataset.Insert(dict(LastName = 'Doe', FirstName = 'John'))
      newid = dataset.Insert(LastName = 'Doe', FirstName = 'John')
    
    You will notice that the returned value is the AutoValue primery
    key (when it exists) which makes it reuse as a foreign key
    immediate.
    
    The API is fully available both in Basic and Python user scripts.
    
    The new service will require its inclusion in the user documentation.
    
    Change-Id: I4f834c4234e5b96ec8fddfffbad791ecf31899df
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159325
    Reviewed-by: Jean-Pierre Ledure <j...@ledure.be>
    Tested-by: Jenkins

diff --git a/wizards/Package_sfdatabases.mk b/wizards/Package_sfdatabases.mk
index bc5636fa1b2f..2919c84dce3c 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_Dataset.xba \
        SF_Datasheet.xba \
        SF_Register.xba \
        __License.xba \
diff --git a/wizards/source/scriptforge/SF_Exception.xba 
b/wizards/source/scriptforge/SF_Exception.xba
index 38e5b2ef24e0..4b0fdb8d5eb1 100644
--- a/wizards/source/scriptforge/SF_Exception.xba
+++ b/wizards/source/scriptforge/SF_Exception.xba
@@ -132,6 +132,10 @@ Const DUPLICATECONTROLERROR                =       
&quot;DUPLICATECONTROLERROR&quot;
 &apos; SF_Database
 Const DBREADONLYERROR                  =       &quot;DBREADONLYERROR&quot;
 Const SQLSYNTAXERROR                   =       &quot;SQLSYNTAXERROR&quot;
+Const SQLSYNTAX2ERROR                  =       &quot;SQLSYNTAX2ERROR&quot;
+Const NOCURRENTRECORDERROR             =       &quot;NOCURRENTRECORDERROR&quot;
+Const RECORDUPDATEERROR                        =       
&quot;RECORDUPDATEERROR&quot;
+Const FIELDEXPORTERROR                 =       &quot;FIELDEXPORTERROR&quot;
 
 &apos; Python
 Const PYTHONSHELLERROR                 =       &quot;PYTHONSHELLERROR&quot;
@@ -1035,12 +1039,25 @@ Try:
                                sMessage = sLocation _
                                        &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; &quot;\n&quot; &amp; .GetText(&quot;VALIDATEERROR&quot;, 
pvArgs(0)) _
                                        &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;DUPLICATECONTROL&quot;, pvArgs(0), 
pvArgs(1), pvArgs(2))
-                       Case DBREADONLYERROR    &apos;  SF_Database.RunSql()
+                       Case DBREADONLYERROR    &apos;  SF_Database.RunSql(), 
SF_Dataset.Delete(), Insert(), Update()
                                sMessage = sLocation _
                                        &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;DBREADONLY&quot;, vLocation(2))
                        Case SQLSYNTAXERROR     &apos;  
SF_Database._ExecuteSql(SQL)
                                sMessage = sLocation _
                                        &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;SQLSYNTAX&quot;, pvArgs(0))
+                       Case SQLSYNTAX2ERROR    &apos;  
SF_Dataset.Reload/_Initialize(SQL, Filter, OrderBy)
+                               sMessage = sLocation _
+                                       &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;SQLSYNTAX2&quot;, pvArgs(0), pvArgs(1), 
pvArgs(2))
+                       Case NOCURRENTRECORDERROR       &apos;  
SF_Dataset.Insert/Update/GetValue/Delete
+                               sMessage = sLocation _
+                                       &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;NOCURRENTRECORD&quot;)
+                       Case RECORDUPDATEERROR  &apos;  
SF_Dataset.Insert/Update(FieldName, FieldValue, FieldType)
+                               sMessage = sLocation _
+                                       &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;RECORDUPDATE&quot;, pvArgs(0), pvArgs(1), 
pvARgs(2))
+                       Case FIELDEXPORTERROR   &apos;  
SF_Dataset.ExportFieldToFile(Arg1Name, FileName, Arg2, Overwrite)
+                               pvArgs(0) = _RightCase(pvArgs(0))       :       
pvArgs(2) = _RightCase(pvArgs(2))
+                               sMessage = sLocation _
+                                       &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;FIELDEXPORT&quot;, pvArgs(0), pvArgs(1), 
pvArgs(2), pvArgs(3))
                        Case PYTHONSHELLERROR   &apos;  
SF_Exception.PythonShell (Python only)
                                sMessage = sLocation _
                                        &amp; &quot;\n&quot; &amp; 
&quot;\n&quot; &amp; .GetText(&quot;PYTHONSHELL&quot;)
diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba 
b/wizards/source/scriptforge/SF_PythonHelper.xba
index 8ad0dfa7c06c..bcb0f8a61e75 100644
--- a/wizards/source/scriptforge/SF_PythonHelper.xba
+++ b/wizards/source/scriptforge/SF_PythonHelper.xba
@@ -776,6 +776,8 @@ Try:
                                        Select Case sServiceName
                                                Case 
&quot;SFDatabases.Database&quot;
                                                        If Script = 
&quot;GetRows&quot; Then            vReturn = vBasicObject.GetRows(vArgs(0), 
vArgs(1), vArgs(2), vArgs(3))
+                                               Case 
&quot;SFDatabases.Dataset&quot;
+                                                       If Script = 
&quot;GetRows&quot; Then            vReturn = vBasicObject.GetRows(vArgs(0), 
vArgs(1))
                                                Case 
&quot;SFDialogs.Dialog&quot;
                                                        If Script = 
&quot;Controls&quot; Then           vReturn = vBasicObject.Controls(vArgs(0))
                                                Case 
&quot;SFDialogs.DialogControl&quot;
@@ -945,7 +947,7 @@ Try:
                vReturnArray(1) = V_OBJECT
                Select Case True
                        Case bUno                       :       vReturnArray(2) 
= objUNO
-                       Case bDICT                      :       vReturnArray(2) 
= objDICT
+                       Case bDict                      :       vReturnArray(2) 
= objDICT
                        Case bBasicClass        :       vReturnArray(2) = 
objCLASS
                        Case Else                       :       vReturnArray(2) 
= objMODULE
                End Select
diff --git a/wizards/source/scriptforge/SF_Root.xba 
b/wizards/source/scriptforge/SF_Root.xba
index 488e8bfc2e8f..dc1bfa32a49c 100644
--- a/wizards/source/scriptforge/SF_Root.xba
+++ b/wizards/source/scriptforge/SF_Root.xba
@@ -1028,7 +1028,7 @@ Try:
                                                                        &amp;   
&quot;%2: A string\n&quot; _
                                                                        &amp;   
&quot;%3: A dialog name&quot; _
                                        )
-       &apos;  SF_Database.RunSql
+       &apos;  SF_Database.RunSql, SF_Dataset.Delete/Insert/Update
                        .AddText(       Context := &quot;DBREADONLY&quot; _
                                                , MsgId := &quot;The database 
has been opened in read-only mode.\n&quot; _
                                                                        &amp; 
&quot;The &apos;%1&apos; method must not be executed in this context.&quot; _
@@ -1043,6 +1043,53 @@ Try:
                                                , Comment :=    
&quot;SF_Database can&apos;t interpret SQL statement\n&quot; _
                                                                        &amp;   
&quot;%1: The statement&quot; _
                                        )
+       &apos;  SF_Dataset.Reload/_Initialize
+                       .AddText(       Context := &quot;SQLSYNTAX2&quot; _
+                                               , MsgId := &quot;An SQL 
statement could not be interpreted or executed by the database system.\n&quot; _
+                                                                       &amp; 
&quot;Check its syntax, table and/or field names, ...\n\n&quot; _
+                                                                       &amp; 
&quot;SQL Statement : « %1 »\n&quot; _
+                                                                       &amp; 
&quot;combined with\n&quot; _
+                                                                       &amp; 
&quot;    « %2 »\n&quot; _
+                                                                       &amp; 
&quot;    « %3 »&quot; _
+                                               , Comment :=    
&quot;SF_Database can&apos;t interpret SQL statement\n&quot; _
+                                                                       &amp;   
&quot;%1: The statement\n&quot; _
+                                                                       &amp;   
&quot;%2: a WHERE clause\n&quot; _
+                                                                       &amp;   
&quot;%3: a ORDER BY clause&quot; _
+                                       )
+       &apos;  SF_Dataset.Update/Insert/Delete/GetValue
+                       .AddText(       Context := &quot;NOCURRENTRECORD&quot; _
+                                               , MsgId := &quot;A database 
record could not be retrieved, inserted or updated by the database 
system.\n&quot; _
+                                                                       &amp; 
&quot;The current record could not be determined.\n&quot; _
+                                               , Comment :=    
&quot;SF_Dataset can&apos;t read field values or store field updates&quot; _
+                                       )
+       &apos;  SF_Dataset._SetColumnValue
+                       .AddText(       Context := &quot;RECORDUPDATE&quot; _
+                                               , MsgId := &quot;A database 
record could not be inserted or updated by the database system.\n&quot; _
+                                                                       &amp; 
&quot;Possible reasons:\n&quot; _
+                                                                       &amp; 
&quot;- the field is not updatable\n&quot; _
+                                                                       &amp; 
&quot;- a [NULL] value is provided which is forbidden for the field\n&quot; _
+                                                                       &amp; 
&quot;- the type of value and the type of field are incompatible\n&quot; _
+                                                                       &amp; 
&quot;- the input binary file does not exist or is empty\n&quot; _
+                                                                       &amp; 
&quot;- the field type is not supported\n\n&quot; _
+                                                                       &amp; 
&quot;Field name : « %1 »\n&quot; _
+                                                                       &amp; 
&quot;Field value :  « %2 »\n&quot; _
+                                                                       &amp; 
&quot;Field type :  « %3 »&quot; _
+                                               , Comment :=    
&quot;SF_Database can&apos;t store field updates\n&quot; _
+                                                                       &amp;   
&quot;%1: The field name\n&quot; _
+                                                                       &amp;   
&quot;%2: the value to store in the field&quot; _
+                                       )
+       &apos;  SF_Dataset.ExportFieldToFile
+                       .AddText(       Context := &quot;FIELDEXPORT&quot; _
+                                               , MsgId := &quot;The database 
field could not be exported.\n&quot; _
+                                                                       &amp; 
&quot;Either the destination file must not be overwritten, or it has a 
read-only attribute set.\n\n&quot; _
+                                                                       &amp; 
&quot;%1 = &apos;%2&apos;\n&quot; _
+                                                                       &amp; 
&quot;%3 = %4&quot; _
+                                               , Comment :=    
&quot;SF_Dataset.ExportToFile error message\n&quot; _
+                                                                       &amp;   
&quot;%1: An identifier\n&quot; _
+                                                                       &amp;   
&quot;%2: A file name\n&quot; _
+                                                                       &amp;   
&quot;%3: An identifier\n&quot; _
+                                                                       &amp;   
&quot;%4: True or False\n&quot; _
+                                       )
        &apos;  SF_Exception.PythonShell (Python only)
                        .AddText(       Context := &quot;PYTHONSHELL&quot; _
                                                , MsgId := &quot;The APSO 
extension could not be located in your LibreOffice installation.&quot; _
diff --git a/wizards/source/scriptforge/po/ScriptForge.pot 
b/wizards/source/scriptforge/po/ScriptForge.pot
index 644399bbbd15..814f75ec041f 100644
--- a/wizards/source/scriptforge/po/ScriptForge.pot
+++ b/wizards/source/scriptforge/po/ScriptForge.pot
@@ -14,7 +14,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: 
https://bugs.libreoffice.org/enter_bug.cgi?product=LibreOffice&bug_status=UNCONFIRMED&component=UI\n";
-"POT-Creation-Date: 2023-09-03 13:05:04\n"
+"POT-Creation-Date: 2023-11-11 15:24:14\n"
 "PO-Revision-Date: YYYY-MM-DD HH:MM:SS\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
@@ -990,6 +990,69 @@ msgid  ""
 "SQL Statement : « %1 »"
 msgstr ""
 
+#. SF_Database can't interpret SQL statement
+#. %1: The statement
+#. %2: a WHERE clause
+#. %3: a ORDER BY clause
+#, kde-format
+msgctxt "SQLSYNTAX2"
+msgid  ""
+"An SQL statement could not be interpreted or executed by the "
+"database system.\n"
+"Check its syntax, table and/or field names, ...\n"
+"\n"
+"SQL Statement : « %1 »\n"
+"combined with\n"
+"    « %2 »\n"
+"    « %3 »"
+msgstr ""
+
+#. SF_Dataset can't read field values or store field updates
+msgctxt "NOCURRENTRECORD"
+msgid  ""
+"A database record could not be retrieved, inserted or updated by the "
+"database system.\n"
+"The current record could not be determined.\n"
+""
+msgstr ""
+
+#. SF_Database can't store field updates
+#. %1: The field name
+#. %2: the value to store in the field
+#, kde-format
+msgctxt "RECORDUPDATE"
+msgid  ""
+"A database record could not be inserted or updated by the database "
+"system.\n"
+"Possible reasons:\n"
+"- the field is not updatable\n"
+"- a [NULL] value is provided which is forbidden for the field\n"
+"- the type of value and the type of field are incompatible\n"
+"- the input binary file does not exist or is empty\n"
+"- the field type is not supported\n"
+"\n"
+"Field name : « %1 »\n"
+"Field value :  « %2 »\n"
+"Field type :  « %3 »"
+msgstr ""
+
+#. SF_Dataset.ExportToFile error message
+#. %1: An identifier
+#. %2: A file name
+#. %3: An identifier
+#. %4: True or False
+#. 
+#, kde-format
+msgctxt "FIELDEXPORT"
+msgid  ""
+"The database field could not be exported.\n"
+"Either the destination file must not be overwritten, or it has a "
+"read-only attribute set.\n"
+"\n"
+"%1 = '%2'\n"
+"%3 = %4"
+msgstr ""
+
 #. SF_Exception.PythonShell error messageAPSO: to leave unchanged
 msgctxt "PYTHONSHELL"
 msgid  ""
diff --git a/wizards/source/scriptforge/po/en.po 
b/wizards/source/scriptforge/po/en.po
index 644399bbbd15..814f75ec041f 100644
--- a/wizards/source/scriptforge/po/en.po
+++ b/wizards/source/scriptforge/po/en.po
@@ -14,7 +14,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: 
https://bugs.libreoffice.org/enter_bug.cgi?product=LibreOffice&bug_status=UNCONFIRMED&component=UI\n";
-"POT-Creation-Date: 2023-09-03 13:05:04\n"
+"POT-Creation-Date: 2023-11-11 15:24:14\n"
 "PO-Revision-Date: YYYY-MM-DD HH:MM:SS\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
@@ -990,6 +990,69 @@ msgid  ""
 "SQL Statement : « %1 »"
 msgstr ""
 
+#. SF_Database can't interpret SQL statement
+#. %1: The statement
+#. %2: a WHERE clause
+#. %3: a ORDER BY clause
+#, kde-format
+msgctxt "SQLSYNTAX2"
+msgid  ""
+"An SQL statement could not be interpreted or executed by the "
+"database system.\n"
+"Check its syntax, table and/or field names, ...\n"
+"\n"
+"SQL Statement : « %1 »\n"
+"combined with\n"
+"    « %2 »\n"
+"    « %3 »"
+msgstr ""
+
+#. SF_Dataset can't read field values or store field updates
+msgctxt "NOCURRENTRECORD"
+msgid  ""
+"A database record could not be retrieved, inserted or updated by the "
+"database system.\n"
+"The current record could not be determined.\n"
+""
+msgstr ""
+
+#. SF_Database can't store field updates
+#. %1: The field name
+#. %2: the value to store in the field
+#, kde-format
+msgctxt "RECORDUPDATE"
+msgid  ""
+"A database record could not be inserted or updated by the database "
+"system.\n"
+"Possible reasons:\n"
+"- the field is not updatable\n"
+"- a [NULL] value is provided which is forbidden for the field\n"
+"- the type of value and the type of field are incompatible\n"
+"- the input binary file does not exist or is empty\n"
+"- the field type is not supported\n"
+"\n"
+"Field name : « %1 »\n"
+"Field value :  « %2 »\n"
+"Field type :  « %3 »"
+msgstr ""
+
+#. SF_Dataset.ExportToFile error message
+#. %1: An identifier
+#. %2: A file name
+#. %3: An identifier
+#. %4: True or False
+#. 
+#, kde-format
+msgctxt "FIELDEXPORT"
+msgid  ""
+"The database field could not be exported.\n"
+"Either the destination file must not be overwritten, or it has a "
+"read-only attribute set.\n"
+"\n"
+"%1 = '%2'\n"
+"%3 = %4"
+msgstr ""
+
 #. SF_Exception.PythonShell error messageAPSO: to leave unchanged
 msgctxt "PYTHONSHELL"
 msgid  ""
diff --git a/wizards/source/scriptforge/python/scriptforge.py 
b/wizards/source/scriptforge/python/scriptforge.py
index 13ceadca96fc..bcaff12f5cc5 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -29,7 +29,7 @@
     program document macros with much less hassle and get quicker results.
 
     The use of the ScriptForge interfaces in user scripts hides the complexity 
of the usual UNO interfaces.
-    However it does not replace them. At the opposite their coexistence is 
ensured.
+    However, it does not replace them. At the opposite their coexistence is 
ensured.
     Indeed, ScriptForge provides a number of shortcuts to key UNO objects.
 
     The scriptforge.py module
@@ -216,7 +216,7 @@ class ScriptForge(object, metaclass = _Singleton):
             """
 
         def ParseScript(_script):
-            # Check ParamArray arguments
+            # Check ParamArray, scope, script to run, arguments
             _paramarray = False
             if _script[0] == '@':
                 _script = _script[1:]
@@ -241,7 +241,7 @@ class ScriptForge(object, metaclass = _Singleton):
                     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
+            _fullscript = ('@' if _paramarray else '') + scope + '#' + _script
             try:
                 _xscript = cls.scriptprovider.getScript(uri)     # 
com.sun.star.script.provider.XScript
             except Exception:
@@ -1784,6 +1784,9 @@ class SFDatabases:
         def CloseDatabase(self):
             return self.ExecMethod(self.vbMethod, 'CloseDatabase')
 
+        def CreateDataset(self, sqlcommand, directsql = False, filter = '', 
orderby = ''):
+            return self.ExecMethod(self.vbMethod, 'CreateDataset', sqlcommand, 
directsql, filter, orderby)
+
         def DAvg(self, expression, tablename, criteria = ''):
             return self.ExecMethod(self.vbMethod, 'DAvg', expression, 
tablename, criteria)
 
@@ -1820,6 +1823,85 @@ class SFDatabases:
         def RunSql(self, sqlcommand, directsql = False):
             return self.ExecMethod(self.vbMethod, 'RunSql', sqlcommand, 
directsql)
 
+    # #########################################################################
+    # SF_Dataset CLASS
+    # #########################################################################
+    class SF_Dataset(SFServices):
+        """
+            A dataset represents a set of tabular data produced by a database.
+            In the user interface of LibreOffice a dataset corresponds with 
the data
+            displayed in a form, a data sheet (table, query).
+            To use datasets, the database instance must exist but the Base 
document may not be open.
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDatabases.Dataset'
+        servicesynonyms = ()    # CreateScriptService is not applicable here
+        serviceproperties = dict(BOF = True, DefaultValues = False, EOF = 
True, Fields = False, Filter = False,
+                                 OrderBy = False, ParentDatabase = False, 
RowCount = False, RowNumber = False,
+                                 Source = False, SourceType = False, 
UpdatableFields = False, Values = False,
+                                 XRowSet = False)
+        forceGetProperty = True
+
+        @classmethod
+        def _dictargs(cls, args, kwargs):
+            """
+                Convert a set of keyword arguments to a dictionary to pass to 
the Basic world
+                """
+            if len(args) == 0 and len(kwargs) > 0:
+                return kwargs
+            if len(args) > 0:
+                if len(kwargs) == 0:
+                    if isinstance(args[0], dict):
+                        return args[0]
+                    return {args[i]: args[i + 1] for i in range(0, len(args), 
2)}
+            return None
+
+        def CloseDataset(self):
+            return self.ExecMethod(self.vbMethod, 'CloseDataset')
+
+        def CreateDataset(self, filter = ScriptForge.cstSymMissing, orderby = 
ScriptForge.cstSymMissing):
+            return self.ExecMethod(self.vbMethod, 'CreateDataset', filter, 
orderby)
+
+        def Delete(self):
+            return self.ExecMethod(self.vbMethod, 'Delete')
+
+        def ExportValueToFile(self, fieldname, filename, overwrite = False):
+            return self.ExecMethod(self.vbMethod, 'ExportValueToFile', 
fieldname, filename, overwrite)
+
+        def GetRows(self, header = False, maxrows = 0):
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 
'GetRows', header, maxrows)
+
+        def GetValue(self, fieldname):
+            return self.ExecMethod(self.vbMethod, 'GetValue', fieldname)
+
+        def Insert(self, *args, **kwargs):
+            updateslist = self._dictargs(args, kwargs)
+            if updateslist is None:
+                return -1   # The insertion could not be done
+            return self.ExecMethod(self.vbMethod + self.flgDictArg, 'Insert', 
updateslist)
+
+        def MoveFirst(self):
+            return self.ExecMethod(self.vbMethod, 'MoveFirst')
+
+        def MoveLast(self):
+            return self.ExecMethod(self.vbMethod, 'MoveLast')
+
+        def MoveNext(self, offset = 1):
+            return self.ExecMethod(self.vbMethod, 'MoveNext', offset)
+
+        def MovePrevious(self, offset = 1):
+            return self.ExecMethod(self.vbMethod, 'MovePrevious', offset)
+
+        def Reload(self, filter = ScriptForge.cstSymMissing, orderby = 
ScriptForge.cstSymMissing):
+            return self.ExecMethod(self.vbMethod, 'Reload', filter, orderby)
+
+        def Update(self, *args, **kwargs):
+            updateslist = self._dictargs(args, kwargs)
+            if updateslist is None:
+                return False   # The update could not be done
+            return self.ExecMethod(self.vbMethod + self.flgDictArg, 'Update', 
updateslist)
+
     # #########################################################################
     # SF_Datasheet CLASS
     # #########################################################################
diff --git a/wizards/source/sfdatabases/SF_Database.xba 
b/wizards/source/sfdatabases/SF_Database.xba
index f280762d8146..50d2e2e41cd3 100644
--- a/wizards/source/sfdatabases/SF_Database.xba
+++ b/wizards/source/sfdatabases/SF_Database.xba
@@ -53,6 +53,7 @@ REM 
================================================================== EXCEPTION
 
 Private Const DBREADONLYERROR          =       &quot;DBREADONLYERROR&quot;
 Private Const SQLSYNTAXERROR           =       &quot;SQLSYNTAXERROR&quot;
+Private Const SQLSYNTAX2ERROR          =       &quot;SQLSYNTAX2ERROR&quot;
 
 REM ============================================================= PRIVATE 
MEMBERS
 
@@ -153,6 +154,105 @@ Finally:
        Exit Sub
 End Sub
 
+REM 
-----------------------------------------------------------------------------
+Public Function CreateDataset(Optional ByVal SQLCommand As Variant _
+                                                                       , 
Optional ByVal DirectSql As Variant _
+                                                                       , 
Optional ByVal Filter As Variant _
+                                                                       , 
Optional ByVal OrderBy As Variant _
+                                                                       ) As 
Object
+&apos;&apos;&apos;     Create and return a Dataset class instance based on a 
table, a query
+&apos;&apos;&apos;     or an SQL SELECT statement.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             SQLCommand: as a case-sensitive string, a table 
name, a query name
+&apos;&apos;&apos;                     or a valid SQL SELECT statement. 
Identifiers may be srrounded
+&apos;&apos;&apos;                     with square brackets
+&apos;&apos;&apos;             DirectSql: when True, the statement is 
processed by the targeted RDBMS
+&apos;&apos;&apos;             Filter: an additional condition that records 
must match, expressed
+&apos;&apos;&apos;                     as a valid SQL WHERE clause without the 
WHERE keyword
+&apos;&apos;&apos;             OrderBy: the ordering of the dataset expressed 
as a valid SQL ORDER BY clause
+&apos;&apos;&apos;                     without the ORDER BY keywords
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A SF_Dataset instance or Nothing when not 
successful
+&apos;&apos;&apos;     Exceptions
+&apos;&apos;&apos;             SQLSYNTAX2ERROR                 The given SQL 
statement is incorrect
+
+Dim oDataset As Object                 &apos;  Return value
+Dim bDirect As Boolean                 &apos;  Alias of DirectSql
+Dim sSql As String                             &apos;  SQL statement
+Dim sType As String                            &apos;  TABLE, QUERY or SQL
+Dim oQuery As Object                   &apos;  com.sun.star.ucb.XContent
+Dim ARR As Object                              :       Set ARR = 
ScriptForge.SF_Array
+
+Const cstThisSub = &quot;SFDatabases.Database.CreateDataset&quot;
+Const cstSubArgs = &quot;SQLCommand, [DirectSQL=False], 
[Filter=&quot;&quot;&quot;&quot;], [OrderBy=&quot;&quot;&quot;&quot;]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oDataset = Nothing
+
+Check:
+       If IsMissing(DirectSQL) Or IsEmpty(DirectSQL) Then DirectSQL = False
+       If IsMissing(Filter) Or IsEmpty(Filter) Then Filter = &quot;&quot;
+       If IsMissing(OrderBy) Or IsEmpty(OrderBy) Then OrderBy = &quot;&quot;
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(SQLCommand, 
&quot;SQLCommand&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(DirectSQL, 
&quot;DirectSQL&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(Filter, 
&quot;Filter&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(OrderBy, 
&quot;OrderBy&quot;, V_STRING) Then GoTo Finally
+       End If
+
+Try:
+       &apos;  Table, query of SQL ? Prepare dataset
+       If ARR.Contains(Tables, SQLCommand, CaseSensitive := True, SortOrder := 
&quot;ASC&quot;) Then
+               If Len(Filter) + Len(OrderBy) = 0 Then          &apos;  Filter 
seems not applicable on pure TABLE resultset
+                       sType = &quot;TABLE&quot;
+                       sSql = SQLCommand
+               Else
+                       sType = &quot;SQL&quot;
+                       sSql = &quot;SELECT * FROM [&quot; &amp; SQLCommand 
&amp; &quot;]&quot;
+               End If
+               bDirect = DirectSQL
+       ElseIf ARR.Contains(Queries, SQLCommand, CaseSensitive := True, 
SortOrder := &quot;ASC&quot;) Then
+               Set oQuery = _Connection.Queries.getByName(SQLCommand)
+               If Len(Filter) + Len(OrderBy) = 0 Then          &apos;  Filter 
seems not applicable on pure QUERY resultset
+                       sType = &quot;QUERY&quot;
+                       sSql = SQLCommand
+               Else
+                       sType = &quot;SQL&quot;
+                       sSql = oQuery.Command
+               End If
+               bDirect = Not oQuery.EscapeProcessing
+       ElseIf ScriptForge.SF_String.StartsWith(SQLCommand, &quot;SELECT&quot;, 
CaseSensitive := False) Then
+               sType = &quot;SQL&quot;
+               sSql = SQLCommand
+               bDirect = DirectSQL
+       Else
+               If Not ScriptForge.SF_Utils._Validate(SQLCommand, 
&quot;SQLCommand&quot;, V_STRING _
+                       , ARR.Flatten(ARR.Append(Tables, Queries))) Then GoTo 
Finally
+       End If
+
+       Set oDataset = New SF_Dataset
+       With oDataset
+               Set .[Me] = oDataset
+               Set ._ParentDatabase = [Me]
+               ._DatasetType = sType
+               ._Command = SQLCommand
+               ._Sql = _ReplaceSquareBrackets(sSql)
+               ._DirectSql = bDirect
+               ._Filter = _ReplaceSquareBrackets(Filter)
+               ._OrderBy = _ReplaceSquareBrackets(OrderBy)
+               ._ReadOnly = _ReadOnly
+               &apos;  If creation not successful, then cancel everything
+               If Not ._Initialize() Then Set oDataset = .Dispose()
+       End With
+
+Finally:
+       Set CreateDataset = oDataset
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Database.CreateDataset
+
 REM 
-----------------------------------------------------------------------------
 Public Function DAvg(Optional ByVal Expression As Variant _
                                                                , Optional 
ByVal TableName As Variant _
@@ -354,7 +454,7 @@ Try:
 
        With oResult
                &apos;Initialize output array with header row
-               Set oColumns = oResult.getColumns()
+               Set oColumns = .getColumns()
                lCols = oColumns.Count - 1
                If Header Then
                        lRows = 0
@@ -397,6 +497,7 @@ Public Function Methods() As Variant
 
        Methods = Array( _
                                        &quot;CloseDatabase&quot; _
+                                       , &quot;CreateDataset&quot; _
                                        , &quot;DAvg&quot; _
                                        , &quot;DCount&quot; _
                                        , &quot;DLookup&quot; _
@@ -803,9 +904,7 @@ Try:
        &apos;  Execute the SQL statement and retain the first column of the 
first record
        Set oResult = _ExecuteSql(sSql, True)
        If Not IsNull(oResult) And Not IsEmpty(oResult) Then
-               If Not oResult.first() Then Goto Finally
-               If oResult.isAfterLast() Then GoTo Finally
-               vResult = _GetColumnValue(oResult, 1, True)             &apos;  
Force return of binary field
+               If oResult.first() Then vResult = _GetColumnValue(oResult, 1) 
Else GoTo Finally
        End If
        Set oResult = Nothing
 
@@ -861,6 +960,7 @@ Finally:
        Set oStatement = Nothing
        Exit Function
 Catch_Sql:
+       On Local Error GoTo 0
        ScriptForge.SF_Exception.RaiseFatal(SQLSYNTAXERROR, sSql)
        GoTo Finally
 Catch:
@@ -870,20 +970,17 @@ End Function      &apos;  
SFDatabases.SF_Database._ExecuteSql
 REM 
-----------------------------------------------------------------------------
 Private Function _GetColumnValue(ByRef poResultSet As Object _
                                                                        , ByVal 
plColIndex As Long _
-                                                                       , 
Optional ByVal pbReturnBinary As Boolean _
                                                                        ) As 
Variant
 &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 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
 &apos;&apos;&apos;     Returns:
 &apos;&apos;&apos;             The Variant value found in the column
 &apos;&apos;&apos;             Dates and times are returned as Basic dates
 &apos;&apos;&apos;             Null values are returned as Null
+&apos;&apos;&apos;             Binary fields are returned as a Long giving 
their length
 &apos;&apos;&apos;             Errors or strange data types are returned as 
Null as well
        
 Dim vValue As Variant                  &apos;  Return value
@@ -897,7 +994,6 @@ Const cstMaxBinlength = 2 * 65535
 
        On Local Error Goto 0                   &apos;  Disable error handler
        vValue = Empty                                  &apos;  Default value 
if error
-       If IsMissing(pbReturnBinary) Then pbReturnBinary = False
 
        With com.sun.star.sdbc.DataType
                lType = poResultSet.MetaData.getColumnType(plColIndex)
@@ -908,20 +1004,11 @@ Const cstMaxBinlength = 2 * 65535
                        Case .BINARY, .VARBINARY, .LONGVARBINARY, .BLOB
                                Set oStream = 
poResultSet.getBinaryStream(plColIndex)
                                If bNullable Then
-                                       If Not poResultSet.wasNull() Then
-                                               If Not 
ScriptForge.SF_Session.HasUNOMethod(oStream, &quot;getLength&quot;) Then &apos; 
 When no recordset
-                                                       lSize = cstMaxBinLength
-                                               Else
-                                                       lSize = 
CLng(oStream.getLength())
-                                               End If
-                                               If lSize &lt;= cstMaxBinLength 
And pbReturnBinary Then
-                                                       vValue = Array()
-                                                       
oStream.readBytes(vValue, lSize)
-                                               Else    &apos;  Return length 
of field, not content
-                                                       vValue = lSize
-                                               End If
-                                       End If
+                                       If Not poResultSet.wasNull() Then lSize 
= CLng(oStream.getLength()) Else lSize = 0
+                               Else
+                                       lSize = CLng(oStream.getLength())
                                End If
+                               vValue = lSize  &apos;  Return length of field, 
not content
                                If Not IsNull(oStream) Then oStream.closeInput()
                        Case .BIT, .BOOLEAN                             :       
vValue = poResultSet.getBoolean(plColIndex)
                        Case .DATE
@@ -935,16 +1022,10 @@ Const cstMaxBinlength = 2 * 65535
                        Case .BIGINT                                    :       
vValue = CLng(poResultSet.getLong(plColIndex))
                        Case .DECIMAL, .NUMERIC                 :       vValue 
= poResultSet.getDouble(plColIndex)
                        Case .SQLNULL                                   :       
vValue = poResultSet.getNull(plColIndex)
-                       Case .OBJECT, .OTHER, .STRUCT   :       vValue = Null
                        Case .REF                                               
:       vValue = poResultSet.getRef(plColIndex)
                        Case .TINYINT                                   :       
vValue = poResultSet.getShort(plColIndex)
-                       Case .CHAR, .VARCHAR                    :       vValue 
= poResultSet.getString(plColIndex)
-                       Case .LONGVARCHAR, .CLOB
-                               If bNullable Then
-                                       If Not poResultSet.wasNull() Then 
vValue = poResultSet.getString(plColIndex)
-                               Else
-                                       vValue = &quot;&quot;
-                               End If
+                       Case .CHAR, .VARCHAR, .LONGVARCHAR, .CLOB
+                                                                               
                vValue = poResultSet.getString(plColIndex)
                        Case .TIME
                                vDateTime = poResultSet.getTime(plColIndex)
                                If Not poResultSet.wasNull() Then vValue = 
TimeSerial(vDateTime.Hours, vDateTime.Minutes, vDateTime.Seconds)&apos;, 
vDateTime.HundredthSeconds)
@@ -956,6 +1037,7 @@ Const cstMaxBinlength = 2 * 65535
                                vValue = poResultSet.getString(plColIndex)      
                &apos;GIVE STRING A TRY
                                If IsNumeric(vValue) Then vValue = Val(vValue)  
        &apos;Required when type = &quot;&quot;, sometimes numeric fields are 
returned as strings (query/MSAccess)
                End Select
+               &apos;  .wasNull() must be preceded by getXXX(). Done. Test for 
Null here.
                If bNullable Then
                        If poResultSet.wasNull() Then vValue = Null
                End If
@@ -963,7 +1045,7 @@ Const cstMaxBinlength = 2 * 65535
        
        _GetColumnValue = vValue
        
-End Function   &apos;  SFDatabases.SF_Database.GetColumnValue
+End Function   &apos;  SFDatabases.SF_Database._GetColumnValue
 
 REM 
-----------------------------------------------------------------------------
 Public Function _OpenDatasheet(Optional ByVal psCommand As Variant _
@@ -1088,4 +1170,4 @@ Private Function _Repr() As String
 End Function   &apos;  SFDatabases.SF_Database._Repr
 
 REM ============================================ END OF SFDATABASES.SF_DATABASE
-</script:module>
+</script:module>
\ No newline at end of file
diff --git a/wizards/source/sfdatabases/SF_Dataset.xba 
b/wizards/source/sfdatabases/SF_Dataset.xba
new file mode 100644
index 000000000000..e25f714f6ddf
--- /dev/null
+++ b/wizards/source/sfdatabases/SF_Dataset.xba
@@ -0,0 +1,1664 @@
+<?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_Dataset" 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_Dataset
+&apos;&apos;&apos;     ==========
+&apos;&apos;&apos;             A dataset represents a set of tabular data 
produced by a database.
+&apos;&apos;&apos;             In the user interface of LibreOffice a dataset 
corresponds with the data
+&apos;&apos;&apos;             displayed in a form or a data sheet (table, 
query).
+&apos;&apos;&apos;             To use datasets, the database instance must 
exist but the Base document may not be open.
+&apos;&apos;&apos;
+&apos;&apos;&apos;             In the context of ScriptForge, a dataset may be 
created automatically by script code :
+&apos;&apos;&apos;                     - at any moment =&gt; in this case the 
Base document may or may not be open.
+&apos;&apos;&apos;                     - any SELECT SQL statement may define 
the dataset.
+&apos;&apos;&apos;
+&apos;&apos;&apos;             The proposed API supports next main purposes:
+&apos;&apos;&apos;                     - browse for- and backward thru the 
dataset to get its content
+&apos;&apos;&apos;                     - update any record with new values
+&apos;&apos;&apos;                     - create new records or delete some.
+&apos;&apos;&apos;             So-called &quot;CRUD&quot; operations (create, 
read, update, delete).
+&apos;&apos;&apos;
+&apos;&apos;&apos;             Service invocation:
+&apos;&apos;&apos;                     A dataset is characterized by
+&apos;&apos;&apos;                             - the parent database
+&apos;&apos;&apos;                             - a table/query name or an SQL 
SELECT statemnt
+&apos;&apos;&apos;                             - the DirectSQL option to 
bypass the processing of SQL by LibreOffice
+&apos;&apos;&apos;                             - an optional filter
+&apos;&apos;&apos;                             - an optional sorting order
+&apos;&apos;&apos;                     1) From a database class instance
+&apos;&apos;&apos;                             Dim db As Object, FileName As 
String, Dataset As Object, Dataset2 As Object
+&apos;&apos;&apos;                             Set db = 
CreateScriptService(&quot;SFDatabases.Database&quot;, FileName, , ReadOnly := 
False)
+&apos;&apos;&apos;                             Set Dataset = 
db.CreateDataset(&quot;myTable&quot;, DirectSql := False, Filter := 
&quot;[City]=&apos;Brussels&apos;&quot;)
+&apos;&apos;&apos;                     2) From an existing dataset
+&apos;&apos;&apos;                             Set Dataset2 = 
Dataset.CreateDataset(Filter := &quot;[City]=&apos;Paris&apos;&quot;)
+&apos;&apos;&apos;
+&apos;&apos;&apos;             Dataset browsing with the MoveNext(), 
MovePrevious(), ... methods
+&apos;&apos;&apos;                     After creation of the dataset, the 
current record is positioned BEFORE the first record.
+&apos;&apos;&apos;                     Every MoveXXX() method returns False 
when no record could be retrieved, otherwise True.
+&apos;&apos;&apos;                     When False, the current record is reset 
either in BOF or EOF positions.
+&apos;&apos;&apos;                     Typically:
+&apos;&apos;&apos;                             Set dataset = 
db.CreateDataset(&quot;myTable&quot;)
+&apos;&apos;&apos;                             With Dataset
+&apos;&apos;&apos;                                     Do While .MoveNext()
+&apos;&apos;&apos;                                             ...
+&apos;&apos;&apos;                                     Loop
+&apos;&apos;&apos;                                     .CloseDataset()
+&apos;&apos;&apos;                             End With
+&apos;&apos;&apos;
+&apos;&apos;&apos;             Updates performance:
+&apos;&apos;&apos;                     This module provides methods to update 
data stored in database tables.
+&apos;&apos;&apos;                     Note that the proposed Update() and 
Insert() methods wil always be
+&apos;&apos;&apos;                     SLOWER or MUCH SLOWER than equivalent 
SQL statements.
+&apos;&apos;&apos;                     Always privilege SQL when considering 
massive updates.
+&apos;&apos;&apos;
+&apos;&apos;&apos;             Detailed user documentation:
+&apos;&apos;&apos;                     
https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/SF_Dataset.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
+
+&apos; Error in the dataset&apos;s initial SQL statement
+Private Const SQLSYNTAX2ERROR          =       &quot;SQLSYNTAX2ERROR&quot;
+&apos; The current record could not be determined
+Private Const NOCURRENTRECORDERROR     =       &quot;NOCURRENTRECORDERROR&quot;
+&apos; Database is read-only. Method rejected
+Private Const DBREADONLYERROR          =       &quot;DBREADONLYERROR&quot;
+&apos; Database fields update error
+&apos;         Value to store does not fit the type of the field
+&apos;         Field is not nullable and value = Null
+&apos;         Field is not writable or autovalue
+&apos;         Input file does not exist or is empty
+&apos;         Field type is not supported
+Private Const RECORDUPDATEERROR                =       
&quot;RECORDUPDATEERROR&quot;
+&apos; The destination file exists and cannot be overwritten
+Private Const FIELDEXPORTERROR         =       &quot;FIELDEXPORTERROR&quot;
+
+REM ============================================================= PRIVATE 
MEMBERS
+
+Private [Me]                           As Object
+Private ObjectType                     As String               &apos; Must be 
DATASET
+Private ServiceName                    As String
+
+Private _ParentDatabase                As Object               &apos; The 
parent SF_Database instance (must not be void)
+Private _DatasetType           As String               &apos; TABLE, QUERY or 
SQL
+Private _Command                       As String               &apos; Table 
name, query name or SQL statement
+Private _Sql                           As String               &apos; 
Equivalent SQL command
+Private _DirectSql                     As Boolean              &apos; When 
True, SQL processed by RDBMS
+Private _Filter                                As String               &apos; 
WHERE clause without WHERE
+Private _OrderBy                       As String               &apos; ORDER BY 
clause without ORDER BY
+Private _ReadOnly                      As Boolean              &apos; When 
True, updates are forbidden
+
+Private _RowSet                                As Object               &apos; 
com.sun.star.sdb.RowSet
+
+Private _Fields                                As Variant              &apos; 
Array of field names
+Private _UpdatableFields       As Variant              &apos; Array of 
updatable field names
+Private _DefaultValues         As Variant              &apos; Array of field 
default values // _Fields
+Private _AutoValue                     As Long                 &apos; Index of 
AutoValue field. None = -1
+
+REM ============================================================ MODULE 
CONSTANTS
+
+REM ====================================================== 
CONSTRUCTOR/DESTRUCTOR
+
+REM 
-----------------------------------------------------------------------------
+Private Sub Class_Initialize()
+       Set [Me] = Nothing
+       ObjectType = &quot;DATASET&quot;
+       ServiceName = &quot;SFDatabases.Dataset&quot;
+       Set _ParentDatabase = Nothing
+       _DatasetType = &quot;&quot;
+       _Command = &quot;&quot;
+       _DirectSql = False
+       _Filter = &quot;&quot;
+       _OrderBy = &quot;&quot;
+       _ReadOnly = False
+       Set _RowSet = Nothing
+       _Fields = Array()
+       _UpdatableFields = Array()
+       _DefaultValues = Array()
+       _AutoValue = -1
+End Sub                &apos;  SFDatabases.SF_Dataset Constructor
+
+REM 
-----------------------------------------------------------------------------
+Private Sub Class_Terminate()
+       Call Class_Initialize()
+End Sub                &apos;  SFDatabases.SF_Dataset Destructor
+
+REM 
-----------------------------------------------------------------------------
+Public Function Dispose() As Variant
+       Call Class_Terminate()
+       Set Dispose = Nothing
+End Function   &apos;  SFDatabases.SF_Dataset Explicit Destructor
+
+REM ================================================================== 
PROPERTIES
+
+REM 
-----------------------------------------------------------------------------
+Property Get BOF() As Variant
+&apos;&apos;&apos;     The BOF property returns True if the current record 
position is before the first record
+&apos;&apos;&apos;     in the Dataset, otherwise it returns False.
+       Bof = _PropertyGet(&quot;BOF&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.BOF (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Let BOF(Optional ByVal pvBOF As Variant)
+&apos;&apos;&apos;     Set the updatable property BOF.
+&apos;&apos;&apos;     Setting BOF to True positions the current record before 
the first record.
+&apos;&apos;&apos;     Setting it to False is ignored. True is the only 
relevant value.
+       _PropertySet(&quot;BOF&quot;, pvBOF)
+End Property   &apos;  SFDatabases.SF_Dataset.BOF (let)
+
+REM 
-----------------------------------------------------------------------------
+Property Get DefaultValues() As Variant
+&apos;&apos;&apos;     Returns a dictionary (field name =&gt; default value).
+&apos;&apos;&apos;     The database field type is converted to the 
corresponding Basic/Python variable types.
+&apos;&apos;&apos;     When undefined: returns either Null (field is nullable) 
or Empty
+&apos;&apos;&apos;     The output dictionary should be disposed by the user 
script
+       DefaultValues = _PropertyGet(&quot;DefaultValues&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.DefaultValues (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Get EOF() As Variant
+&apos;&apos;&apos;     The EOF property returns True if the current record 
position is after the last record
+&apos;&apos;&apos;     in the Dataset, otherwise it returns False.
+       EOF = _PropertyGet(&quot;EOF&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.EOF (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Let EOF(Optional ByVal pvEOF As Variant)
+&apos;&apos;&apos;     Set the updatable property EOF.
+&apos;&apos;&apos;     Setting EOF to True positions the current record after 
the last record.
+&apos;&apos;&apos;     Setting it to False is ignored. True is the only 
relevant value.
+       _PropertySet(&quot;EOF&quot;, pvEOF)
+End Property   &apos;  SFDatabases.SF_Dataset.EOF (let)
+
+REM 
-----------------------------------------------------------------------------
+Property Get Fields() As Variant
+&apos;&apos;&apos;     Returns the list of the field names contained in the 
dataset
+       Fields = _PropertyGet(&quot;Fields&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.Fields (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Get Filter() As Variant
+&apos;&apos;&apos;     The Filter is a SQL WHERE clause without the WHERE 
keyword
+       Filter = _PropertyGet(&quot;Filter&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.Filter (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Get OrderBy() As Variant
+&apos;&apos;&apos;     The OrderBy is an SQL ORDER BY clause without the ORDER 
BY keyword
+       OrderBy = _PropertyGet(&quot;OrderBy&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.OrderBy (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Get ParentDatabase() As Object
+&apos;&apos;&apos;     Returns the database instance to which the dataset 
belongs
+       Set ParentDatabase = _PropertyGet(&quot;ParentDatabase&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.ParentDatabase
+
+REM 
-----------------------------------------------------------------------------
+Property Get RowCount() As Long
+&apos;&apos;&apos;     Returns the number of records present in the dataset
+&apos;&apos;&apos;     When that number exceeds a certain limit, its 
determination requires
+&apos;&apos;&apos;     that the whole dataset has been read first, up to its 
last row.
+&apos;&apos;&apos;     For huge datasets, this can represent a significant 
performance cost.
+       RowCount = _PropertyGet(&quot;RowCount&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.RowCount
+
+REM 
-----------------------------------------------------------------------------
+Property Get RowNumber() As Long
+&apos;&apos;&apos;     Returns the sequence number &gt;= 1 of the current 
record. Returns 0 if unknown.
+       RowNumber = _PropertyGet(&quot;RowNumber&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.RowNumber
+
+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_Dataset.Source
+
+REM 
-----------------------------------------------------------------------------
+Property Get SourceType() As String
+&apos;&apos;&apos;     Returns the type of source of the data: TABLE, QUERY or 
SQL
+       SourceType = _PropertyGet(&quot;SourceType&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.SourceType
+
+REM 
-----------------------------------------------------------------------------
+Property Get UpdatableFields() As Variant
+&apos;&apos;&apos;     Returns the list of the names of the updatable fields 
contained in the dataset
+       UpdatableFields = _PropertyGet(&quot;UpdatableFields&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.UpdatableFields (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Get Values() As Variant
+&apos;&apos;&apos;     Returns a dictionary (field name =&gt; field value) 
applied on the current record
+&apos;&apos;&apos;     Binary fields ? =&gt; their length is returned
+&apos;&apos;&apos;     The output dictionary should be disposed by the user 
script
+&apos;&apos;&apos;     Returns Nothing when there is no current record
+       Values = _PropertyGet(&quot;Values&quot;)
+End Property   &apos;  SFDatabases.SF_Dataset.Values (get)
+
+REM 
-----------------------------------------------------------------------------
+Property Get XRowSet() As Object
+&apos;&apos;&apos;     Returns the com.sun.star.sdb.RowSet UNO object 
representing the dataset
+       XRowSet = _PropertyGet(&quot;XRowSet&quot;)
+End Property   &apos;  SFDocuments.SF_Document.XRowSet
+
+REM ===================================================================== 
METHODS
+
+REM 
-----------------------------------------------------------------------------
+Public Function CloseDataset() As Boolean
+&apos;&apos;&apos; Close the actual dataset
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             dataset.CloseDataset()
+
+Dim bClose As Boolean          &apos;  Return value
+Const cstThisSub = &quot;SFDatabases.Sataset.CloseDataset&quot;
+Const cstSubArgs = &quot;&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bClose = False
+
+Check:
+       SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+Try:
+       If Not IsNull(_RowSet) Then
+               With _RowSet
+                       .close()
+                       .dispose()
+               End With
+               Dispose()
+               bClose = True
+       End If
+
+Finally:
+       CloseDataset = bClose
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;   SFDatabases.SF_Dataset.CloseDataset
+
+REM 
-----------------------------------------------------------------------------
+Public Function CreateDataset(Optional ByVal Filter As Variant _
+                                                                       , 
Optional ByVal OrderBy As Variant _
+                                                                       ) As 
Object
+&apos;&apos;&apos;     Create and return a Dataset class instance based on the 
actual Dataset
+&apos;&apos;&apos;     Filter and OrderBy properties may be redefined.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Filter: an additional condition that records 
must match, expressed
+&apos;&apos;&apos;                     as a valid SQL WHERE clause without the 
WHERE keyword
+&apos;&apos;&apos;                     Default: the filter applied on the 
actual dataset.
+&apos;&apos;&apos;             OrderBy: the ordering of the dataset expressed 
as a valid SQL ORDER BY clause
+&apos;&apos;&apos;                     without the ORDER BY keywords.
+&apos;&apos;&apos;                     Default: the same sorting order as the 
actual dataset.
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             A SF_Dataset instance or Nothing when not 
successful
+&apos;&apos;&apos;     Exceptions
+&apos;&apos;&apos;             SQLSYNTAX2ERROR                 The given SQL 
statement is incorrect
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             Dim ds1 As Object, ds2 As Object, ds3 As 
Object, ds4 As Object
+&apos;&apos;&apos;             Set ds1 = dataset.CreateDataset()               
                &apos;  dataset and ds1 contain the same set of data
+&apos;&apos;&apos;             Set ds2 = dataset.CreateDataset(Filter := 
&quot;&quot;) &apos;  Suppress the current filter
+&apos;&apos;&apos;             Set ds3 = dataset.CreateDataset(Filter := 
&quot;[Name] LIKE &apos;A%&apos;&quot;)
+&apos;&apos;&apos;                                                             
                                                &apos;  Define a new filter
+&apos;&apos;&apos;             Set ds4 = dataset.CreateDataset(Filter := 
&quot;(&quot; &amp; dataset.Filter &amp; &quot;) AND [Name] LIKE 
&apos;A%&apos;&quot;)
+&apos;&apos;&apos;                                                             
                                                &apos;  Combine actual filter 
with an additional condition
+
+Dim oDataset As Object                 &apos;  Return value
+
+Const cstThisSub = &quot;SFDatabases.Dataset.CreateDataset&quot;
+Const cstSubArgs = &quot;[Filter=&quot;&quot;...filter...&quot;&quot;], 
[OrderBy=&quot;&quot;...orderby...&quot;&quot;]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       Set oDataset = Nothing
+
+Check:
+       If IsMissing(Filter) Or IsEmpty(Filter) Then Filter = _Filter
+       If IsMissing(OrderBy) Or IsEmpty(OrderBy) Then OrderBy = _OrderBy
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(Filter, 
&quot;Filter&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(OrderBy, 
&quot;OrderBy&quot;, V_STRING) Then GoTo Finally
+       End If
+
+Try:
+       Set oDataset = New SF_Dataset
+       With oDataset
+               Set .[Me] = oDataset
+               Set ._ParentDatabase = _ParentDatabase
+               ._DatasetType = _DatasetType
+               ._Command = _Command
+               ._Sql = _Sql
+               ._DirectSql = _DirectSql
+               ._Filter = _ParentDatabase._ReplaceSquareBrackets(Filter)
+               ._OrderBy = _ParentDatabase._ReplaceSquareBrackets(OrderBy)
+               ._ReadOnly = _ReadOnly
+               &apos;  If creation not successful, then cancel everything
+               If Not ._Initialize() Then Set oDataset = .Dispose()
+       End With
+
+Finally:
+       Set CreateDataset = oDataset
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.CreateDataset
+
+REM 
-----------------------------------------------------------------------------
+Public Function Delete() As Boolean
+&apos;&apos;&apos;     Deletes the current record, from the dataset and from 
the database.
+&apos;&apos;&apos;     The cursor is set on the record following immediately 
the deleted record,
+&apos;&apos;&apos;     or after the last record if the deleted one was the 
last one.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             DBREADONLYERROR                 The actual 
method cannot be executed
+&apos;&apos;&apos;             NOCURRENTRECORDERROR    The current record 
could not be determined
+&apos;&apos;&apos;     Examples
+&apos;&apos;&apos;             dataset.Delete()
+
+Dim bDelete As Boolean                 &apos;  Return value
+Dim bLast As Boolean                   &apos;  True when the current record is 
the last one
+Const cstThisSub = &quot;SFDatabases.Dataset.Delete&quot;
+Const cstSubArgs = &quot;&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bDelete = False
+
+       With _RowSet
+
+Check:
+               ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+               If _ReadOnly Then GoTo CatchreadOnly
+               If .isBeforeFirst() Or .isAfterLast() Or .rowDeleted() Then 
GoTo CatchCurrent
+
+Try:
+               bLast = .isLast()
+               .deleteRow()
+               bDelete = .rowDeleted
+               If bLast Then .afterLast() Else .next()
+
+       End With
+
+Finally:
+       Delete = bDelete
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+CatchCurrent:
+       ScriptForge.SF_Exception.RaiseFatal(NOCURRENTRECORDERROR)
+       GoTo Finally
+CatchReadOnly:
+       ScriptForge.SF_Exception.RaiseFatal(DBREADONLYERROR)
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.Delete
+
+REM 
-----------------------------------------------------------------------------
+Public Function ExportValueToFile(Optional ByVal FieldName As Variant _
+                                                                       , 
Optional ByVal FileName As Variant _
+                                                                       , 
Optional ByVal Overwrite As Variant _
+                                                                       ) As 
Boolean
+&apos;&apos;&apos;     Export the content of a binary field to a given file
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             FieldName: the name of a binary field as a 
case-sensitive string
+&apos;&apos;&apos;             FileName: the destination file name in 
ScriptForge.FileSystem service notation
+&apos;&apos;&apos;             Overwrite: when True, the destination file may 
be overwritten
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             NOCURRENTRECORDERROR    The current record 
could not be determined
+&apos;&apos;&apos;             FIELDEXPORTERROR                The destination 
has its readonly attribute set or overwriting rejected
+
+Dim bExport As Variant                 &apos;  Return value
+Dim oSfa As Object                             &apos;  
com.sun.star.ucb.SimpleFileAccess
+Dim sFile As String                            &apos;  Alias of FileName
+Dim lColIndex As Long                  &apos;  Column index
+Dim oColumn As Object                  &apos;  com.sun.star.sdb.ODataColumn
+Dim oStream As Object                  &apos;  com.sun.star.io.XInputStream
+Const cstThisSub = &quot;SFDatabases.Dataset.ExportValueToFile&quot;
+Const cstSubArgs = &quot;FieldName, FileName, [Overwrite=False]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+        bExport = False
+
+Check:
+       If IsMissing(Overwrite) Or IsEmpty(Overwrite) Then Overwrite = False
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(FieldName, 
&quot;FieldName&quot;, V_STRING, _Fields) Then GoTo Catch
+               If Not ScriptForge.SF_Utils._ValidateFile(FileName, 
&quot;FileName&quot;) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(Overwrite, 
&quot;Overwrite&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+       End If
+
+       &apos;  Check destination file overwriting
+       sFile = ConvertToUrl(FileName)
+       Set oSfa = ScriptForge.SF_Utils._GetUNOService(&quot;FileAccess&quot;)
+       If oSfa.exists(sFile) Then
+               If Not Overwrite Then GoTo CatchFile
+               If oSfa.isReadonly(sFile) Then GoTo CatchFile
+       End If
+
+       &apos;  Check the current record
+       With _RowSet
+               If .isBeforeFirst() Or .isAfterLast() Or .rowDeleted() Then 
GoTo CatchCurrent
+       End With
+
+Try:
+       lColIndex = ScriptForge.SF_Array.IndexOf(_Fields, FieldName, 
CaseSensitive := True)
+       If lColIndex &gt;= 0 Then
+
+               &apos;  Establish the input stream
+               Set oColumn =  _RowSet.Columns.getByIndex(lColIndex)
+               With com.sun.star.sdbc.DataType
+                       Select Case oColumn.Type
+                               Case .BINARY, .VARBINARY, .LONGVARBINARY, .BLOB
+                                       Set oStream = oColumn.getBinaryStream()
+                               &apos;Case .VARCHAR, .LONGVARCHAR, .CLOB
+                               Case Else
+                                       Set oStream = Nothing
+                       End Select
+               End With
+
+               &apos;  Process NULL value
+               If Not IsNull(oStream) And oColumn.IsNullable = 
com.sun.star.sdbc.ColumnValue.NULLABLE Then
+                       If oColumn.wasNull() Then
+                               oStream.closeInput()
+                               Set oStream = Nothing
+                       End If
+               End If
+               
+               &apos;  Dump field into file
+               If Not IsNull(oStream) Then
+                       If oStream.getLength() &gt; 0 Then
+                               oSfa.writeFile(sFile, oStream)
+                       End If
+                       oStream.closeInput()
+               End If
+       End If
+
+       bExport = True
+
+Finally:
+       ExportValueToFile = bExport
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+CatchCurrent:
+       ScriptForge.SF_Exception.RaiseFatal(NOCURRENTRECORDERROR)
+       GoTo Finally
+CatchFile:
+       ScriptForge.SF_Exception.RaiseFatal(FIELDEXPORTERROR, 
&quot;FileName&quot;, FileName, &quot;Overwrite&quot;, Overwrite)
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.ExportValueToFile
+
+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.Dataset.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_Dataset.GetProperty
+
+REM 
-----------------------------------------------------------------------------
+Public Function GetRows(Optional ByVal Header As Variant _
+                                                       , Optional ByVal 
MaxRows As Variant _
+                                                       ) As Variant
+&apos;&apos;&apos;     Return the content of the dataset as an array
+&apos;&apos;&apos;     This operation can be done in chunks:
+&apos;&apos;&apos;             - The collected data starts at the current row 
+ 1
+&apos;&apos;&apos;             - When MaxRows &gt; 0 then the collection stops 
after this limit has been reached.
+&apos;&apos;&apos;               Otherwise all the data up to the end is 
collected.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Header:         When True, a header row is 
inserted at the top of the array with the column names. Default = False
+&apos;&apos;&apos;             MaxRows:        The maximum number of returned 
rows. If absent, all records up to the end are returned
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             a 2D array(row, column), even if only 1 column 
and/or 1 record
+&apos;&apos;&apos;             an empty array if no records returned
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             Dim a As Variant, lMaxRows As Long
+&apos;&apos;&apos;                     lMaxRows = 100
+&apos;&apos;&apos;                     Do
+&apos;&apos;&apos;                             a = dataset.GetRows(Header := 
True, MaxRows := lMaxRows)
+&apos;&apos;&apos;                             If UBound(a, 1) &gt;= 0 Then
+&apos;&apos;&apos;                                     &apos;  ...
+&apos;&apos;&apos;                             End If
+&apos;&apos;&apos;                     Loop Until UBound(a, 1) &lt; lMaxRows   
&apos;  Includes empty array - Use ... &lt; lMaxRows - 1 when Header := False
+
+Dim vResult As Variant                 &apos;  Return value
+Dim lCols As Long                              &apos;  Number of columns
+Dim lRows As Long                              &apos;  Number of rows
+Dim oColumns As Object                 &apos;  Collection of 
com.sun.star.sdb.ODataColumn
+Dim bRead As Boolean                   &apos;  When True, next record has been 
read successfully
+Dim i As Long
+Const cstThisSub = &quot;SFDatabases.Dataset.GetRows&quot;
+Const cstSubArgs = &quot;[Header=False], [MaxRows=0]&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       vResult = Array()
+
+Check:
+       If IsMissing(Header) Or IsEmpty(Header) Then Header = False
+       If IsMissing(MaxRows) Or IsEmpty(MaxRows) Then MaxRows = 0
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(Header, 
&quot;Header&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(MaxRows, 
&quot;MaxRows&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
+       End If
+
+Try:
+       With _RowSet
+
+               &apos;  Check if there is any data to collect
+               bRead = .next()
+
+               If bRead Then
+                       &apos;Initialize output array with header row
+                       Set oColumns = .getColumns()
+                       lCols = oColumns.Count - 1
+                       If Header Then
+                               lRows = 0
+                               ReDim vResult(0 To lRows, 0 To lCols)
+                               For i = 0 To lCols
+                                       vResult(lRows, i) = 
oColumns.getByIndex(i).Name
+                               Next i
+                               If MaxRows &gt; 0 Then MaxRows = MaxRows + 1
+                       Else
+                               lRows = -1
+                       End If
+
+                       &apos;  Load data
+                       Do While bRead And (MaxRows = 0 Or lRows &lt; MaxRows - 
1)
+                               lRows = lRows + 1
+                               If lRows = 0 Then
+                                       ReDim vResult(0 To lRows, 0 To lCols)
+                               Else
+                                       ReDim Preserve vResult(0 To lRows, 0 To 
lCols)
+                               End If
+                               For i = 0 To lCols
+                                       vResult(lRows, i) = 
_ParentDatabase._GetColumnValue(_RowSet, i + 1)
+                               Next i
+                               bRead = .next()
+                       Loop
+
+               Else
+                       vResult = Array()
+               End If
+
+       End With
+       
+Finally:
+       GetRows = vResult
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.GetRows
+
+REM 
-----------------------------------------------------------------------------
+Public Function GetValue(Optional ByVal FieldName As Variant) As Variant
+&apos;&apos;&apos;     Returns the value of a given field in the current record
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             FieldName: the name of a field as a 
case-sensitive string
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             The found value as a Basic variable
+&apos;&apos;&apos;             The length of binary fields is returned,not 
their content.
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             NOCURRENTRECORDERROR    The current record 
could not be determined
+
+Dim vValue As Variant                  &apos;  Return value
+Dim lColIndex As Long                  &apos;  Column index
+Const cstThisSub = &quot;SFDatabases.Dataset.GetValue&quot;
+Const cstSubArgs = &quot;FieldName&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       vValue = Null
+
+Check:
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(FieldName, 
&quot;FieldName&quot;, V_STRING, _Fields) Then GoTo Catch
+       End If
+
+       With _RowSet
+               If .isBeforeFirst() Or .isAfterLast() Or .rowDeleted() Then 
GoTo CatchCurrent
+       End With
+
+Try:
+       lColIndex = ScriptForge.SF_Array.IndexOf(_Fields, FieldName, 
CaseSensitive := True)
+       If lColIndex &gt;= 0 Then vValue = 
_ParentDatabase._GetColumnValue(_RowSet, lColIndex + 1)
+
+Finally:
+       GetValue = vValue
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+CatchCurrent:
+       ScriptForge.SF_Exception.RaiseFatal(NOCURRENTRECORDERROR)
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.GetValue
+
+REM 
-----------------------------------------------------------------------------
+Public Function Insert(ParamArray pvArgs As Variant) As Long
+&apos;&apos;&apos;     Create a new record in the database and initialize its 
fields.
+&apos;&apos;&apos;     The current record is unchanged. The new record is 
inserted at the end of the dataset.
+&apos;&apos;&apos;     Updatable fields not mentioned in the arguments are 
initialized with their default value.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Either a single argument
+&apos;&apos;&apos;                     UpdatesList: a 
ScriptForge.SF_Dictionary object listing pairs of key/item where
+&apos;&apos;&apos;                             the key = an updatable field
+&apos;&apos;&apos;                             the item = its value
+&apos;&apos;&apos;             or an even number of arguments alternating
+&apos;&apos;&apos;                     FieldName: an updatable field
+&apos;&apos;&apos;                     FieldValue: its value
+&apos;&apos;&apos;             The first form is particularly convenient in 
Python scripts
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             When the primary key is an AutoValue field: the 
autovalue of the new record
+&apos;&apos;&apos;                     (to facilitate the use of the new 
primary key in foreign keys)
+&apos;&apos;&apos;             Otherwise: 0 (= successful), -1 (= not 
sucessful)
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             DBREADONLYERROR                 The actual 
method cannot be executed
+&apos;&apos;&apos;             RECORDUPDATEERROR               When value to 
store does not fit the type of the field
+&apos;&apos;&apos;                                                             
or when field is not nullable and value = Null
+&apos;&apos;&apos;                                                             
or when field is not writable or is an autovalue
+&apos;&apos;&apos;                                                             
or when input file does not exist or is empty
+&apos;&apos;&apos;                                                             
or when field type is not supported
+&apos;&apos;&apos;             TABLEPRIMARYKEYERROR    Primary key duplication
+&apos;&apos;&apos;     Examples
+&apos;&apos;&apos;             (Basic)
+&apos;&apos;&apos;                     Dim newID As Long
+&apos;&apos;&apos;                     newID = 
dataset.Insert(&quot;LastName&quot;, &quot;Doe&quot;, &quot;FirstName&quot;, 
&quot;John&quot;)
+&apos;&apos;&apos;                             &apos;  ... is equivalent to:
+&apos;&apos;&apos;                     Dim dict As Object, newID As Long
+&apos;&apos;&apos;                     Set dict = 
CreateScriptService(&quot;ScriptForge.Dictionary&quot;)
+&apos;&apos;&apos;                     dict.Add(&quot;LastName&quot;, 
&quot;Doe&quot;)
+&apos;&apos;&apos;                     dict.Add(&quot;FirstName&quot;, 
&quot;John&quot;)
+&apos;&apos;&apos;                     newID = dataset.Insert(dict)
+&apos;&apos;&apos;             (Python) - next statements are equivalent
+&apos;&apos;&apos;                     newid = 
dataset.Insert(&apos;LastName&apos;, &apos;Doe&apos;, &apos;FirstName&apos;, 
&apos;John&apos;)
+&apos;&apos;&apos;                     newid = 
dataset.Insert({&apos;LastName&apos;: &apos;Doe&apos;, &apos;FirstName&apos;: 
&apos;John&apos;})
+&apos;&apos;&apos;                     newid = dataset.Insert(dict(LastName = 
&apos;Doe&apos;, FirstName = &apos;John&apos;))
+&apos;&apos;&apos;                     newid = dataset.Insert(LastName = 
&apos;Doe&apos;, FirstName = &apos;John&apos;)
+
+Dim lInsert As Long                            &apos;  Return value
+Dim sSubArgs As String                 &apos;  Alias of cstSubArgs
+Dim sField As String                   &apos;  A single field name
+Dim oUpdates As Object                 &apos;  A SF_Dictionary object
+Dim lColIndex As Long                  &apos;  Column index
+Dim vKeys As Variant                   &apos;  List of keys in the dictionary
+Dim sKey As String                             &apos;  A single key in vKeys
+Dim i As Long
+Const cstThisSub = &quot;SFDatabases.Dataset.Insert&quot;
+Const cstSubArgs1 = &quot;UpdatesList&quot;
+Const cstSubArgs2 = &quot;FieldName1, FieldValue1, [FieldName2, FieldValue2], 
...&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       lInsert = -1
+
+Check:
+       If UBound(pvArgs) = 0 Then                      &apos;  Dictionary case
+               sSubArgs = cstSubArgs1
+               If ScriptForge.SF_Utils._EnterFunction(cstThisSub, sSubArgs) 
Then
+                       If Not ScriptForge.SF_Utils._Validate(pvArgs(0), 
&quot;UpdatesList&quot;, ScriptForge.V_OBJECT) Then GoTo Catch
+               End If
+               Set oUpdates = pvArgs(0)
+       Else
+               sSubArgs = cstSubArgs2                  &apos;  Arguments list 
case
+               ScriptForge.SF_Utils._EnterFunction(cstThisSub, sSubArgs)
+               For i = 0 To UBound(pvArgs) Step 2
+                       If Not ScriptForge.SF_Utils._Validate(pvArgs(i), 
&quot;FieldName&quot; &amp; i, V_STRING, _UpdatableFields) Then GoTo Catch
+               Next i
+       End If
+
+       If _ReadOnly Then GoTo CatchReadOnly
+
+Try:
+       With _RowSet
+
+               &apos;  Initialize the insertion row
+               .moveToInsertRow()
+               &apos;  Initial storage of default values
+               For Each sField In _UpdatableFields
+                       lColIndex = ScriptForge.SF_Array.IndexOf(_Fields, 
sField, CaseSensitive := True)
+                       _SetColumnValue(lColIndex, _DefaultValues(lColIndex))
+               Next sField
+
+               If UBound(pvArgs) = 0 Then
+                       With oUpdates
+                               vKeys = .Keys
+                               For Each sKey in vKeys
+                                       lColIndex = 
ScriptForge.SF_Array.IndexOf(_Fields, sKey, CaseSensitive := True)
+                                       If lColIndex &gt;= 0 Then
+                                               _SetColumnValue(lColIndex, 
.Item(sKey))
+                                       Else    &apos;  To force an error
+                                               If Not 
ScriptForge.SF_Utils._Validate(sKey, &quot;FieldName&quot;, V_STRING, 
_UpdatableFields) Then GoTo Catch
+                                       End If
+                               Next sKey
+                       End With
+               Else
+                       For i = 0 To UBound(pvArgs) Step 2
+                               lColIndex = 
ScriptForge.SF_Array.IndexOf(_Fields, pvArgs(i), CaseSensitive := True)
+                               If lColIndex &gt;= 0 Then
+                                       If i &lt; UBound(pvArgs) Then 
_SetColumnValue(lColIndex, pvArgs(i + 1))
+                               Else    &apos;  To force an error
+                                       If Not 
ScriptForge.SF_Utils._Validate(sKey, &quot;FieldName&quot;, V_STRING, 
_UpdatableFields) Then GoTo Catch
+                               End If
+                       Next i
+               End If
+
+               .insertRow()
+
+               &apos;  Compute the return value: either 0 or the new content 
of the pre-identified AUtoValue field
+               If _AutoValue &lt; 0 Then lInsert = 0 Else lInsert = 
_ParentDatabase._GetColumnValue(_RowSet, _AutoValue + 1)
+
+               .moveToCurrentRow()
+
+       End With
+
+Finally:
+       Insert = lInsert
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+CatchReadOnly:
+       ScriptForge.SF_Exception.RaiseFatal(DBREADONLYERROR)
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.Insert
+
+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;CloseDataset&quot; _
+                                       , &quot;CreateDataset&quot; _
+                                       , &quot;Delete&quot; _
+                                       , &quot;ExportValueToFile&quot; _
+                                       , &quot;GetRows&quot; _
+                                       , &quot;GetValue&quot; _
+                                       , &quot;Insert&quot; _
+                                       , &quot;MoveFirst&quot; _
+                                       , &quot;MoveLast&quot; _
+                                       , &quot;MoveNext&quot; _
+                                       , &quot;MovePrevious&quot; _
+                                       , &quot;Reload&quot; _
+                                       , &quot;Update&quot; _
+                                       )
+
+End Function   &apos;  SFDatabases.SF_Dataset.Methods
+
+REM 
-----------------------------------------------------------------------------
+Public Function MoveFirst() As Boolean
+&apos;&apos;&apos;     Move the cursor to the 1st record
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             False when the Move was unsuccessful
+&apos;&apos;&apos;             When False the cursor is reset before the first 
record
+
+Dim bMove As Boolean           &apos;  Return value
+Const cstThisSub = &quot;SFDatabases.Dataset.MoveFirst&quot;
+Const cstSubArgs = &quot;&quot;
+
+Check:
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+Try:
+       with _RowSet
+               bMove = .first()
+               If Not bMove Then .beforeFirst()
+       End With
+
+Finally:
+       MoveFirst = bMove
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.MoveFirst
+
+REM 
-----------------------------------------------------------------------------
+Public Function MoveLast() As Boolean
+&apos;&apos;&apos;     Move the cursor to the last record
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             False when the Move was unsuccessful
+&apos;&apos;&apos;             When False the cursor is reset before the first 
record
+
+Dim bMove As Boolean           &apos;  Return value
+Const cstThisSub = &quot;SFDatabases.Dataset.MoveLast&quot;
+Const cstSubArgs = &quot;&quot;
+
+Check:
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+Try:
+       with _RowSet
+               bMove = .last()
+               If Not bMove Then .beforeFirst()
+       End With
+
+Finally:
+       MoveLast = bMove
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.MoveLast
+
+REM 
-----------------------------------------------------------------------------
+Public Function MoveNext(Optional ByVal Offset As Variant) As Boolean
+&apos;&apos;&apos;     Move the cursor N records forward. Deleted records are 
skipped.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Offset: number of records to go forward (may be 
negative). Default = 1
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             False when the Move was unsuccessful
+&apos;&apos;&apos;             When False the cursor is reset before the first 
record when Offset &gt; 0, after the last record otherwise
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             dataset.MoveNext(3)             &apos;  3 
records forward
+&apos;&apos;&apos;             dataset.MoveNext(-1)    &apos;  equivalent to 
MovePrevious()
+
+Dim bMove As Boolean           &apos;  Return value
+Dim lRow As Long                       &apos;  Row number
+Const cstThisSub = &quot;SFDatabases.Dataset.MoveNext&quot;
+Const cstSubArgs = &quot;[Offset=1]&quot;
+
+Check:
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+       If IsMissing(Offset) Or IsEmpty(Offset) Then Offset = 1
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(Offset, 
&quot;Offset&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
+       End If
+
+Try:
+       with _RowSet
+               Select Case Offset
+                       Case 0                          :       bMove = True
+                       Case 1                          :       bMove = .next()
+                       Case -1                         :       bMove = 
.previous()
+                       Case &gt; 1                     :       bMove = 
.relative(Offset)       &apos;  RowSet.relative() stops at boundary when moving 
forward only !?
+                       Case Else       &apos;  &lt; -1
+                               lRow = .Row()
+                               If lRow &gt; Abs(Offset) Then bMove = 
.relative(Offset) Else bMove = False
+               End Select
+               If bMove Then
+                       If .rowDeleted() Then
+                               If      Offset &gt;= 0 Then bMove = MoveNext() 
Else bMove = MovePrevious()
+                       End If
+               End If
+       End With
+
+Finally:
+       MoveNext = bMove
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.MoveNext
+
+REM 
-----------------------------------------------------------------------------
+Public Function MovePrevious(Optional ByVal Offset As Variant) As Boolean
+&apos;&apos;&apos;     Move the cursor N records backward. Deleted records are 
skipped.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Offset: number of records to go backward (may 
be negative). Default = 1
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             False when the Move was unsuccessful
+&apos;&apos;&apos;             When False the cursor is reset before the first 
record
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             dataset.MovePrevious(3)         &apos;  3 
records backward
+&apos;&apos;&apos;             dataset.MovePrevious(-1)        &apos;  
equivalent to MoveNext()
+
+Dim bMove As Boolean           &apos;  Return value
+Dim lRow As Long                       &apos;  Row number
+Const cstThisSub = &quot;SFDatabases.Dataset.MovePrevious&quot;
+Const cstSubArgs = &quot;[Offset=1]&quot;
+
+Check:
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+       If IsMissing(Offset) Or IsEmpty(Offset) Then Offset = 1
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(Offset, 
&quot;Offset&quot;, ScriptForge.V_NUMERIC) Then GoTo Catch
+       End If
+
+Try:
+       with _RowSet
+               Select Case Offset
+                       Case 0                          :       bMove = True
+                       Case 1                          :       bMove = 
.previous()
+                       Case -1                         :       bMove = .next()
+                       Case &lt; -1                    :       bMove = 
.relative(- Offset)     &apos;  RowSet.relative() stops at boundary when moving 
forward only !?
+                       Case Else       &apos;  &gt; 1
+                               lRow = .Row()
+                               If lRow &gt; Offset Then bMove = .relative(- 
Offset) Else bMove = False
+               End Select
+               If bMove Then
+                       If .rowDeleted() Then
+                               If      Offset &lt; 0 Then bMove = MoveNext() 
Else bMove = MovePrevious()
+                       End If
+               End If
+       End With
+
+Finally:
+       MovePrevious = bMove
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.MovePrevious
+
+REM 
-----------------------------------------------------------------------------
+Public Function Properties() As Variant
+&apos;&apos;&apos;     Return the list or properties of the Model class as an 
array
+
+       Properties = Array( _
+                                       &quot;BOF&quot; _
+                                       , &quot;DefaultValues&quot; _
+                                       , &quot;EOF&quot; _
+                                       , &quot;Fields&quot; _
+                                       , &quot;Filter&quot; _
+                                       , &quot;OrderBy&quot; _
+                                       , &quot;ParentDatabase&quot; _
+                                       , &quot;RowCount&quot; _
+                                       , &quot;RowNumber&quot; _
+                                       , &quot;Source&quot; _
+                                       , &quot;SourceType&quot; _
+                                       , &quot;UpdatableFields&quot; _
+                                       , &quot;Values&quot; _
+                                       , &quot;XRowSet&quot; _
+                                       )
+
+End Function   &apos;  SFDatabases.SF_Dataset.Properties
+
+REM 
-----------------------------------------------------------------------------
+Public Function Reload(Optional ByVal Filter As Variant _
+                                                                       , 
Optional ByVal OrderBy As Variant _
+                                                                       ) As 
Boolean
+&apos;&apos;&apos;     Reload the dataset from the database.
+&apos;&apos;&apos;     Useful in particular after record deletions and 
insertions.
+&apos;&apos;&apos;     Filter and OrderBy properties may be redefined.
+&apos;&apos;&apos;     The cursor is reset before the first record.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Filter: a condition that records must match, 
expressed
+&apos;&apos;&apos;                     as a valid SQL WHERE clause without the 
WHERE keyword
+&apos;&apos;&apos;                     Default: the actual filter is left 
unchanged.
+&apos;&apos;&apos;             OrderBy: the ordering of the dataset expressed 
as a valid SQL ORDER BY clause
+&apos;&apos;&apos;                     without the ORDER BY keywords.
+&apos;&apos;&apos;                     Default: the actual sorting order is 
left unchanged.
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Exceptions
+&apos;&apos;&apos;             SQLSYNTAX2ERROR                 The given SQL 
statement is incorrect
+&apos;&apos;&apos;     Examples:
+&apos;&apos;&apos;             dataset.Reload()                                
&apos;  dataset is refreshed
+&apos;&apos;&apos;             dataset.Reload(Filter := &quot;&quot;)  &apos;  
Suppress the current filter
+&apos;&apos;&apos;             dataset.Reload(Filter := &quot;[Name] LIKE 
&apos;A%&apos;&quot;)
+&apos;&apos;&apos;                                                             
                &apos;  Define a new filter
+&apos;&apos;&apos;             dataset.Reload(Filter := &quot;(&quot; &amp; 
dataset.Filter &amp; &quot;) AND [Name] LIKE &apos;A%&apos;&quot;)
+&apos;&apos;&apos;                                                             
                &apos;  Combine actual filter with an additional condition
+
+Dim bReload As Boolean                 &apos;  Return value
+Dim bErrorHandler As Boolean   &apos;  Can be set off to ease debugging of 
complex SQL statements
+Const cstThisSub = &quot;SFDatabases.Dataset.Reload&quot;
+Const cstSubArgs = &quot;[Filter=&quot;&quot;...filter...&quot;&quot;], 
[OrderBy=&quot;&quot;...orderby...&quot;&quot;]&quot;
+
+       bErrorHandler = ScriptForge.SF_Utils._ErrorHandling()
+       If bErrorHandler Then On Local Error GoTo Catch
+       bReload = False
+
+Check:
+       If IsMissing(Filter) Or IsEmpty(Filter) Then Filter = _Filter
+       If IsMissing(OrderBy) Or IsEmpty(OrderBy) Then OrderBy = _OrderBy
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(Filter, 
&quot;Filter&quot;, V_STRING) Then GoTo Finally
+               If Not ScriptForge.SF_Utils._Validate(OrderBy, 
&quot;OrderBy&quot;, V_STRING) Then GoTo Finally
+       End If
+
+Try:
+       If Len(Filter) &gt; 0 Then _Filter = 
_ParentDatabase._ReplaceSquareBrackets(Filter) Else _Filter = &quot;&quot;
+       If Len(OrderBy) &gt; 0 Then _OrderBy = 
_ParentDatabase._ReplaceSquareBrackets(OrderBy) Else _OrderBy = &quot;&quot;
+       With _RowSet
+               .Filter = _Filter
+               .ApplyFilter = ( Len(_Filter) &gt; 0 )
+               .Order = _OrderBy
+               If bErrorhandler Then On Local Error GoTo CatchSql
+               .execute()
+       End With
+
+       bReload = True
+
+Finally:
+       Reload = bReload
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+CatchSql:
+       On Local Error GoTo 0
+       ScriptForge.SF_Exception.RaiseFatal(SQLSYNTAX2ERROR, _Sql, &quot;WHERE 
&quot; &amp; _Filter, &quot;ORDER BY &quot; &amp; _OrderBy)
+       GoTo Catch
+End Function   &apos;  SFDatabases.SF_Dataset.Reload
+
+REM 
-----------------------------------------------------------------------------
+Public Function SetProperty(Optional ByVal PropertyName As Variant _
+                                                               , Optional 
ByRef Value As Variant _
+                                                               ) As Boolean
+&apos;&apos;&apos;     Set a new value to the given property
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             PropertyName: the name of the property as a 
string
+&apos;&apos;&apos;             Value: its new value
+&apos;&apos;&apos;     Exceptions
+&apos;&apos;&apos;             ARGUMENTERROR           The property does not 
exist
+
+Const cstThisSub = &quot;SFDatabases.Dataset.SetProperty&quot;
+Const cstSubArgs = &quot;PropertyName, Value&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       SetProperty = False
+
+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:
+       SetProperty = _PropertySet(PropertyName, Value)
+
+Finally:
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.SetProperty
+
+REM 
-----------------------------------------------------------------------------
+Public Function Update(ParamArray pvArgs As Variant) As Boolean
+&apos;&apos;&apos;     Updates a set of fields in the current record
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             Either a single argument
+&apos;&apos;&apos;                     UpdatesList: a 
ScriptForge.SF_Dictionary object listing pairs of key/item where
+&apos;&apos;&apos;                             the key = an updatable field
+&apos;&apos;&apos;                             the item = its new value
+&apos;&apos;&apos;             or an even number of arguments alternating
+&apos;&apos;&apos;                     FieldName: an updatable field
+&apos;&apos;&apos;                     FieldValue: its new value
+&apos;&apos;&apos;             The first form is particularly convenient in 
Python scripts
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             DBREADONLYERROR                 The actual 
method cannot be executed
+&apos;&apos;&apos;             RECORDUPDATEERROR               When value to 
store does not fit the type of the field
+&apos;&apos;&apos;                                                             
or when field is not nullable and value = Null
+&apos;&apos;&apos;                                                             
or when field is not writable or is an autovalue
+&apos;&apos;&apos;                                                             
or when input file does not exist or is empty
+&apos;&apos;&apos;                                                             
or when field type is not supported
+&apos;&apos;&apos;             NOCURRENTRECORDERROR    The current record 
could not be determined
+&apos;&apos;&apos;     Examples
+&apos;&apos;&apos;             (Basic)
+&apos;&apos;&apos;                     dataset.Update(&quot;LastName&quot;, 
&quot;Doe&quot;, &quot;FirstName&quot;, &quot;John&quot;)
+&apos;&apos;&apos;                             &apos;  ... is equivalent to:
+&apos;&apos;&apos;                     Dim dict As Object
+&apos;&apos;&apos;                     Set dict = 
CreateScriptService(&quot;ScriptForge.Dictionary&quot;)
+&apos;&apos;&apos;                     dict.Add(&quot;LastName&quot;, 
&quot;Doe&quot;)
+&apos;&apos;&apos;                     dict.Add(&quot;FirstName&quot;, 
&quot;John&quot;)
+&apos;&apos;&apos;                     dataset.Update(dict)
+&apos;&apos;&apos;             (Python) - next statements are equivalent
+&apos;&apos;&apos;                     dataset.Update({&apos;LastName&apos;: 
&apos;Doe&apos;, &apos;FirstName&apos;: &apos;John&apos;})
+&apos;&apos;&apos;                     dataset.Update(dict(LastName = 
&apos;Doe&apos;, FirstName = &apos;John&apos;))
+&apos;&apos;&apos;                     dataset.Update(LastName = 
&apos;Doe&apos;, FirstName = &apos;John&apos;)
+
+Dim bUpdate As Boolean                 &apos;  Return value
+Dim sSubArgs As String                 &apos;  Alias of cstSubArgs
+Dim oUpdates As Object                 &apos;  A SF_Dictionary object
+Dim lColIndex As Long                  &apos;  Column index
+Dim vKeys As Variant                   &apos;  List of keys in the dictionary
+Dim sKey As String                             &apos;  A single key in vKeys
+Dim i As Long
+Const cstThisSub = &quot;SFDatabases.Dataset.Update&quot;
+Const cstSubArgs1 = &quot;UpdatesList&quot;
+Const cstSubArgs2 = &quot;FieldName1, FieldValue1, [FieldName2, FieldValue2], 
...&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bUpdate = False
+
+Check:
+       If UBound(pvArgs) = 0 Then                      &apos;  Dictionary case
+               sSubArgs = cstSubArgs1
+               If ScriptForge.SF_Utils._EnterFunction(cstThisSub, sSubArgs) 
Then
+                       If Not ScriptForge.SF_Utils._Validate(pvArgs(0), 
&quot;UpdatesList&quot;, ScriptForge.V_OBJECT) Then GoTo Catch
+               End If
+               Set oUpdates = pvArgs(0)
+       Else
+               sSubArgs = cstSubArgs2                  &apos;  Arguments list 
case
+               ScriptForge.SF_Utils._EnterFunction(cstThisSub, sSubArgs)
+               For i = 0 To UBound(pvArgs) Step 2
+                       If Not ScriptForge.SF_Utils._Validate(pvArgs(i), 
&quot;FieldName&quot; &amp; i, V_STRING, _UpdatableFields) Then GoTo Catch
+               Next i
+       End If
+
+       If _ReadOnly Then GoTo CatchReadOnly
+       With _RowSet
+               If .isBeforeFirst() Or .isAfterLast() Or .rowDeleted() Then 
GoTo CatchCurrent
+       End With
+
+Try:
+       If UBound(pvArgs) = 0 Then
+               With oUpdates
+                       vKeys = .Keys
+                       For Each sKey in vKeys
+                               lColIndex = 
ScriptForge.SF_Array.IndexOf(_Fields, sKey, CaseSensitive := True)
+                               If lColIndex &gt;= 0 Then
+                                       _SetColumnValue(lColIndex, .Item(sKey))
+                               Else    &apos;  To force an error
+                                       If Not 
ScriptForge.SF_Utils._Validate(sKey, &quot;FieldName&quot;, V_STRING, 
_UpdatableFields) Then GoTo Catch
+                               End If
+                       Next sKey
+               End With
+       Else
+               For i = 0 To UBound(pvArgs) Step 2
+                       lColIndex = ScriptForge.SF_Array.IndexOf(_Fields, 
pvArgs(i), CaseSensitive := True)
+                       If lColIndex &gt;= 0 Then
+                               If i &lt; UBound(pvArgs) Then 
_SetColumnValue(lColIndex, pvArgs(i + 1))
+                       Else    &apos;  To force an error
+                               If Not ScriptForge.SF_Utils._Validate(sKey, 
&quot;FieldName&quot;, V_STRING, _UpdatableFields) Then GoTo Catch
+                       End If
+               Next i
+       End If
+
+       If _RowSet.IsModified Then _RowSet.updateRow()
+       bUpdate = True
+
+Finally:
+       Update = bUpdate
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+CatchCurrent:
+       ScriptForge.SF_Exception.RaiseFatal(NOCURRENTRECORDERROR)
+       GoTo Finally
+CatchReadOnly:
+       ScriptForge.SF_Exception.RaiseFatal(DBREADONLYERROR)
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset.Update
+
+REM =========================================================== PRIVATE 
FUNCTIONS
+
+REM 
-----------------------------------------------------------------------------
+Private Function _ConvertDefaultValue(ByRef poColumn As Object) As Variant
+&apos;&apos;&apos;     Default values of table fields are stored in the Base 
file or in the database as strings.
+&apos;&apos;&apos;     The actual method converts those strings into a Basic 
native type.
+&apos;&apos;&apos;     Usage: facilitate the initialization of new records
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             poColumn: a com.sun.star.sdb.ODataColumn UNO 
object
+&apos;&apos;&apos;     Returns
+&apos;&apos;&apos;             The default value for the column expressed as a 
string, a number, a date, ...
+&apos;&apos;&apos;             Nullable columns have probably a Null default 
value.
+
+Dim sValue As String                   &apos;  The default value as a string
+Dim vValue As Variant                  &apos;  The default value as a native 
Basic type
+Dim SESSION As Object                  :       Set SESSION = 
ScriptForge.SF_Session
+
+Try:
+       With poColumn
+
+               &apos;  Determine the default value as a string
+               If SESSION.HasUnoProperty(poColumn, &quot;DefaultValue&quot;) 
Then                      &apos;  Default value in database set via SQL 
statement
+                       sValue = .DefaultValue
+               ElseIf SESSION.HasUnoProperty(poColumn, 
&quot;ControlDefault&quot;) Then        &apos;  Default value set in Base via 
table edition
+                       If IsEmpty(.ControlDefault) Then sValue = &quot;&quot; 
Else sValue = .ControlDefault
+               Else
+                       sValue = &quot;&quot;
+               End If
+
+               &apos;  Convert the string to a native type
+               If sValue = &quot;&quot; Then                           &apos;  
No default value =&gt; Null or Empty
+                       If .IsNullable = com.sun.star.sdbc.ColumnValue.NULLABLE 
Then vValue = Null Else vValue = Empty
+               Else
+                       vValue = sValue
+                       With com.sun.star.sdbc.DataType
+                               Select Case poColumn.Type
+                                       Case .CHAR, .VARCHAR, .LONGVARCHAR
+                                       Case .BIT, .BOOLEAN                     
                :       vValue = CBool( sValue = &quot;1&quot; )
+                                       Case .TINYINT                           
                :       vValue = CInt(sValue)
+                                       Case .SMALLINT, .INTEGER, .BIGINT       
:       vValue = CLng(sValue)
+                                       Case .FLOAT                             
                        :       vValue = CSng(sValue)
+                                       Case .REAL, .DOUBLE                     
                :       vValue = CDbl(sValue)
+                                       Case .NUMERIC, .DECIMAL
+                                               If 
SESSION.HasUnoProperty(poColumn, &quot;Scale&quot;) Then
+                                                       If poColumn.Scale &gt; 
0 Then vValue = CDbl(sValue)
+                                               End If
+                                       Case .DATE                              
                        :       vValue = DateValue(sValue)
+                                       Case .TIME                              
                        :       vValue = TimeValue(sValue)
+                                       Case .TIMESTAMP                         
                :       vValue = DateValue(sValue) + TimeValue(sValue)
+                                       Case .BINARY, .VARBINARY, 
.LONGVARBINARY, .BLOB
+                                       Case .CLOB
+                                       Case Else
+                               End Select
+                       End With
+               End If
+
+       End With
+
+Finally:
+       _ConvertDefaultValue = vValue
+       Exit Function
+End Function   &apos;  SFDatabases.SF_Dataset._ConvertDefaultValue
+
+REM 
-----------------------------------------------------------------------------
+Public Function _Initialize() As Boolean
+&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
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             False when Dataset creation is unsuccessful. 
Typically because of SQL error
+
+Dim bDataset As Boolean                        &apos;  Return value
+Dim bErrorHandler As Boolean   &apos;  Can be set off to ease debugging of 
complex SQL statements
+Dim sFields As String                  &apos;  Comma-separated list of field 
names
+Dim sUpdatableFields As String &apos;  Comma-separated list of updatable field 
names
+Dim oColumn As Object                  &apos;  com.sun.star.sdb.ODataColumn
+Dim SESSION As Object                  :       Set SESSION = 
ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Session&quot;)
+Dim i As Long
+
+       bErrorHandler = ScriptForge.SF_Utils._ErrorHandling()
+       If bErrorHandler Then On Local Error GoTo Catch
+
+Try:
+       Set _RowSet = CreateUnoService(&quot;com.sun.star.sdb.RowSet&quot;)
+       With _RowSet
+               Set .ActiveConnection = _ParentDatabase._Connection
+               .Command = _Sql
+               Select Case _DatasetType
+                       Case &quot;TABLE&quot;  :       .CommandType = 
com.sun.star.sdb.CommandType.TABLE
+                       Case &quot;QUERY&quot;  :       .CommandType = 
com.sun.star.sdb.CommandType.QUERY
+                       Case &quot;SQL&quot;            :       .CommandType = 
com.sun.star.sdb.CommandType.COMMAND
+               End Select
+
+               .EscapeProcessing = Not _DirectSql
+               .Filter = _Filter
+               .ApplyFilter = ( Len(_Filter) &gt; 0 )
+               .order = _OrderBy
+               If _ReadOnly Then
+                       .TransactionIsolation = 
com.sun.star.sdbc.TransactionIsolation.READ_UNCOMMITTED
+               Else
+                       .TransactionIsolation = 
com.sun.star.sdbc.TransactionIsolation.READ_COMMITTED
+               End If
+
+               If bErrorHandler Then On Local Error GoTo CatchSql
+               .execute()
+
+               If bErrorHandler Then On Local Error GoTo Catch
+               &apos;  Collect info about columns: field name, updatable, 
default value, AutoValue
+               With .Columns
+                       sFields = &quot;&quot;
+                       sUpdatableFields = &quot;&quot;
+                       ReDim _DefaultValues (0 To .Count - 1)
+                       &apos;  Columns are scanned by index to guarantee that 
names and indexes are aligned
+                       For i = 0 To .Count - 1
+                               Set oColumn = .getByIndex(i)
+                               With oColumn
+                                       &apos;  Field names
+                                       sFields = sFields &amp; &quot;,&quot; 
&amp; .Name
+                                       &apos;  Updatable field names
+                                       If Not _ReadOnly And 
.isDefinitelyWritable And Not .IsAutoIncrement Then sUpdatableFields = 
sUpdatableFields &amp; &quot;,&quot; &amp; .Name
+                                       &apos;  Default values
+                                       _DefaultValues(i) = 
_ConvertDefaultValue(oColumn)
+                                       &apos;  AutoValue
+                                       If _AutoValue &lt; 0 And 
.IsAutoIncrement Then _AutoValue = i
+                               End With
+                       Next i
+                       If Len(sFields) &lt;= 1 Then _Fields = Array() Else 
_Fields = Split(Mid(sFields, 2), &quot;,&quot;)
+                       If Len(sUpdatableFields) &lt;= 1 Then _UpdatableFields 
= Array() Else _UpdatableFields = Split(Mid(sUpdatableFields, 2), &quot;,&quot;)
+               End With
+       End With
+
+       bDataset = True
+
+Finally:
+       _Initialize = bDataset
+       Exit Function
+Catch:
+       bDataset = False
+       GoTo Finally
+CatchSql:
+       On Local Error GoTo 0
+       ScriptForge.SF_Exception.RaiseFatal(SQLSYNTAX2ERROR, _Sql, &quot;WHERE 
&quot; &amp; _Filter, &quot;ORDER BY &quot; &amp; _OrderBy)
+       GoTo Catch
+End Function   &apos;  SFDatabases.SF_Dataset._Initialize
+
+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 vBookmark As Variant                       &apos;  Bookmark on the current 
record
+Dim vValue As Variant                          &apos;  A single record  field 
value
+Dim vValuesDict As Object              &apos;  A dictionary (field name, field 
value)
+Dim i As Long
+
+Dim cstThisSub As String
+Const cstSubArgs = &quot;&quot;
+
+       cstThisSub = &quot;SFDatabases.Dataset.get&quot; &amp; psProperty
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+       ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+       With _RowSet
+               Select Case psProperty
+                       Case &quot;BOF&quot;
+                               _PropertyGet = .isBeforeFirst()
+                       Case &quot;DefaultValues&quot;
+                               &apos;  Load the pairs field name / field 
default value in the dictionary
+                               vValuesDict = 
ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Dictionary&quot;)
+                               For i = 0 To UBound(_DefaultValues)
+                                       vValuesDict.Add(_Fields(i), 
_DefaultValues(i))
+                               Next i
+                               Set _PropertyGet = vValuesDict
+                       Case &quot;EOF&quot;
+                               _PropertyGet = .isAfterLast()
+                       Case &quot;Fields&quot;
+                               _PropertyGet = _Fields
+                       Case &quot;Filter&quot;
+                               _PropertyGet = _Filter
+                       Case &quot;OrderBy&quot;
+                               _PropertyGet = _OrderBy
+                       Case &quot;ParentDatabase&quot;
+                               Set _PropertyGet = _ParentDatabase
+                       Case &quot;RowCount&quot;
+                                       If .IsRowCountFinal Then
+                                               _PropertyGet = .RowCount
+                                       Else
+                                               If .isBeforeFirst() Or 
.isAfterLast() Or .rowDeleted() Then vBookmark = Null Else vBookmark = 
.getBookmark
+                                               .last()
+                                               _PropertyGet = .RowCount
+                                               If IsNull(vBookmark) Then 
.beforeFirst() Else .moveToBookmark(vBookmark)
+                                       End If
+                       Case &quot;RowNumber&quot;
+                                       If .isBeforeFirst() Or .isAfterLast() 
Or .rowDeleted() Then _PropertyGet = 0 Else _PropertyGet = .Row
+                       Case &quot;Source&quot;
+                               _PropertyGet = _Command
+                       Case &quot;SourceType&quot;
+                               _PropertyGet = _DatasetType
+                       Case &quot;UpdatableFields&quot;
+                               _PropertyGet = _UpdatableFields
+                       Case &quot;Values&quot;
+                                       If .isBeforeFirst() Or .isAfterLast() 
Or .rowDeleted() Then
+                                               Set _PropertyGet = Nothing
+                                       Else
+                                               &apos;  Load the pairs field 
name / field value in the dictionary
+                                               vValuesDict = 
ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Dictionary&quot;)
+                                               For i = 0 To UBound(_Fields)
+                                                       vValue = 
_ParentDatabase._GetColumnValue(_RowSet, i + 1, False)
+                                                       
vValuesDict.Add(_Fields(i), vValue)
+                                               Next i
+                                               Set _PropertyGet = vValuesDict
+                                       End If
+                       Case &quot;XRowSet&quot;
+                               Set _PropertyGet = _RowSet
+                       Case Else
+                               _PropertyGet = Null
+               End Select
+       End With
+
+Finally:
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset._PropertyGet
+
+REM 
-----------------------------------------------------------------------------
+Private Function _PropertySet(Optional ByVal psProperty As String _
+                                                               , Optional 
ByVal pvValue As Variant _
+                                                               ) As Boolean
+&apos;&apos;&apos;     Set the new value of the named property
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             psProperty: the name of the property
+&apos;&apos;&apos;             pvValue: the new value of the given property
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True if successful
+
+Dim bSet As Boolean                                                    &apos;  
Return value
+Dim cstThisSub As String
+Const cstSubArgs = &quot;Value&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bSet = False
+
+       cstThisSub = &quot;SFDatabases.Dataset.set&quot; &amp; psProperty
+       ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+
+       bSet = True
+       Select Case UCase(psProperty)
+               Case UCase(&quot;BOF&quot;)
+                       If Not ScriptForge.SF_Utils._Validate(pvValue, 
&quot;BOF&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+                       If pvValue Then _RowSet.beforeFirst()           &apos;  
Only True is valid
+               Case UCase(&quot;EOF&quot;)
+                       If Not ScriptForge.SF_Utils._Validate(pvValue, 
&quot;EOF&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+                       If pvValue Then _RowSet.afterLast()                     
&apos;  Only True is valid
+               Case Else
+                       bSet = False
+       End Select
+
+Finally:
+       _PropertySet = bSet
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Dataset._PropertySet
+
+REM 
-----------------------------------------------------------------------------
+Private Function _Repr() As String
+&apos;&apos;&apos;     Convert the Dataset instance to a readable string, 
typically for debugging purposes (DebugPrint ...)
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Return:
+&apos;&apos;&apos;             &quot;[DATASET]: tablename,base file url&quot;
+
+       _Repr = &quot;[DATASET]: &quot; &amp; _Command &amp; &quot;,&quot; 
&amp; _ParentDatabase._Location
+
+End Function   &apos;  SFDatabases.SF_Dataset._Repr
+
+REM 
-----------------------------------------------------------------------------
+Private Function _SetColumnValue(ByVal plColIndex As Long _
+                                                                       , ByRef 
pvValue As Variant _
+                                                                       ) As 
Boolean
+&apos;&apos;&apos;     Store a value in a given column of the current record
+&apos;&apos;&apos;     The resultset.insertRow() or resultset.updateRow() 
methods are supposed to be executed in the calling routine
+&apos;&apos;&apos;     The type of the column is found in the resultset&apos;s 
metadata
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             plColIndex: the index of the column to extract 
the value from. Starts at 0
+&apos;&apos;&apos;                     Read-only columns are ignored.
+&apos;&apos;&apos;             pvValue:the Variant value to store in the column
+&apos;&apos;&apos;                     Strings and numbers are supplied 
respectively as strings or numeric values
+&apos;&apos;&apos;                     Dates and times are supplied as Basic 
dates
+&apos;&apos;&apos;                     Null values are supplied as Null
+&apos;&apos;&apos;                     Errors or other strange data types are 
ignored
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             RECORDUPDATEERROR               when value to 
store does not fit the type of the field
+&apos;&apos;&apos;                                                             
or when field is not nullable and value = Null
+&apos;&apos;&apos;                                                             
or when field is not writable or is an autovalue
+&apos;&apos;&apos;                                                             
or when input file does not exist or is empty
+&apos;&apos;&apos;                                                             
or when field type is not supported
+       
+Dim bSet As Boolean                            &apos;  Return value
+Dim sColumn As String                  &apos;  Column name
+Dim oColumn As Object                  &apos;  com.sun.star.sdb.DataColumn

... etc. - the rest is truncated

Reply via email to