2

In LibreOffice Basic sub I use a bunch of uno properties in an array. Which is the simplest Unostructure or UnoService that I must "embed" them, in order to use the getByName "function"?

Example:

dim props(1) as new com.sun.star.beans.PropertyValue

props(0).Name = "blahblah1"
props(0).Value = "blahblah1Value"
props(1).Name = "blahblah2"
props(1).Name = 3000

I want to be able to use something like:

b = props.getByName("blahblah2").Value

or something like (assuming I "assigned" them in a structure-like-object called "somestruct") :

 b = somestruct.getprops.getByName("blahblah2").Value

As I understand that this can be done by creating a "UnoService" which supports the getByName and then, somehow, assigning these props to this service Which is the "lightest" such service? (I mean the service that uses less resources)

Thanks in advance.

ilias iliadis
  • 601
  • 8
  • 15

3 Answers3

2

Really supporting the interface XNameAccess is not as easy. The services which implement this interface are supposed using this interface for existing named properties, not for own created ones.

But you can use the service EnumerableMap to achieve what you probably want.

Example:

sub testEnumerableMap

 serviceEnumerableMap = com.sun.star.container.EnumerableMap
 oEnumerableMap = serviceEnumerableMap.create("string", "any")

 oEnumerableMap.put("blahblah1", "blahblah1Value")
 oEnumerableMap.put("blahblah2", 3000)
 oEnumerableMap.put("blahblah3", 1234.67)

 msgbox oEnumerableMap.get("blahblah1")
 msgbox oEnumerableMap.get("blahblah2")
 msgbox oEnumerableMap.get("blahblah3")
 'msgbox oEnumerableMap.get("blahblah4") 'will throw error

 msgbox oEnumerableMap.containsKey("blahblah2")
 msgbox oEnumerableMap.containsValue(3000)

 if oEnumerableMap.containsKey("blahblah4") then 
  msgbox oEnumerableMap.get("blahblah4")
 end if

end sub

But starbasic with option Compatible is also able supporting Class programming like VBA does.

Example: enter image description here

Create a module named myPropertySet. Therein put the following code:

option Compatible
option ClassModule

private aPropertyValues() as com.sun.star.beans.PropertyValue

public sub setProperty(oProp as com.sun.star.beans.PropertyValue)
 bUpdated = false
 for each oPropPresent in aPropertyValues
  if oPropPresent.Name = oProp.Name then 
   oPropPresent.Value = oProp.Value
   bUpdated = true
   exit for
  end if
 next
 if not bUpdated then 
  iIndex = ubound(aPropertyValues) + 1
  redim preserve aPropertyValues(iIndex) 
  aPropertyValues(iIndex) = oProp
 end if
end sub

public function getPropertyValue(sName as string) as variant
 getPropertyValue = "N/A"
 for each oProp in aPropertyValues
  if oProp.Name = sName then 
   getPropertyValue = oProp.Value
   exit for
  end if
 next
end function

Then within a standard module:

sub testClass

 oPropertySet = new myPropertySet
 dim prop as new com.sun.star.beans.PropertyValue

 prop.Name = "blahblah1"
 prop.Value = "blahblah1Value"
 oPropertySet.setProperty(prop) 

 prop.Name = "blahblah2"
 prop.Value = 3000
 oPropertySet.setProperty(prop)

 prop.Name = "blahblah3"
 prop.Value = 1234.56
 oPropertySet.setProperty(prop)

 prop.Name = "blahblah2"
 prop.Value = 8888
 oPropertySet.setProperty(prop)

 msgbox oPropertySet.getPropertyValue("blahblah1")
 msgbox oPropertySet.getPropertyValue("blahblah2")
 msgbox oPropertySet.getPropertyValue("blahblah3")
 msgbox oPropertySet.getPropertyValue("blahblah4")

end sub
Axel Richter
  • 56,077
  • 6
  • 60
  • 87
1

LibreOffice Basic supports the vb6 Collection type.

Dim coll As New Collection
coll.Add("blahblah1Value", "blahblah1")
coll.Add(3000, "blahblah2")
MsgBox(coll("blahblah1"))

Arrays of property values are the only thing that will work for certain UNO interfaces such as dispatcher calls. If you simply need a better way to deal with arrays of property values, then use a helper function.

