Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

28 Ноябрь 2020, 19:16 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Часто задаваемые вопросы по LibreOffice и Apache OpenOffice.org
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1   Вниз
  Печать  
Автор Тема: VBA Collection in Basic  (Прочитано 218 раз)
0 Пользователей и 1 Гость смотрят эту тему.
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Online Online

Пол: Мужской
Сообщений: 194



« Стартовое сообщение: 15 Ноябрь 2020, 00:32 »

Кто подскажет, поддерживает ли 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. За время эксперимента ошибок не возникало.


* Снимок экрана от 2020-11-15 02-31-03.png (6.42 Кб, 230x178 - просмотрено 0 раз.)

* Снимок экрана от 2020-11-15 03-07-09.png (81.33 Кб, 756x368 - просмотрено 1 раз.)
« Последнее редактирование: 15 Ноябрь 2020, 03:24 от eeigor » Записан
sokol92
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 227


WWW
« Ответ #1: 15 Ноябрь 2020, 13:10 »

Аналогом объекта 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
Записан

Владимир.
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Online Online

Пол: Мужской
Сообщений: 194



« Ответ #2: 15 Ноябрь 2020, 15:01 »

Спасибо, Владимир. Это пригодится.
Записан
Страниц: 1   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!