LibreOffice Calcのfodsファイルを読み書きするサンプルをweb API化してみた

これは [LibreOffice Advent Calendar 2021](https://adventar.org/calendars/6425) の11日目の記事です。

<!--
JRuby で ods ファイルを読み書きするサンプルを Sinatra で包んで web API 化してみる

odsファイルの読み書きをウェブAPI化してみる
-->

↓これにちょろっと付け足して web API 化してみただけの記事です。

<!--
JRubyでLibreOffice Calcのfodsファイルを読み書きするサンプル 2021 - Qiita
-->

https://qiita.com/sonota88/items/b88c89d763cf872db5a1


# できたもの

`webapi-2021` ブランチ

https://github.com/sonota88/libreoffice-jruby-sample/tree/webapi-2021


Java 版でやろうかと考えていたのですが、億劫になって JRuby 版でやりました。 JRuby で Sinatra 使った方が速い。

主な部分だけ抜き出すとこんな感じ。考えるのが面倒だったので REST ではなく RPC風で。普通に [Sinatra](http://sinatrarb.com/) を使ってるだけですね。あんまり書くことがない…… :sweat:


```ruby
# app.rb

require "sinatra"
require_relative "libo_calc"

post "/calc" do
  file = params["file"]
  sheet_name = params["sheet"]

  data = {}

  Calc.open(file) do |doc|
    sheet = doc.get_sheet_by_name(sheet_name)
    case params["command"]
    when "cell_get"
      data = cell_get(sheet, params)
    when "cell_set"
      cell_set(sheet, params)
      doc.save()
    when "dump"
      data = dump(sheet)
    else
      raise "unsupported command"
    end
  end

  content_type :json
  JSON.pretty_generate(data)
end
```


# 動かし方

イメージをビルド

```
docker build \
  --build-arg USER=$USER \
  --build-arg GROUP=$(id -gn) \
  -t my:libo-jruby-webapi-2021 .
```

APIサーバ起動

```
./docker_run.sh  ./jruby.sh app.rb -o 0.0.0.0
```

# curl で動作確認

ファイルのパス、シート名、コマンド、パラメータを POST で渡します。

```bash
curl -XPOST 'http://localhost:4567/calc' \
  -d 'file=./sample.fods' -d 'sheet=Sheet1' \
  -d 'command=cell_set' \
  -d 'col=0' -d 'row=2' -d "val=$(date "+%F_%T")"

#=>
{}

curl -XPOST 'http://localhost:4567/calc' \
  -d 'file=./sample.fods' -d 'sheet=Sheet1' \
  -d 'command=cell_get' \
  -d 'col=0' -d 'row=2'

#=>
{
  "val": "2021-12-11_11:03:20"
}

curl -XPOST 'http://localhost:4567/calc' \
  -d 'file=./sample.fods' -d 'sheet=Sheet1' \
  -d 'command=dump'

#=>
{
  "rows": [
    [
      "(0, 0) 日本語テキスト 2021-01-02 14:34:26 +0900",
      "b1"
    ],
    [
      "a2",
      "(1, 1) 2021-01-02 14:34:26 +0900"
    ],
    [
      "2021-12-11_11:03:20",
      "12.34"
    ],
    [
      "",
      "0"
    ]
  ]
}
```

読み書きできてます。



# Ruby + Faraday

適当な HTTP クライアントライブラリを使って試してみました。

```ruby
require "faraday"

puts "cell_set =>"
res = Faraday.post(
  "http://localhost:4567/calc",
  {
    file: "./sample.fods", sheet: "Sheet1",
    command: "cell_set",
    col: 0, row: 2, val: Time.now.to_s
  }
)

puts res.body

puts "cell_get =>"
res = Faraday.post(
  "http://localhost:4567/calc",
  {
    file: "./sample.fods", sheet: "Sheet1",
    command: "cell_get",
    col: 0, row: 2
  }
)

puts res.body

puts "dump =>"
res = Faraday.post(
  "http://localhost:4567/calc",
  {
    file: "./sample.fods", sheet: "Sheet1",
    command: "dump"
  }
)

puts res.body
```

```bash
$ bundle exec ruby sample_webapi_client.rb
cell_set =>
{
}
cell_get =>
{
  "val": "2021-12-11 11:09:49 +0900"
}
dump =>
{
  "rows": [
    [
      "(0, 0) 日本語テキスト 2021-01-02 14:34:26 +0900",
      "b1"
    ],
    [
      "a2",
      "(1, 1) 2021-01-02 14:34:26 +0900"
    ],
    [
      "2021-12-11 11:09:49 +0900",
      "12.34"
    ],
    [
      "",
      "0"
    ]
  ]
}
```

大丈夫ですね。普通ですね。

----

というわけで、任意の HTTP クライアントからセルの読み書きができるようになりました。この記事は以上です。