wizards/source/scriptforge/SF_PythonHelper.xba    |    4 +
 wizards/source/scriptforge/SF_Session.xba         |   85 ++++++++++++++++++++++
 wizards/source/scriptforge/python/scriptforge.py  |    3 
 wizards/source/scriptforge/python/scriptforge.pyi |   26 ++++++
 wizards/source/scriptforge/script.xlb             |   32 ++++----
 5 files changed, 133 insertions(+), 17 deletions(-)

New commits:
commit e72f7d6dd36bafebe085ed91e38602158ac561f0
Author:     Jean-Pierre Ledure <j...@ledure.be>
AuthorDate: Wed Aug 6 12:51:15 2025 +0200
Commit:     Jean-Pierre Ledure <j...@ledure.be>
CommitDate: Wed Aug 6 14:34:55 2025 +0200

    ScriptForge new session.GetRangeFromCalc method
    
    The
       GetRangeFromCalc(filename: str, range: str)
    method (stored in the Session service)
    reads the values contained in the given
    range located in the given Calc file.
    
    The file does not need to be open. This
    makes this shortcut particularly useful.
    
    The content of the range is returned either
    - as a scalar for a single cell
    - as a 1D-array or a tuple when the range
      is contained in a single row or column
    - as a 2D-array or a tuple of tuples for
      a rectangular range of adjacent cells.
    
    Clean error management is included in the code.
    
    The method is available for Basic and Python
    user scripts.
    
    The user documentation needs to be updated.
    
    Change-Id: I39cd218f0bf3a6a21e3ada42826069eeee451c6e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189000
    Reviewed-by: Jean-Pierre Ledure <j...@ledure.be>
    Tested-by: Jenkins

diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba 
b/wizards/source/scriptforge/SF_PythonHelper.xba
index 8328af61c1b4..4de5bf74d44e 100644
--- a/wizards/source/scriptforge/SF_PythonHelper.xba
+++ b/wizards/source/scriptforge/SF_PythonHelper.xba
@@ -808,6 +808,10 @@ Try:
                                        vReturn = vBasicObject.Properties()
                                Else
                                        Select Case sServiceName
+                                               Case 
&quot;ScriptForge.SF_Session&quot;
+                                                       Select Case Script
+                                                               Case 
&quot;GetRangeFromCalc&quot;       :       vReturn = 
vBasicObject.GetRangeFromCalc(vArgs(0), vArgs(1))
+                                                       End Select
                                                Case 
&quot;SFDatabases.Database&quot;
                                                        If Script = 
&quot;GetRows&quot; Then            vReturn = vBasicObject.GetRows(vArgs(0), 
vArgs(1), vArgs(2), vArgs(3))
                                                Case 
&quot;SFDatabases.Dataset&quot;
diff --git a/wizards/source/scriptforge/SF_Session.xba 
b/wizards/source/scriptforge/SF_Session.xba
index 30d220d3be4c..281ff301727a 100644
--- a/wizards/source/scriptforge/SF_Session.xba
+++ b/wizards/source/scriptforge/SF_Session.xba
@@ -19,6 +19,7 @@ Option Explicit
 &apos;&apos;&apos;                     - UNO introspection utilities
 &apos;&apos;&apos;                     - clipboard management
 &apos;&apos;&apos;                     - invocation of external scripts or 
programs
+&apos;&apos;&apos;                     - access to the content of Calc files
 &apos;&apos;&apos;
 &apos;&apos;&apos;             Service invocation example:
 &apos;&apos;&apos;                     Dim session As Variant
@@ -31,6 +32,7 @@ Option Explicit
 REM ================================================================== 
EXCEPTIONS
 
 Const CALCFUNCERROR                            =       
&quot;CALCFUNCERROR&quot;               &apos;  Calc function execution failed
+Const CALCADDRESSERROR                 =       &quot;CALCADDRESSERROR&quot;    
&apos;  Invalid Calc range
 Const NOSCRIPTERROR                            =       
&quot;NOSCRIPTERROR&quot;               &apos;  Script could not be located
 Const SCRIPTEXECERROR                  =       &quot;SCRIPTEXECERROR&quot;     
&apos;  Exception during script execution
 Const WRONGEMAILERROR                  =       &quot;WRONGEMAILERROR&quot;     
&apos;  Wrong email address
@@ -326,6 +328,88 @@ Catch:
        GoTo Finally
 End Function   &apos;  ScriptForge.SF_Session.ExecutePythonScript
 
