支持getByName的最简单的Unostructure

时间:2016-08-04 06:29:24

标签: libreoffice basic uno

在LibreOffice Basic子句中,我在数组中使用了一堆uno属性。为了使用getByName“函数”,我必须“嵌入”它们的最简单的Unostructure或UnoService?

示例:

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

我希望能够使用类似的东西:

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

或类似的东西(假设我在一个名为“somestruct”的类似结构的对象中“分配”它们):

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

据我所知,这可以通过创建支持getByName的“UnoService”来完成,然后以某种方式将这些道具分配给此服务 哪种“最轻”的服务? (我的意思是使用较少资源的服务)

提前致谢。

3 个答案:

答案 0 :(得分:2)

真正支持界面XNameAccess并不容易。假设实现此接口的服务使用此接口用于现有命名属性,而不是用于自己创建的属性。

但您可以使用服务EnumerableMap来实现您可能想要的目标。

示例:

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

但是option Compatible的starbasic也能够像VBA一样支持类编程。

实施例: enter image description here

创建名为myPropertySet的模块。其中包含以下代码:

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

然后在标准模块中:

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

答案 1 :(得分:0)

LibreOffice Basic支持vb6 Collection type

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

属性值数组是唯一适用于某些UNO接口(如调度程序调用)的东西。如果您只是需要一种更好的方法来处理属性值数组,那么使用辅助函数。

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用于UNO容器,例如Calc表。通常,这些容器是从UNO接口获得的,而不是创建的。

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

可能UNO对象支持XPropertySet接口。通常这些也是从UNO界面获得的,而不是创建的。

paraStyleName = cellcursor.getPropertyValue("ParaStyleName")

可以在Java中创建一个实现XPropertySet的新类。但是,Basic使用辅助函数而不是类方法。

答案 2 :(得分:0)

我认为 serviceEnumerableMap 就是答案(到目前为止)。创建值并搜索它们比在动态数组中创建道具并使用基本的for循环搜索它们要快得多。 (我不会"敢于"使用"选项兼容",虽然我是VB6和VBA的一大乐趣,因为可能出现代码中的问题)。 我用这段代码以一种形式测试时间:

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