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

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

14 Июль 2020, 14:01 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Вы можете задать вопрос по LibreOffice или Apache OpenOffice без регистрации, используя форму
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1 2 3 »   Вниз
  Печать  
Автор Тема: "Собрать" функцию из переменных.  (Прочитано 1446 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Tigrik
Форумчанин
***
Offline Offline

Сообщений: 94


« Стартовое сообщение: 7 Июнь 2020, 16:46 »

Здравствуйте!

Если я ничего не путаю, так как видел это краем глазом, да и достаточно давно, то в Calc можно было "собрать" саму функцию (и её параметры) с помощью переменных (символьных, строковых, любых).
Если это действительно так, то можно такое же сделать и в Basic?
По поиску ничего не нашёл - если пропустил подобные вопросы и ответы, то, пожалуйста, "направьте".

Спасибо.
Записан
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #1: 7 Июнь 2020, 17:57 »

Если Вы имеете в виду функции Basic, которые могут указываться в формулах ячеек листа, то да. Об этом написано в разделе 15.7 книги А.Питоньяка OOME_4_0.odt
Функция должна быть в библиотеке Standard документа или приложения.
Записан

Владимир.
Tigrik
Форумчанин
***
Offline Offline

Сообщений: 94


« Ответ #2: 7 Июнь 2020, 18:28 »

Если Вы имеете в виду функции Basic, которые могут указываться в формулах ячеек листа, то да. Об этом написано в разделе 15.7 книги А.Питоньяка OOME_4_0.odt
Функция должна быть в библиотеке Standard документа или приложения.
Спасибо за ссылку, но у меня есть этот текст. Я не до такой степени владею английским, что бы понимать такого рода текст, но у меня есть переводной Питоньяк, но более ранний.
Там я не нашёл то, о чём спрашиваю.
Поясню на примере.
Допустим, есть две функции, имена которых получаются из переменных. Есть ли возможность эти функции запустить?
Код:
Sub my_Proba01()
'  Код
End Sub

Sub my_Proba02()
'  Код
End Sub

Sub Start_Proba()
Dim str$, i%
For i = 1 To 2
str = "my_Proba0" & i
' Запуск функций по циклу: сначала - my_Proba01; затем - my_Proba02
Next
End Sub
Записан
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #3: 7 Июнь 2020, 18:39 »

В LO есть аналог метода Excel Application.Run. Посмотрите ответ  Rami здесь
« Последнее редактирование: 8 Июнь 2020, 12:45 от rami » Записан

Владимир.
Bigor
Мастер
*****
Offline Offline

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


« Ответ #4: 7 Июнь 2020, 19:00 »

Есть ли возможность эти функции запустить?
Да. Третьей процедурой Улыбка
Код:
sub run_2_macr
For i=1 to 2
Test_ i
next
End sub

Код:
Sub Test_(param)
If param = 1 then test_1
If param = 2 then test_2
End Sub

Код:
Sub test_1
Print "Macros1"
End sub

Код:
Sub test_2
Print "Macros2"
End sub

Ну или в основной процедуре условие прописать, можно case использовать.
« Последнее редактирование: 7 Июнь 2020, 19:02 от Bigor » Записан

Поддержать разработчиков LibreOffice можно можно тут, а наш форум вот тут
Tigrik
Форумчанин
***
Offline Offline

Сообщений: 94


« Ответ #5: 7 Июнь 2020, 22:24 »

Некоторые бытовые проблемы отвлекли на самом интересном месте.
---
Спасибо большое за ответы.
Прошу извинить, если я что-то "не догоняю".
В LO есть аналог метода Excel Application.Run. Посмотрите ответ Rami здесь
Правильно ли я понимаю, что это процедура используется для вызова, в данной случае, для макроса "my_Proba01" и в ней достаточно вставить путь до макроса?
Или ещё что-то нужно изменить в ней?
Код:
Sub Sub_App
Dim scriptUri$, scriptProvider, script
scriptUri="vnd.sun.star.script:Standard.Module2.my_Proba01?language=Basic&location=document"
scriptProvider=ThisComponent.scriptProvider
script=scriptProvider.getScript(scriptUri)
script.invoke(array(),array(),array())
End Sub
Выдает сообщение:
Ошибка времени выполнения Basic.
Вызвано исключение
Type: com.sun.star.script.provider.ScriptFrameworkErrorException
Message: The following Basic script could not be found:
library: 'Standard'
module: 'Module2'
method: 'my_Proba01'
location: 'document'
.
=======
Да. Третьей процедурой Улыбка

Ну или в основной процедуре условие прописать, можно case использовать.
Возможно, я, опять, не совсем внятно объяснил.
Хотя, предложенное решения, для меня, также интересно и будет ещё "испытываться", но я спрашивал немного о другом.
В этом примере всего 2 запускаемых макроса и их спокойно можно запускать и из первого макроса без всякого цикла: по условию или через Case.
Если, предположим, нужно запустить 100 подобных макросов, то этот вариант как-то, скажем прямо, "не камильфо".
Есть ли возможность запускать макрос, имя которого "собрано", допустим в цикле, прямо из этого же макроса (где этот цикл) без "посредника"-процедуры?

Возможно, что метод, предложенный Rami (через скрипт) и можно реализовать (строка в пути легко "собирается" в цикле), но я, пока, не смог с этим разобраться.
Записан
Bigor
Мастер
*****
Offline Offline

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


« Ответ #6: 8 Июнь 2020, 11:45 »

Выдает сообщение:
Ошибка времени выполнения Basic.
Вызвано исключение
Type: com.sun.star.script.provider.ScriptFrameworkErrorException
Message: The following Basic script could not be found:
library: 'Standard'
module: 'Module2'
method: 'my_Proba01'
а Ваш макрос my_Proba01 во 2-м модуле?

ps еще варианты
« Последнее редактирование: 8 Июнь 2020, 11:52 от Bigor » Записан

Поддержать разработчиков LibreOffice можно можно тут, а наш форум вот тут
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #7: 8 Июнь 2020, 11:48 »

А Вы попробуйте сделать так, как советует сообщение об ошибке. Добавьте в библиотеку Standard документа модуль Module2, в нем создайте процедуру:

Код:
Sub my_Proba01()
  Msgbox "Вызвана  my_Proba01"
End Sub
Записан

Владимир.
Tigrik
Форумчанин
***
Offline Offline

Сообщений: 94


« Ответ #8: 8 Июнь 2020, 14:01 »

а Ваш макрос my_Proba01 во 2-м модуле?
А Вы попробуйте сделать так, как советует сообщение об ошибке. Добавьте в библиотеку Standard документа модуль Module2, в нем создайте процедуру:
Конечно, эта процедура (my_Proba01) находится в нужном модуле и библиотеке - иначе, в ошибке будет пустая строка напротив метода - я уже это проверял.

Но, в данном случае, всё оказалось намного проще - для location было определено document, а нужно было application - подумал же, что здесь "собака порылась" - много вариантов перепробовал, а application не догадался.
Спасибо ссылкам от sokol92 и, особенно, от Bigor, где и было решение:
еще варианты
Код:
Sub Sub_App
Dim scriptUri$, scriptProvider, script
scriptUri="vnd.sun.star.script:Standard.Module2.my_Proba01?language=Basic&location=application"
scriptProvider=ThisComponent.scriptProvider
script=scriptProvider.getScript(scriptUri)
script.invoke(array(),array(),array())
End Sub
Всё работает.

Осталось только разобраться и понять, что это за параметры в последней команде:
s.invoke(array(), array(), array())
Записан
Tigrik
Форумчанин
***
Offline Offline

Сообщений: 94


« Ответ #9: 8 Июнь 2020, 15:28 »

Осталось только разобраться и понять, что это за параметры в последней команде:
s.invoke(array(), array(), array())
Нашёл в
последней версии руководства:
Executing Python Scripts
The LibreOffice Application Programming Interface (API) Scripting Framework supports inter-language script execution between Python and Basic, or other supported programming languages for that matter. Arguments can be passed back and fourth across calls, providing they represent primitives data types that both languages recognize, and assuming that the Scripting Framework converts them appropriately.

Syntax
workstation_name = script.invoke(Array(), Array(), Array())
opSysName = script.invoke(Array(), in_outs, Array()) ' in_out is an Array
file_len = script.invoke(Array(systemFilePath), Array(), Array())
normalizedPath = script.invoke(Array(systemFilePath), Array(), Array())
Записан
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #10: 8 Июнь 2020, 15:33 »

Описание здесь (на английском). Если у Вас нет выходных параметров, то в первом массиве Вы указываете (входные) параметры макроса, второй и третий параметры оставляете как есть (пустые массивы). Например (вызываемый макрос имеет 3 параметра):

s.invoke(array("Text", 2, True), array(), array())
« Последнее редактирование: 8 Июнь 2020, 15:41 от sokol92 » Записан

Владимир.
Tigrik
Форумчанин
***
Offline Offline

Сообщений: 94


« Ответ #11: 8 Июнь 2020, 18:08 »

Описание здесь (на английском). Если у Вас нет выходных параметров, то в первом массиве Вы указываете (входные) параметры макроса, второй и третий параметры оставляете как есть (пустые массивы). Например (вызываемый макрос имеет 3 параметра):

s.invoke(array("Text", 2, True), array(), array())
Благодарю, sokol92.
Поэксперементировал и, вроде бы, нормально получается:
Код:
Sub Sub_App_03
Dim scriptUri$, sPathIF$
scriptUri = "Standard.Module2.my_Proba03"
sPathIF = "vnd.sun.star.script:" '  РАБОТАЕТ!
' sPathIF = "com.sun.star.script.provider.XScript:" '  НЕ РАБОТАЕТ?
' sPathIF = "com.sun.star.script:" '  НЕ РАБОТАЕТ?
scriptUri = sPathIF & scriptUri & "?language=Basic&location=application"
ThisComponent.scriptProvider.getScript(scriptUri).invoke(array("Text", 2, True), aOutParamIndex, aOutParam)
End Sub

Sub my_Proba03( i, j, k) : Msgbox (i &chr(10)& j &chr(10)& k) : End Sub
Второй и третий массивы - это возвращаемая информация от вызываемой процедуры (индексы параметров и сами значения).

У меня не получилось использовать интерфейс, в котором определен этот метод invoke.
Опять, наверное, что-то не то делаю?
Записан
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #12: 8 Июнь 2020, 20:09 »

Муторное это дело. Улыбка Объясню на примерах, как я это понимаю (здесь есть кому исправить).

Составим процедуру my_Proba04, которая складывает первый и второй параметры и помещает в третий. Вызываем ее и показываем результирующие массивы (через точку с запятой):

Код:
' Складывает два первых параметра и помещает в третий
Sub  my_Proba04(i,  j, k)
  k=i+j
End Sub  

Sub Sub_App_04
Dim oScript, aOutParamIndex, aOutParam
    oScript=ThisComponent.scriptProvider.getScript("vnd.sun.star.script:Standard.Module2.my_Proba04?language=Basic&location=application")
    oScript.invoke(array(5, 10, 0), aOutParamIndex, aOutParam)

    Msgbox "aOutParamIndex: " & Join(aOutParamIndex, ";") &  chr(10) &  _
             "aOutParam: " &  Join(aOutParam, ";")   ' выводит содержание массивов, элементы разделяются точкой с запятой
End Sub

Отметим, что в первом параметре метода invoke мы указали три элемента массива: два первых для сложения (5 и 10, соответствуют параметрам i и j процедуры my_Proba04) и третий - "пустышку" (0, аргумент k), так как третий параметр my_Proba04 используется только для формирования результата. Второй и третий аргументы метода invoke (aOutParamIndex, aOutParam) заполняются самим методом invoke.

Поскольку мы описали параметры процедуры my_Proba04 без модификатора Byval, то считается, что мы передаем эти параметры по ссылке, а не по значению. В этом случае они интерпретируются как входные-выходные (inout). Метод invoke нам возвращает массив aOutParamIndex из трех элементов 0,1,2 - номера выходных параметров, а также массив aOutParam из 3 элементов 5,10,15 (15 - это результат работы my_Proba04).

Теперь модифицируем процедуру так:
Код:
' Складывает два первых параметра (in) и помещает в третий (out)
Sub  my_Proba04(Byval i,  Byval j, k)
  k=i+j
End Sub  
Мы два первых параметра указали с модификатором Byval, что означает передачу по значению. Они будут интерпретироваться как входные (in). Третий параметр мы должны указать по ссылке (без указания Byval), иначе мы не сможем получить его значение по завершению работы процедуры.
Метод invoke нам возвращает массив aOutParamIndex из одного элемента (у нас в процедуре my_Proba04 только один inout параметр: k) и массив aOutParam из одного элемента (естественно, 15).
Уфф Улыбка
« Последнее редактирование: 8 Июнь 2020, 21:01 от sokol92 » Записан

Владимир.
Tigrik
Форумчанин
***
Offline Offline

Сообщений: 94


« Ответ #13: 8 Июнь 2020, 22:37 »

Спасибо sokol92, очень интересно!

Я, немного, потестил различные варианты и выяснилось, что, естественно, можно возвращать сколько угодно параметров, но обязательно объявлять это в вызываемой функции и задавать место в первом массиве invoke для всех параметров (входных и выходных).
Причём, в этом массиве и возвращаемым параметрам можно присваивать значения и их использовать в вызываемой функции, и окончательные значения параметров будут занесены в массив aOutParam.

Это в основной процедуре:
Код:
dValue = oScript.invoke(array(5, 10, 6.5, 0, "Text", 0), aOutParamIndex, aOutParam)

Код:
Sub  my_Proba04(Byval i,  Byval j, k!, z, strTx$, x#) As Double
k=i + j + k : z=i * j : strTx = "k=i + j + k + " & strTx : x = z / k
my_Proba04 = x
End Sub
Единственное, что не получилось - это с параметрами типа Double.
invoke с ним работает, но значение этого параметра не вносится в aOutParam.
Конечно, можно передать это значение через саму вызываемую функцию, но если таких параметров несколько, то тогда придется возвращать массив значений.

Может быть, что-то не доглядел.
Записан
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #14: 9 Июнь 2020, 14:49 »

Спасибо за исследование!

Вы заметили интересную особенность. Если мы в условиях ответа #12 (оба варианта my_Proba04) вызовем процедуру так:

Код:
oScript.invoke(array(5.1, 10, 0), aOutParamIndex, aOutParam)

то (неожиданно, по крайней мере, для меня) получим в возвращаемом значении 15 (а не 15.1).
Не спасает и явное описание параметра k as Double, а также передача третьего элемента массива как Cdbl(0). Помогает только такой трюк (любое дробное значение в "пустышке"):

Код:
oScript.invoke(array(5.1, 10, 0.1), aOutParamIndex, aOutParam)


Я могу это интерпретировать (тексты не смотрел, нет свободных пары дней на поиски Улыбка) только таким образом: тип параметра k "угадывается" по значению "пустышки", при этом исходный тип значения где-то теряется по дороге...

« Последнее редактирование: 9 Июнь 2020, 14:58 от sokol92 » Записан

Владимир.
Страниц: 1 2 3 »   Вверх
  Печать  
 
Перейти в:  

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