+REM 
-----------------------------------------------------------------------------
+Public Function GetRangeFromCalc(Optional ByVal FileName As Variant _
+                                                               , Optional 
ByVal Range As Variant _
+                                                               ) As Variant
+&apos;&apos;&apos;     Extract the content of a range of adjacent cells stored 
in a Calc file.
+&apos;&apos;&apos;     The file may be open or closed. If the file is open in 
the actual LibreOffice
+&apos;&apos;&apos;     session, its actual content will be read. Otherwise the 
content will be
+&apos;&apos;&apos;     read from the file on disk.
+&apos;&apos;&apos;     Inspired by 
https://bugs.documentfoundation.org/show_bug.cgi?id=148040
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             FileName: the full file name, given in 
FileSystem.FileNaming notation.
+&apos;&apos;&apos;                     The file must exist.
+&apos;&apos;&apos;             Range: either
+&apos;&apos;&apos;                     &quot;sheet.cells&quot;, where 
&quot;sheet&quot; is the mandatory sheet name, eventually
+&apos;&apos;&apos;                             surrounded with single wuotes 
when it contains special characters,
+&apos;&apos;&apos;                             and &quot;cells&quot; is the 
single cell or the range of cells
+&apos;&apos;&apos;                             to be considered, in A1 
notation with or without dollar signs
+&apos;&apos;&apos;                     a defined name at document-global level.
+&apos;&apos;&apos;                     Current selection shortcuts 
(&quot;~&quot;) are forbidden in this context.
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             Either a scalar, or a 1D array when the range 
is located in a single row or column,
+&apos;&apos;&apos;             or a 2D array.
+&apos;&apos;&apos;             The returned values are either strings or 
numbers. No dates, booleans, ...
+&apos;&apos;&apos;             To convert doubles to dates, use the CDate 
builtin function.
+&apos;&apos;&apos;             Empty cells are returned as empty strings.
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             UNKNOWNFILEERROR                The Calc file 
does not exist
+&apos;&apos;&apos;             CALCADDRESSERROR                Invalid Calc 
range
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             value = 
session.GetFromFileName(&quot;C:\myFile.ods&quot;, &quot;Sheet1.A1:J10&quot;)
+
+Dim vReturn As Variant                 &apos;  Returned value
+Dim oCalc As Object                            &apos;  Give access to the 
com.sun.star.sheet.FunctionAccess service
+Dim sArgument As String                        &apos;  The argument given to 
the &quot;Indirect&quot; Calc function
+
+Const cstThisSub = &quot;Session.GetRangeFromCalc&quot;
+Const cstSubArgs = &quot;FileName, Range&quot;
+
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       vReturn = Empty
+
+Check:
+       If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) 
Then GoTo Finally
+               If Not SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) 
Then GoTo Finally
+       End If
+
+       If Not SF_FileSystem.FileExists(FileName) Then GoTo CatchNotExists
+
+Try:
+       &apos;  The execution results from the 
com.sun.star.sheet.FunctionAccess service
+       Set oCalc = SF_Utils._GetUNOService(&quot;FunctionAccess&quot;)
+
+       &apos;  Error trapping, execution, error reset
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo CatchCall
+       sArgument = &quot;&apos;&quot; &amp; 
SF_FileSystem._ConvertToUrl(FileName) &amp; &quot;&apos;#&quot; &amp; Range
+       vReturn = oCalc.callFunction(&quot;INDIRECT&quot;, Array(sArgument))
+       If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+
+       &apos;  Transform the arrays of subarrays =&gt; 2D arrays, only in Basic
+       Select Case SF_Array.CountDims(vReturn)
+               Case -1, 0, 2
+                       &apos;  Do nothing: scalar or empty array or 2D array 
(should not happen)
+               Case 1
+                       If IsArray(vReturn(0)) And Not _SF_.TriggeredByPython 
Then vReturn = SF_Array.ConvertFromDataArray(vReturn, IsRange := True)
+               Case Else
+       End Select
+
+Finally:
+       GetRangeFromCalc = vReturn
+       SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+CatchNotExists:
+       SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, 
FileName)
+       GoTo Finally
+CatchCall:
+       ScriptForge.SF_Exception.RaiseFatal(CALCADDRESSERROR, 
&quot;Range&quot;, Range, &quot;FileName&quot;, FileName)
+       GoTo Finally
+End Function   &apos;  ScriptForge.SF_Session.GetRangeFromCalc
+
 REM 
-----------------------------------------------------------------------------
 Public Function GetPDFExportOptions() As Variant
 &apos;&apos;&apos;     Return the actual values of the PDF export options
@@ -506,6 +590,7 @@ Public Function Methods() As Variant
                                        &quot;ExecuteBasicScript&quot; _
                                        , &quot;ExecuteCalcFunction&quot; _
                                        , &quot;ExecutePythonScript&quot; _
+                                       , &quot;GetRangeFromCalc&quot; _
                                        , &quot;HasUnoMethod&quot; _
                                        , &quot;HasUnoProperty&quot; _
                                        , &quot;OpenURLInBrowser&quot; _
diff --git a/wizards/source/scriptforge/python/scriptforge.py 
b/wizards/source/scriptforge/python/scriptforge.py
index ddad6364009c..eb1a39ad6809 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -1571,6 +1571,9 @@ class SFScriptForge:
         def ExecutePythonScript(cls, scope = '', script = '', *args):
             return cls.SIMPLEEXEC(scope + '#' + script, *args)
 
