1
0
Fork 0
libreoffice/wizards/source/sfdatabases/SF_Dataset.xba
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

1672 lines
No EOL
70 KiB
XML

<?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 through 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 statement
&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 will 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
Private _DatasetIndex As Long &apos; Index of the dataset in the _Datasets array of the parent database
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
_DatasetIndex = -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
If _DatasetIndex &gt;= 0 Then Set _ParentDatabase._Datasets(_DatasetIndex) = Nothing
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, True) 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
If MaxRows &lt; 0 Then MaxRows = 1
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
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
If MaxRows = 0 Or lRows &lt; MaxRows - 1 Then bRead = .next() Else bRead = False
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, True) 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 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; 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, True) 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, True) 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, True) 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, True) 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, True) 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, True) 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 .IsWritable 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
&apos; Insert the instance in the _Datasets array of the parent database
_DatasetIndex = _ParentDatabase._AddToDatasets([Me])
bDataset = ( _DatasetIndex &gt;= 0 )
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 (with case-sensitive comparison of keys)
vValuesDict = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Dictionary&quot;, True)
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 (with case-sensitive comparison of keys)
vValuesDict = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.Dictionary&quot;, True)
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
Dim lType As Long &apos; SQL column type: com.sun.star.sdbc.DataType
Dim vDateTime As Variant &apos; com.sun.star.util.DateTime
Dim bNullable As Boolean &apos; The field is defined as accepting Null values
Dim vTemp As Variant &apos; Work variable for date and time related conversions
Dim sFile As String &apos; File name in FileSystem notation
Dim oSimpleFileAccess As Object &apos; com.sun.star.ucb.SimpleFileAccess
Dim oStream As Object &apos; com.sun.star.io.XInputStream
Dim lFileLength As Long &apos; Binary file length in bytes
Dim UTILS As Object : Set UTILS = ScriptForge.SF_Utils
Dim SESS As Object : Set SESS = ScriptForge.SF_Session
bSet = False
On Local Error GoTo CatchError
Check:
Set oColumn = _RowSet.Columns.getByIndex(plColIndex)
sColumn = oColumn.Name
If _ReadOnly Then GoTo CatchError
If Not ScriptForge.SF_Array.Contains(_UpdatableFields, sColumn, CaseSensitive := True) Then GoTo CatchError
Try:
With com.sun.star.sdbc.DataType
If IsEmpty(pvValue) Then &apos; An empty default value means not nullable and no default =&gt; ignore
ElseIf IsNull(pvValue) Then
If oColumn.IsNullable = com.sun.star.sdbc.ColumnValue.NULLABLE Then oColumn.updateNull() Else Goto CatchError
Else
Select Case oColumn.Type
Case .BIT, .BOOLEAN
If VarType(pvValue) &lt;&gt; UTILS.V_BOOLEAN Then GoTo CatchError
oColumn.updateBoolean(pvValue)
Case .TINYINT
If UTILS._VarTypeExt(pvValue) &lt;&gt; UTILS.V_NUMERIC Then Goto CatchError
If pvValue &lt; -128 Or pvValue &gt; +127 Then Goto CatchError
oColumn.updateShort(CInt(pvValue))
Case .SMALLINT
If UTILS._VarTypeExt(pvValue) &lt;&gt; UTILS.V_NUMERIC Then Goto CatchError
If pvValue &lt; -32768 Or pvValue &gt; 32767 Then Goto CatchError
oColumn.updateInt(CInt(pvValue))
Case .INTEGER
If UTILS._VarTypeExt(pvValue) &lt;&gt; UTILS.V_NUMERIC Then Goto CatchError
If pvValue &lt; -2147483648 Or pvValue &gt; 2147483647 Then Goto CatchError
oColumn.updateInt(CLng(pvValue))
Case .BIGINT
If UTILS._VarTypeExt(pvValue) &lt;&gt; UTILS.V_NUMERIC Then Goto CatchError
oColumn.updateLong(pvValue) &apos; No proper type conversion for HYPER data type
Case .FLOAT
If UTILS._VarTypeExt(pvValue) &lt;&gt; UTILS.V_NUMERIC Then Goto CatchError
If Abs(pvValue) &lt; 3.402823E38 And Abs(pvValue) &gt; 1.401298E-45 Then oColumn.updateFloat(CSng(pvValue)) Else Goto CatchError
Case .REAL, .DOUBLE
If UTILS._VarTypeExt(pvValue) &lt;&gt; UTILS.V_NUMERIC Then Goto CatchError
&apos;If Abs(pvValue) &lt; 1.79769313486232E308 And Abs(pvValue) &gt; 4.94065645841247E-307 Then oColumn.updateDouble(CDbl(pvValue)) Else Goto CatchError
oColumn.updateDouble(CDbl(pvValue))
Case .NUMERIC, .DECIMAL
If UTILS._VarTypeExt(pvValue) &lt;&gt; UTILS.V_NUMERIC Then Goto CatchError
If SESS.HasUnoProperty(oColumn, &quot;Scale&quot;) Then
If oColumn.Scale &gt; 0 Then
&apos;If Abs(pvValue) &lt; 1.79769313486232E308 And Abs(pvValue) &gt; 4.94065645841247E-307 Then oColumn.updateDouble(CDbl(pvValue)) Else Goto CatchError
oColumn.updateDouble(CDbl(pvValue))
Else
oColumn.updateString(CStr(pvValue))
End If
Else
Column.updateString(CStr(pvValue))
End If
Case .CHAR, .VARCHAR, .LONGVARCHAR, .CLOB
If VarType(pvValue) &lt;&gt; V_STRING Then GoTo CatchError
If SESS.HasUnoProperty(oColumn, &quot;Precision&quot;) Then
If oColumn.Precision &gt; 0 And Len(pvValue) &gt; oColumn.Precision Then Goto CatchError
End If
oColumn.updateString(pvValue)
Case .DATE
If VarType(pvValue) &lt;&gt; V_DATE Then GoTo CatchError
vTemp = New com.sun.star.util.Date
With vTemp
.Day = Day(pvValue)
.Month = Month(pvValue)
.Year = Year(pvValue)
End With
oColumn.updateDate(vTemp)
Case .TIME
If VarType(pvValue) &lt;&gt; V_DATE Then GoTo CatchError
vTemp = New com.sun.star.util.Time
With vTemp
.Hours = Hour(pvValue)
.Minutes = Minute(pvValue)
.Seconds = Second(pvValue)
.NanoSeconds = 0
End With
oColumn.updateTime(vTemp)
Case .TIMESTAMP
If VarType(pvValue) &lt;&gt; V_DATE Then GoTo CatchError
vTemp = New com.sun.star.util.DaWHEREteTime
With vTemp
.Day = Day(pvValue)
.Month = Month(pvValue)
.Year = Year(pvValue)
.Hours = Hour(pvValue)
.Minutes = Minute(pvValue)
.Seconds = Second(pvValue)
.NanoSeconds = 0
End With
oColumn.updateTimestamp(vTemp)
Case .BINARY, .VARBINARY, .LONGVARBINARY, .BLOB
If VarType(pvValue) &lt;&gt; V_STRING Then GoTo CatchError
If Not UTILS._ValidateFile(pvValue, &quot;FieldValue&quot;) Then GoTo CatchError
&apos; Verify file
sFile = ConvertToUrl(pvValue)
oSimpleFileAccess = UTILS._GetUnoService(&quot;FileAccess&quot;)
If Not oSimpleFileAccess.exists(sFile) Then Goto CatchError
&apos; Load the binary data
Set oStream = oSimpleFileAccess.openFileRead(sFile)
lFileLength = oStream.getLength()
If lFileLength = 0 Then Goto CatchError &apos; &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; PUT NULL
oColumn.updateBinaryStream(oStream, lFileLength)
oStream.closeInput()
Case Else
Goto CatchError
End Select
End If
End With
bSet = True
Finally:
_SetColumnValue = bSet
Exit Function
CatchError:
On Local Error GoTo 0
ScriptForge.SF_Exception.RaiseFatal(RECORDUPDATEERROR, sColumn, ScriptForge.SF_String.Represent(pvValue), oColumn.TypeName)
GoTo Finally
End Function &apos; SFDatabases.SF_Dataset._SetColumnValue
REM ============================================ END OF SFDATABASES.SF_DATASET
</script:module>