Calc/Add-In/Simple Calc Add-In

From Apache OpenOffice Wiki
< Calc‎ | Add-In
Revision as of 13:46, 4 April 2008 by ErAck (Talk | contribs)

Jump to: navigation, search

This is a step by step guide on how to write a simple component (a Calc add-in) for (OOo) in C++. Even though the instructions are for Linux, this guide should give an idea on how to write components on other operating systems as well.


Make sure you have a C++ compiler and standard C library development files, preferably GNU C++ and GNU C library development files. Most Linux distributions either come with them or have them in their repositories. For example in Ubuntu 5.10-7.04 the package names are g++ and libc6-dev.

You need to install OOo version 2.0 or above if you do not already have it. Most Linux distributions come with it. For Ubuntu 7.04 the package name is, and it is installed at /usr/lib/openoffice.

Our major reference will be the OOo SDK, so go ahead download it from or install the package named Extract the SDK to somewhere you have write access to. You can delete the .tar.gz file after the extraction. The index.html file in the SDK directory is the main page of the OOo SDK documentation. Reading the SDK documentation fully or major parts of it would be a very good practice before trying to write code for OOo (For now ignore the "Installation Guide" part). You will use "Developer's Guide", "IDL Reference" and "C++ Reference" parts the most.

Open a terminal, go to the extracted SDK directory with cd command and type (replace /usr/lib/openoffice2 with your full OOo installation directory)

echo export OOoSDK='"'`pwd`'"' > OOoSetenv
echo export PATH='"$OOoSDK/linux/bin:$PATH"' >> OOoSetenv
echo export OOo='"/usr/lib/openoffice2/program"' >> OOoSetenv
echo export LD_LIBRARY_PATH='"$OOo:$LD_LIBRARY_PATH"' >> OOoSetenv

This will prepare a script named OOoSetenv (for environment parameters). You will need to type "source OOoSetenv" in a terminal every time you want to use the SDK (For each terminal session it is enough to do it once), so go ahead and type it.

Later we will link against which should be in $OOo directory. In your terminal type "ls $OOo/*cppuhelper*". If you see file listed, then everything is fine. If not then you should see something like, and you should type "sudo ln -s $OOo/ $OOo/" in your terminal, enter your password if asked (This requires a user that can do super user tasks with sudo, a sudoer). This just creates a symbolic link named to the original file in the same directory. If your Linux distribution does not have sudo command then become super user with su command, type the previous command without sudo at the beginning (you may need to write $OOo explicitly) and return to your user account (by typing exit).

In your terminal type "mkdir myProjects". This will create a directory named "myProjects" in the SDK directory. We will put our projects here. Close the terminal window now.


