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

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

7 Март 2021, 04:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Доступно и просто о работе в офисных пакетах
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1   Вниз
  Печать  
Автор Тема: Использование функций Calc в коде Basic  (Прочитано 9287 раз)
0 Пользователей и 1 Гость смотрят эту тему.
calc4fem
Форумчанин
***
Offline Offline

Сообщений: 278


« Стартовое сообщение: 3 Июль 2014, 18:44 »

когда то читал про эту возможность, но сейчас найти не могу.
Подскажите пожалуйста ссылку на вики или пример.
Записан
Yakov
Администратор
**
Offline Offline

Сообщений: 2 568


WWW
« Ответ #1: 3 Июль 2014, 18:54 »

Это было на codesnippets, но их удалили
вот восстановленная копия из веб-архива  восстановленная копия из веб-архива

OO-Snippets: Call built-in functions
Commons
Keywords   built-in function, function, min
Language   OOBasic
Application   Calc
Authors   Kohei Yoshida (initial)
Paolo Mantovani
Supported Versions   1.0.x  1.1.x  2.0.x 
Supported OS   All 
Question   
Answer   

To use Calc's built-in functions in Basic macro, you need to first create a service object of com.sun.star.sheet.FunctionAccess, and call the method "callFunction". Arguments are passed to this method as an array object even if there is only one argument. If the argument is a cell range, a cell range object must first be created, and passed into an array object before it is injected into the callFunction method (see the example code).
Code-Snippet-Listing (snippet-source)

Код:
Sub callFunction

       svc = createUnoService( "com.sun.star.sheet.FunctionAccess" )

       ' Calculate min of numbers.
       arg = array( 10, 23, 5, 345 )
       print svc.callFunction( "MIN", arg )

       ' Calculate min of values in cell range A1:A17
       oSheet = ThisComponent.Sheets(0) ' Get leftmost sheet
       oCellRange = oSheet.getCellRangeByPosition( 0, 0, 0, 16 ) 'A1:A17
       arg = array( oCellRange )
       print svc.callFunction( "MIN", arg )

End Sub
Записан
rami
Гуру
*******
Offline Offline

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


iMac, LibreOffice и Apache OpenOffice


« Ответ #2: 3 Июль 2014, 21:36 »

Читайте Питоньяка. http://admin-smolensk.ru/~websprav/freesoft/freesoft/OpenOffice.org%20Macros%20Explained.Master.pdf
Вот один из примеров: заполните числами диапазон A1:D10
Код:
Sub asd
dim cus, a$, b$, c$, z()
Sheet = ThisComponent.CurrentController.ActiveSheet
 cus=createUnoService("com.sun.star.sheet.FunctionAccess")   'доступ к функциям
 a="Максимум"
 b="Среднее"
 c="Ячеек"
 z=Sheet.getCellRangeByPosition(0, 0, 4, 9)
print a;cus.callFunction("max",array(z)),b;cus.callFunction("average",array(z)),c;cus.callFunction("count",array(z))
End Sub
А вот снимок стр. 391 из книги "Эндрю Питоньяк. OpenOffice.org Объяснение Макросов."


* Снимок Экрана.png (210.02 Кб, 1016x740 - просмотрено 121 раз.)
Записан

calc4fem
Форумчанин
***
Offline Offline

Сообщений: 278


« Ответ #3: 4 Июль 2014, 01:10 »

