Использование функций Calc в коде Basic

Автор calc4fem, 3 июля 2014, 19:44

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

calc4fem

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

Yakov

Это было на 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

Читайте Питоньяка. 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 Объяснение Макросов."

calc4fem

Да - спасибо. В принципе все ясно.
Проблема общая для Бэйсик - то что матрицы которые приходят из 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

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

calc4fem

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

calc4fem

#6
Спасибо - нашел ошибку
сам даже у себя. Все таки отладчик в 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


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

Hasim

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

calc4fem

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

dndn

Доброго времени суток!
"Стою на асфальте я, в лыжи обутый..."  ;D
Необходимо найти значение элемента в массиве. В 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"
Понятно, что неправильно передается массив в массиве. Так что надо, что лыжи поехали?

Hasim

#10
Работает, если передается не массив, а ссылка на строку или столбец, как и написано в справке:
Цитировать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


Можно ли массив превратить в ссылку - вопрос?

rami

Номер 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

Если все-таки хочется использовать функцию 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