【Rust】RustでExcelを操作したかった話

2022/07/23に公開

~前置き~

RustでExcel操作したい!

これまでPythonopenpyxl
C#ClosedXMLなどでExcelの操作をすることはあったのですが、
こういうのRustでもできんかな~と調べていました。

ちょっと前に調べたときは
windows-rsとかwinapiを使う記事が上の方に出てきて
「ちょっとハードル高いなぁ……」と思っていたのですが、
最近調べるともっと簡単に操作できそうな
calamineクレートというのが見つかったので早速使ってみました。

~前置き終わり~

calamineのdocs.rs
https://docs.rs/calamine/latest/calamine/

こっちはGithub
https://github.com/tafia/calamine

Rustを勉強してると大体英語のリファレンスとか記事なんですよね……。
禁断症状が出そうです……。

使ってみた

前準備としてCargo.toml[dependencies]に以下を記述します。
以下は7月下旬ごろのバージョンです。
この記事を読んだ時期によってはバージョンが変わっていて、
calamineの記述方法も変わってると思うので注意してください。

[dependencies]
calamine = "0.18.0"

今回は読み込みだけです。
書き込みは……気が向いた時にやりますゆるして()

Excelブックの読み込み

ブックの読み込みは以下のように書きます。

use calamine::{open_workbook, Reader, Xlsx}; 

fn main() {
    let xl_book_path = "Your Excel Book Path .xlsx";
    let mut wb: Xlsx<_> = open_workbook(xl_book_path).expect("cannot open xl book");
}

めっちゃかんたーん!

シートの読み込み

ここは公式の書き方に習っています。
なんかもう少しうまい書き方があるような気がしますが
試す時間がなかったのでそのままで。

(シートの読み込みというよりかは、指定したシートのRange情報とってきてるのかも……?)

if let Some(Ok(range)) = wb.worksheet_range("sheet name") {
    [処理]
}

セルの値を取得する

openpyxlとかClosedXMLに比べるとちょっと違う書き方をしていますが、
まぁ、わからんでもないなという感じです。

if let Some(Ok(range)) = wb.worksheet_range("sheet name") {
    let cell_value = range.get_value((row, column)).unwrap();
}

get_valueの後に2つ括弧があることに注意してください。

ちなみにrowcolumnの部分に変数を使用する場合は
u32じゃないとダメみたいです。
for文とかでぶん回してその値をそのまま渡したりすると
「それはusizeだるるぉ?」って怒られます……。
なのでちゃんとas u32って書いて変換しておきましょう。

if let Some(Ok(range)) = wb.worksheet_range("sheet name") {

    for row in 0..10{
        let cell_value = range.get_value((row as u32, 1)).unwrap();
    }
}

最大行と最大列の取得

get_sizeを使うだけです。
インデックス0に行、1に列が入っています。

if let Some(Ok(range)) = wb.worksheet_range("sheet name") {
    let max_row = range.get_size().0;
    let max_column = range.get_size().1;
}

ここはusizeで出てきます。
u32じゃないのね~。

終わりに

今回書いた内容で一通り簡単な読み込みはできるかな~と思います。
ちょっと特殊な事しようと思うとまた変わってくるかもです。
(VBAプロジェクト読み込む……とか)

Discussion