Page 1 of 1

[Solved] How to call calc built in functions?

PostPosted: Tue Feb 10, 2015 6:31 pm
by steadyonabix
Hi All

Hi All

I want to perform a number of functions from a basic macro like average and standard deviation and so on.

I see here:

https://wiki.openoffice.org/wiki/Docume ... E_function

That there are a whole bunch of built in functions that do what I want but I have no idea how to call them from a basic macro. I know that if I click on the function (=) icon on a spreadsheet I can call them, but not from a basic macro.

Can someone post an example usage I could crib? Perhaps how to average the range B0:F0 on a sheet?

Regards

Brad

Re: How to call calc built in functions?

PostPosted: Tue Feb 10, 2015 6:40 pm
by steadyonabix
Have just found this which looks promising:

http://www.oooforum.org/forum/viewtopic.phtml?p=441547

Wil give it a try

Re: How to call calc built in functions?

PostPosted: Tue Feb 10, 2015 7:20 pm
by steadyonabix
I have a number of questions about this.

My scratch function: -

Code: Select all   Expand viewCollapse view
Function fnAverage() AS Long

   Dim oFunctionAccess : oFunctionAccess = createUnoService( "com.sun.star.sheet.FunctionAccess" )
   Dim sRange AS String : sRange = "$BL1DAT1_timing.$B$0:$F$0"
   sRange = "B0:F0"
   
   fnAverage = oFunctionAccess.CallFunction( "AVERAGE", sRange)

End Function


1 - What sheet is used when I call the function AVERAGE using sRange set to "B0:F0". (As you can see I have tried using an absolute name. Although the syntax shown here shows a cell address - https://wiki.openoffice.org/wiki/Docume ... E_function)

2 - running the above gives an Object Variable Not Set error where I call the function.

I assume the error is because I am calling the function incorrectly?

Any help much appreciated

Brad

Re: How to call calc built in functions?

PostPosted: Tue Feb 10, 2015 10:22 pm
by rudolfo
www.openoffice.org/api/docs XFunctionAccess wrote:::com::sun::star::table::XCellRange
for a SheetCellRange object that contains the data.

this means the second parameter should be a CellRange, not a string that specifies a cell range.
So you better try:
Code: Select all   Expand viewCollapse view
Dim oFunctionAccess As Object
Dim oSheet As Object, oRange As Object

oFunctionAccess = createUnoService( "com.sun.star.sheet.FunctionAccess" )
' get the first sheet of the document
oSheet = ThisComponent.getSheets().getByIndex(0)
oRange = oSheet.getCellRangeByPosition(1, 0, 5, 0)  ' B1 to F1
'or oRange = oSheet.getCellRangeByName("B1:F1")

fnAverage = oFunctionAccess.CallFunction( "AVERAGE", oRange)


You have used "B0" and "F0", but that would be wrong. When using the ...ByName methods you can use the cell specifier in the same way as you see it on the sheet: "A1" for the upper left most cell, "B1" for its right neighbour, and so on. Only if you use the ...ByPosition methods you have to start counting at zero: "A1" is (0,0) and "F2" is (5,1). First number is the column and the second one the row.

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 11:36 am
by steadyonabix
Thanks Rudolfo

I have been misunderstanding how to drill down into the documentation. Your quote for XCellRange pointed me in the right direction.

I will try your suggestion.

Many thanks

Brad

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 1:22 pm
by steadyonabix
Hi

I am having mixed results with this call to FunctionAccess.CallFunction:

Call to AVERAGE

This works:
Code: Select all   Expand viewCollapse view
Function fnAverage(sSheet AS String, sRange AS String) AS Double
   Dim oFunctionAccess : oFunctionAccess = createUnoService( "com.sun.star.sheet.FunctionAccess" )   
   Dim L(3) as long
   L(0) = 10
   L(2) = 20
   L(3) = 30
   fnAverage = oFunctionAccess.CallFunction( "AVERAGE", L)
End Function


But this throws illegal argument exception when called this way:

Code: Select all   Expand viewCollapse view
n = fnAverage("BL1DAT1_timing", "B1:F1")

Code: Select all   Expand viewCollapse view
Function fnAverage(sSheet AS String, sRange AS String) AS Double
   Dim oFunctionAccess : oFunctionAccess = createUnoService( "com.sun.star.sheet.FunctionAccess" )
   Dim oDoc, oSheet, oRange AS Object
   
   oDoc = ThisComponent
   oSheet = oDoc.sheets.getByName(sSheet)
   oRange = oSheet.getCellRangeByName(sRange)

   fnAverage = oFunctionAccess.CallFunction( "AVERAGE", oRange)
End Function


Error Message is - "cannot coerce argument type during coreflection call!."

But according to the docs it should accept the range as an argument.
Also the call to getCellRangeByName should return a XCellRange.

So I don't see what is wrong there.

Perhaps I shopuld read out the range properties into an array of doubles and use that.

Brad

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 1:41 pm
by Zizi64
...As rudolfo wrote:
this means the second parameter should be a CellRange, not a string that specifies a cell range.


The "B1:F1" string NOT represent a Cellrange, but it represents the NAME of the Cellrange only. The average function can not calculate any result from a string.

You need get the CELLRANGE based on its NAME.
The Cellrange will be an Object type variable, but the name is a String type variable.

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 1:46 pm
by steadyonabix
Sorry Zizi, but I am confused.

Forgive me I am new to this.

I thought the call to getCellRangeByName returned the cell range object and that is what I was passing to CallFunction

Have I misunderstood?

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 2:02 pm
by Zizi64
https://forum.openoffice.org/en/forum/v ... 45&t=24323

The argument of the Built in Average function must be an Array type variable. You need "convert" the values of the Cellrange object to an Array variable:

When the passed parameter is an Object :

Code: Select all   Expand viewCollapse view
Function fnAverage(oRange AS Object) AS Double
Dim oFunctionAccess : oFunctionAccess = createUnoService( "com.sun.star.sheet.FunctionAccess" )
   arg = Array(oRange)
   fnAverage = oFunctionAccess.CallFunction( "AVERAGE", arg)
End Function

- usage: just select calculable cellrange after typing the name of the user defined function (and the beginning parenthesis)

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 2:06 pm
by Zizi64
or when you passed the NAME of the Sheet and the NAME of the Cellrange (as String variable):

Code: Select all   Expand viewCollapse view
Function fnAverage(sSheet AS String, sRange AS String) AS Double
   Dim oFunctionAccess : oFunctionAccess = createUnoService( "com.sun.star.sheet.FunctionAccess" )
   Dim oDoc, oSheet, oRange AS Object
   
   oDoc = ThisComponent
   oSheet = oDoc.sheets.getByName(sSheet)
   oRange = oSheet.getCellRangeByName(sRange)
   
   arg = Array(oRange)
   fnAverage = oFunctionAccess.CallFunction( "AVERAGE", arg)
End Function


Usage:
=fnAverage("$BL1DAT1_timing";"$B$0:$F$0")

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 2:24 pm
by steadyonabix
Many Thanks Zizi

I thought I was going to have to write the functions myself.

So I guess this was telling me to use an array for a range:

any[][]
for a mixed array, where each element must be of void, long, double or string type.
::com::sun::star::table::XCellRange
for a SheetCellRange object that contains the data.

Thanks for saving me a lot of work reinventing the wheel. :)

