Node.js-библиотека для Office — быстрый старт
npm-пакет office-oxide — это нативная привязка к Node.js: через koffi динамически загружает liboffice_oxide и отдаёт компактный, идиоматический JS API. Быстрее и меньше, чем WebAssembly-сборка, но поставляется с предсобранными бинарниками для конкретных платформ, а не одним переносимым файлом.
Если нужен один артефакт, который работает в браузере, бандлерах или Node без нативных библиотек — берите
office-oxide-wasm.
Установка
npm install office-oxide
На postinstall пакет ищет совместимый prebuild в node_modules/office-oxide/prebuilds/<platform>-<arch>/. Если его нет, перед первым использованием настройте одно из следующего:
OFFICE_OXIDE_LIB— абсолютный путь к библиотеке (например,/opt/office_oxide/liboffice_oxide.so).- Каталог prebuild — положите библиотеку в
prebuilds/<platform>-<arch>/(например,linux-x64,darwin-arm64,win32-x64) внутри пакета. - Системный путь библиотек — установите так, чтобы её находили
LD_LIBRARY_PATH/DYLD_LIBRARY_PATH/PATH.
Работает на Node 18+.
Прочитать документ
import { Document } from 'office-oxide';
const doc = Document.open('report.docx');
try {
console.log(doc.plainText());
} finally {
doc.close();
}
Или с TC39 explicit resource management (Node 22+):
import { Document } from 'office-oxide';
using doc = Document.open('report.docx');
console.log(doc.plainText());
// doc.close() вызовется автоматически при выходе из области
Одноразовый помощник:
import { extractText } from 'office-oxide';
console.log(extractText('report.docx'));
Базовый API
import { Document } from 'office-oxide';
const doc = Document.open('file.xlsx');
try {
console.log(doc.format); // "xlsx"
console.log(doc.plainText());
console.log(doc.toMarkdown());
console.log(doc.toHtml());
const ir = doc.toIr(); // распарсенный объект
doc.saveAs('file.docx'); // целевой формат — по расширению
} finally {
doc.close();
}
Из сырых байтов (Uint8Array или Buffer):
import { readFileSync } from 'node:fs';
import { Document } from 'office-oxide';
const data = readFileSync('report.pptx');
using doc = Document.fromBytes(data, 'pptx');
console.log(doc.toMarkdown());
format должен быть 'docx' | 'xlsx' | 'pptx' | 'doc' | 'xls' | 'ppt'.
Шорткаты модульного уровня:
import { extractText, toMarkdown, toHtml, detectFormat, version } from 'office-oxide';
extractText('file.docx'); // string
toMarkdown('file.pptx'); // string
toHtml('file.xlsx'); // string
detectFormat('mystery.bin'); // "docx" | ... | null
version(); // "0.1.0"
Редактирование
Editable-handle сохраняет все нетронутые OPC-части. Только DOCX, XLSX, PPTX.
import { EditableDocument } from 'office-oxide';
using ed = EditableDocument.open('template.docx');
const n = ed.replaceText('{{name}}', 'Alice');
console.log(`${n} замен`);
ed.save('out.docx');
Запись ячеек XLSX
import { EditableDocument } from 'office-oxide';
using wb = EditableDocument.open('budget.xlsx');
wb.setCell(0, 'A1', 'Total'); // строка
wb.setCell(0, 'B1', 42.5); // число
wb.setCell(0, 'C1', true); // булево
wb.setCell(0, 'D1', null); // пусто
wb.save('budget.xlsx');
sheetIndex нумеруется с нуля; cellRef — стандартная нотация.
Формат-независимый IR
using doc = Document.open('report.docx');
const ir = doc.toIr();
for (const section of ir.sections) {
console.log(section.title);
for (const el of section.elements) {
// el.kind: "Heading" | "Paragraph" | "Table" | "List" | ...
}
}
Работа с байтами
import { Document } from 'office-oxide';
const res = await fetch('https://example.com/report.docx');
const data = new Uint8Array(await res.arrayBuffer());
using doc = Document.fromBytes(data, 'docx');
console.log(doc.toMarkdown());
Legacy-форматы
using doc = Document.open('old.xls');
doc.saveAs('modern.xlsx');
CommonJS
const { Document } = require('office-oxide');
const doc = Document.open('file.docx');
try { console.log(doc.plainText()); } finally { doc.close(); }
Ошибки
Сбои бросают OfficeOxideError с числовым code и полем operation:
import { Document, OfficeOxideError } from 'office-oxide';
try {
using doc = Document.open('missing.docx');
} catch (e) {
if (e instanceof OfficeOxideError) {
console.error(`code=${e.code} op=${e.operation}`);
} else {
throw e;
}
}
| Код | Значение |
|---|---|
| 0 | OK |
| 1 | неверный аргумент |
| 2 | IO-ошибка |
| 3 | ошибка парсинга |
| 4 | сбой извлечения |
| 5 | внутренняя ошибка |
| 6 | формат не поддерживается |
Диагностика
| Симптом | Что делать |
|---|---|
office-oxide: failed to load native library |
Установите OFFICE_OXIDE_LIB в абсолютный путь или положите подходящий prebuild в пакет. |
koffi: ABI mismatch |
Prebuild не подходит платформе/архитектуре Node — переустановите или возьмите свежий. |
TypeError: data must be a Uint8Array or Buffer |
Document.fromBytes принимает только бинарные типы. Используйте Buffer.from(base64, 'base64'). |
Document is closed |
Метод вызван после close() или по выходу из using. Откройте новую handle. |
Legacy .doc открывается, но показывает кашу |
Зашифрованные документы Word 97 не дешифруются — расшифруйте через LibreOffice. |
Смотрите также
- WASM-сборка — один переносимый бинарник, работает в браузере и бандлерах
- Бенчмарки производительности
- Пакет: npm