Calc/Add-In/Simple Calc Add-In

From Apache OpenOffice Wiki
< Calc‎ | Add-In
Revision as of 17:26, 17 April 2006 by SergeMoutou (Talk | contribs)

Jump to: navigation, search

Simple Calc Add-in for OOo

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 OSes as well.

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 I have Ubuntu 5.10, and 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 5.10 the package name is openoffice.org2, and it is installed at /usr/lib/openoffice2.

Our major reference will be the OOo SDK, so 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.

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 libcppuhelpergcc3.so which should be in $OOo directory. In your terminal type "ls $OOo/*cppuhelper*". If you see libcppuhelpergcc3.so file listed, then everything is fine. If not then you should see something like libcppuhelpergcc3.so.3, and you should type "sudo ln -s $OOo/libcppuhelpergcc3.so.3 $OOo/libcppuhelpergcc3.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 libcppuhelpergcc3.so to the original file libcppuhelpergcc3.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 (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.

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.

Preparation

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.

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

[unoidl]

  1. ifndef _org_openoffice_sheet_addin_RNG_idl_
  2. define _org_openoffice_sheet_addin_RNG_idl_
  1. 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; }; }; }; };

  1. 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

class RNG_impl : public ::cppu::WeakImplHelper4< ::org::openoffice::sheet::addin::XRNG,
sheet::XAddIn, lang::XServiceName, lang::XServiceInfo > //4-parameter template

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 -Tcom.sun.star.sheet.XAddIn -Tcom.sun.star.lang.XServiceName -Tcom.sun.star.lang.XServiceInfo -Tcom.sun.star.lang.XTypeProvider -Tcom.sun.star.uno.XWeak -Tcom.sun.star.uno.XAggregation -Tcom.sun.star.lang.XMultiServiceFactory -Tcom.sun.star.uno.XComponentContext -Tcom.sun.star.lang.XSingleComponentFactory -Tcom.sun.star.lang.XSingleServiceFactory -Tcom.sun.star.registry.XRegistryKey $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 libRNG.so -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 libRNG.so and RNG.rdb files without any error. If not we have spare ones, _libRNG.so_ and _RNG.rdb_ :). Copy RNG.rdb and libRNG.so 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

UNO_TYPES=$ORIGIN/types.rdb $ORIGIN/RNG.rdb
UNO_SERVICES=$ORIGIN/services.rdb $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 what was there

[oobas] 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

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 : an other 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 Author: Serhat Sevki Dincer (C) 2006, jfcgaussATgmail. All rights reserved.

Personal tools