Rust Office ライブラリ — クイックスタート
office_oxide は Office ドキュメント(DOCX、XLSX、PPTX、およびレガシーバイナリ形式 DOC、XLS、PPT)の解析・変換・編集を行う純粋 Rust 製クレートです。1 つのクレート、統一された Document ハンドル、ネイティブ依存ゼロ。
インストール
[dependencies]
office_oxide = "0.1.0"
オプションフィーチャ:
office_oxide = { version = "0.1.0", features = ["mmap"] } # 大きな OOXML 用に mmap オープン
office_oxide = { version = "0.1.0", features = ["parallel"] } # rayon ベースの並列パース
ドキュメントを読む
use office_oxide::Document;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = Document::open("report.docx")?;
println!("{}", doc.plain_text());
Ok(())
}
ワンショットヘルパー:
let text = office_oxide::extract_text("report.docx")?;
コア API
Document ハンドルはどのフォーマットでも同じ使い方です。拡張子検出に加えてマジックバイトでも検証されます。
use office_oxide::{Document, DocumentFormat};
let doc = Document::open("file.xlsx")?;
assert_eq!(doc.format(), DocumentFormat::Xlsx);
let plain = doc.plain_text();
let md = doc.to_markdown();
let html = doc.to_html();
let ir = doc.to_ir(); // フォーマット非依存の IR
doc.save_as("file.docx")?; // legacy → OOXML も可能
Document::open は AsRef<Path>、Document::from_reader は明示的な DocumentFormat を伴う Read + Seek + Send + 'static を受け付けます。
モジュールレベルの便利関数:
let text = office_oxide::extract_text("file.docx")?;
let md = office_oxide::to_markdown("file.pptx")?;
let html = office_oxide::to_html("file.xlsx")?;
フォーマット固有のアクセス
シート、スライド、テーブルセルなど、フォーマット固有の情報が必要なときは内部ドキュメントをアンラップします:
if let Some(xlsx) = doc.as_xlsx() {
for sheet in xlsx.sheets() {
println!("sheet: {}", sheet.name());
}
}
as_docx、as_pptx、as_doc、as_xls、as_ppt も同じパターンです。
編集
EditableDocument は read-modify-write を実行し、変更されていない OPC パーツ(画像、グラフ、スタイル、リレーションシップ)をすべて温存します。編集対象は DOCX、XLSX、PPTX のみ。
use office_oxide::edit::EditableDocument;
let mut doc = EditableDocument::open("template.docx")?;
let n = doc.replace_text("{{name}}", "Alice");
println!("{n} 件置換");
doc.save("out.docx")?;
replace_text は DOCX の <w:t> 要素と PPTX の <a:t> 要素を走査し、置換件数を返します(XLSX では 0 — 代わりに set_cell を使用)。
XLSX セルの設定
use office_oxide::edit::EditableDocument;
use office_oxide::xlsx::edit::CellValue;
let mut wb = EditableDocument::open("budget.xlsx")?;
wb.set_cell(0, "B2", CellValue::Number(42.0))?;
wb.set_cell(0, "A1", CellValue::String("Total".into()))?;
wb.set_cell(0, "C1", CellValue::Boolean(true))?;
wb.set_cell(0, "D1", CellValue::Empty)?;
wb.save("budget.xlsx")?;
シートインデックスは 0 始まり、セル参照は標準的な表計算記法(A1、AA12)です。
フォーマット非依存の IR
DocumentIR はフォーマット間の構造的なブリッジで、to_html、save_as、レガシー → OOXML 変換を支えます。Serialize / Deserialize を実装しているので JSON として出力できます。
let legacy = Document::open("old.doc")?;
legacy.save_as("migrated.docx")?; // CFB → OOXML を 1 行で
バイト列から開く
use std::io::Cursor;
use office_oxide::{Document, DocumentFormat};
let bytes = std::fs::read("file.pptx")?;
let doc = Document::from_reader(Cursor::new(bytes), DocumentFormat::Pptx)?;
メモリマップオープン
mmap フィーチャを有効にすると、Document::open_mmap で大きな OOXML ファイルをヒープにコピーせずに開けます:
let doc = Document::open_mmap("huge.xlsx")?;
mmap 可能なのは DOCX/XLSX/PPTX のみで、レガシー CFB パーサは所有バッファが必要です。
エラー
すべてのエラーパスは office_oxide::Result<T>、つまり Result<T, OfficeError> を返します。エラー列挙型は IO、パース、未対応フォーマット、抽出失敗をカバーします。
use office_oxide::{Document, OfficeError};
match Document::open("weird.file") {
Ok(doc) => println!("{}", doc.plain_text()),
Err(OfficeError::UnsupportedFormat(ext)) => eprintln!(".{ext} は開けません"),
Err(e) => eprintln!("失敗: {e}"),
}
トラブルシューティング
| 症状 | 原因 |
|---|---|
UnsupportedFormat("(none)") |
パスに拡張子なし — from_reader で明示的な DocumentFormat を指定。 |
| DOC のテキストが文字化け | 暗号化や珍しい piece-table エンコーディングの可能性。CFB マジック D0 CF 11 E0 を確認。 |
| DOCX のハイパーリンク欠落 | ハイパーリンクは w:rels 経由で解決されます。.rels サイドカーが ZIP 内にあるか確認。 |
| 小さなスタックスレッドでスタックオーバーフロー | office_oxide は RLIMIT_STACK < 12 MB のとき 16 MB のパーススレッドを生成します。独自のスレッドプールでは Builder::stack_size(16 * 1024 * 1024) を指定してください。 |
関連項目
- Python クイックスタート — 同じ API を Python で
- パフォーマンスベンチマーク — 6,062 ファイルの全数値
- アーキテクチャ: ARCHITECTURE.md
- クレート: crates.io、ドキュメント: docs.rs