Biblioteca Office para C# / .NET — Inicio Rápido
OfficeOxide es el binding .NET para la biblioteca Rust office_oxide. Da a las aplicaciones .NET parseo, conversión y edición rápidos y eficientes en memoria para DOCX / XLSX / PPTX / DOC / XLS / PPT — por debajo, P/Invoke LibraryImport compatible con AOT.
Instalación
dotnet add package OfficeOxide --version 0.1.0
Requiere .NET 8 o .NET 10. El paquete NuGet incluye librerías nativas precompiladas para win-x64, linux-x64, linux-arm64, osx-x64, osx-arm64 bajo runtimes/<rid>/native/. dotnet publish coloca la correcta junto a tu binario automáticamente.
Leer un documento
using OfficeOxide;
using var doc = Document.Open("report.docx");
Console.WriteLine(doc.PlainText());
API principal
Document es el handle de solo lectura; haz dispose (preferiblemente con using) para liberar la memoria 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 destino inferido por la extensión
Wrapper async para IO bloqueante:
using var doc = await Document.OpenAsync("huge.pptx", ct);
Abrir desde bytes (sin archivo temporal):
byte[] data = File.ReadAllBytes("report.docx");
using var doc = Document.FromBytes(data, "docx");
format debe ser "docx", "xlsx", "pptx", "doc", "xls" o "ppt".
Helpers estáticos para llamadas únicas:
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 si no se soporta
Console.WriteLine(Document.Version); // "0.1.0"
Edición
La edición conserva todas las partes OPC sin tocar (imágenes, gráficos, relaciones) al guardar. Solo DOCX, XLSX y PPTX.
using OfficeOxide;
using var ed = EditableDocument.Open("template.docx");
long n = ed.ReplaceText("{{name}}", "Alice");
Console.WriteLine($"{n} reemplazos");
ed.Save("out.docx");
ReplaceText devuelve la cantidad de reemplazos (0 en XLSX — usa SetCell).
Reemplazar texto en 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);
Establecer celdas XLSX (cuatro 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"); // vacía la celda
wb.Save("budget.xlsx");
sheetIndex empieza en cero; cellRef sigue la notación estándar de hojas de cálculo (A1, AA12).
IR independiente del formato
ToIrJson() devuelve una cadena JSON acorde a la forma de la DocumentIR de 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 basados en 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 heredados
using var legacy = Document.Open("old.xls");
legacy.SaveAs("modern.xlsx");
AOT / trimming
El proyecto define IsAotCompatible=true e IsTrimmable=true. Todos los P/Invoke usan el generador de fuente LibraryImport, así que dotnet publish -c Release -p:PublishAot=true genera un único ejecutable self-contained.
Errores
Los fallos lanzan OfficeOxideException con la propiedad tipada Code:
try
{
using var doc = Document.Open("missing.docx");
}
catch (OfficeOxideException ex)
{
Console.WriteLine($"code={ex.Code} op={ex.Operation}");
}
Llamar métodos en un handle ya dispose lanza ObjectDisposedException.
| Código | Nombre | Significado |
|---|---|---|
| 0 | Ok |
éxito |
| 1 | InvalidArg |
null / vacío / cadena de formato errónea |
| 2 | Io |
error de filesystem |
| 3 | Parse |
documento corrupto |
| 4 | Extraction |
el parseo fue bien, pero falló el render |
| 5 | Internal |
bug — abre una issue |
| 6 | Unsupported |
extensión/función no soportada |
Solución de problemas
| Síntoma | Solución |
|---|---|
DllNotFoundException: office_oxide |
La librería nativa no se copió junto al binario. Ejecuta dotnet publish en lugar de solo dotnet build. |
BadImageFormatException en Windows |
Desfase de arquitectura — despliega el build correcto win-x64 o win-arm64. |
OfficeOxideException con código Unsupported en .doc |
Asegura que la extensión esté en minúsculas o pasa el formato explícitamente vía FromBytes. |
| Faltan símbolos tras trimming | Añade OfficeOxide a <TrimmerRootAssembly>. |
| macOS “no se puede abrir porque no se ha podido verificar al desarrollador” | Ejecuta xattr -d com.apple.quarantine /path/to/liboffice_oxide.dylib o firma el bundle. |
Véase también
- Benchmarks de rendimiento
- Paquete en NuGet