CG7112 CalcMacros
CG7112 CalcMacros
Chapter 12
Macros
Automating repetitive tasks
Copyright
This document is Copyright © 2021 by the LibreOffice Documentation Team. Contributors are
listed below. You may distribute it and/or modify it under the terms of either the GNU General
Public License (http://www.gnu.org/licenses/gpl.html), version 3 or later, or the Creative
Commons Attribution License (http://creativecommons.org/licenses/by/4.0/), version 4.0 or later.
All trademarks within this guide belong to their legitimate owners.
Contributors
To this edition
Felipe Viggiano Kees Kriek Vasudev Narayanan
Jean Hollis Weber
To previous editions
Andrew Pitonyak Barbara Duprey Jean Hollis Weber
Simon Brydon Steve Fanning Leo Moons
Felipe Viggiano Olivier Hallot Kees Kriek
Feedback
Please direct any comments or suggestions about this document to the Documentation Team’s
mailing list: documentation@global.libreoffice.org.
Note
Everything you send to a mailing list, including your email address and any other
personal information that is written in the message, is publicly archived and cannot
be deleted.
Note
Use Tools > Options > LibreOffice > Advanced on the Menu bar and select the
Enable macro recording (may be limited) option to enable the macro recorder.
1) Use File > New > Spreadsheet on the Menu bar to create a new spreadsheet.
2) Enter the numbers shown in Figure 1 into cells A1:C3 of Sheet1 in the new spreadsheet.
Note
The libraries, modules, and macro names must follow some strict rules. Following the main
rules, the names must:
• Comprise lower case letters (a..z), upper case letters (A..Z), digits (0..9), and
underscore characters (_)
• Begin with a letter or an underscore
• Not contain any other spaces, punctuation symbols, or special characters (including
accents)
11) Click the OK button to create a new module. As no macro libraries exist in our current
document, Calc automatically creates and uses a Standard library.
12) On the Basic Macros dialog, select the entry for the newly created module in the Save
Macro In area, type the text PasteMultiply in the Macro Name box, and click the Save
button (Figure 7).
sub PasteMultiply
rem --------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem --------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem --------------------------------------------------------------
dim args1(5) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Flags"
args1(0).Value = "A"
args1(1).Name = "FormulaCommand"
args1(1).Value = 3
args1(2).Name = "SkipEmptyCells"
args1(2).Value = false
args1(3).Name = "Transpose"
args1(3).Value = false
args1(4).Name = "AsLink"
args1(4).Value = false
args1(5).Name = "MoveMode"
args1(5).Value = 4
end sub
Note
The component model used in LibreOffice is Universal Network Objects (UNO) and
the macro recorder uses the UNO dispatcher for most commands. However, there
are two problems associated with this technical approach. One is that the dispatches
are not fully documented and may be subject to change. Another is that the recorder
ignores some values from dialogs that are opened while recording a macro – it is
possible, therefore, that you will record a complicated macro that will not actually
execute everything as expected. For more information, search for “macro recording –
limitations” in the Help index.
Figure 12 shows the default configuration for the LibreOffice Basic IDE. This comprises:
• A menu bar.
• Two toolbars (Macro and Standard). The Macro toolbar provides various icons for
editing and testing programs.
• The Object Catalog, enabling the selection of the required library container, library,
module, and macro.
• The Editor Window, in which you can edit the LibreOffice Basic program code. The
column on the left side is used to set breakpoints in the program code.
• The Watch Window (located at the left, below the Object Catalog and Editor
Window) displays the contents of variables or arrays during a single step process.
• The Calls Window (located to the right, below the Object Catalog and Editor
Window) provides information about the call stack of procedures and functions
when a program runs.
• A tab control area.
• A status bar.
The LibreOffice Basic IDE provides powerful facilities for the development and debugging
of LibreOffice Basic macros. A fuller description of this facility is beyond the scope of this
document, but more information can be found in the Help system.
7) In the Editor Window, modify the code so that it is the same as that shown in Listing 2.
The important addition is the creation of the NumberFive function, which returns the value
5.
Sub Main
End Sub
Function NumberFive ()
NumberFive = 5
End Function
8) Within the LibreOffice Basic IDE select File > Save on the Menu bar, or click the Save
icon on the Standard toolbar, or press Ctrl+C, to save the modified Module1.
Tip
Function names are not case sensitive. In Figure 13, the function name was entered
as NumberFive() but Calc displays it as NUMBERFIVE() in the Formula bar.
Use Tools > Macros > Organize Macros > Basic on the Menu bar to open the Basic Macros
dialog (Figure 17). The icon for a loaded library (for example, Standard) has a different
appearance to the icon for a library that is not loaded (for example, AuthorsCalcMacros).
Click the expand icon next to AuthorsCalcMacros to load the library. The icon changes
appearance to indicate that the library is now loaded. Click Close to close the Basic Macros
dialog.
Function NumberFive_Implementation ()
NumberFive_Implementation = 5
End Function
3) Click the Select Macro button in the Standard toolbar of the LibreOffice Basic IDE to
open the Basic Macros dialog (Figure 18).
Function NumberFive()
If NOT BasicLibraries.isLibraryLoaded("AuthorsCalcMacros") Then
BasicLibraries.LoadLibrary("AuthorsCalcMacros")
End If
NumberFive = NumberFive_Implementation()
End Function
6) Save, close, and reopen the Calc document. This time, if macros are enabled, the
NumberFive() function works as expected.
Function PositiveSum(Optional x)
Dim TheSum As Double
Dim iRow As Integer
Dim iCol As Integer
TheSum = 0.0
If NOT IsMissing(x) Then
If NOT IsArray(x) Then
If x > 0 Then TheSum = x
Else
For iRow = LBound(x, 1) To UBound(x, 1)
For iCol = LBound(x, 2) To UBound(x, 2)
If x(iRow, iCol) > 0 Then TheSum = TheSum + x(iRow, iCol)
Next
Next
End If
End If
PositiveSum = TheSum
End Function
The macro in Listing 5 demonstrates some important techniques:
1) The argument x is Optional. When an argument is not Optional and the function is
called without it, Calc outputs a warning message every time the macro is called. If Calc
calls the function many times, then the error is displayed many times.
2) The function IsMissing checks that an argument was passed before it is used.
3) The function IsArray checks to see if the argument is a single value, or an array. For
example, =PositiveSum(7) or =PositiveSum(A4). In the first case, the number 7 is
Tip
The macro in Listing 5 is careful and checks to see if the argument is an array or a
single argument. The macro does not verify that each value is numeric. You may be
as careful as you like. The more things you check, the more robust the macro is, but
the slower it runs.
Passing one argument is as easy as passing two: add another argument to the function definition
(see Listing 6). When calling a function with two arguments, separate the arguments with a
comma; for example, =TestMax(3, -4).
Listing 6. TestMax accepts two arguments and returns the larger
Function TestMax(x, y)
If x >= y Then
TestMax = x
Else
TestMax = y
End If
End Function
Function SumCellsAllSheets()
Dim TheSum As Double
Dim i As integer
TheSum = 0
oSheets = ThisComponent.getSheets()
For i = 0 To oSheets.getCount() - 1
oSheet = oSheets.getByIndex(i)
oCell = oSheet.getCellByPosition(0, 1) ' GetCell A2
TheSum = TheSum + oCell.getValue()
Next
SumCellsAllSheets = TheSum
End Function
Tip
A cell object supports the methods getValue(), getString(), and getFormula() to get
the numerical value, the string value, or the formula used in a cell. Use the
corresponding set functions to set appropriate values.
Function SumCellsAllSheets()
Dim TheSum As Double
Dim iRow As Integer, iCol As Integer, i As Integer
Dim oSheets, oSheet, oCells
Dim oRow(), oRows()
TheSum = 0
oSheets = ThisComponent.getSheets()
For i = 0 To oSheets.getCount() - 1
oSheet = oSheets.getByIndex(i)
oCells = oSheet.getCellRangeByName("A2:C5")
oRows() = oCells.getData()
For iRow = LBound(oRows()) To UBound(oRows())
oRow() = oRows(iRow)
For iCol = LBound(oRow()) To UBound(oRow())
TheSum = TheSum + oRow(iCol)
Next
Next
Next
SumCellsAllSheets = TheSum
End Function
Sorting
Consider sorting the data shown in Figure 20. First, sort on column B descending and then on
column A ascending.
Sub SortRange
Dim oSheet ' Calc sheet containing data to sort.
Dim oCellRange ' Data range to sort.
Sorting | 19
REM If column B has two cells with the same value,
REM then use column A ascending to decide the order.
oSortFields(1).Field = 0
oSortFields(1).SortAscending = TRUE
BeanShell macros
BeanShell is a Java-like scripting language that was first released in 1999.
When you select Tools > Macros > Organize Macros > BeanShell on the Menu bar, Calc
displays the BeanShell Macros dialog (Figure 22).
Click the Edit button on the BeanShell Macros dialog to access the BeanShell Debug Window
(Figure 23).
Listing 10 is an example of a BeanShell macro that inserts the text “Hello World from BeanShell”
in cell A1 of the active Calc spreadsheet.
import com.sun.star.uno.UnoRuntime;
import com.sun.star.sheet.XSpreadsheetView;
import com.sun.star.text.XText;
model = XSCRIPTCONTEXT.getDocument();
controller = model.getCurrentController();
sheet = view.getActiveSheet();
textCursor = cellText.createTextCursor();
return 0;
JavaScript macros
JavaScript is a high-level scripting language that was first released in 1995.
When you select Tools > Macros > Organize Macros > JavaScript on the Menu bar, Calc
displays the JavaScript Macros dialog (Figure 24).
Listing 11 is an example of a JavaScript macro that inserts the text “Hello World from JavaScript”
in cell A1 of the first sheet in a Calc spreadsheet.
Listing 11. Sample JavaScript macro
importClass(Packages.com.sun.star.uno.UnoRuntime);
importClass(Packages.com.sun.star.sheet.XSpreadsheetDocument);
importClass(Packages.com.sun.star.container.XIndexAccess);
importClass(Packages.com.sun.star.table.XCellRange);
importClass(Packages.com.sun.star.table.XCell);
documentRef = XSCRIPTCONTEXT.getDocument();
allSheets = UnoRuntime.queryInterface(XIndexAccess,
spreadsheetInterface.getSheets());
theSheet = allSheets.getByIndex(0);
Cells = UnoRuntime.queryInterface(XCellRange,theSheet);
cellA1 = Cells.getCellByPosition(0,0);
theCell = UnoRuntime.queryInterface(XCell,cellA1);
Python macros
Python is a high-level, general-purpose programming language that was first released in 1991.
When you select Tools > Macros > Organize Macros > Python on the Menu bar, Calc displays
the Python Macros dialog (Figure 26).
import uno
def HelloWorld():
doc = XSCRIPTCONTEXT.getDocument()
cell = doc.Sheets[0]['A1']
cell.setString('Hello World from Python')
return
Note
The support for VBA is not complete but covers a large portion of the common usage
patterns.
When VBASupport is enabled, LibreOffice Basic function arguments and return values are the
same as their VBA counterparts. When the support is disabled, LibreOffice Basic functions may
accept arguments and return values different from their VBA counterparts.
Listing 13. Option VBASupport usage
Option VBASupport 1
Sub Example
Dim sVar As Single
sVar = Worksheets("Sheet1").Range("A1")
Print sVar
End Sub
Without the Option VBASupport statement, the code in Listing 13 must be converted to the
LibreOffice Basic of Listing 14.
Listing 14. Converted VBA code
Sub Example
Dim sVar As Single
Dim oSheet as Object
Dim oCell as Object
REM Worksheets(“Sheet1”).
oSheet = ThisComponent.getSheets().getByIndex(0)
REM Range("A1")
oCell = oSheet.getCellByPosition(0, 0)
sVar = oCell.getValue()
Print sVar
End Sub
Option VBASupport may affect or assist in the following situations:
• Allow special characters as identifiers. All characters that are defined as letters in the
Latin-1 (ISO 8859-1) character set, are accepted as part of identifiers. For example,
variables with accented characters in their names.
• Create VBA constants including non-printable characters (vbCrLf, vbNewLine,...).
• Support Private/Public keywords for procedures.
Sub MyProc
MyForm.Show
End Sub
Listing 16. LibreOffice Basic display of a UserForm [Dialog] called “MyForm”
Note
The oDlg variable is visible at the module level to all other procedures that are
accessing controls on the dialog. This means all the procedures manipulating or
accessing controls on this dialog panel are housed in a single module.
Conclusion
This chapter provides an overview of how to create libraries and modules, using the macro
recorder, using macros as Calc functions, writing your own macros without the macro recorder,
and converting VBA to LibreOffice Basic. Each topic deserves at least one chapter, and writing
your own macros for Calc could easily fill an entire book. In other words, this is just the beginning
of what you can learn.
If you are already familiar with the Basic language (or with one programming language), the
LibreOffice Extensions website has a set of LibreOffice Basic quick reference cards at the
address https://extensions.libreoffice.org/?Tags%5B%5D=53&Tags%5B%5D=173.
Additional detail about Calc’s macro facilities can be obtained from the Help system
(https://help.libreoffice.org/7.0/en-US/text/sbasic/shared/main0601.html?DbPAR=BASIC for
general macros information, or, to find some specific VBA Support information go to
https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03103350.html), The Document
Foundation’s wiki pages (https://wiki.documentfoundation.org/Macros) and other Internet sources
(for example the https://ask.libreoffice.org/ Q&A site).