Is there any service or interface accepting or working with the com.sun.star.script.ArrayWrapper structure?

Or is the structure only made to associate a sequence representing an array with one piece of meta data? Rest left to the user? To what or whom else?

As far as I remember, @Villeroy once mentioned this more than 10 years ago in context with a basic UDF … python bridge.
Within Python, I currently see no difference whether and with which .IsZeroIndex parameter is used.

from com.sun.star.script import ArrayWrapper

test = (1, 2, 3, 4)
print(test)  #→→(1, 2, 3, 4)
aw = ArrayWrapper()
aw.IsZeroIndex = True
aw.Array = test
print(aw.Array) #→→ (1, 2, 3, 4)
print(aw.Array[1]) #→→ 2
aw.IsZeroIndex = False
print(aw.Array[1]) #→→ 2

The structure is simple, has no behavior, just two data fields. Setting one does not affect the other. The intent of the IsZeroIndex is to notify the party that can use either 0-based or 1-based indices that 0-based indexing is intended, because there is no other way to express that when crossing UNO layer (the css::uno::Any stored in the Array field can store css::uno::Sequence, which itself does not define which indexing base was/should be used on the script side).

1 Like

EDIT: I found and fixed the mistake why the python func returned only half of the expected array.
Many years ago I had a working array wrapper exchanging arrays between Basic and Python. The example was on the old openoffice forum which is lost by now.
The attached spreadsheet document is as far as I can get. A1:C2 has 2 rows and 3 cols of data.
The hyperlink is just a test if I got the URL right pointing to the embedded Python script. It raises an error about wrong param count which indicates that it tries to call the right script.
The script URL is used by a Basic function which itself can be called by array formula =DOUBLE(A1:C2)

– embedded PYTHON CODE –

import uno
def double(aw):
    a = aw.Array
    aret = a * 2
    aw2 = uno.createUnoStruct('com.sun.star.script.ArrayWrapper')
    aw2.Array = aret
    aw2.IsZeroIndex = True
    return aw2

When multiplying the array in A1:C2 (2 rows, 3 columns) I would expect a return array with 4 rows and 3 columns because on the command line Python does the following.

>>> a = ((1,2,3),('a','b','c'))
>>> a * 2
((1, 2, 3), ('a', 'b', 'c'), (1, 2, 3), ('a', 'b', 'c'))

– embedded BASIC CODE –

Const URL_Main = "vnd.sun.star.script:pyModule.py$"
Const URL_Args = "?language=Python&location=document"

Function DOUBLE(a)
Dim aw as new com.sun.star.script.ArrayWrapper
aw.Array = a
aw.IsZeroIndex = False

   sURL = URL_Main & "double" & URL_Args
   oSP = ThisComponent.ScriptProvider
   oScript = oSP.getScript(sURL)
   
   x = oScript.invoke(Array(aw), Array(), Array())
DOUBLE = x
End Function

However, what we get in return when entering array formula =DOUBLE(A1:C2) is a copy of A1:C2.
When we save and reload the file with the array formula we get a script error on load and the formula remains uncalculated until we do a hard recalculation.
arraywrap.ods (17.0 KB) (fixed version returning the correct result to E1:G4 (4 rows, 3 columns).

2 Likes

I test it without creating a new »ArrayWrapper« -struct in python, and it works also:

def double(aw):
    a = aw.Array
    aret = a * 2
    aw.Array = aret
    aw.IsZeroIndex = True
    return aw

Ah, yes. Thank you. I had serious difficulties to get this working. The extra struct was a residue of my struggle.
The answer to the topic’s question " Is there any service or interface accepting or working with the com.sun.star.script.ArrayWrapper structure?" is c.s.s.script.provider.XScript

Just some background.
Every document gets a “runtime UID” in IMPL_SfxBaseModel_DataContainer ctor. This UID is later used to refer to this document using a special vnd.sun.star.tdoc URI, handled by “tdoc UCP” - it is in ucb/source/ucp/tdoc. Its OfficeDocumentsManager handles a list of documents accessible using this scheme - and an interesting part is its documentEventOccured, which adds documents to the list upon “OnLoadFinished”/“OnCreate” events. Before that, any attempt to create an identifier using respective ContentProvider::createDocumentContentIdentifier fails. Which explains why there is a time between the document creation and the “OnLoadFinished” event, when any operation requiring such a tdoc URI (like calling a script with “location=document”, which has to pass the document context using such an URI) fails.

I’d think that we need to add to the provider earlier, in the mentioned IMPL_SfxBaseModel_DataContainer ctor, and remove from the list in its dtor, to avoid this problem. However, I don’t know the complications related to use of not fully loaded document in this case.

No. What you observe in your sample is not css::script::provider::XScript “accepting or working” with the discussed structure. Any UNO structure can be stored in an Any, including css::script::ArrayWrapper; and it is transmitted unchanged in it, when returned from XScript's invoke. It’s Basic that handles the struct in its method call routine - specifically, when it processes the line x = oScript.invoke(Array(aw), Array(), Array()), it has to obtain the value of a “variable” named invoke, and it “notifies” it about the need to obtain that value. SbUnoObject::Notify is called, which actually calls the UNO invoke method, and then, after it returns its result, explicitly converts it to a Basic data type using the unoToSbxValue mentioned in my answer. The bottom line is: the structure is just a container, transported by UNO, and only handled outside.

4 Likes

css::script::ArrayWrapper is solely used for the purposes of passing through the UNO. It is handled in basic/source/classes/sbunoobj.cxx ( unoToSbxValue detects when it’s passed, e.g. in invoke, and converts it to a multi-dimensional Basic array) and sc/source/ui/vba/vbarange.cxx (so the VBA ranges return it in Value/Value2 properties).

2 Likes