jrunscript/RhinoでLibreOffice Calcのセルの読み書き(ついでにxls,xlsxも)

(追記)2019年末にこういうのも書きました。あわせてどうぞ。

memo88.hatenablog.com


WSH を使った Excelファイルの読み書きのように、「Java が入っていれば JavaScript をササッと書いて自動化できる!」みたいなお手軽環境があるといいなあと思ってやってみました。
あんまりドッグフーディングしてなくてサンプルというかデモ程度です。

必要なファイルは gist に置きました:
https://gist.github.com/sonota88/4b2232e8aa0fb25c76a9

準備

  1. LibreOffice をインストール … LibreOffice_4.2.5_Win_x86.msi
  2. LibreOffice SDK をインストール … LibreOffice_4.2.5_Win_x86_sdk.msi
  3. Java 7 をインストール … Pleiades のがすでに入っていたのでそれを使用

OS は Windows 7 64bit。

サンプルスクリプト

スクリプトとして手軽に使いたいので、UNOまわりとかの面倒なところは libo_calc.js に押し込めています。

sample.js:

// ライブラリをロード
load("libo_calc.js");
 
Calc.open(
    "C:/Users/user/foo/bar/sample.ods",
    function(doc){

    // シートの一覧を取得
    var sheets = doc.getSheets();
    // シートをイテレート
    sheets.forEach(function(sheet, i){
        puts("----------------");
        puts(i + ": " + sheet.name);
        // col, row / 文字列でセルの内容を取得
        puts("(0, 0) => " + sheet.get(0, 0));
        // セルに文字列をセット
        sheet.set(0, 0, "(0, 0) 日本語テキスト " + new Date());
        puts("(0, 0) => " + sheet.get(0, 0));
    });

    // 名前でシートを取得
    var sheet = doc.getSheetByName("Sheet1");

    puts("----------------");
    puts("(1, 1) => " + sheet.get(1, 1));
    sheet.set(1, 1, "(1, 1) " + new Date());
    puts("(1, 1) => " + sheet.get(1, 1));

    puts("----------------");
    sheet.set(1, 2, "12.34");
    // 整数として取得
    puts("getInt => " + sheet.getInt(1, 2));
    // 浮動小数として取得
    puts("getFloat => " + sheet.getFloat(1, 2));

    puts("----------------");
    var count = sheet.getInt(1, 3);
    if(isNaN(count)){
      count = 0;
    }
    sheet.set(1, 3, count + 1);
    puts("count => " + sheet.get(1, 3));

    // 上書き保存
    doc.save();
});

実行

  • libo_calc.js
  • libo_calc.bat
  • sample.js

を同じフォルダに置いて

libo_calc.bat sample.js

のように実行します。

あとはここらへんと合わせたりしていろいろできますね。

xls, xlsx でも同じように読み書きできる

当然といえば当然ですが xls, xlsx ファイルのパスを渡してやれば同じように操作できます。
(やっていることは LibreOffice 起動 → ファイル開く → セルの読み書き → 上書き保存 なので)

その他

ほんとは jjs/Nashorn(Java 8)で動かすとこまでやりたかったんですが、型絡みでエラーが出て時間がかかりそうだったので今回は見送り……。

Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodException: None of the fixed arity signatures [(com.sun.star.uno.Type, java.lang.Object), (java.lang.Class, java.lang.Object)] of method com.sun.star.uno.UnoRuntime.queryInterface match the argument types [jdk.internal.dynalink.beans.StaticClass, com.sun.proxy.$Proxy0]
        at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:382)
        at jdk.nashorn.tools.Shell.apply(Shell.java:381)
        at jdk.nashorn.tools.Shell.runScripts(Shell.java:310)
        at jdk.nashorn.tools.Shell.run(Shell.java:166)
        at jdk.nashorn.tools.Shell.main(Shell.java:130)
        at jdk.nashorn.tools.Shell.main(Shell.java:109)
Caused by: java.lang.NoSuchMethodException: None of the fixed arity signatures [(com.sun.star.uno.Type, java.lang.Object), (java.lang.Class, java.lang.Object)] of method com.sun.star.uno.UnoRuntime.queryInterface match the argument types [jdk.internal.dynalink.beans.StaticClass, com.sun.proxy.$Proxy0]
        at jdk.internal.dynalink.beans.OverloadedMethod.throwNoSuchMethod(OverloadedMethod.java:199)
        at jdk.nashorn.internal.scripts.Script$libo_calc._L44$_L48(libo_calc.js:73)
        at jdk.nashorn.internal.scripts.Script$sample_8.runScript(sample_8.js:4)
        at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:498)
        at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:206)
        at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
        ... 5 more

Linux での動作確認

追記 2014-07-28

Ubuntu Linux 14.04 64bit でも動くことを確認しました。
gist に libo_calc.sh を追加しました。

動かす前に次の2つのパッケージをインストールしました。