JavaでLibreOffice Calcのfodsファイルを読み書きするサンプル 2019

5年前に JavaScript で書いたもの を大体そのまま Java に書き直しただけです。 例外のハンドリングは適当です。 今では推奨されない古い書き方が残ってたりするかもしれません。

sonota88/libreoffice-java-sample at 20191202
https://github.com/sonota88/libreoffice-java-sample/tree/20191202

処理の内容的には fods ファイルを開いてセルの内容の最低限の読み書きするというもの。


以下は今回調べたりしたことのメモです。 開発環境は Ubuntu 18.04。

jar の設定を pom.xml に書く

Java から LibreOfficeAPI を使う場合、 SDK をインストールして、それに付いてくる jar を使う、というのが普通のやり方だったと思います。たしか。

Eclipse の場合は

  • プロジェクトのプロパティ
  • Java Build Path>「Libraries」タブ>Add External JARs...

から追加します。 ここで jar を追加すると、プロジェクトの .classpath ファイルに

<classpathentry kind="lib" path="/usr/lib/libreoffice/program/classes/juh.jar"/>

このような設定が追加されます。

これだと Eclipse 用の設定になってしまうので、 pom.xml に書けないんだっけと思って調べたところ、 下記のように system スコープで dependency を書けばよいようでした。 (groupId, artifactId、バージョンは適当です)

<dependency>
  <groupId>juh-g</groupId>
  <artifactId>juh-a</artifactId>
  <version>0.0.1</version>
  <scope>system</scope>
  <systemPath>/usr/lib/libreoffice/program/classes/juh.jar</systemPath>
</dependency>

参考:

ただ、 jar はこれでいけるんですが、共有ライブラリ libjpipe.sopom.xml で設定できるか分からず、これだけ Eclipse 側で設定しました。 (Eclipse 上でユニットテストなどで実行するときに必要で、プログラム書いてコンパイルするだけなら不要っぽいです)

関連:
(solved) Exception in thread "main" java.lang.UnsatisfiedLinkError: no jpipe in java.library.path - memo88
https://memo88.hatenablog.com/entry/20140723/1406123992

Ubuntu 18.04 でのパッケージまわりのメモ

libreoffice-java-common ... unoil を含む
libreoffice-common ... ure に依存
ure ... juh, jurt, ridl, jpipe を含む

dpkg や apt-cache コマンドで調べられます:

パッケージに含まれるファイル一覧
dpkg -L {パッケージ名}

パッケージの依存関係
apt-cache depends {パッケージ名}
apt-cache rdepends {パッケージ名}

ところで libreoffice-dev というパッケージもありますがこれって何でしたっけ?

$ apt-cache depends libreoffice-dev           
libreoffice-dev
  Depends: libreoffice-core
  Depends: libreoffice-dev-common
  Depends: ucpp
  Depends: libc6
  Depends: libgcc1
  Depends: libstdc++6
  Depends: libx11-6
  Depends: uno-libs3
  Depends: ure
  Conflicts: libreoffice
  Conflicts: libreoffice-dev-doc
  Breaks: libreoffice-dev-common
  Recommends: g++
  Recommends: libreoffice-java-common
 |Recommends: default-jre
 |Recommends: <sun-java6-jre>
 |Recommends: <java6-runtime>
    default-jre
    openjdk-11-jre
    openjdk-8-jre
  Recommends: <jre>
  Suggests: libmythes-dev
  Suggests: libreoffice-dev-doc
  Suggests: libreofficekit-dev
  Replaces: libreoffice-dev-common

なるほど。パッケージの説明は

office productivity suite -- SDK -- architecture-dependent parts

となっています。

Mavenリポジトリにある jar を使う

共有ライブラリ libjpipe.so を除くと、他は jar を使っているだけといえばだけです(たぶん)。それなら、ひょっとして Mavenリポジトリから取ってきて普通の Maven プロジェクトっぽくできたりしないでしょうか?

探したら Maven のセントラルリポジトリにありました。

"org.libreoffice" の検索結果:
https://search.maven.org/search?q=org.libreoffice

これを使えば、 libreoffice-java-common をインストールしなくても必要な jar を Maven の流儀に従って使えばよく、より普通の Maven プロジェクトっぽく扱えて嬉しいような。

pom.xml に普通にこんな感じで書けばよいと。普通ですね。いいですね。

    <dependency>
      <groupId>org.libreoffice</groupId>
      <artifactId>ridl</artifactId>
      <version>6.3.2</version>
    </dependency>

ふむふむ、いいじゃない、となったのですが、 この方法だと 5年前のこれと同じところで引っかかるのです……。

(solved) com.sun.star.comp.helper.BootstrapException: no office executable found! - memo88
https://memo88.hatenablog.com/entry/20140721/1405966864

上記の記事から5年経ちましたが、 Bootstrap クラスが含まれている juh.jar の位置を起点にして実行ファイル soffice を探す部分は変わっていないようで、 今回のサンプルでは Mavenリポジトリを利用する方向は見送りました。

Maven でライブラリ取ってくると ~/.m2/ 以下に jar が入ったり、 fat jar 作ったらその中に入ったりするので、そこから相対パスで探しても soffice が見つけられないんですよね……。

本体のコード(Bootstrap.java) を借用&修正して使っても動きましたが、その場合は公開の際に本体のライセンスに従う必要があるでしょう。

Docker コンテナで実行する

先日 LibreOffice 本体だけ Docker で動かすメモ を書きましたが、 ついでに SDK もイメージに入れておけば便利かも? と思いついて、これも試してみました。

以下の3つのパッケージを入れておけば今回のサンプルは動きました。

  • libreoffice-calc
  • libreoffice-java-common
  • openjdk-8-jre

あとはコンテナ内で

java -cp "{ライブラリのパス}:{ビルドしたjarのパス}" \
  sample.Main {残りの引数}

で実行できます。 詳しくはリポジトリに入っているスクリプト run.shDockerfile を見てください。