ScriptForge

Автор eeigor, 28 марта 2021, 08:57

0 Пользователи и 1 гость просматривают эту тему.

eeigor

Сразу оговорюсь, что это ни в коем случае не критика (!), а просто попытка разобраться с новым набором инструментов
Оценить многие вещи мне не позволяет... квалификация :)

ScriptForge Dictionary vs EnumerableMap (?)
Где-то @sokol92 уже писал о том, что разработчики, видимо, не знали о существования сервиса "com.sun.star.container.EnumerableMap", добавив "Dictionary" в библиотеку "ScriptForge", который реализован через VBA Collection в режиме совместимости в виде модуля класса. Осталось неясно: зачем (?).

Работает с массивом пользовательского типа данных:
ReDim Preserve MapItems(1 To _MapSize)
Вряд ли это эффективно по быстродействию.
Это из описания:
'''      Why a Dictionary class beside the builtin Collection class ?
'''         A standard Basic collection does not support the retrieval of the keys
'''         Additionally it may contain only simple data (strings, numbers, ...)

Кроме того, для этого модуля (для таких модулей) у меня не работает переход из каталога объектов к процедуре по двойному щелчку. Из-за режима совместимости, что ли? Надо прокручивать текст вручную...
Внедрён новый стиль программирования (обработка ошибок). Не хватает руководств с примерами...

Сервис EnumerableMap уже был здесь "опробован" для решения задачи с "раскраской" дубликатов в диапазоне ячеек.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

eeigor

#1
Впрочем, таких "непоняток" много:
Функция TrimExt() 'Extended, надо полагать, но "расширить" функциональность забыли
   If Len(InputStr) > 0 Then
      sTrim = SF_String.ReplaceRegex(InputStr, REGEXLTRIM, "")  'Trim left
      sTrim = SF_String.ReplaceRegex(sTrim, REGEXRTRIM, "")  'Trim right
   End If

Returns the input string without its leading and trailing whitespaces.
А что делает штатная функция Basic Trim()? То же самое, в отличие от одноимённой функции листа. Где же удаление лишних пробелов в центре строки? Впрочем, несложно добавить... :) Кто будет использовать TrimExt вместо Trim, непонятно, и главное - зачем?
Впрочем, регулярное выражение "[\s]+" удалит не только пробелы... но всё равно этого мало. Нужна была функция TrimAll().
Недавно решал ту же задачу (блок 2 With удаляет лишние пробелы в середине строки):
With oReplace: .SearchRegularExpression = True: .SearchWords = False
.setSearchString("^\s+|\s+$")  'any spaces at the start or end...
.setReplaceString("")  '...replaces with null string
End With
nCount = oRanges.replaceAll(oReplace)

With oReplace
.setSearchString("\s{2,}")  '2+ consecutive spaces...
.setReplaceString(" ")  '...replaces with one
End With
nCount = nCount + oRanges.replaceAll(oReplace)


Прочий код перегружен своими "обёртками" разного рода, которые "собирают в кучу" то, что лучше оставить "на месте":
oTextSearch = SF_Utils._GetUNOService("TextSearch")  ' это вместо: oTextSearch = CreateUnoService("com.sun.star.util.TextSearch")

UPD:
Зачем нужны примитивные процедуры? Всё это риторические вопросы...
Sub RefreshDataPilot()
Dim oSheet As Object, oTables As Object, oTable As Object

'oSheet = ThisComponent.Sheets.getByIndex(3)
oSheet = ThisComponent.CurrentController.ActiveSheet
oTables = oSheet.getDataPilotTables()

'Dim sTableName As String
'sTableName = oTables.ElementNames(0)  '"DataPilot1"
'oTable = oTables.getByName(sTableName)
oTable = oTables.getByIndex(0)  'всего одна таблица на листе

oTable.refresh
End Sub

Я обновляю свои сводные таблицы при активации листа, и для этого не надо загружать внешнюю библиотеку.
К тому же код имеет ограничение:
oTables.getByIndex(0)  'всего одна таблица на листе

UPD2:
А функция FindRegex() может не больше (или меньше?), чем функция листа, доступная через FunctionAccess (убрали аргумент Occurrence, добавили Start: первое - это номер вхождения, что и нужно; второе - номер символа в строке). Я ожидал, что будет возращён массив всех вхождений, но здесь надо организовывать цикл, зато ищет Forward/Backward (если это нужно кому-то).
Но поиск организован с использованием объектов и методов/свойств, что и ожидалось.
@sokol92, предлагаю сравнить решение от разработчиков с нашими дискуссиями...
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

mikekaganski

Цитата: eeigor от 28 марта 2021, 11:29предлагаю сравнить решение от разработчиков с нашими дискуссиями...

Некорректно называть это "решением от разработчиков". Фактически два человека - разработчик библиотеки макросов Access2Base и человек, занимающийся документированием скриптовых языков  LO - решили, что нужно их собственные наработки включить в пакет. Все присутствующие на форуме - в не меньшей степени разработчики, за исключением того что те двое всё-таки решили делать, а у нас doers decide.
С уважением,
Михаил Каганский

eeigor

#3
@mikekaganski, добрый день. Я оговорился. Речь о разработчиках конкретных библиотек. Код в любом случае полезен, ибо туда смотрим, к себе переносим. По пути встречаем много нового. Но в отношении ссылки на решение, то там всё так, как надо: поиск по тексту организован правильно, то есть без цикла (regex vs InStr).
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

#4
Сервис EnumerableMap создает объект, являющийся аналогом объекта Scripting.Dictionary MS Windows.
Основные отклонения:
EnumerableMap не имеет счетчика  элементов (count)
EnumerableMap не имеет метода для переименования ключа
Dictionary не имеет метода для проверки наличия значения (метод containsValue)
EnumerableMap нумерует ключи по возрастанию (хотя это и не указано явно в документации). Если мы хотим для Dictionary получить массив ключей по возрастанию, то ключи нужно отсортировать самостоятельно.

Тесты, которые я использовал для проверки быстродействия и сопоставления с Dictionary.


' Тестирование сервиса EnumerableMap
Sub testEnumerableMap
Dim 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")
 
oEnumerableMap = com.sun.star.container.EnumerableMap.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
ReDim v(nmax-1)
While KeyEnum.hasMoreElements
  v(i)=KeyEnum.NextElement
  i=i+1
Wend

s=s & chr(10) & "Нумератор " & i & ": " & (GetSystemTicks()-t)
 
Msgbox s
End Sub


Для VBA (c объектом Scripting.Dictionary):
Option Explicit
Sub testEnumerableMap()
Dim 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")
 
Set oEnumerableMap = CreateObject("Scripting.Dictionary")

t = GetSystemTicks()
For i = 1 To nmax
   oEnumerableMap.Add key & i, i
Next i

s = "Запись " & nmax & ": " & (GetSystemTicks() - t)
t = GetSystemTicks()

For i = 1 To nmax
   v = oEnumerableMap.Item(key & i)
Next i

s = s & Chr(10) & "Чтение " & nmax & ": " & (GetSystemTicks() - t)
t = GetSystemTicks()

keyEnum = oEnumerableMap.keys
i = UBound(keyEnum) + 1

s = s & Chr(10) & "Нумератор " & i & ": " & (GetSystemTicks() - t)
 
MsgBox s
End Sub

Function GetSystemTicks() As Long
 GetSystemTicks = CLng(Timer * 1000)
End Function


На мой взгляд, оценка для EnumerableMap - "отлично".
Владимир.

eeigor

#5
Просмотрел модуль SF_Timer
Честное слово, подход от @sokol92 (здесь выше) с системной функцией GetSystemTicks() в разы проще и лучше. Я под "инкапсуляцией" разумею другое. Класса я не увидел. Нет, он есть, но я его не увидел... Впрочем, это ведь не класс, а служба! Кстати, в модуле вызывается функция листа NOW через систему обёрток и завуалированных констант. Короче, налицо неоправданная сложность, имхо. Чувствуется "проникновение" Python в Basic (комментарий в начале процедуры предваряется тройной кавычкой) :) . Но Python - это краткость и ясность. Однако объем проделанной работы огромен.
Это хоть какой-то учебный материал, с которым можно много и долго работать. Тем более, что с некоторыми темами, затронутыми авторами, я не знаком.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

eeigor

#6
Презентация...
На VBA написаны тонны кода... И здесь в нашем распоряжении такая "тонна" примитивного (термин авторов библиотеки, используется в значении «базового», «основного», «необходимого») кода, который авторы любезно предоставили в наше распоряжение. За это им спасибо.

UPD:
Ещё один важный момент. Присвоение имён – это не простой вопрос, как может показаться на первый взгляд. Библиотека содержит всю необходимую лексику. Пользуйтесь.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community