# Beispiel zur Automatisierung von Open Office Scalc Spreadsheets mit Java via UNO



## Thomas Darimont (1. Juli 2008)

Hallo,

hier mal ein kleines Beispiel für die einfache Automatisierung von Open Office scalc Spreadsheets mit Java via UNO.
Als Open Office Version verwende ich hier: 2.4.0

```
/**
 * 
 */
package de.tutorials;

import com.sun.star.beans.PropertyValue;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.container.XEnumeration;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.lang.EventObject;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XEventListener;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.sheet.CellFlags;
import com.sun.star.sheet.XCellRangesQuery;
import com.sun.star.sheet.XSheetCellRanges;
import com.sun.star.sheet.XSpreadsheet;
import com.sun.star.sheet.XSpreadsheetDocument;
import com.sun.star.table.XCell;
import com.sun.star.uno.AnyConverter;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;

/**
 * @author Thomas.Darimont
 * 
 */
public class OOExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        final XComponentContext componentContext = Bootstrap.bootstrap();
        XMultiComponentFactory multiComponentFactory = componentContext
                .getServiceManager();

        XComponentLoader componentLoader = convert(multiComponentFactory
                .createInstanceWithContext("com.sun.star.frame.Desktop",
                        componentContext));

        final XComponent component = componentLoader.loadComponentFromURL(
                "private:factory/scalc", "_blank", 0, new PropertyValue[0]);

        XSpreadsheetDocument spreadsheetDocument = convert(component);

        XSpreadsheet spreadsheet = convert(spreadsheetDocument
                .getSheets()
                .getByName(spreadsheetDocument.getSheets().getElementNames()[0]));

        XCell cell = spreadsheet.getCellByPosition(0, 0);
        cell.setValue(1);
        cell = spreadsheet.getCellByPosition(0, 1);
        cell.setValue(2);
        cell = spreadsheet.getCellByPosition(0, 2);
        cell.setFormula("=sum(A1:A2)");

        XCellRangesQuery cellRangesQuery = convert(spreadsheet);
        XSheetCellRanges sheetCellRanges = cellRangesQuery
                .queryContentCells((short) CellFlags.VALUE);
        XEnumeration cellEnumeration = sheetCellRanges.getCells()
                .createEnumeration();
        while (cellEnumeration.hasMoreElements()) {
            Object element = cellEnumeration.nextElement();
            System.out.println(element);
            XCell currentCell = convertAny(element);
            System.out.println(currentCell.getValue());
        }

        component.addEventListener(new XEventListener() {
            @Override
            public void disposing(EventObject eventObject) {
                System.out.println("Closing...");
                System.exit(0);
            }
        });

    }

    @SuppressWarnings("unchecked")
    public static <TTarget> TTarget convert(Object instance, TTarget... args) {
        return (TTarget) UnoRuntime.queryInterface(args.getClass()
                .getComponentType(), instance);
    }

    @SuppressWarnings("unchecked")
    public static <TTarget> TTarget convertAny(Object instance, TTarget... args) {
        try {
            return (TTarget) AnyConverter.toObject(args.getClass()
                    .getComponentType(), instance);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        return null;
    }

}
```

Ausgabe:

```
Any[Type[com.sun.star.table.XCell], [Proxy:3195425,7d81688;msci[0];9eb8c73d1d5749528db88bd98c4e3d1c,Type[com.sun.star.table.XCell]]]
1.0
Any[Type[com.sun.star.table.XCell], [Proxy:18426253,7aff978;msci[0];9eb8c73d1d5749528db88bd98c4e3d1c,Type[com.sun.star.table.XCell]]]
2.0
Closing...
```

Mit ein wenig Java 5 magic ersparen wir uns das lässtige Casten, dass man in den ganzen OO Tutorials findet...

Anstatt

```
XSpreadsheetDocument xSpreadsheetDocument = (XSpreadsheetDocument)UnoRuntime.queryInterface(XSpreadsheetDocument.class, xSpreadsheetComponent);
```

Schreiben wir nur noch:

```
XSpreadsheetDocument spreadsheetDocument = convert(component);
```

Das vereinfacht das ganze erheblich und macht den Code IMHO viel lesbarer!


```
@SuppressWarnings("unchecked")
    public static <TTarget> TTarget convert(Object instance, TTarget... args) {
        return (TTarget) UnoRuntime.queryInterface(args.getClass()
                .getComponentType(), instance);
    }
```

Ergibt folgendes Dokument:


Gruß Tom


----------



## Kylex (21. Januar 2010)

Hallo Thomas,

entschuldige, dass ich den alten Thread hier rausgrabe aber ich konnte leider keine Antwort über Google finden und ein wirkliches "Thema" konnte ich nicht finden, was als sinnvoller Titel gedient hätte.

Ich bin sehr fasziniert von deiner convert-Funktion und würde sie auch gerne für meine Entwicklung mit OO nutzen, jedoch würde ich sie vorher noch besser verstehen. Der Knackpunkt ist, dass ich nicht verstehe wie der zweite Parameter übergeben wird und wie die Syntax dabei genau ist.

convert(Object instance, TTarget... args)

Beim Funktionsaufruf verwendest du lediglich einen Parameter, welcher dann in der Funktion mit instance angepsprochen werden kann. Der zweite Parameter ist allerdings anscheinend der Typ , in welchen schluss endlich gecastet werden soll. Ich verstehe nicht wie er übergeben wird und leider konnte ich auch keinen Anhaltspunkt finden wie diese Art Parameterübergabe heißt und wo sie dokumentiert ist. Welche Technik wird dabei verwendet? Ich  bin die Änderungen zu Java 1.5 im einzelnen durchgegangen und dort ist diese Art der Parameterübergabe nicht erwähnt.

Ein entsprechender Link zu dieser Technik oder auch nur ein Stichwort wie diese Technik genannt wird reicht mir schon.

Gruß,
Kylex


----------



## deepthroat (21. Januar 2010)

Hi.

Das ganze nennt sich "variadische" Funktionen (siehe z.B. http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.23.2C_VB.net.2C_and_Java) oder auch einfach varargs (http://java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html)

Hinzu kommen generische Methoden, Typinferenz und etwas Reflection.

Gruß


----------



## Thomas Darimont (3. März 2012)

Hallo,

das Beispiel funktioniert auch noch mit Open Office 3.3.

Um das Beispiel ausführen zu können benötigt man folgende Jars / Verzeichnisse im Classpath:
- C:\Program Files (x86)\OpenOffice.org 3\program
- C:\Program Files (x86)\OpenOffice.org 3\URE\java\juh.jar
- C:\Program Files (x86)\OpenOffice.org 3\URE\java\ridl.jar
- C:\Program Files (x86)\OpenOffice.org 3\URE\java\jurt.jar
- C:\Program Files (x86)\OpenOffice.org 3\Basis\program\classes\unoil.jar

Achtung: Open Office 3.3 (und auch frühere Versionen) ist ein 32-Bit Programm welches mit der UNO API so leider auch nur von einer 32-Bit Java VM automatisiert werden kann!

Gruß Tom


----------