Brad

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 2:27 pm
by steadyonabix
PS

How do I mark this as solved?

Re: How to call calc built in functions?

PostPosted: Wed Feb 11, 2015 2:40 pm
by Zizi64
Edit the title of the first post in this topic:
[Solved] How to call calc built in functions?

Re: [solved] How to call calc built in functions?

PostPosted: Fri Feb 13, 2015 2:53 am
by rudolfo
I have to admit, I did not test my code from my last post. It just seemed to be what is expected by the API. Obviously it is not.
For the records I gave it another go with the .getDataArray() method of the XCellRange interface. At least the name of the method seems to promise that an array is returned. But it is not the kind of array that is expected by the CallFunction API.

Code: Select all   Expand viewCollapse view
  oCellRange = oSheet.getCellRangeByPosition(0,0, 0,3)
  ' the following fails (as we all know)
  'dblValue = oFunctionAccess.CallFunction( "AVERAGE", oCellRange)

  oDataArray = oCellRange.getDataArray()
  ' The next line will also fail
  dblValue = oFunctionAccess.CallFunction( "AVERAGE", oDataArray)

  args = Array(oDataArray)
  ' now it works !!
  dblValue = oFunctionAccess.CallFunction( "AVERAGE", args)


This seemed strange to me, so I started the Basic IDE debugger and inspected the arrays. This is what the "Watch" window shows for oDataArray and args = Array(oDataArray):
Code: Select all   Expand viewCollapse view
|Variable                  | Value   | Type
|--------------------------+---------+-----------------
|- oDataArray              :         : Object(0 to 3)
|  - oDataArray(0)         :         : Variant(0 to 0)
|       oDataArray(0)(0)   : 10      : Variant/Double
|  + oDataArray(1)         :         : Variant(0 to 0)
|  + oDataArray(2)         :         : Variant(0 to 0)
|  + oDataArray(3)         :         : Variant(0 to 0)
|--------------------------+---------+-----------------
|- args                    :         : Variant(0 to 0)
|  - args(0)               :         : Object(0 to 3)
|    - args(0)(0)          :         : Variant(0 to 0)
|         args(0)(0)(0)    : 10      : Variant/Double
|    + args(0)(1)          :         : Variant(0 to 0)
|    + args(0)(2)          :         : Variant(0 to 0)
|    + args(0)(3)          :         : Variant(0 to 0)


Both array look very similar, but the second one has one nesting level more. And actually the inner content can be quite different as Zizi's approach with wrapping the XCellRange directly into an array shows. The following is a screenshot of the watch window for the case with args = Array(oCellRange):

different-arrays.png
DataArray of a range and Array with a range as element

Re: [solved] How to call calc built in functions?

PostPosted: Fri Feb 13, 2015 2:09 pm
by steadyonabix
That's interesting.

Always a good feeling to understand why.

On a general note to all who helped me with my project, thanks very much. It all works perfectly now. :)

Re: [Solved] How to call calc built in functions?

PostPosted: Sun Jan 27, 2019 4:03 pm
by misitu
Thanks to you I have managed to figure this out for my own needs (max, min of column values to establish good y axis max and min on automated charts).

Grateful Thanks
David