Кто подскажет, поддерживает ли Basic что-то вроде VBA Collection?
Что это за объект: com.sun.star.script.NativeObjectWrapper?
Его нет в числе ThisComponent.AvailableServiceNames, но Xray его видит-таки...
http://www.openoffice.org/api/docs/common/ref/com/sun/star/script/NativeObjectWrapper.html
Обратите внимание на то, что в примере строка "Option Compatible" закомментирована. Компилятор понимает...
Или это из области "недокументированного"?.. В примере ниже код работает. Данные извлекаются по ключу, как и требуется. При копировании структуры копируется указатель, как и ожидалось (по аналогии с массивами)...
'Option Compatible 'turns on the VBA-compatible Basic compiler mode at the module level
Sub TestVBACollection()
Dim obj As New Collection 'com.sun.star.script.NativeObjectWrapper
obj.Add("Entry 1", "foo") 'key = "foo", Item = "Entry 1"
obj.Add("Entry 2", "bar") 'key = "bar", Item = "Entry 2"
Print "Count: "; obj.Count, obj("foo"), obj("bar") '>> Count: 2 Entry 1 Entry 2
End Sub
В чём главное отличие от массива? Доступ как по индексу, так и по ключу, а не только по индексу (то есть без поиска перебором элементов). Ключ надо знать. В процедуре должна быть обработка ошибки доступа по ложному ключу. Метод "Add" объекта VBA Collection позволяет вставить элемент в заданную позицию:
.Add(item, [key], [before, after])
А как здесь?
UPD: И здесь также.
Sub TestVBACollectio3()
Dim obj As New Collection 'com.sun.star.script.NativeObjectWrapper
obj.Add("Entry 1", "foo") 'Item = "Entry 1", key = "foo",
obj.Add("Entry 2", "bar", 1) 'Item = "Entry 2", key = "bar", before:=1
For Each v In obj
s = s & v & Chr$(10) '>> Entry2 Entry 1
Next
MsgBox s, , "Готово"
Print obj("foo"), obj(2) '>> Entry1 Entry 1
obj.remove("foo")
Print obj.Count '>> 1
End Sub
Элемент "Entry 2" вставлен перед первым элементов в коллекции (на скриншоте).
Такую коллекцию легко поддерживать в отсортированном виде, вставляя новый элемент в заданную позицию (в лексикографическом порядке).
Далее элемент удаляется из коллекции. См. также описание на скриншоте 2.
Странно, что переменная obj объявлена как Collection, а не Object.
Хотя уже и так ясно, что это именно Collection, и добавлен он для совместимости с VBA.
Будет ли безопасным его использование в Basic?
UPD2: Объяснение нашлось вот здесь
https://libocon.org/assets/libocon2020/Slides/OsLo-2020.libOBasic.pdf
Правда, требуется установка опции Compatible. Может, она где в настройках задана по умолчанию?
Ещё бы что-то вроде Scripting.Dictionary найти (у меня Linux)... Ведь объект NativeObjectWrapper объявлен как any ObjectId.
P.S. За время эксперимента ошибок не возникало.
Аналогом объекта Scripting.Dictionary является сервис com.sun.star.container.EnumerableMap. Мой тест (ниже) показывает, что сервис обладает вполне приемлемыми скоростными характеристиками. Приятный, но недокументированный (?) бонус - метод createKeyEnumeration нумерует ключи по возрастанию.
Sub testEnumerableMap
Dim serviceEnumerableMap, oEnumerableMap, keyEnum
Dim nmax as Long, i as Long, key as String, t as Long, s as String, v
Nmax=100000
key=String(200, "a")
serviceEnumerableMap=com.sun.star.container.EnumerableMap
oEnumerableMap = serviceEnumerableMap.create("string", "any")
t=GetSystemTicks()
For i=1 To nmax
oEnumerableMap.put key & i, i
Next i
s="Запись " & nmax & ": " & (GetSystemTicks()-t)
t=GetSystemTicks()
For i=1 To nmax
v=oEnumerableMap.get(key & i)
Next i
s=s & chr(10) & "Чтение " & nmax & ": " & (GetSystemTicks()-t)
t=GetSystemTicks()
KeyEnum=oEnumerableMap.createKeyEnumeration(0)
i=0
While KeyEnum.hasMoreElements
v=KeyEnum.NextElement
i=i+1
Wend
s=s & chr(10) & "Нумератор " & i & ": " & (GetSystemTicks()-t)
Msgbox s
End Sub
Спасибо, Владимир. Это пригодится.