A component is an add-on (Merriam-Webster says "add-on : something (as an accessory or added feature) that enhances the thing it is added to") for OOo. They are more specifically called UNO components (See "3 Professional UNO" and "4 Writing UNO Components" in the SDK's "Developer's Guide" part). You can write components for OOo in many programming languages, including C++ and Java.

Calc is the spreadsheet application of OOo. We will write a Calc add-in, which is a special UNO component, that provides a Random Number Generator (RNG) service. For example, the "RAND()" function of Calc is a RNG that returns a random number between 0 and 1. So let's do something new and write a RNG that returns exponentially distributed (See and random numbers. In this guide we will do things that are the same for general UNO components and/or Calc add-ins written in C++, so we will not be doing anything specific to RNGs, it is just something we can implement for Calc. See for more information about sampling arbitrary random variables with closed form inverse cumulative distribution functions.


Open a terminal window, go to the SDK directory and type "source OOoSetenv" and then "cd myProjects". Keep the terminal window open. Then download the MyRNG.tar.gz file, extract it into the myProjects directory, and type "cd myRNG" in the terminal. There should be six files in the myRNG directory.


Writing a component for OOo starts with writing its "Interface Specification". Interface Specification is simply defining your component in a way that is independent from whichever implementation language (like C++, Java) you use. For OOo there is a special language called UNOIDL (UNO Interface Definition Language) to write interface specifications (See "4.2 Using UNOIDL to Specify New Components" in the SDK's "Developer's Guide" part). UNOIDL is very simple, and similar to C++. As you may have guessed, RNG.idl file is our interface specification. What is inside it is

#ifndef _org_openoffice_sheet_addin_RNG_idl_
#define _org_openoffice_sheet_addin_RNG_idl_
#include <com/sun/star/uno/XInterface.idl>
module org { module openoffice { module sheet { module addin {
	interface XRNG : com::sun::star::uno::XInterface
		double expo( [in] double m );
	service RNG : XRNG;
}; }; }; };

First you define an interface. Our interface is XRNG (derived from XInterface which is the base interface for any component) which has the definition for our RNG function (expo) that produces exponentially distributed random numbers. It is a convention that interface names start with X. Then we have a service, RNG, that uses our interface XRNG. Read the 3rd and 4th chapters of the developer's guide for more information about module, interface and service keywords. UNO components are put under org.openoffice module, Calc add-ins are put under org.openoffice.sheet.addin.


A UNO component must implement XInterface, XTypeProvider, XServiceInfo and XWeak interfaces (See "4.4 Core Interfaces to Implement" of developer's guide). Luckily there are helper template classes for C++ (See "4.6 C++ Component" of developer's guide, and WeakImplHelper* under cppu in "C++ Reference") that take care of XInterface, XTypeProvider, XWeak implementations. In addition to these interfaces that every UNO component should implement, a Calc add-in must implement XAddIn and XServiceName (See "8.6 Spreadsheet Add-Ins" of the developer's guide) interfaces. As you read the SDK documentation more, things will become clearer. The RNG_impl.cxx file is our implementation. In it we have our RNG_impl class' definition with the WeakImplHelper4 helper template

// 4-parameter template
class RNG_impl : public ::cppu::WeakImplHelper4<
        lang::XServiceInfo >

and implementations of XRNG, XAddIn, XServiceName, XServiceInfo and XLocalizable (just a small detail) classes. In addition to these it has the functions create_RNG_impl (creates a single instance of our RNG service), component_getImplementationEnvironment, component_writeInfo, component_getFactory and the struct s_component_entries (See "4.6 C++ Component" of the developer's guide). After reading the SDK documentation and taking closer looks into RNG_impl.cxx file a few times, everything in RNG_impl.cxx file should be reasonably clear :).

Other Files

In order to ease the development there is a build script named "build" in the myRNG directory. What is inside it is

rm -rf com org *.rdb *.urd
idlc -C -I$OOoSDK/idl RNG.idl
regmerge RNG.rdb /UCR RNG.urd
cppumaker -BUCR -Torg.openoffice.sheet.addin.XRNG $OOo/types.rdb RNG.rdb
g++ -O2 -fomit-frame-pointer -c -o RNG_impl.o -DUNX -DGCC -DLINUX -DCPPU_ENV=gcc3 -I. -I$OOoSDK/include RNG_impl.cxx
ld -o -shared -L$OOo --retain-symbols-file symbols.txt RNG_impl.o -lcppuhelpergcc3
rm -rf com org *.urd RNG_impl.o
regcomp -register -r *.rdb -c *.so

For details about idlc, regmerge, cppumaker and regcomp tools see "4.2.2 Generating Source Code from UNOIDL Definitions" of the developer's guide and "Development Tools". A component must export only three symbols, the function names which start with "component_", and "--retain-symbols-file symbols.txt" option to the linker ld serves this purpose. In your terminal you can type "man ld" to read about --retain-symbols-file option.

Building & Testing

If everything went right typing "./build" in the terminal should produce and RNG.rdb files without any error. If not we have spare ones, _libRNG.so_ and _RNG.rdb_ :). Copy RNG.rdb and into $OOo by typing "sudo cp *.so *.rdb $OOo" in the terminal. Edit the $OOo/unorc file by typing "sudo nano $OOo/unorc" and add "$ORIGIN/RNG.rdb" to the end of lines starting with UNO_TYPES and UNO_SERVICES (See "4.6.10 Building and Testing C++ Components" of the developer's guide). Those two lines should look similar to this


Save and exit nano. Now it is time to try our RNG. Open OOo Calc, go to Tools > Macros > Organize Macros > Basic menu and click "Edit" in the new window. Then copy-paste the following lines into the Basic code editing window overwriting everything what was there

Sub Main
	mgr = getProcessServiceManager()
	o = mgr.createInstance("org.openoffice.sheet.addin.RNG")
	MsgBox o.expo(10)
End Sub

Save and run your Basic macro. You should see something like this

RNG shot.png


Dig into the SDK documentation more and study the examples in the SDK, both Java and C++, then you should be ready to write your own UNO component.

A more complete C++ add-in can be found here : another Example

See also

Public Documentation License Notice

The contents of this Documentation are subject to the Public Documentation License Version 1.0 (the "License"); you may only use this Documentation if you comply with the terms of this License. A copy of the License is available at

Original Author: Serhat Sevki Dincer (C) 2006, jfcgaussATgmail. All rights reserved.

Personal tools