Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / wizards / source / sfdatabases / SF_Database.xba
blob109d4c57d909d6cd08201e32f6febcc88915245a
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
3 <script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Database" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
4 REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
5 REM === The SFDatabases library is one of the associated libraries. ===
6 REM === Full documentation is available on https://help.libreoffice.org/ ===
7 REM =======================================================================================================================
9 Option Compatible
10 Option ClassModule
12 Option Explicit
14 &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
15 &apos;&apos;&apos; SF_Database
16 &apos;&apos;&apos; ===========
17 &apos;&apos;&apos; Management of databases embedded in or related to Base documents
18 &apos;&apos;&apos; Each instance of the current class represents a single database, with essentially its tables, queries and data
19 &apos;&apos;&apos;
20 &apos;&apos;&apos; The exchanges with the database are done in SQL only.
21 &apos;&apos;&apos; To make them more readable, use optionally square brackets to surround table/query/field names
22 &apos;&apos;&apos; instead of the (RDBMS-dependent) normal surrounding character (usually, double-quote, single-quote or other).
23 &apos;&apos;&apos; SQL statements may be run in direct or indirect mode. In direct mode the statement is transferred literally
24 &apos;&apos;&apos; without syntax checking nor review to the database system.
25 &apos;&apos;&apos;
26 &apos;&apos;&apos; The provided interfaces include simple tables, queries and fields lists, and access to database metadata.
27 &apos;&apos;&apos;
28 &apos;&apos;&apos; Service invocation and usage:
29 &apos;&apos;&apos; 1) To access any database at anytime
30 &apos;&apos;&apos; Dim myDatabase As Object
31 &apos;&apos;&apos; Set myDatabase = CreateScriptService(&quot;SFDatabases.Database&quot;, FileName, , [ReadOnly], [User, [Password]])
32 &apos;&apos;&apos; &apos; Args:
33 &apos;&apos;&apos; &apos; FileName: the name of the Base file compliant with the SF_FileSystem.FileNaming notation
34 &apos;&apos;&apos; &apos; RegistrationName: the name of a registered database (mutually exclusive with FileName)
35 &apos;&apos;&apos; &apos; ReadOnly: Default = True
36 &apos;&apos;&apos; &apos; User, Password: additional connection arguments to the database server
37 &apos;&apos;&apos; &apos; ... Run queries, SQL statements, ...
38 &apos;&apos;&apos; myDatabase.CloseDatabase()
39 &apos;&apos;&apos;
40 &apos;&apos;&apos; 2) To access the database related to the current Base document
41 &apos;&apos;&apos; Dim myDoc As Object, myDatabase As Object, ui As Object
42 &apos;&apos;&apos; Set ui = CreateScriptService(&quot;UI&quot;)
43 &apos;&apos;&apos; Set myDoc = ui.OpenBaseDocument(&quot;myDb.odb&quot;)
44 &apos;&apos;&apos; Set myDatabase = myDoc.GetDatabase() &apos; user and password are supplied here, if needed
45 &apos;&apos;&apos; &apos; ... Run queries, SQL statements, ...
46 &apos;&apos;&apos; myDoc.CloseDocument()
47 &apos;&apos;&apos;
48 &apos;&apos;&apos; Detailed user documentation:
49 &apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_database.html?DbPAR=BASIC
50 &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
52 REM ================================================================== EXCEPTIONS
54 Private Const DBREADONLYERROR = &quot;DBREADONLYERROR&quot;
55 Private Const SQLSYNTAXERROR = &quot;SQLSYNTAXERROR&quot;
57 REM ============================================================= PRIVATE MEMBERS
59 Private [Me] As Object
60 Private [_Parent] As Object
61 Private ObjectType As String &apos; Must be DATABASE
62 Private ServiceName As String
63 Private _DataSource As Object &apos; com.sun.star.comp.dba.ODatabaseSource
64 Private _Connection As Object &apos; com.sun.star.sdbc.XConnection
65 Private _URL As String &apos; Text on status bar
66 Private _Location As String &apos; File name
67 Private _ReadOnly As Boolean
68 Private _MetaData As Object &apos; com.sun.star.sdbc.XDatabaseMetaData
70 REM ============================================================ MODULE CONSTANTS
72 Const cstToken = &quot;//&quot; &apos; Form names accept special characters but not slashes
74 REM ===================================================== CONSTRUCTOR/DESTRUCTOR
76 REM -----------------------------------------------------------------------------
77 Private Sub Class_Initialize()
78 Set [Me] = Nothing
79 Set [_Parent] = Nothing
80 ObjectType = &quot;DATABASE&quot;
81 ServiceName = &quot;SFDatabases.Database&quot;
82 Set _DataSource = Nothing
83 Set _Connection = Nothing
84 _URL = &quot;&quot;
85 _Location = &quot;&quot;
86 _ReadOnly = True
87 Set _MetaData = Nothing
88 End Sub &apos; SFDatabases.SF_Database Constructor
90 REM -----------------------------------------------------------------------------
91 Private Sub Class_Terminate()
92 Call Class_Initialize()
93 End Sub &apos; SFDatabases.SF_Database Destructor
95 REM -----------------------------------------------------------------------------
96 Public Function Dispose() As Variant
97 Call Class_Terminate()
98 Set Dispose = Nothing
99 End Function &apos; SFDatabases.SF_Database Explicit Destructor
101 REM ================================================================== PROPERTIES
103 REM -----------------------------------------------------------------------------
104 Property Get Queries() As Variant
105 &apos;&apos;&apos; Return the list of available queries in the database
106 Queries = _PropertyGet(&quot;Queries&quot;)
107 End Property &apos; SFDatabases.SF_Database.Queries (get)
109 REM -----------------------------------------------------------------------------
110 Property Get Tables() As Variant
111 &apos;&apos;&apos; Return the list of available Tables in the database
112 Tables = _PropertyGet(&quot;Tables&quot;)
113 End Property &apos; SFDatabases.SF_Database.Tables (get)
115 REM -----------------------------------------------------------------------------
116 Property Get XConnection() As Variant
117 &apos;&apos;&apos; Return a com.sun.star.sdbc.XConnection UNO object
118 XConnection = _PropertyGet(&quot;XConnection&quot;)
119 End Property &apos; SFDatabases.SF_Database.XConnection (get)
121 REM -----------------------------------------------------------------------------
122 Property Get XMetaData() As Variant
123 &apos;&apos;&apos; Return a com.sun.star.sdbc.XDatabaseMetaData UNO object
124 XMetaData = _PropertyGet(&quot;XMetaData&quot;)
125 End Property &apos; SFDatabases.SF_Database.XMetaData (get)
127 REM ===================================================================== METHODS
129 REM -----------------------------------------------------------------------------
130 Public Sub CloseDatabase()
131 &apos;&apos;&apos; Close the current database connection
133 Const cstThisSub = &quot;SFDatabases.Database.CloseDatabase&quot;
134 Const cstSubArgs = &quot;&quot;
136 On Local Error GoTo 0 &apos; Disable useless error checking
138 Check:
139 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
141 Try:
142 With _Connection
143 If Not IsNull(_Connection) Then
144 If ScriptForge.SF_Session.HasUnoMethod(_Connection, &quot;flush&quot;) Then .flush()
145 .close()
146 .dispose()
147 End If
148 Dispose()
149 End With
151 Finally:
152 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
153 Exit Sub
154 End Sub
156 REM -----------------------------------------------------------------------------
157 Public Function DAvg(Optional ByVal Expression As Variant _
158 , Optional ByVal TableName As Variant _
159 , Optional ByVal Criteria As Variant _
160 ) As Variant
161 &apos;&apos;&apos; Compute the aggregate function AVG() on a field or expression belonging to a table
162 &apos;&apos;&apos; filtered by a WHERE-clause.
163 &apos;&apos;&apos; Args:
164 &apos;&apos;&apos; Expression: an SQL expression
165 &apos;&apos;&apos; TableName: the name of a table
166 &apos;&apos;&apos; Criteria: an optional WHERE clause without the word WHERE
168 DAvg = _DFunction(&quot;Avg&quot;, Expression, TableName, Criteria)
170 End Function &apos; SFDatabases.SF_Database.DAvg
172 REM -----------------------------------------------------------------------------
173 Public Function DCount(Optional ByVal Expression As Variant _
174 , Optional ByVal TableName As Variant _
175 , Optional ByVal Criteria As Variant _
176 ) As Variant
177 &apos;&apos;&apos; Compute the aggregate function COUNT() on a field or expression belonging to a table
178 &apos;&apos;&apos; filtered by a WHERE-clause.
179 &apos;&apos;&apos; Args:
180 &apos;&apos;&apos; Expression: an SQL expression
181 &apos;&apos;&apos; TableName: the name of a table
182 &apos;&apos;&apos; Criteria: an optional WHERE clause without the word WHERE
184 DCount = _DFunction(&quot;Count&quot;, Expression, TableName, Criteria)
186 End Function &apos; SFDatabases.SF_Database.DCount
188 REM -----------------------------------------------------------------------------
189 Public Function DLookup(Optional ByVal Expression As Variant _
190 , Optional ByVal TableName As Variant _
191 , Optional ByVal Criteria As Variant _
192 , Optional ByVal OrderClause As Variant _
193 ) As Variant
194 &apos;&apos;&apos; Compute the aggregate function Lookup() on a field or expression belonging to a table
195 &apos;&apos;&apos; filtered by a WHERE-clause.
196 &apos;&apos;&apos; To order the results, a pvOrderClause may be precised. The 1st record will be retained.
197 &apos;&apos;&apos; Args:
198 &apos;&apos;&apos; Expression: an SQL expression
199 &apos;&apos;&apos; TableName: the name of a table
200 &apos;&apos;&apos; Criteria: an optional WHERE clause without the word WHERE
201 &apos;&apos;&apos; pvOrderClause: an optional order clause incl. &quot;DESC&quot; if relevant
203 DLookup = _DFunction(&quot;Lookup&quot;, Expression, TableName, Criteria, OrderClause)
205 End Function &apos; SFDatabases.SF_Database.DLookup
207 REM -----------------------------------------------------------------------------
208 Public Function DMax(Optional ByVal Expression As Variant _
209 , Optional ByVal TableName As Variant _
210 , Optional ByVal Criteria As Variant _
211 ) As Variant
212 &apos;&apos;&apos; Compute the aggregate function MAX() on a field or expression belonging to a table
213 &apos;&apos;&apos; filtered by a WHERE-clause.
214 &apos;&apos;&apos; Args:
215 &apos;&apos;&apos; Expression: an SQL expression
216 &apos;&apos;&apos; TableName: the name of a table
217 &apos;&apos;&apos; Criteria: an optional WHERE clause without the word WHERE
219 DMax = _DFunction(&quot;Max&quot;, Expression, TableName, Criteria)
221 End Function &apos; SFDatabases.SF_Database.DMax
223 REM -----------------------------------------------------------------------------
224 Public Function DMin(Optional ByVal Expression As Variant _
225 , Optional ByVal TableName As Variant _
226 , Optional ByVal Criteria As Variant _
227 ) As Variant
228 &apos;&apos;&apos; Compute the aggregate function MIN() on a field or expression belonging to a table
229 &apos;&apos;&apos; filtered by a WHERE-clause.
230 &apos;&apos;&apos; Args:
231 &apos;&apos;&apos; Expression: an SQL expression
232 &apos;&apos;&apos; TableName: the name of a table
233 &apos;&apos;&apos; Criteria: an optional WHERE clause without the word WHERE
235 DMin = _DFunction(&quot;Min&quot;, Expression, TableName, Criteria)
237 End Function &apos; SFDatabases.SF_Database.DMin
239 REM -----------------------------------------------------------------------------
240 Public Function DSum(Optional ByVal Expression As Variant _
241 , Optional ByVal TableName As Variant _
242 , Optional ByVal Criteria As Variant _
243 ) As Variant
244 &apos;&apos;&apos; Compute the aggregate function Sum() on a field or expression belonging to a table
245 &apos;&apos;&apos; filtered by a WHERE-clause.
246 &apos;&apos;&apos; Args:
247 &apos;&apos;&apos; Expression: an SQL expression
248 &apos;&apos;&apos; TableName: the name of a table
249 &apos;&apos;&apos; Criteria: an optional WHERE clause without the word WHERE
251 DSum = _DFunction(&quot;Sum&quot;, Expression, TableName, Criteria)
253 End Function &apos; SFDatabases.SF_Database.DSum
255 REM -----------------------------------------------------------------------------
256 Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
257 &apos;&apos;&apos; Return the actual value of the given property
258 &apos;&apos;&apos; Args:
259 &apos;&apos;&apos; PropertyName: the name of the property as a string
260 &apos;&apos;&apos; Returns:
261 &apos;&apos;&apos; The actual value of the property
262 &apos;&apos;&apos; Exceptions:
263 &apos;&apos;&apos; ARGUMENTERROR The property does not exist
264 &apos;&apos;&apos; Examples:
265 &apos;&apos;&apos; myDatabase.GetProperty(&quot;Queries&quot;)
267 Const cstThisSub = &quot;SFDatabases.Database.GetProperty&quot;
268 Const cstSubArgs = &quot;&quot;
270 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
271 GetProperty = Null
273 Check:
274 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
275 If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
276 End If
278 Try:
279 GetProperty = _PropertyGet(PropertyName)
281 Finally:
282 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
283 Exit Function
284 Catch:
285 GoTo Finally
286 End Function &apos; SFDatabases.SF_Database.GetProperty
288 REM -----------------------------------------------------------------------------
289 Public Function GetRows(Optional ByVal SQLCommand As Variant _
290 , Optional ByVal DirectSQL As Variant _
291 , Optional ByVal Header As Variant _
292 , Optional ByVal MaxRows As Variant _
293 ) As Variant
294 &apos;&apos;&apos; Return the content of a table, a query or a SELECT SQL statement as an array
295 &apos;&apos;&apos; Args:
296 &apos;&apos;&apos; SQLCommand: a table name, a query name or a SELECT SQL statement
297 &apos;&apos;&apos; DirectSQL: when True, no syntax conversion is done by LO. Default = False
298 &apos;&apos;&apos; Ignored when SQLCommand is a table or a query name
299 &apos;&apos;&apos; Header: When True, a header row is inserted on the top of the array with the column names. Default = False
300 &apos;&apos;&apos; MaxRows: The maximum number of returned rows. If absent, all records are returned
301 &apos;&apos;&apos; Returns:
302 &apos;&apos;&apos; a 2D array(row, column), even if only 1 column and/or 1 record
303 &apos;&apos;&apos; an empty array if no records returned
304 &apos;&apos;&apos; Example:
305 &apos;&apos;&apos; Dim a As Variant
306 &apos;&apos;&apos; a = myDatabase.GetRows(&quot;SELECT [First Name], [Last Name] FROM [Employees] ORDER BY [Last Name]&quot;, Header := True)
308 Dim vResult As Variant &apos; Return value
309 Dim oResult As Object &apos; com.sun.star.sdbc.XResultSet
310 Dim oQuery As Object &apos; com.sun.star.ucb.XContent
311 Dim sSql As String &apos; SQL statement
312 Dim bDirect &apos; Alias of DirectSQL
313 Dim lCols As Long &apos; Number of columns
314 Dim lRows As Long &apos; Number of rows
315 Dim oColumns As Object &apos; Collection of com.sun.star.sdb.ODataColumn
316 Dim bRead As Boolean &apos; When True, next record has been read successfully
317 Dim i As Long
318 Const cstThisSub = &quot;SFDatabases.Database.GetRows&quot;
319 Const cstSubArgs = &quot;SQLCommand, [DirectSQL=False], [Header=False], [MaxRows=0]&quot;
321 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
322 vResult = Array()
324 Check:
325 If IsMissing(DirectSQL) Or IsEmpty(DirectSQL) Then DirectSQL = False
326 If IsMissing(Header) Or IsEmpty(Header) Then Header = False
327 If IsMissing(MaxRows) Or IsEmpty(MaxRows) Then MaxRows = 0
328 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
329 If Not ScriptForge.SF_Utils._Validate(SQLCommand, &quot;SQLCommand&quot;, V_STRING) Then GoTo Finally
330 If Not ScriptForge.SF_Utils._Validate(DirectSQL, &quot;DirectSQL&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
331 If Not ScriptForge.SF_Utils._Validate(Header, &quot;Header&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
332 If Not ScriptForge.SF_Utils._Validate(MaxRows, &quot;MaxRows&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
333 End If
335 Try:
336 &apos; Table, query of SQL ? Prepare resultset
337 If ScriptForge.SF_Array.Contains(Tables, SQLCommand, CaseSensitive := True, SortOrder := &quot;ASC&quot;) Then
338 sSql = &quot;SELECT * FROM [&quot; &amp; SQLCommand &amp; &quot;]&quot;
339 bDirect = True
340 ElseIf ScriptForge.SF_Array.Contains(Queries, SQLCommand, CaseSensitive := True, SortOrder := &quot;ASC&quot;) Then
341 Set oQuery = _Connection.Queries.getByName(SQLCommand)
342 sSql = oQuery.Command
343 bDirect = Not oQuery.EscapeProcessing
344 ElseIf ScriptForge.SF_String.StartsWith(SQLCommand, &quot;SELECT&quot;, CaseSensitive := False) Then
345 sSql = SQLCommand
346 bDirect = DirectSQL
347 Else
348 GoTo Finally
349 End If
351 &apos; Execute command
352 Set oResult = _ExecuteSql(sSql, bDirect)
353 If IsNull(oResult) Then GoTo Finally
355 With oResult
356 &apos;Initialize output array with header row
357 Set oColumns = oResult.getColumns()
358 lCols = oColumns.Count - 1
359 If Header Then
360 lRows = 0
361 ReDim vResult(0 To lRows, 0 To lCols)
362 For i = 0 To lCols
363 vResult(lRows, i) = oColumns.getByIndex(i).Name
364 Next i
365 If MaxRows &gt; 0 Then MaxRows = MaxRows + 1
366 Else
367 lRows = -1
368 End If
370 &apos; Load data
371 bRead = .first()
372 Do While bRead And (MaxRows = 0 Or lRows &lt; MaxRows - 1)
373 lRows = lRows + 1
374 If lRows = 0 Then
375 ReDim vResult(0 To lRows, 0 To lCols)
376 Else
377 ReDim Preserve vResult(0 To lRows, 0 To lCols)
378 End If
379 For i = 0 To lCols
380 vResult(lRows, i) = _GetColumnValue(oResult, i + 1)
381 Next i
382 bRead = .next()
383 Loop
384 End With
386 Finally:
387 GetRows = vResult
388 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
389 Exit Function
390 Catch:
391 GoTo Finally
392 End Function &apos; SFDatabases.SF_Database.GetRows
394 REM -----------------------------------------------------------------------------
395 Public Function Methods() As Variant
396 &apos;&apos;&apos; Return the list of public methods of the Database service as an array
398 Methods = Array( _
399 &quot;CloseDatabase&quot; _
400 , &quot;DAvg&quot; _
401 , &quot;DCount&quot; _
402 , &quot;DLookup&quot; _
403 , &quot;DMax&quot; _
404 , &quot;DMin&quot; _
405 , &quot;DSum&quot; _
406 , &quot;GetRows&quot; _
407 , &quot;OpenFormDocument&quot; _
408 , &quot;OpenQuery&quot; _
409 , &quot;OpenSql&quot; _
410 , &quot;OpenTable&quot; _
411 , &quot;RunSql&quot; _
414 End Function &apos; SFDatabases.SF_Database.Methods
416 REM -----------------------------------------------------------------------------
417 Public Function OpenFormDocument(Optional ByVal FormDocument As Variant) As Object
418 &apos;&apos;&apos; Open the FormDocument given by its hierarchical name in normal mode
419 &apos;&apos;&apos; If the form document is already open, the form document is made active
420 &apos;&apos;&apos; Args:
421 &apos;&apos;&apos; FormDocument: a valid form document name as a case-sensitive string
422 &apos;&apos;&apos; When hierarchical, the hierarchy must be rendered with forward slashes (&quot;/&quot;)
423 &apos;&apos;&apos; Returns:
424 &apos;&apos;&apos; A FormDocument instance or Nothing
425 &apos;&apos;&apos; Exceptions:
426 &apos;&apos;&apos; Form name is invalid
427 &apos;&apos;&apos; Example:
428 &apos;&apos;&apos; Set oForm = oDb.OpenFormDocument(&quot;Folder1/myFormDocument&quot;)
430 Dim oOpen As Object &apos; Return value
431 Dim oFormDocuments As Variant &apos; com.sun.star.comp.dba.ODocumentContainer
432 Dim vFormNames As Variant &apos; Array of all document form names present in the document
433 Dim vOpenArgs As Variant &apos; Array of property values
434 Dim oNewForm As Object &apos; Output of loadComponent()
435 Const cstThisSub = &quot;SFDatabases.Database.OpenFormDocument&quot;
436 Const cstSubArgs = &quot;FormDocument&quot;
438 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
439 Set oOpen = Nothing
441 Check:
442 &apos; Build list of available FormDocuments recursively with _CollectFormDocuments
443 Set oFormDocuments = _Connection.Parent.DataBaseDocument.FormDocuments
445 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
446 vFormNames = Split(_CollectFormDocuments(oFormDocuments), cstToken)
447 If Not ScriptForge.SF_Utils._Validate(FormDocument, &quot;FormDocument&quot;, V_STRING, vFormNames) Then GoTo Finally
448 End If
450 Try:
451 vOpenArgs = Array(SF_Utils._MakePropertyValue(&quot;ActiveConnection&quot;, _Connection) _
452 , SF_Utils._MakePropertyValue(&quot;OpenMode&quot;, &quot;open&quot;) _
454 Set oNewForm = oFormDocuments.loadComponentFromURL(FormDocument, &quot;&quot;, 0, vOpenArgs)
456 Set oOpen = ScriptForge.SF_Services.CreateScriptService(&quot;SFDocuments.FormDocument&quot;, oNewForm)
458 &apos; Prevent desynchonization when using .last(), .next() etc immediately after component loading. Bug #156836
459 Wait 1
461 Finally:
462 Set OpenFormDocument = oOpen
463 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
464 Exit Function
465 Catch:
466 GoTo Finally
467 End Function &apos; SF_Databases.SF_Database.OpenFormDocument
469 REM -----------------------------------------------------------------------------
470 Public Function OpenQuery(Optional ByVal QueryName As Variant) As Object
471 &apos;&apos;&apos; Open the query given by its name
472 &apos;&apos;&apos; The datasheet will live independently from any other (typically Base) component
473 &apos;&apos;&apos; Args:
474 &apos;&apos;&apos; QueryName: a valid query name as a case-sensitive string
475 &apos;&apos;&apos; Returns:
476 &apos;&apos;&apos; A Datasheet class instance if the query could be opened, otherwise Nothing
477 &apos;&apos;&apos; Exceptions:
478 &apos;&apos;&apos; Query name is invalid
479 &apos;&apos;&apos; Example:
480 &apos;&apos;&apos; oDb.OpenQuery(&quot;myQuery&quot;)
482 Dim oOpen As Object &apos; Return value
483 Const cstThisSub = &quot;SFDatabases.Database.OpenQuery&quot;
484 Const cstSubArgs = &quot;QueryName&quot;
486 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
487 Set oOpen = Nothing
489 Check:
490 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
491 If Not ScriptForge.SF_Utils._Validate(QueryName, &quot;QueryName&quot;, V_STRING, Queries) Then GoTo Finally
492 End If
494 Try:
495 Set oOpen = _OpenDatasheet(QueryName, com.sun.star.sdb.CommandType.QUERY _
496 , _Connection.Queries.getByName(QueryName).EscapeProcessing)
498 Finally:
499 Set OpenQuery = oOpen
500 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
501 Exit Function
502 Catch:
503 GoTo Finally
504 End Function &apos; SFDocuments.SF_Base.OpenQuery
506 REM -----------------------------------------------------------------------------
507 Public Function OpenSql(Optional ByRef Sql As Variant _
508 , Optional ByVal DirectSql As Variant _
509 ) As Object
510 &apos;&apos;&apos; Open the datasheet based on a SQL SELECT statement.
511 &apos;&apos;&apos; The datasheet will live independently from any other (typically Base) component
512 &apos;&apos;&apos; Args:
513 &apos;&apos;&apos; Sql: a valid Sql statement as a case-sensitive string.
514 &apos;&apos;&apos; Identifiers may be surrounded by square brackets
515 &apos;&apos;&apos; DirectSql: when True, the statement is processed by the targeted RDBMS
516 &apos;&apos;&apos; Returns:
517 &apos;&apos;&apos; A Datasheet class instance if it could be opened, otherwise Nothing
518 &apos;&apos;&apos; Example:
519 &apos;&apos;&apos; oDb.OpenSql(&quot;SELECT * FROM [Customers] ORDER BY [CITY]&quot;)
521 Dim oOpen As Object &apos; Return value
522 Const cstThisSub = &quot;SFDatabases.Database.OpenSql&quot;
523 Const cstSubArgs = &quot;Sql, [DirectSql=False]&quot;
525 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
526 Set oOpen = Nothing
528 Check:
529 If IsMissing(DirectSql) Or IsEmpty(DirectSql) Then DirectSql = False
530 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
531 If Not ScriptForge.SF_Utils._Validate(Sql, &quot;Sql&quot;, V_STRING) Then GoTo Finally
532 If Not ScriptForge.SF_Utils._Validate(DirectSql, &quot;DirectSql&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
533 End If
535 Try:
536 Set oOpen = _OpenDatasheet(_ReplaceSquareBrackets(Sql), com.sun.star.sdb.CommandType.COMMAND, Not DirectSql)
538 Finally:
539 Set OpenSql = oOpen
540 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
541 Exit Function
542 Catch:
543 GoTo Finally
544 End Function &apos; SFDocuments.SF_Base.OpenSql
546 REM -----------------------------------------------------------------------------
547 Public Function OpenTable(Optional ByVal TableName As Variant) As Object
548 &apos;&apos;&apos; Open the table given by its name
549 &apos;&apos;&apos; The datasheet will live independently from any other (typically Base) component
550 &apos;&apos;&apos; Args:
551 &apos;&apos;&apos; TableName: a valid table name as a case-sensitive string
552 &apos;&apos;&apos; Returns:
553 &apos;&apos;&apos; A Datasheet class instance if the table could be opened, otherwise Nothing
554 &apos;&apos;&apos; Exceptions:
555 &apos;&apos;&apos; Table name is invalid
556 &apos;&apos;&apos; Example:
557 &apos;&apos;&apos; oDb.OpenTable(&quot;myTable&quot;)
559 Dim oOpen As Object &apos; Return value
560 Const cstThisSub = &quot;SFDatabases.Database.OpenTable&quot;
561 Const cstSubArgs = &quot;TableName&quot;
563 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
564 Set oOpen = Nothing
566 Check:
567 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
568 If Not ScriptForge.SF_Utils._Validate(TableName, &quot;TableName&quot;, V_STRING, Tables) Then GoTo Finally
569 End If
571 Try:
572 Set oOpen = _OpenDatasheet(TableName, com.sun.star.sdb.CommandType.TABLE, True)
574 Finally:
575 Set OpenTable = oOpen
576 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
577 Exit Function
578 Catch:
579 GoTo Finally
580 End Function &apos; SFDocuments.SF_Base.OpenTable
582 REM -----------------------------------------------------------------------------
583 Public Function Properties() As Variant
584 &apos;&apos;&apos; Return the list or properties of the Database class as an array
586 Properties = Array( _
587 &quot;Queries&quot; _
588 , &quot;Tables&quot; _
589 , &quot;XConnection&quot; _
590 , &quot;XMetaData&quot; _
593 End Function &apos; SFDatabases.SF_Database.Properties
595 REM -----------------------------------------------------------------------------
596 Public Function RunSql(Optional ByVal SQLCommand As Variant _
597 , Optional ByVal DirectSQL As Variant _
598 ) As Boolean
599 &apos;&apos;&apos; Execute an action query (table creation, record insertion, ...) or SQL statement on the current database
600 &apos;&apos;&apos; Args:
601 &apos;&apos;&apos; SQLCommand: a query name or an SQL statement
602 &apos;&apos;&apos; DirectSQL: when True, no syntax conversion is done by LO. Default = False
603 &apos;&apos;&apos; Ignored when SQLCommand is a query name
604 &apos;&apos;&apos; Exceptions:
605 &apos;&apos;&apos; DBREADONLYERROR The method is not applicable on a read-only database
606 &apos;&apos;&apos; Example:
607 &apos;&apos;&apos; myDatabase.RunSql(&quot;INSERT INTO [EMPLOYEES] VALUES(25, &apos;SMITH&apos;, &apos;John&apos;)&quot;, DirectSQL := True)
609 Dim bResult As Boolean &apos; Return value
610 Dim oStatement As Object &apos; com.sun.star.sdbc.XStatement
611 Dim oQuery As Object &apos; com.sun.star.ucb.XContent
612 Dim sSql As String &apos; SQL statement
613 Dim bDirect &apos; Alias of DirectSQL
614 Const cstQuery = 2, cstSql = 3
615 Const cstThisSub = &quot;SFDatabases.Database.RunSql&quot;
616 Const cstSubArgs = &quot;SQLCommand, [DirectSQL=False]&quot;
618 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
619 bResult = False
621 Check:
622 If IsMissing(DirectSQL) Or IsEmpty(DirectSQL) Then DirectSQL = False
623 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
624 If Not ScriptForge.SF_Utils._Validate(SQLCommand, &quot;SQLCommand&quot;, V_STRING) Then GoTo Finally
625 If Not ScriptForge.SF_Utils._Validate(DirectSQL, &quot;DirectSQL&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
626 End If
627 If _ReadOnly Then GoTo Catch_ReadOnly
629 Try:
630 &apos; Query of SQL ?
631 If ScriptForge.SF_Array.Contains(Queries, SQLCommand, CaseSensitive := True, SortOrder := &quot;ASC&quot;) Then
632 Set oQuery = _Connection.Queries.getByName(SQLCommand)
633 sSql = oQuery.Command
634 bDirect = Not oQuery.EscapeProcessing
635 ElseIf Not ScriptForge.SF_String.StartsWith(SQLCommand, &quot;SELECT&quot;, CaseSensitive := False) Then
636 sSql = SQLCommand
637 bDirect = DirectSQL
638 Else
639 GoTo Finally
640 End If
642 &apos; Execute command
643 bResult = _ExecuteSql(sSql, bDirect)
645 Finally:
646 RunSql = bResult
647 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
648 Exit Function
649 Catch:
650 GoTo Finally
651 Catch_ReadOnly:
652 ScriptForge.SF_Exception.RaiseFatal(DBREADONLYERROR)
653 GoTo Finally
654 End Function &apos; SFDatabases.SF_Database.RunSql
656 REM -----------------------------------------------------------------------------
657 Public Function SetProperty(Optional ByVal PropertyName As Variant _
658 , Optional ByRef Value As Variant _
659 ) As Boolean
660 &apos;&apos;&apos; Set a new value to the given property
661 &apos;&apos;&apos; Args:
662 &apos;&apos;&apos; PropertyName: the name of the property as a string
663 &apos;&apos;&apos; Value: its new value
664 &apos;&apos;&apos; Exceptions
665 &apos;&apos;&apos; ARGUMENTERROR The property does not exist
667 Const cstThisSub = &quot;SFDatabases.Database.SetProperty&quot;
668 Const cstSubArgs = &quot;PropertyName, Value&quot;
670 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
671 SetProperty = False
673 Check:
674 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
675 If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
676 End If
678 Try:
679 Select Case UCase(PropertyName)
680 Case Else
681 End Select
683 Finally:
684 SF_Utils._ExitFunction(cstThisSub)
685 Exit Function
686 Catch:
687 GoTo Finally
688 End Function &apos; SFDatabases.SF_Database.SetProperty
690 REM =========================================================== PRIVATE FUNCTIONS
692 REM -----------------------------------------------------------------------------
693 Private Function _CollectFormDocuments(ByRef poContainer As Object) As String
694 &apos;&apos;&apos; Returns a token-separated string of all hierarchical formdocument names
695 &apos;&apos;&apos; depending on the formdocuments container in argument
696 &apos;&apos;&apos; The function traverses recursively the whole tree below the container
697 &apos;&apos;&apos; The initial call starts from the container _Component.getFormDocuments
698 &apos;&apos;&apos; The list contains closed and open forms
700 Dim sCollectNames As String &apos; Return value
701 Dim oSubItem As Object &apos; com.sun.star.container.XNameAccess (folder) or com.sun.star.ucb.XContent (form)
702 Dim i As Long
703 Const cstFormType = &quot;application/vnd.oasis.opendocument.text&quot;
704 &apos; Identifies forms. Folders have a zero-length content type
706 On Local Error GoTo Finally
708 Try:
709 sCollectNames = &quot;&quot;
710 With poContainer
711 For i = 0 To .Count - 1
712 Set oSubItem = .getByIndex(i)
713 If oSubItem.ContentType = cstFormType Then &apos; Add the form to the list
714 sCollectNames = sCollectNames &amp; cstToken &amp; oSubItem.HierarchicalName
715 Else
716 sCollectNames = sCollectNames &amp; cstToken &amp; _CollectFormDocuments(oSubItem)
717 End If
718 Next i
719 End With
721 Finally:
722 If Len(sCollectNames) &gt; 0 Then
723 _CollectFormDocuments = Mid(sCollectNames, Len(cstToken) + 1) &apos; Skip the initial token
724 Else
725 _CollectFormDocuments = &quot;&quot;
726 End If
727 Exit Function
728 End Function &apos; SFDocuments.SF_Base._CollectFormDocuments
730 REM -----------------------------------------------------------------------------------------------------------------------
731 Private Function _DFunction(ByVal psFunction As String _
732 , Optional ByVal pvExpression As Variant _
733 , Optional ByVal pvTableName As Variant _
734 , Optional ByVal pvCriteria As Variant _
735 , Optional ByVal pvOrderClause As Variant _
736 ) As Variant
737 &apos;&apos;&apos; Build and execute a SQL statement computing the aggregate function psFunction
738 &apos;&apos;&apos; on a field or expression pvExpression belonging to a table pvTableName
739 &apos;&apos;&apos; filtered by a WHERE-clause pvCriteria.
740 &apos;&apos;&apos; To order the results, a pvOrderClause may be precised.
741 &apos;&apos;&apos; Only the 1st record will be retained anyway.
742 &apos;&apos;&apos; Args:
743 &apos;&apos;&apos; psFunction an optional aggregate function: SUM, COUNT, AVG, LOOKUP
744 &apos;&apos;&apos; pvExpression: an SQL expression
745 &apos;&apos;&apos; pvTableName: the name of a table, NOT surrounded with quoting char
746 &apos;&apos;&apos; pvCriteria: an optional WHERE clause without the word WHERE
747 &apos;&apos;&apos; pvOrderClause: an optional order clause incl. &quot;DESC&quot; if relevant
748 &apos;&apos;&apos; (meaningful only for LOOKUP)
750 Dim vResult As Variant &apos; Return value
751 Dim oResult As Object &apos; com.sun.star.sdbc.XResultSet
752 Dim sSql As String &apos; SQL statement.
753 Dim sExpr As String &apos; For inclusion of aggregate function
754 Dim sTarget as String &apos; Alias of pvExpression
755 Dim sWhere As String &apos; Alias of pvCriteria
756 Dim sOrderBy As String &apos; Alias of pvOrderClause
757 Dim sLimit As String &apos; TOP 1 clause
758 Dim sProductName As String &apos; RDBMS as a string
759 Const cstAliasField = &quot;[&quot; &amp; &quot;TMP_ALIAS_ANY_FIELD&quot; &amp; &quot;]&quot; &apos; Alias field in SQL expression
760 Dim cstThisSub As String : cstThisSub = &quot;SFDatabases.SF_Database.D&quot; &amp; psFunction
761 Const cstSubArgs = &quot;Expression, TableName, [Criteria=&quot;&quot;&quot;&quot;], [OrderClause=&quot;&quot;&quot;&quot;]&quot;
762 Const cstLookup = &quot;Lookup&quot;
764 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
765 vResult = Null
767 Check:
768 If IsMissing(pvCriteria) Or IsEmpty(pvCriteria) Then pvCriteria = &quot;&quot;
769 If IsMissing(pvOrderClause) Or IsEmpty(pvOrderClause) Then pvOrderClause = &quot;&quot;
770 If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
771 If Not ScriptForge.SF_Utils._Validate(pvExpression, &quot;Expression&quot;, V_STRING) Then GoTo Finally
772 If Not ScriptForge.SF_Utils._Validate(pvTableName, &quot;TableName&quot;, V_STRING, Tables) Then GoTo Finally
773 If Not ScriptForge.SF_Utils._Validate(pvCriteria, &quot;Criteria&quot;, V_STRING) Then GoTo Finally
774 If Not ScriptForge.SF_Utils._Validate(pvOrderClause, &quot;OrderClause&quot;, V_STRING) Then GoTo Finally
775 End If
777 Try:
778 If pvCriteria &lt;&gt; &quot;&quot; Then sWhere = &quot; WHERE &quot; &amp; pvCriteria Else sWhere = &quot;&quot;
779 If pvOrderClause &lt;&gt; &quot;&quot; Then sOrderBy = &quot; ORDER BY &quot; &amp; pvOrderClause Else sOrderBy = &quot;&quot;
780 sLimit = &quot;&quot;
782 pvTableName = &quot;[&quot; &amp; pvTableName &amp; &quot;]&quot;
784 sProductName = UCase(_MetaData.getDatabaseProductName())
786 Select Case sProductName
787 Case &quot;MYSQL&quot;, &quot;SQLITE&quot;
788 If psFunction = cstLookup Then
789 sTarget = pvExpression
790 sLimit = &quot; LIMIT 1&quot;
791 Else
792 sTarget = UCase(psFunction) &amp; &quot;(&quot; &amp; pvExpression &amp; &quot;)&quot;
793 End If
794 sSql = &quot;SELECT &quot; &amp; sTarget &amp; &quot; AS &quot; &amp; cstAliasField &amp; &quot; FROM &quot; &amp; psTableName &amp; sWhere &amp; sOrderBy &amp; sLimit
795 Case &quot;FIREBIRD (ENGINE12)&quot;
796 If psFunction = cstLookup Then sTarget = &quot;FIRST 1 &quot; &amp; pvExpression Else sTarget = UCase(psFunction) &amp; &quot;(&quot; &amp; pvExpression &amp; &quot;)&quot;
797 sSql = &quot;SELECT &quot; &amp; sTarget &amp; &quot; AS &quot; &amp; cstAliasField &amp; &quot; FROM &quot; &amp; pvTableName &amp; sWhere &amp; sOrderBy
798 Case Else &apos; Standard syntax - Includes HSQLDB
799 If psFunction = cstLookup Then sTarget = &quot;TOP 1 &quot; &amp; pvExpression Else sTarget = UCase(psFunction) &amp; &quot;(&quot; &amp; pvExpression &amp; &quot;)&quot;
800 sSql = &quot;SELECT &quot; &amp; sTarget &amp; &quot; AS &quot; &amp; cstAliasField &amp; &quot; FROM &quot; &amp; pvTableName &amp; sWhere &amp; sOrderBy
801 End Select
803 &apos; Execute the SQL statement and retain the first column of the first record
804 Set oResult = _ExecuteSql(sSql, True)
805 If Not IsNull(oResult) And Not IsEmpty(oResult) Then
806 If Not oResult.first() Then Goto Finally
807 If oResult.isAfterLast() Then GoTo Finally
808 vResult = _GetColumnValue(oResult, 1, True) &apos; Force return of binary field
809 End If
810 Set oResult = Nothing
812 Finally:
813 _DFunction = vResult
814 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
815 Exit Function
816 Catch:
817 GoTo Finally
818 End Function &apos; SFDatabases.SF_Database._DFunction
820 REM -----------------------------------------------------------------------------
821 Private Function _ExecuteSql(ByVal psSql As String _
822 , ByVal pbDirect As Boolean _
823 ) As Variant
824 &apos;&apos;&apos; Return a read-only Resultset based on a SELECT SQL statement or execute the given action SQL (INSERT, CREATE TABLE, ...)
825 &apos;&apos;&apos; The method raises a fatal error when the SQL statement cannot be interpreted
826 &apos;&apos;&apos; Args:
827 &apos;&apos;&apos; psSql : the SQL statement. Square brackets are replaced by the correct field surrounding character
828 &apos;&apos;&apos; pbDirect: when True, no syntax conversion is done by LO. Default = False
829 &apos;&apos;&apos; Exceptions
830 &apos;&apos;&apos; SQLSYNTAXERROR The given SQL statement is incorrect
832 Dim vResult As Variant &apos; Return value - com.sun.star.sdbc.XResultSet or Boolean
833 Dim oStatement As Object &apos; com.sun.star.sdbc.XStatement
834 Dim sSql As String &apos; Alias of psSql
835 Dim bSelect As Boolean &apos; True when SELECT statement
836 Dim bErrorHandler As Boolean &apos; Can be set off to ease debugging of complex SQL statements
838 Set vResult = Nothing
839 bErrorHandler = ScriptForge.SF_Utils._ErrorHandling()
840 If bErrorHandler Then On Local Error GoTo Catch
842 Try:
843 sSql = _ReplaceSquareBrackets(psSql)
844 bSelect = ScriptForge.SF_String.StartsWith(sSql, &quot;SELECT&quot;, CaseSensitive := False)
846 Set oStatement = _Connection.createStatement()
847 With oStatement
848 If bSelect Then
849 .ResultSetType = com.sun.star.sdbc.ResultSetType.SCROLL_INSENSITIVE
850 .ResultSetConcurrency = com.sun.star.sdbc.ResultSetConcurrency.READ_ONLY
851 End If
852 .EscapeProcessing = Not pbDirect
854 &apos; Setup the result set
855 If bErrorHandler Then On Local Error GoTo Catch_Sql
856 If bSelect Then Set vResult = .executeQuery(sSql) Else vResult = .execute(sSql)
857 End With
859 Finally:
860 _ExecuteSql = vResult
861 Set oStatement = Nothing
862 Exit Function
863 Catch_Sql:
864 ScriptForge.SF_Exception.RaiseFatal(SQLSYNTAXERROR, sSql)
865 GoTo Finally
866 Catch:
867 GoTo Finally
868 End Function &apos; SFDatabases.SF_Database._ExecuteSql
870 REM -----------------------------------------------------------------------------
871 Private Function _GetColumnValue(ByRef poResultSet As Object _
872 , ByVal plColIndex As Long _
873 , Optional ByVal pbReturnBinary As Boolean _
874 ) As Variant
875 &apos;&apos;&apos; Get the data stored in the current record of a result set in a given column
876 &apos;&apos;&apos; The type of the column is found in the resultset&apos;s metadata
877 &apos;&apos;&apos; Args:
878 &apos;&apos;&apos; poResultSet: com.sun.star.sdbc.XResultSet or com.sun.star.awt.XTabControllerModel
879 &apos;&apos;&apos; plColIndex: the index of the column to extract the value from. Starts at 1
880 &apos;&apos;&apos; pbReturnBinary: when True, the method returns the content of a binary field,
881 &apos;&apos;&apos; as long as its length does not exceed a maximum length.
882 &apos;&apos;&apos; Default = False: binary fields are not returned, only their length
883 &apos;&apos;&apos; Returns:
884 &apos;&apos;&apos; The Variant value found in the column
885 &apos;&apos;&apos; Dates and times are returned as Basic dates
886 &apos;&apos;&apos; Null values are returned as Null
887 &apos;&apos;&apos; Errors or strange data types are returned as Null as well
889 Dim vValue As Variant &apos; Return value
890 Dim lType As Long &apos; SQL column type: com.sun.star.sdbc.DataType
891 Dim vDateTime As Variant &apos; com.sun.star.util.DateTime
892 Dim oStream As Object &apos; Long character or binary streams
893 Dim bNullable As Boolean &apos; The field is defined as accepting Null values
894 Dim lSize As Long &apos; Binary field length
896 Const cstMaxBinlength = 2 * 65535
898 On Local Error Goto 0 &apos; Disable error handler
899 vValue = Empty &apos; Default value if error
900 If IsMissing(pbReturnBinary) Then pbReturnBinary = False
902 With com.sun.star.sdbc.DataType
903 lType = poResultSet.MetaData.getColumnType(plColIndex)
904 bNullable = ( poResultSet.MetaData.IsNullable(plColIndex) = com.sun.star.sdbc.ColumnValue.NULLABLE )
906 Select Case lType
907 Case .ARRAY : vValue = poResultSet.getArray(plColIndex)
908 Case .BINARY, .VARBINARY, .LONGVARBINARY, .BLOB
909 Set oStream = poResultSet.getBinaryStream(plColIndex)
910 If bNullable Then
911 If Not poResultSet.wasNull() Then
912 If Not ScriptForge.SF_Session.HasUNOMethod(oStream, &quot;getLength&quot;) Then &apos; When no recordset
913 lSize = cstMaxBinLength
914 Else
915 lSize = CLng(oStream.getLength())
916 End If
917 If lSize &lt;= cstMaxBinLength And pbReturnBinary Then
918 vValue = Array()
919 oStream.readBytes(vValue, lSize)
920 Else &apos; Return length of field, not content
921 vValue = lSize
922 End If
923 End If
924 End If
925 If Not IsNull(oStream) Then oStream.closeInput()
926 Case .BIT, .BOOLEAN : vValue = poResultSet.getBoolean(plColIndex)
927 Case .DATE
928 vDateTime = poResultSet.getDate(plColIndex)
929 If Not poResultSet.wasNull() Then vValue = DateSerial(CInt(vDateTime.Year), CInt(vDateTime.Month), CInt(vDateTime.Day))
930 Case .DISTINCT, .OBJECT, .OTHER, .STRUCT
931 vValue = Null
932 Case .DOUBLE, .REAL : vValue = poResultSet.getDouble(plColIndex)
933 Case .FLOAT : vValue = poResultSet.getFloat(plColIndex)
934 Case .INTEGER, .SMALLINT : vValue = poResultSet.getInt(plColIndex)
935 Case .BIGINT : vValue = CLng(poResultSet.getLong(plColIndex))
936 Case .DECIMAL, .NUMERIC : vValue = poResultSet.getDouble(plColIndex)
937 Case .SQLNULL : vValue = poResultSet.getNull(plColIndex)
938 Case .OBJECT, .OTHER, .STRUCT : vValue = Null
939 Case .REF : vValue = poResultSet.getRef(plColIndex)
940 Case .TINYINT : vValue = poResultSet.getShort(plColIndex)
941 Case .CHAR, .VARCHAR : vValue = poResultSet.getString(plColIndex)
942 Case .LONGVARCHAR, .CLOB
943 If bNullable Then
944 If Not poResultSet.wasNull() Then vValue = poResultSet.getString(plColIndex)
945 Else
946 vValue = &quot;&quot;
947 End If
948 Case .TIME
949 vDateTime = poResultSet.getTime(plColIndex)
950 If Not poResultSet.wasNull() Then vValue = TimeSerial(vDateTime.Hours, vDateTime.Minutes, vDateTime.Seconds)&apos;, vDateTime.HundredthSeconds)
951 Case .TIMESTAMP
952 vDateTime = poResultSet.getTimeStamp(plColIndex)
953 If Not poResultSet.wasNull() Then vValue = DateSerial(CInt(vDateTime.Year), CInt(vDateTime.Month), CInt(vDateTime.Day)) _
954 + TimeSerial(vDateTime.Hours, vDateTime.Minutes, vDateTime.Seconds)&apos;, vDateTime.HundredthSeconds)
955 Case Else
956 vValue = poResultSet.getString(plColIndex) &apos;GIVE STRING A TRY
957 If IsNumeric(vValue) Then vValue = Val(vValue) &apos;Required when type = &quot;&quot;, sometimes numeric fields are returned as strings (query/MSAccess)
958 End Select
959 If bNullable Then
960 If poResultSet.wasNull() Then vValue = Null
961 End If
962 End With
964 _GetColumnValue = vValue
966 End Function &apos; SFDatabases.SF_Database.GetColumnValue
968 REM -----------------------------------------------------------------------------
969 Public Function _OpenDatasheet(Optional ByVal psCommand As Variant _
970 , piDatasheetType As Integer _
971 , pbEscapeProcessing As Boolean _
972 ) As Object
973 &apos;&apos;&apos; Open the datasheet given by its name and its type
974 &apos;&apos;&apos; The datasheet will live independently from any other component
975 &apos;&apos;&apos; Args:
976 &apos;&apos;&apos; psCommand: a valid table or query name or an SQL statement as a case-sensitive string
977 &apos;&apos;&apos; piDatasheetType: one of the com.sun.star.sdb.CommandType constants
978 &apos;&apos;&apos; pbEscapeProcessing: == Not DirectSql
979 &apos;&apos;&apos; Returns:
980 &apos;&apos;&apos; A Datasheet class instance if the datasheet could be opened, otherwise Nothing
982 Dim oOpen As Object &apos; Return value
983 Dim oNewDatasheet As Object &apos; com.sun.star.lang.XComponent
984 Dim oURL As Object &apos; com.sun.star.util.URL
985 Dim oDispatch As Object &apos; com.sun.star.frame.XDispatch
986 Dim vArgs As Variant &apos; Array of property values
988 On Local Error GoTo Catch
989 Set oOpen = Nothing
991 Try:
992 &apos; Setup the dispatcher
993 Set oURL = New com.sun.star.util.URL
994 oURL.Complete = &quot;.component:DB/DataSourceBrowser&quot;
995 Set oDispatch = StarDesktop.queryDispatch(oURL, &quot;_blank&quot;, com.sun.star.frame.FrameSearchFlag.CREATE)
997 &apos; Setup the arguments of the component to create
998 With ScriptForge.SF_Utils
999 vArgs = Array( _
1000 ._MakePropertyValue(&quot;ActiveConnection&quot;, _Connection) _
1001 , ._MakePropertyValue(&quot;CommandType&quot;, piDatasheetType) _
1002 , ._MakePropertyValue(&quot;Command&quot;, psCommand) _
1003 , ._MakePropertyValue(&quot;ShowMenu&quot;, True) _
1004 , ._MakePropertyValue(&quot;ShowTreeView&quot;, False) _
1005 , ._MakePropertyValue(&quot;ShowTreeViewButton&quot;, False) _
1006 , ._MakePropertyValue(&quot;Filter&quot;, &quot;&quot;) _
1007 , ._MakePropertyValue(&quot;ApplyFilter&quot;, False) _
1008 , ._MakePropertyValue(&quot;EscapeProcessing&quot;, pbEscapeProcessing) _
1010 End With
1012 &apos; Open the targeted datasheet
1013 Set oNewDatasheet = oDispatch.dispatchWithReturnValue(oURL, vArgs)
1014 If Not IsNull(oNewDatasheet) Then Set oOpen = ScriptForge.SF_Services.CreateScriptService(&quot;SFDatabases.Datasheet&quot;, oNewDatasheet, [Me])
1016 Finally:
1017 Set _OpenDatasheet = oOpen
1018 Exit Function
1019 Catch:
1020 GoTo Finally
1021 End Function &apos; SFDocuments.SF_Base._OpenDatasheet
1023 REM -----------------------------------------------------------------------------
1024 Private Function _PropertyGet(Optional ByVal psProperty As String) As Variant
1025 &apos;&apos;&apos; Return the value of the named property
1026 &apos;&apos;&apos; Args:
1027 &apos;&apos;&apos; psProperty: the name of the property
1029 Dim cstThisSub As String
1030 Const cstSubArgs = &quot;&quot;
1032 cstThisSub = &quot;SFDatabases.Database.get&quot; &amp; psProperty
1033 If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
1035 ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
1037 Select Case psProperty
1038 Case &quot;Queries&quot;
1039 If Not IsNull(_Connection) Then _PropertyGet = _Connection.Queries.getElementNames() Else _PropertyGet = Array()
1040 Case &quot;Tables&quot;
1041 If Not IsNull(_Connection) Then _PropertyGet = _Connection.Tables.getElementNames() Else _PropertyGet = Array()
1042 Case &quot;XConnection&quot;
1043 Set _PropertyGet = _Connection
1044 Case &quot;XMetaData&quot;
1045 Set _PropertyGet = _MetaData
1046 Case Else
1047 _PropertyGet = Null
1048 End Select
1050 Finally:
1051 ScriptForge.SF_Utils._ExitFunction(cstThisSub)
1052 Exit Function
1053 Catch:
1054 GoTo Finally
1055 End Function &apos; SFDatabases.SF_Database._PropertyGet
1057 REM -----------------------------------------------------------------------------
1058 Private Function _ReplaceSquareBrackets(ByVal psSql As String) As String
1059 &apos;&apos;&apos; Returns the input SQL command after replacement of square brackets by the table/field names quoting character
1061 Dim sSql As String &apos; Return value
1062 Dim sQuote As String &apos; RDBMS specific table/field surrounding character
1063 Dim sConstQuote As String &apos; Delimiter for string constants in SQL - usually the single quote
1064 Const cstDouble = &quot;&quot;&quot;&quot; : Const cstSingle = &quot;&apos;&quot;
1066 Try:
1067 sQuote = _MetaData.IdentifierQuoteString
1068 sConstQuote = Iif(sQuote = cstSingle, cstDouble, cstSingle)
1070 &apos; Replace the square brackets
1071 sSql = Join(ScriptForge.SF_String.SplitNotQuoted(psSql, &quot;[&quot;, , sConstQuote), sQuote)
1072 sSql = Join(ScriptForge.SF_String.SplitNotQuoted(sSql, &quot;]&quot;, , sConstQuote), sQuote)
1074 Finally:
1075 _ReplaceSquareBrackets = sSql
1076 Exit Function
1077 End Function &apos; SFDatabases.SF_Database._ReplaceSquareBrackets
1079 REM -----------------------------------------------------------------------------
1080 Private Function _Repr() As String
1081 &apos;&apos;&apos; Convert the Database instance to a readable string, typically for debugging purposes (DebugPrint ...)
1082 &apos;&apos;&apos; Args:
1083 &apos;&apos;&apos; Return:
1084 &apos;&apos;&apos; &quot;[DATABASE]: Location (Statusbar)&quot;
1086 _Repr = &quot;[DATABASE]: &quot; &amp; _Location &amp; &quot; (&quot; &amp; _URL &amp; &quot;)&quot;
1088 End Function &apos; SFDatabases.SF_Database._Repr
1090 REM ============================================ END OF SFDATABASES.SF_DATABASE
1091 </script:module>