Skip to content

C# / .NET-библиотека для Office — быстрый старт

OfficeOxide — это .NET-привязка для Rust-библиотеки office_oxide. Даёт .NET-приложениям быстрый и экономный по аллокациям парсинг, конвертацию и редактирование DOCX / XLSX / PPTX / DOC / XLS / PPT — под капотом AOT-совместимый LibraryImport-P/Invoke.

Установка

dotnet add package OfficeOxide --version 0.1.0

Требуется .NET 8 или .NET 10. NuGet-пакет поставляет prebuild-нативки для win-x64, linux-x64, linux-arm64, osx-x64, osx-arm64 под runtimes/<rid>/native/. dotnet publish сам положит нужную рядом с бинарём.

Прочитать документ

using OfficeOxide;

using var doc = Document.Open("report.docx");
Console.WriteLine(doc.PlainText());

Базовый API

Document — read-only handle; диспозьте (лучше через using), чтобы освободить нативную память.

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");              // целевой формат — по расширению

Async-обёртка для блокирующего IO:

using var doc = await Document.OpenAsync("huge.pptx", ct);

Открыть из байтов (без temp-файла):

byte[] data = File.ReadAllBytes("report.docx");
using var doc = Document.FromBytes(data, "docx");

format должен быть "docx", "xlsx", "pptx", "doc", "xls" или "ppt".

Статические хелперы для одноразовых вызовов:

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 если не поддерживается
Console.WriteLine(Document.Version);                // "0.1.0"

Редактирование

Редактирование сохраняет дословно все нетронутые OPC-части (изображения, диаграммы, отношения). Только DOCX, XLSX и PPTX.

using OfficeOxide;

using var ed = EditableDocument.Open("template.docx");
long n = ed.ReplaceText("{{name}}", "Alice");
Console.WriteLine($"{n} замен");
ed.Save("out.docx");

ReplaceText возвращает количество замен (на XLSX — 0; используйте SetCell).

Замена текста в 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);

Запись ячеек XLSX (четыре перегрузки)

using var wb = EditableDocument.Open("budget.xlsx");

wb.SetCell(0u, "A1", "Total");        // string-перегрузка
wb.SetCell(0u, "B1", 42.5);           // double-перегрузка
wb.SetCell(0u, "C1", true);           // bool-перегрузка
wb.SetCellEmpty(0u, "D1");            // очистить

wb.Save("budget.xlsx");

sheetIndex нумеруется с нуля; cellRef — стандартная нотация (A1, AA12).

Формат-независимый IR

ToIrJson() возвращает JSON-строку, совпадающую с Rust-структурой DocumentIR:

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());
}

Работа с байтами

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());

Legacy-форматы

using var legacy = Document.Open("old.xls");
legacy.SaveAs("modern.xlsx");

AOT / Trimming

Проект задаёт IsAotCompatible=true и IsTrimmable=true. Все P/Invoke используют LibraryImport-source generator, так что dotnet publish -c Release -p:PublishAot=true даёт единый self-contained executable.

Ошибки

Сбои бросают OfficeOxideException с типизированным свойством Code:

try
{
    using var doc = Document.Open("missing.docx");
}
catch (OfficeOxideException ex)
{
    Console.WriteLine($"code={ex.Code} op={ex.Operation}");
}

Вызов методов на disposed-handle бросает ObjectDisposedException.

Код Имя Значение
0 Ok успех
1 InvalidArg null / пусто / неправильная строка формата
2 Io ошибка файловой системы
3 Parse повреждённый документ
4 Extraction парсинг ОК, но рендер сорвался
5 Internal баг — заведите issue
6 Unsupported расширение/фича не поддерживаются

Диагностика

Симптом Что делать
DllNotFoundException: office_oxide Нативная библиотека не скопирована рядом с бинарём. Запускайте dotnet publish, а не голый dotnet build.
BadImageFormatException на Windows Несовпадение архитектуры — выкатите соответствующую сборку win-x64 или win-arm64.
OfficeOxideException с кодом Unsupported на .doc Убедитесь, что расширение в нижнем регистре, или передавайте формат явно через FromBytes.
После trimming не хватает символов Добавьте OfficeOxide в <TrimmerRootAssembly>.
macOS «нельзя открыть, разработчик не подтверждён» Выполните xattr -d com.apple.quarantine /path/to/liboffice_oxide.dylib или подпишите бандл.

Смотрите также