Rust-Bibliothek für Office — Schnellstart
office_oxide ist eine reine Rust-Crate zum Parsen, Konvertieren und Bearbeiten von Office-Dokumenten: DOCX, XLSX, PPTX sowie deren binäre Vorgänger DOC, XLS und PPT. Eine Crate, ein einheitliches Document-Handle, keine nativen Abhängigkeiten.
Installation
[dependencies]
office_oxide = "0.1.0"
Optionale Features:
office_oxide = { version = "0.1.0", features = ["mmap"] } # mmap-Öffnen großer OOXML-Dateien
office_oxide = { version = "0.1.0", features = ["parallel"] } # Hilfsmittel für paralleles Parsen via rayon
Ein Dokument lesen
use office_oxide::Document;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = Document::open("report.docx")?;
println!("{}", doc.plain_text());
Ok(())
}
Oder der Einzelaufruf-Helfer:
let text = office_oxide::extract_text("report.docx")?;
Kern-API
Das Document-Handle verhält sich für alle Formate gleich — Erkennung über die Erweiterung plus Verifizierung per Magic-Bytes.
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(); // formatunabhängige IR
doc.save_as("file.docx")?; // legacy → OOXML klappt auch
Document::open nimmt AsRef<Path>, Document::from_reader braucht Read + Seek + Send + 'static und ein explizites DocumentFormat.
Modul-Shortcuts:
let text = office_oxide::extract_text("file.docx")?;
let md = office_oxide::to_markdown("file.pptx")?;
let html = office_oxide::to_html("file.xlsx")?;
Formatspezifischer Zugriff
Wenn du formatspezifische Daten brauchst — Tabellenblätter, Folien, Tabellenzellen — pack das innere Dokument aus:
if let Some(xlsx) = doc.as_xlsx() {
for sheet in xlsx.sheets() {
println!("sheet: {}", sheet.name());
}
}
Das gleiche Muster gilt für as_docx, as_pptx, as_doc, as_xls, as_ppt.
Bearbeiten
EditableDocument macht read-modify-write und bewahrt dabei alle unveränderten OPC-Teile (Bilder, Diagramme, Stile, Beziehungen). Unterstützt sind nur DOCX, XLSX und PPTX.
use office_oxide::edit::EditableDocument;
let mut doc = EditableDocument::open("template.docx")?;
let n = doc.replace_text("{{name}}", "Alice");
println!("{n} Ersetzungen");
doc.save("out.docx")?;
replace_text läuft in DOCX über <w:t>-Elemente und in PPTX über <a:t>. Es liefert die Zahl der Ersetzungen (für XLSX 0 — dort set_cell benutzen).
XLSX-Zellen setzen
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")?;
Sheet-Indizes sind nullbasiert; Zellreferenzen folgen der Standard-Notation (A1, AA12).
Formatunabhängige IR
DocumentIR ist die strukturelle Brücke zwischen Formaten — sie trägt to_html, save_as und die Legacy-Konvertierung. Sie implementiert Serialize / Deserialize, also kannst du JSON für nachgelagertes Tooling rausschreiben.
let legacy = Document::open("old.doc")?;
legacy.save_as("migrated.docx")?; // CFB → OOXML in einer Zeile
Aus Bytes öffnen
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)?;
Memory-mapped Öffnen
Mit dem Feature mmap kopiert Document::open_mmap große OOXML-Dateien nicht in den Heap:
let doc = Document::open_mmap("huge.xlsx")?;
mmap funktioniert nur für DOCX/XLSX/PPTX; die Legacy-CFB-Parser brauchen Owned-Buffer.
Fehler
Alle fehlbaren Einstiegspunkte liefern office_oxide::Result<T>, also Result<T, OfficeError>. Das Enum deckt IO, Parsing, nicht unterstützte Formate und Extraktionsfehler ab.
use office_oxide::{Document, OfficeError};
match Document::open("weird.file") {
Ok(doc) => println!("{}", doc.plain_text()),
Err(OfficeError::UnsupportedFormat(ext)) => eprintln!(".{ext} kann nicht geöffnet werden"),
Err(e) => eprintln!("fehlgeschlagen: {e}"),
}
Fehlersuche
| Symptom | Wahrscheinliche Ursache |
|---|---|
UnsupportedFormat("(none)") |
Pfad ohne Erweiterung — über from_reader mit explizitem DocumentFormat öffnen. |
| Wirrer DOC-Text | Datei evtl. verschlüsselt oder mit ungewöhnlicher Piece-Table-Kodierung. CFB-Magic D0 CF 11 E0 prüfen. |
| Fehlende Hyperlinks im DOCX | Hyperlinks werden über w:rels aufgelöst. Sieh nach, ob die .rels-Datei im ZIP steckt. |
| Stack-Overflow auf kleinen Stack-Threads | office_oxide startet einen 16-MB-Parsing-Thread, wenn RLIMIT_STACK < 12 MB. In eigenen Pools mit Builder::stack_size(16 * 1024 * 1024) arbeiten. |
Siehe auch
- Python-Schnellstart — dieselbe API in Python
- Performance-Benchmarks — vollständige Zahlen über 6.062 Dateien
- Architektur: ARCHITECTURE.md
- Crate auf crates.io, Docs auf docs.rs