Calc
Libre Office is extendable using Macros. The terminology is confusing because Macros seem to encompass both scripting in Calc, but also recording a sequence of events similar to Photoshop's actions. I don't care about the second, but the first is very useful.
Macro Modules can be written in LibreOffice freebasic, and Python among other languages.
NOTE
If you are embedding macros in a document, you must enable them in
Tools > Options > Security > Macro Security > Medium
GUI
Dropdown Lists
Dropdown lists are a nice way of enforcing consistency. Select your cell, and click:
Data > Validity > List
Enter the options that you would like
Buttons
View > Toolbars > Form Controls
To create a button that refreshes all calculations (and macros), in the macro editor, define:
' Recalculate All Macros '------------------------ Sub ReCalculate() ThisComponent.calculateAll() End SubThen Create a Button that executes that Macro when pushed.
Anatomy of LibreOfficeBasic
Open the Macro IDE {{{Tools > Macros > Organize Macros > LibreOffice Basic}}}
Universal Macros
You can create generic MacroModules under
My Macros & Dialogs > Standard > Module1
Embedded Macros
You can also create Macro Modules embedded in your spreadsheet. They will be listed under
SpreadsheetTitle.ods > Standard > YourCustomModuleName
Note that you will have to enable Macros so that your embedded Macros work. If this hasn't been done before you create an Embedded Macro, you will have to restart LibreOffice Calc before the Functions can be used in cells.
To Safely Enable Macros, I recommend:
Tools > Options > Security > Macro Security > Medium
If you modify a macro, you will have to retype the equasion for it to be reloaded. Simply entering edit mode, and hitting enter again doesn't seem to do it.
To create an embedded Module, From the Macro Editor:
Tools > Macros > Organize Macros > LibreOffice Basic Click on SpreadsheetTitle.ods Click on New
Hello World
Once you are in the Macro Editor with a module open, you can start declaring functions. Using a function from the Macro Editor is simple. Once it is declared you can call it in the spreadsheet with {{{=myFunctionName()}}}. To get you started, here is an example 'Hello World' function:
Function helloWorld(someVar) as string helloWorld = "Hello World!" EndFunctionFrom this point forwards, in any cell you can call the function with:
=helloWorld()
Function names are not case-sensitive.
Alternative Hello World (print)
The function above writes the return value to your cell. Sometimes if you aren't sure of the datatype, or are trying to diagnose where your script is breaking you can use the print function.
print "hello world!"The result is a messagebox with your information
Syntax
Functions
### function with return value, with forced return value type "string" ##---------------------------------------- Function functionName(inputA, inputB) as string REM using the function name as a variable specifies the return value. functionName = "Hello World!" End Function ### CALL WITH: functionName(1) ### function with return value, conditional ##---------------------------------------- Function helloWorld(someVar) as string If someVar = 1 then helloWorld = "Hello World!" ElseIf someVar = 0 then helloWorld = "never mind then" Else helloWorld = "hell yes" End If End Function ### CALL WITH: helloWorld(1) ### function with array passed to it: ##---------------------------------------- Function testArrayA(arrayRange) total = 0 i = 1 For each i in arrayRange total = total + i next i testarray = total End Function ### CALL WITH: =testArray(E1:E22) ### function with array passed to it and used in scope ##---------------------------------------- Function testArrayB( arrayRange ) count = 0 dim array(10) as integer for each i in arrayRange array(count) = i count = count + 1 next i testMatrix = array(2) End Function ### CALL WITH: =testArray(E1:E22)
Variables
Variable Scope:
REM Variable Types global varName as integer REM valid everywhere until libreOffice closed public varName as integer REM valid across all modules private varName as integer REM local scope dim varName as integer REM local scope
Variable Types:
dim varName as integer REM 2 dim varName as single REM (float) 3.176 dim varName as double REM (float) dim varName as string REM 'blahblah' dim varname as boolean REM 'True' or 'False' dim varName as long REM long integers. From -2147483648 to 2147483647 dim varName as date REM ?
Arrays
' Arrays in freebasic are like arrays in C, their size is not dynamically ' allocated, so you must do that yourself. ubound(list) ' get array length 'expanding arrays' '----------------- ' expand array dim list(10) as single dim ibuffer as integer ibuffer = ubound(list) ' get current size of array ReDim preserve list( ibuffer +1 ) as single ' use ibuffer to expand list. (cannot use ' ubound list while redeclaring it. bummer) ' preserve means to keep previous values while ' redeclaring var ' Ex: grab cell range, convert to array ' -------------------------------------- Function rangeToArray() 'convert listRange to list() count = 0 for each i in listRange redim preserve list(count) list(count) = i count = count + 1 next i End Function
Conditionals
If someVar = 1 then helloWorld = "Hello World" ElseIf someVar = 0 then helloWorld = "Forget about it" Else helloWorld = "Supersize!!!" End If
Reading and Writing Cells
Cell Types
Cells can be of 3 different types. When reading or especially when writing it is important that you specify the type of data you wish to enter.
value -- a number string -- a string formula -- would typically begin with an '=' signQuery Selected Cell
Note that this is entirely based on the selected cell. If you refresh macros and your cursor is not overtop of your desired cell it will not behave as expected!!!! </syntaxhighlight lang="freebasic"> Function getCell() print ThisComponent.getCurrentSelection.CellAddress.Sheet print ThisComponent.getCurrentSelection.CellAddress.Column print ThisComponent.getcurrentSelection.CellAddress.Row End Function </syntaxhighlight>
Writing To Cells
You can edit as many cells as you like at a time from a Macro.
dim sheet as object, cell as object Function writeToCell() sheet=thisComponent.sheets(1) ##indicates sheet number you are writing to (begins at 0) cell=sheet.getCellByPosition(3,28) ##specify a cell. A=0, so A1=0,0. Easier to work with numbers than letters cell.string = "yes" -or- cell.value = 100 -or- cell.formula = "sum(100/2)" End Function
Querying Namned Cells
' Functions to pull values from named cell ' https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=17204 ' =getValue("namedCell") ' Returns the value from a named single cell Function getValue(namedValue As String) getValue = getRange(namedValue)(1, 1).value End Function ' Returns a named range of cells Function getRange(namedRange As String) getRange = StarDesktop.CurrentComponent.NamedRanges.getByName(namedRange).getReferredCells() End Function