Skip to content

Biblioteca Office para Node.js — Início Rápido

O pacote npm office-oxide é o binding nativo para Node.js: carrega dinamicamente liboffice_oxide via koffi e expõe uma API JavaScript pequena e idiomática. Mais rápido e mais leve que o build WebAssembly, mas distribui prebuilds específicos por plataforma em vez de um único binário portátil.

Se você precisa de um único artefato que rode no navegador, em bundlers ou no Node sem libs nativas, use office-oxide-wasm.

Instalação

npm install office-oxide

No postinstall, o pacote procura um prebuild compatível em node_modules/office-oxide/prebuilds/<platform>-<arch>/. Se não encontrar, configure antes do primeiro uso uma das opções:

  1. OFFICE_OXIDE_LIB — caminho absoluto da biblioteca (ex.: /opt/office_oxide/liboffice_oxide.so).
  2. Diretório de prebuild — coloque a biblioteca em prebuilds/<platform>-<arch>/ (ex.: linux-x64, darwin-arm64, win32-x64) dentro do pacote.
  3. Caminho de bibliotecas do sistema — instale onde LD_LIBRARY_PATH / DYLD_LIBRARY_PATH / PATH consigam achá-la.

Funciona em Node 18+.

Ler um documento

import { Document } from 'office-oxide';

const doc = Document.open('report.docx');
try {
  console.log(doc.plainText());
} finally {
  doc.close();
}

Ou com TC39 explicit resource management (Node 22+):

import { Document } from 'office-oxide';

using doc = Document.open('report.docx');
console.log(doc.plainText());
// doc.close() é chamado automaticamente ao sair do escopo

Helper de uma só chamada:

import { extractText } from 'office-oxide';
console.log(extractText('report.docx'));

API principal

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();           // objeto já parseado

  doc.saveAs('file.docx');         // formato-alvo inferido pela extensão
} finally {
  doc.close();
}

A partir de bytes brutos (Uint8Array ou 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 precisa ser 'docx' | 'xlsx' | 'pptx' | 'doc' | 'xls' | 'ppt'.

Helpers no nível do módulo:

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"

Edição

Handles editáveis preservam todas as partes OPC inalteradas no salvamento. Apenas DOCX, XLSX e PPTX.

import { EditableDocument } from 'office-oxide';

using ed = EditableDocument.open('template.docx');
const n = ed.replaceText('{{name}}', 'Alice');
console.log(`${n} substituições`);
ed.save('out.docx');

Definir células XLSX

import { EditableDocument } from 'office-oxide';

using wb = EditableDocument.open('budget.xlsx');

wb.setCell(0, 'A1', 'Total');   // string
wb.setCell(0, 'B1', 42.5);      // número
wb.setCell(0, 'C1', true);      // booleano
wb.setCell(0, 'D1', null);      // vazio

wb.save('budget.xlsx');

sheetIndex começa em zero; cellRef segue a notação padrão de planilhas.

IR independente de formato

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" | ...
  }
}

Pipelines em bytes

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

Formatos legados

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

Erros

Falhas disparam OfficeOxideError com code numérico e 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;
  }
}
Código Significado
0 OK
1 argumento inválido
2 erro de IO
3 erro de parse
4 falha na extração
5 erro interno
6 formato não suportado

Solução de problemas

Sintoma O que fazer
office-oxide: failed to load native library Defina OFFICE_OXIDE_LIB com caminho absoluto, ou coloque um prebuild compatível dentro do pacote.
koffi: ABI mismatch O prebuild não bate com a plataforma/arquitetura do processo Node — reinstale ou pegue um novo.
TypeError: data must be a Uint8Array or Buffer Document.fromBytes só aceita tipos binários. Use Buffer.from(base64, 'base64').
Document is closed Você chamou um método após close() ou após sair de um escopo using. Abra um novo handle.
.doc legado abre, mas o texto sai embaralhado Documentos Word 97 criptografados não são descriptografados — descriptografe antes via LibreOffice.

Veja também