+        def GetRangeFromCalc(self, filename, range):
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 
'GetRangeFromCalc', filename, range)
+
         def GetPDFExportOptions(self):
             return self.ExecMethod(self.vbMethod, 'GetPDFExportOptions')
 
diff --git a/wizards/source/scriptforge/python/scriptforge.pyi 
b/wizards/source/scriptforge/python/scriptforge.pyi
index 637422ecce57..1b7067bba499 100644
--- a/wizards/source/scriptforge/python/scriptforge.pyi
+++ b/wizards/source/scriptforge/python/scriptforge.pyi
@@ -1872,6 +1872,30 @@ class SFScriptForge:
                 """
             ...
 
+        def GetRangeFromCalc(self, filename: FILE, range: RANGE):
+               """
+                   Extract the content of a range of adjacent cells stored in 
a Calc file. The file may be open
+                   or closed. If the file is open in the actual LibreOffice 
session, its actual content will be read.
+                   Otherwise, the content will be read from the file on disk.
+                       Args
+                           ``filename``: the full file name, given in 
``FileSystem.FileNaming`` notation.
+
+                           ``range``: either
+                               - "sheet.cells", where "sheet" is the mandatory 
sheet name, eventually surrounded with
+                               single quotes when it contains special 
characters, and "cells" is the single cell
+                               or the range of cells to be considered, in A1 
notation with or without dollar signs
+
+                               - a defined name at document-global level.
+                       Note
+                           Current selection shortcuts ("~") are forbidden in 
this context.
+                       Returns
+                           Either a scalar, or a tuple when the range is 
located in a single row or column,
+                           or a tuple of tuples. The returned values are 
either strings or numbers. No dates, booleans, ...
+                           To convert doubles to dates, use the 
``basic.CDate()`` method.
+                           Empty cells are returned as empty strings.
+                   """
+               ...
+
         def GetPDFExportOptions(self) -> DICTIONARY:
             """
                 Returns the current PDF export settings defined in the ``PDF 
Options`` dialog, which can be accessed
@@ -5938,7 +5962,7 @@ class SFDocuments:
                         or quotes to improve its readability.
 
                         ``directsql``: when ``True``, the SQL command is sent 
to the database engine without
-                        pre-analysis. Default is ``False``. The argument is 
ignored for tables.For queries,
+                        pre-analysis. Default is ``False``. The argument is 
ignored for tables. For queries,
                         the applied option is the one set when the query was 
defined.
                 """
             ...
diff --git a/wizards/source/scriptforge/script.xlb 
b/wizards/source/scriptforge/script.xlb
index f78d358ee606..98570642b8e2 100644
--- a/wizards/source/scriptforge/script.xlb
+++ b/wizards/source/scriptforge/script.xlb
@@ -1,23 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 
1.0//EN" "library.dtd">
 <library:library xmlns:library="http://openoffice.org/2000/library"; 
library:name="ScriptForge" library:readonly="false" 
library:passwordprotected="false">
- <library:element library:name="SF_Timer"/>
+ <library:element library:name="SF_Root"/>
+ <library:element library:name="__License"/>
+ <library:element library:name="SF_Region"/>
+ <library:element library:name="SF_L10N"/>
+ <library:element library:name="SF_String"/>
+ <library:element library:name="_ModuleModel"/>
+ <library:element library:name="SF_UI"/>
+ <library:element library:name="SF_Services"/>
+ <library:element library:name="SF_PythonHelper"/>
+ <library:element library:name="SF_Platform"/>
+ <library:element library:name="SF_Array"/>
+ <library:element library:name="SF_TextStream"/>
+ <library:element library:name="SF_Utils"/>
  <library:element library:name="SF_FileSystem"/>
- <library:element library:name="SF_Dictionary"/>
- <library:element library:name="SF_Exception"/>
+ <library:element library:name="SF_Timer"/>
  <library:element library:name="SF_Session"/>
- <library:element library:name="SF_Services"/>
+ <library:element library:name="SF_Exception"/>
+ <library:element library:name="SF_Dictionary"/>
  <library:element library:name="_CodingConventions"/>
- <library:element library:name="_ModuleModel"/>
- <library:element library:name="SF_String"/>
- <library:element library:name="SF_L10N"/>
- <library:element library:name="SF_Region"/>
- <library:element library:name="__License"/>
- <library:element library:name="SF_Root"/>
- <library:element library:name="SF_Utils"/>
- <library:element library:name="SF_TextStream"/>
- <library:element library:name="SF_Array"/>
- <library:element library:name="SF_Platform"/>
- <library:element library:name="SF_PythonHelper"/>
- <library:element library:name="SF_UI"/>
 </library:library>
\ No newline at end of file

Reply via email to