Sub DisplayMyPropertyValue
    Dim props(0 To 1) As New com.sun.star.beans.PropertyValue
    props(0).Name = "blahblah1"
    props(0).Value = "blahblah1Value"
    props(1).Name = "blahblah2"
    props(1).Name = 3000
    MsgBox(GetPropertyByName(props, "blahblah1"))
End Sub

Function GetPropertyByName(props As Array, propname As String)
    For Each prop In props
        If prop.Name = propname Then
            GetPropertyByName = prop.Value
            Exit Function
        End If
    Next
    GetPropertyByName = ""
End Function

XNameAccess is used for UNO containers such as Calc sheets. Normally these containers are obtained from the UNO interface, not created.

oSheet = ThisComponent.Sheets.getByName("Sheet1")

May UNO objects support the XPropertySet interface. Normally these are also obtained from the UNO interface, not created.

paraStyleName = cellcursor.getPropertyValue("ParaStyleName")

It may be possible to create a new class in Java that implements XPropertySet. However, Basic uses helper functions instead of class methods.

Jim K
  • 12,824
  • 2
  • 22
  • 51
  • (Function is GetPropertyByName so return values should have that name) – ilias iliadis Aug 05 '16 at 05:39
  • I have used in the past both (the Collection style and a function that searches array members as GetPropertyByName does) but my "idea" is to use something like an existing structure thinking that it will be more effective and faster. – ilias iliadis Aug 05 '16 at 05:48
0

I think the serviceEnumerableMap is the answer (so far). Creating the values and searching them was much faster then creating props in a dynamic array and searching them with a for loop in basic. (I do not "dare" to use "option Compatible", although I was a big fun of VB6 and VBA, because of the problems in code that maybe arise). I used this code to test time in a form:

SUB testlala(Event)
    TESTPROPS(Event)
'   TESTENUM(Event)
    MSGBOX "END OF TEST"
END SUB

SUB TESTENUM(Event)
    DIM xcounter AS LONG

    'b = now()
    serviceEnumerableMap = com.sun.star.container.EnumerableMap
    oEnumerableMap = serviceEnumerableMap.create("string", "any")
    FOR xcounter= 0 TO 10000
        oEnumerableMap.put("pr" & FORMAT(xcounter,"0000"), xcounter -10000)
    NEXT
    'b=now()-b
    b = now()
    FOR xcounter = 1 TO 5000
        lala = Int((9000 * Rnd) +1)
        g =oEnumerableMap.get("pr" & FORMAT(lala,"0000"))
        'MSGBOX GetValueFromName(props,"pr" & FORMAT(xcounter,"0000"))
    NEXT
    b=now()-b
    MSGBOX b*100000
END SUB

SUB TESTPROPS(Event)
    DIM props()
    DIM xcounter AS LONG

    'b = now()
    FOR xcounter= 0 TO 10000
        AppendProperty(props,"pr" & FORMAT(xcounter,"0000"), xcounter -10000)
    NEXT
    'b=now()-b
    b = now()
    FOR xcounter = 1 TO 5000
        lala = Int((9000 * Rnd) +1)
        g = GetValueFromName(props,"pr" & FORMAT(lala,"0000"))
        'MSGBOX GetValueFromName(props,"pr" & FORMAT(xcounter,"0000"))
    NEXT
    b=now()-b
    MSGBOX b*100000
END SUB

REM FROM Andrew Pitonyak's OpenOffice Macro Information ------------------
Sub AppendToArray(oData(), ByVal x)
  Dim iUB As Integer  'The upper bound of the array.
  Dim iLB As Integer  'The lower bound of the array.
  iUB = UBound(oData()) + 1
  iLB = LBound(oData())
  ReDim Preserve oData(iLB To iUB)
  oData(iUB) = x
End Sub

Function CreateProperty(sName$, oValue) As com.sun.star.beans.PropertyValue
  Dim oProperty As New com.sun.star.beans.PropertyValue
  oProperty.Name = sName
  oProperty.Value = oValue
  CreateProperty() = oProperty
End Function

Sub AppendProperty(oProperties(), sName As String, ByVal oValue)
  AppendToArray(oProperties(), CreateProperty(sName, oValue))
End Sub
ilias iliadis
  • 601
  • 8
  • 15