Biblioteca Office para C# / .NET — Início Rápido
OfficeOxide é o binding .NET para a biblioteca Rust office_oxide. Dá às aplicações .NET parsing, conversão e edição rápidos e econômicos em alocações para DOCX / XLSX / PPTX / DOC / XLS / PPT — por baixo, P/Invoke LibraryImport compatível com AOT.
Instalação
dotnet add package OfficeOxide --version 0.1.0
Requer .NET 8 ou .NET 10. O pacote NuGet entrega bibliotecas nativas pré-compiladas para win-x64, linux-x64, linux-arm64, osx-x64, osx-arm64 em runtimes/<rid>/native/. O dotnet publish coloca a correta ao lado do seu binário automaticamente.
Ler um documento
using OfficeOxide;
using var doc = Document.Open("report.docx");
Console.WriteLine(doc.PlainText());
API principal
Document é o handle somente-leitura; faça dispose (de preferência via using) para liberar a memória nativa.
using OfficeOxide;
using var doc = Document.Open("file.xlsx");
Console.WriteLine(doc.Format); // "xlsx"
Console.WriteLine(doc.PlainText());
Console.WriteLine(doc.ToMarkdown());
Console.WriteLine(doc.ToHtml());
Console.WriteLine(doc.ToIrJson());
doc.SaveAs("file.docx"); // formato-alvo inferido pela extensão
Wrapper assíncrono para IO bloqueante:
using var doc = await Document.OpenAsync("huge.pptx", ct);
Abrir a partir de bytes (sem arquivo temporário):
byte[] data = File.ReadAllBytes("report.docx");
using var doc = Document.FromBytes(data, "docx");
format precisa ser "docx", "xlsx", "pptx", "doc", "xls" ou "ppt".
Helpers estáticos para chamadas de uma vez:
string text = OfficeOxide.ExtractText("file.docx");
string md = OfficeOxide.ToMarkdown("file.pptx");
string html = OfficeOxide.ToHtml("file.xlsx");
string? fmt = Document.DetectFormat("mystery.bin"); // null se não suportado
Console.WriteLine(Document.Version); // "0.1.0"
Edição
A edição preserva todas as partes OPC inalteradas (imagens, gráficos, relações) ao salvar. Apenas DOCX, XLSX e PPTX.
using OfficeOxide;
using var ed = EditableDocument.Open("template.docx");
long n = ed.ReplaceText("{{name}}", "Alice");
Console.WriteLine($"{n} substituições");
ed.Save("out.docx");
ReplaceText devolve a quantidade de substituições (0 em XLSX — use SetCell).
Substituir texto em DOCX / PPTX
using var ed = EditableDocument.Open("slides.pptx");
ed.ReplaceText("Q3", "Q4");
ed.ReplaceText("2024", "2025");
byte[] bytes = ed.SaveToBytes();
File.WriteAllBytes("slides_q4.pptx", bytes);
Definir células XLSX (quatro overloads)
using var wb = EditableDocument.Open("budget.xlsx");
wb.SetCell(0u, "A1", "Total"); // overload string
wb.SetCell(0u, "B1", 42.5); // overload double
wb.SetCell(0u, "C1", true); // overload bool
wb.SetCellEmpty(0u, "D1"); // limpa a célula
wb.Save("budget.xlsx");
sheetIndex começa em zero; cellRef segue a notação padrão de planilhas (A1, AA12).
IR independente de formato
ToIrJson() devolve uma string JSON que segue a forma da DocumentIR em Rust:
using System.Text.Json;
using var doc = Document.Open("report.docx");
string json = doc.ToIrJson();
using var ir = JsonDocument.Parse(json);
foreach (var section in ir.RootElement.GetProperty("sections").EnumerateArray())
{
if (section.TryGetProperty("title", out var t) && t.ValueKind != JsonValueKind.Null)
Console.WriteLine(t.GetString());
}
Pipelines em bytes
using var http = new HttpClient();
byte[] data = await http.GetByteArrayAsync("https://example.com/file.docx");
using var doc = Document.FromBytes(data, "docx");
Console.WriteLine(doc.ToMarkdown());
Formatos legados
using var legacy = Document.Open("old.xls");
legacy.SaveAs("modern.xlsx");
AOT / trimming
O projeto define IsAotCompatible=true e IsTrimmable=true. Todos os P/Invokes usam o gerador de fonte LibraryImport, então dotnet publish -c Release -p:PublishAot=true produz um único executável self-contained.
Erros
Falhas disparam OfficeOxideException com a propriedade tipada Code:
try
{
using var doc = Document.Open("missing.docx");
}
catch (OfficeOxideException ex)
{
Console.WriteLine($"code={ex.Code} op={ex.Operation}");
}
Chamar métodos em um handle já dispose-ado lança ObjectDisposedException.
| Código | Nome | Significado |
|---|---|---|
| 0 | Ok |
sucesso |
| 1 | InvalidArg |
null / vazio / string de formato errada |
| 2 | Io |
erro de filesystem |
| 3 | Parse |
documento corrompido |
| 4 | Extraction |
parsing OK, mas o render falhou |
| 5 | Internal |
bug — abra uma issue |
| 6 | Unsupported |
extensão/feature não suportada |
Solução de problemas
| Sintoma | Solução |
|---|---|
DllNotFoundException: office_oxide |
A biblioteca nativa não foi copiada ao lado do binário. Rode dotnet publish em vez de só dotnet build. |
BadImageFormatException no Windows |
Mismatch de arquitetura — implemente o build correto win-x64 ou win-arm64. |
OfficeOxideException com código Unsupported em .doc |
Confirme a extensão em minúsculas ou passe o formato explicitamente via FromBytes. |
| Falta símbolos após trimming | Adicione OfficeOxide em <TrimmerRootAssembly>. |
| macOS “não pode ser aberto porque o desenvolvedor não pode ser verificado” | Rode xattr -d com.apple.quarantine /path/to/liboffice_oxide.dylib ou assine o bundle. |
Veja também
- Benchmarks de performance
- Pacote no NuGet