Да - спасибо. В принципе все ясно.
Проблема общая для Бэйсик - то что матрицы которые приходят из UNO или как там его
и матрицы которые его родные - они как бы немного разные.
То есть первые при проверке переменных выводятся как то так aux(1,2)
вторые aux(1)(2) что то типа того.
после некоторых экспериментов получилось вот что
1) svc.callFunction - получается
2) вывести массив полученный таким образом на лист не получается - только после "приведения к стандартному виду" через цикл
3) какой то фэйл с "MMULT" (возможно размерности матриц не правильно ввел
Если удасться то что задумывал - отпишусь еще

Код:
Function Linsolu(K,P)
'Spreadsheet Array Function for Solving linear system {K}{u}={P}
'returns  vector {u}
'
 svc = createUnoService( "com.sun.star.sheet.FunctionAccess" )
'даю знать шо это массивы
arg=array(K)
arg1=array(P)
'пытаюсь обратить функцию
arg2= svc.callFunction("MINVERSE",arg())
'получилось

'Пытаюсь умножить одну матрицу на другую
'Linsolu=svc.callFunction("MMULT", array(arg2,arg1) )
'Не получается, может что то не так.

'Пытаюсь вывести обращенную матрицу как результат
'Linsolu=arg2
' фейл

'Преобразую обращенную матрицу в несколько иной вид - новая матрица arg3
Dim arg3(1 To dimension_of_array, 1 To dimension_of_array)

dimension_of_array=UBound(arg2,1)+1
For i=1 To dimension_of_array
auxvararray=arg2(i-1)
For j=1 To dimension_of_array
arg3(i,j)=auxvararray(j-1)
Next j
Next i


Linsolu=arg3 ' вот так получается вернуть хоть что то.



End Function
Записан
Hasim
Форумчанин
***
Offline Offline

Сообщений: 754

Woe from wit


« Ответ #4: 4 Июль 2014, 10:29 »

calc4fem
Вместо только одной функции целиком ваш файл не покажете?
Чтобы не ломать голову, какие такие матрицы вы перемножаете.
Записан
calc4fem
Форумчанин
***
Offline Offline

Сообщений: 278


« Ответ #5: 7 Июль 2014, 08:51 »

файл есть в принципе тут https://forum.openoffice.org/en/forum/viewtopic.php?f=20&p=146663
и проблема в том что не получается задействовать функцию MMULT таким образом
вот тут тоже свой файл прилагаю
кстати при попытке гуглить что то - oooforum постоянно висит, доссится что ли опять?

* test1.ods (9.3 Кб - загружено 13 раз.)
Записан
calc4fem
Форумчанин
***
Offline Offline

Сообщений: 278


« Ответ #6: 7 Июль 2014, 21:18 »

Спасибо - нашел ошибку
сам даже у себя. Все таки отладчик в StarBasic не очень доходчивый, просто не понял где и что.
Интересный вопрос который я пока не выяснил. Есть ли у сложных математических вычислений фора по производительности
если делать их через функции Calc или же программировать непосредственно в Basic (через цикл - поэлементно)
По идее первое должно быть производительней, ведь Calc наверняка оперирует целыми массивами в одной из своих нативных библиотек, а код Бэйсика - вроде бы интерпретируемый.
Но это надо брать большие матрицы чтобы выяснить что на самом деле

Код:
Function mmult1(K,P)

'Тест для произведения матриц
 svc = createUnoService( "com.sun.star.sheet.FunctionAccess" )



'
arg2=svc.callFunction("MMULT", Array(K,P) )

dimension_of_array=UBound(arg2,1)+1


'Преобразую  матрицу в несколько иной вид - новая матрица arg3
Dim arg3(1 To dimension_of_array, 1 To dimension_of_array)

dimension_of_array=UBound(arg2,1)+1
For i=1 To dimension_of_array
auxvararray=arg2(i-1)
For j=1 To dimension_of_array
arg3(i,j)=auxvararray(j-1)
Next j
Next i


mmult1=arg3



End Function

Тут выкладываю файлы с тестом для произведения матриц и с тем что я сначала хотел- функцией для решения линейных уравнений

* test11.ods (9.78 Кб - загружено 6 раз.)
* LinearSolution.ods (29.45 Кб - загружено 9 раз.)
« Последнее редактирование: 7 Июль 2014, 22:16 от calc4fem » Записан
Hasim
Форумчанин
***
Offline Offline

Сообщений: 754

Woe from wit


« Ответ #7: 8 Июль 2014, 08:45 »

Интересный вопрос который я пока не выяснил. Есть ли у сложных математических вычислений фора по производительности
если делать их через функции Calc или же программировать непосредственно в Basic (через цикл - поэлементно)
По идее первое должно быть производительней, ведь Calc наверняка оперирует целыми массивами в одной из своих нативных библиотек, а код Бэйсика - вроде бы интерпретируемый.
Тут "к бабке не ходи" - код Бэйсика на 2-3 порядка медленнее функций Калка - проверено многократно.
Записан
calc4fem
Форумчанин
***
Offline Offline

Сообщений: 278


« Ответ #8: 8 Июль 2014, 08:59 »

Спасибо, проверю конечно обязательно (чтобы подтвердить эту мысль насчет скорости)
В принципе медленность не играет роли в большинстве практических приложений, но решение СЛАУ - как раз тот случай где может и играть.
Насчет разного вида массивов - с чем это связано, что после всякого UnoService приходится преобразовывать массивы в традиционный вид? Вероятно что ни с чем, просто так, от java все пошло?
Записан
dndn
Форумчанин
***
Offline Offline

Сообщений: 93


WWW
« Ответ #9: 18 Декабрь 2014, 13:57 »

Доброго времени суток!
"Стою на асфальте я, в лыжи обутый..."  Смеющийся
Необходимо найти значение элемента в массиве. В Calc для этого есть соответствующая функция "MATCH". Аргументы: искомое значение; массив; тип.
В то же время для вызова функции Calc в макросе Бэйсика аргументы: наименование функции; массив аргументов.
Как задать массив в массиве аргументов?

Ну например, для функции "MAX" все просто:
Код:
FuncService = CreateUnoService("com.sun.star.sheet.FunctionAccess")
FuncResult = FuncService.callFunction("MAX", array(1,3,8,19,2))

А для "MATCH":
Код:
FuncResult = FuncService.callFunction("MATCH", array (3, array (1, 2, 3, 4, 5), 0))

выдает ошибку "com.sun.star.lang.IllegalArgumentException"
Понятно, что неправильно передается массив в массиве. Так что надо, что лыжи поехали?
« Последнее редактирование: 18 Декабрь 2014, 14:01 от dndn » Записан
Hasim
Форумчанин
***
Offline Offline

Сообщений: 754

Woe from wit


« Ответ #10: 24 Декабрь 2014, 00:12 »

Работает, если передается не массив, а ссылка на строку или столбец, как и написано в справке:
Цитата:
MATCH(Условие поиска; Массив; Тип)
Условие_поиска: значение для поиска в массиве с одной строкой или столбцом.
Массив: ссылка для поиска. Это может быть одна строка или столбец, либо часть одной строки или столбца.
Тип: параметр, который может принимать значения 1, 0 или -1.
Код:
sub Main

 FuncService = CreateUnoService("com.sun.star.sheet.FunctionAccess")
 
 oRange = ThisComponent.Sheets(0).getCellRangeByName("A1:A17")

 FuncResult = FuncService.callFunction("MATCH", Array(71, oRange, 0) )

 MsgBox FuncResult

End sub

Можно ли массив превратить в ссылку - вопрос?
« Последнее редактирование: 24 Декабрь 2014, 00:14 от Hasim » Записан
rami
Гуру
*******
Offline Offline

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


iMac, LibreOffice и Apache OpenOffice


« Ответ #11: 24 Декабрь 2014, 01:05 »

Номер i элемента x в массиве a() я бы искал перебором так:
Код:
Sub Main Dim i, a(), x     'вычисляет номер элемента массива
x=222
a=array(5,3,8,19,2,22)
For i=0 To UBound(a)
If a(i)=x Then Exit For
If i=UBound(a) Then Print x & " не найдено" : Exit Sub
Next
Print x & " находится на " & i & " месте"
End Sub
Записан

Hasim
Форумчанин
***
Offline Offline

Сообщений: 754

Woe from wit


« Ответ #12: 24 Декабрь 2014, 01:38 »

Если все-таки хочется использовать функцию MATCH, а не заниматься перебором, как rami, то надо вспомнить старый добрый VBA от Microsoft:
Код:
Option VBASupport 1

Sub zaq()
 Dim arr(6)

 arr(0) = 10
 arr(1) = 11
 arr(2) = 12
 arr(3) = 13
 arr(4) = 14
 arr(5) = 15
 
 am = Application.Match(13, arr, 0)
 
 MsgBox am-1

End Sub
Записан
Страниц: 1   Вверх
  Печать  
 
Перейти в:  

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