Calc/Add-In/Simple Calc Add-In

From Apache OpenOffice Wiki
< Calc‎ | Add-In
Jump to: navigation, search

This is a step by step guide on how to write a simple component (a Calc add-in) for OpenOffice.org (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. This document has been updated for OOo version 3, an earlier revision of this page pertaining to OOo version 2 can be found here.

Requirements

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 3.0 or above if you do not already have it. Most Linux distributions come with it. For Ubuntu 7.04 the package name is openoffice.org, and it is installed at /usr/lib/openoffice.

Later we will link against libuno_cppuhelpergcc3.so which should be in the lib subdirectory of OpenOffice.org's ure (Uno Runtime Environment) directory. For example on my machine the relevant path is /usr/lib64/openoffice.org/ure/lib. In a command line terminal, cd to the ure lib directory and type "ls *cppuhelper*". If you see libuno_cppuhelpergcc3.so file listed, then everything is fine. If not then you should see something like libuno_cppuhelpergcc3.so.3, and you should type "sudo ln -s libuno_cppuhelpergcc3.so.3 libuno_cppuhelpergcc3.so" 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 libuno_cppuhelpergcc3.so to the original file libuno_cppuhelpergcc3.so.3 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 and return to your user account (by typing exit).

Our major reference will be the OOo SDK. Install the relevant package for your distro if it is available. Otherwise go ahead and download it from http://download.openoffice.org/680/sdk.html. 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.

Introduction

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 http://mathworld.wolfram.com/ExponentialDistribution.html and http://en.wikipedia.org/wiki/Exponential_distribution) 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 http://en.wikipedia.org/wiki/Inverse_transform_sampling_method for more information about sampling arbitrary random variables with closed form inverse cumulative distribution functions.

Preparation

Download MyRNG.OOo3.tar.gz and uncompress it. Open a terminal window and cd to the myRNG directory. There should be five files in the directory, one of them is script setenv which is used for setting environment parameters. Edit the file and update the paths as necessary for your system. You will need to type "source setenv" 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.

IDL

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;
}; }; }; };
#endif

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.

Implementation

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<
        ::org::openoffice::sheet::addin::XRNG,
        ::sheet::XAddIn,
        lang::XServiceName,
        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

The myRNG directory contains a Makefile to automate the build. Look in the Makefile to see what steps are necessary to build an addin. 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

Still at the command line in the myRNG directory, type "make". If all goes well the build should complete without error and produce files libRNG.so and RNG.rdb. Copy these two files into $OOo (the OpenOffice.org program directory) by typing "sudo cp *.so *.rdb $OOo" in the terminal. Edit the $OOo/fundamentalbasisrc file by typing "sudo nano $OOo/fundamentalbasisrc" and add "$ORIGIN/RNG.rdb" to the end of lines starting with URE_MORE_SERVICES and URE_MORE_TYPES (See "4.6.10 Building and Testing C++ Components" of the developer's guide). Those two lines should look similar to this

URE_MORE_SERVICES=${${$ORIGIN/unorc:PKG_UserUnoFile}:UNO_SERVICES} ${${$ORIGIN/unorc:PKG_SharedUnoFile}:UNO_SERVICES} $ORIGIN/services.rdb $ORIGIN/RNG.rdb
URE_MORE_TYPES=$ORIGIN/offapi.rdb $ORIGIN/oovbaapi.rdb ${${$ORIGIN/unorc:PKG_SharedUnoFile}:UNO_TYPES} ${${$ORIGIN/unorc:PKG_UserUnoFile}:UNO_TYPES} $ORIGIN/RNG.rdb

Save and exit nano. Now it is time to try our RNG. Open OOo Calc, go to Tools > Macros > Organize Macros > OpenOffice.org Basic menu and click "Edit" in the new window. Then copy-paste the following lines into the Basic code editing window, overwriting everything that 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:

MyRNG.OOo3.png

Further

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 http://www.openoffice.org/licenses/PDL.html.

Original Document: Copyright (C) 2006 Serhat Sevki Dincer, jfcgaussATgmail. All rights reserved.
Updates For OOo 3: Copyright (C) 2009 Eric Ehlers, Nazcatech sprl Brussels.
Personal tools