Biblioteca Office para Rust — Início Rápido
office_oxide é uma crate em Rust puro para analisar, converter e editar documentos do Office: DOCX, XLSX, PPTX, mais os predecessores binários DOC, XLS e PPT. Uma única crate, um handle Document unificado, zero dependências nativas.
Instalação
[dependencies]
office_oxide = "0.1.0"
Features opcionais:
office_oxide = { version = "0.1.0", features = ["mmap"] } # abertura via mmap para OOXML grandes
office_oxide = { version = "0.1.0", features = ["parallel"] } # auxiliares de parsing paralelo via rayon
Ler um documento
use office_oxide::Document;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = Document::open("report.docx")?;
println!("{}", doc.plain_text());
Ok(())
}
Ou o helper de uma só chamada:
let text = office_oxide::extract_text("report.docx")?;
API principal
O handle Document se comporta igual em todos os formatos — detecção pela extensão mais verificação por 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(); // IR independente de formato
doc.save_as("file.docx")?; // legado → OOXML também
Document::open aceita AsRef<Path>; Document::from_reader recebe Read + Seek + Send + 'static mais um DocumentFormat explícito.
Atalhos no nível do módulo:
let text = office_oxide::extract_text("file.docx")?;
let md = office_oxide::to_markdown("file.pptx")?;
let html = office_oxide::to_html("file.xlsx")?;
Acesso por formato
Quando precisar de dados específicos do formato — planilhas, slides, células de tabela — desempacote o documento interno:
if let Some(xlsx) = doc.as_xlsx() {
for sheet in xlsx.sheets() {
println!("sheet: {}", sheet.name());
}
}
as_docx, as_pptx, as_doc, as_xls e as_ppt seguem o mesmo padrão.
Edição
EditableDocument faz read-modify-write preservando todas as partes OPC inalteradas (imagens, gráficos, estilos, relações). Suportado apenas em DOCX, XLSX e PPTX.
use office_oxide::edit::EditableDocument;
let mut doc = EditableDocument::open("template.docx")?;
let n = doc.replace_text("{{name}}", "Alice");
println!("{n} substituições");
doc.save("out.docx")?;
replace_text percorre <w:t> em DOCX e <a:t> em PPTX, devolvendo a quantidade de substituições (XLSX devolve 0 — use set_cell).
Definir células 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")?;
Índices de planilha começam em zero; referências de célula seguem a notação padrão (A1, AA12).
IR independente de formato
DocumentIR é a ponte estrutural entre formatos — sustenta to_html, save_as e a conversão de formatos legados. Implementa Serialize / Deserialize, então pode emitir JSON.
let legacy = Document::open("old.doc")?;
legacy.save_as("migrated.docx")?; // CFB → OOXML em uma linha
Abrir a partir de bytes
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)?;
Abertura via memory map
Com a feature mmap, Document::open_mmap evita copiar arquivos OOXML grandes para a heap:
let doc = Document::open_mmap("huge.xlsx")?;
Apenas DOCX/XLSX/PPTX podem ser mmap-eados; os parsers CFB legados precisam de buffers próprios.
Erros
Toda chamada falível devolve office_oxide::Result<T> — isto é, Result<T, OfficeError>. O enum cobre IO, parsing, formato não suportado e falhas de extração.
use office_oxide::{Document, OfficeError};
match Document::open("weird.file") {
Ok(doc) => println!("{}", doc.plain_text()),
Err(OfficeError::UnsupportedFormat(ext)) => eprintln!("não foi possível abrir .{ext}"),
Err(e) => eprintln!("falhou: {e}"),
}
Solução de problemas
| Sintoma | Causa provável |
|---|---|
UnsupportedFormat("(none)") |
Caminho sem extensão — abra via from_reader informando DocumentFormat. |
| Texto DOC ilegível | Arquivo pode estar criptografado ou usar piece-table incomum. Verifique o magic CFB D0 CF 11 E0. |
| Hyperlinks ausentes em DOCX | Hyperlinks são resolvidos via w:rels. Confira se o .rels está presente no ZIP. |
| Stack overflow em threads de stack pequena | office_oxide cria uma thread de parsing de 16 MB quando RLIMIT_STACK < 12 MB. Em pools próprios, defina Builder::stack_size(16 * 1024 * 1024). |
Veja também
- Início rápido em Python — a mesma API em Python
- Benchmarks de performance — números completos sobre 6.062 arquivos
- Arquitetura: ARCHITECTURE.md
- Crate em crates.io, docs em docs.rs