Skip to content

Biblioteca Office para Node.js — Inicio Rápido

El paquete npm office-oxide es el binding nativo para Node.js: carga dinámicamente liboffice_oxide mediante koffi y expone una API JavaScript pequeña e idiomática. Más rápido y compacto que el build WebAssembly, pero distribuye prebuilds específicos por plataforma en lugar de un único binario portátil.

Si necesitas un solo artefacto que corra en navegadores, bundlers o Node sin librerías nativas, usa office-oxide-wasm.

Instalación

npm install office-oxide

En postinstall, el paquete busca un prebuild compatible en node_modules/office-oxide/prebuilds/<platform>-<arch>/. Si no aparece, configura antes del primer uso una de estas opciones:

  1. OFFICE_OXIDE_LIB — ruta absoluta a la librería (por ejemplo /opt/office_oxide/liboffice_oxide.so).
  2. Directorio de prebuilds — coloca la librería en prebuilds/<platform>-<arch>/ (por ejemplo linux-x64, darwin-arm64, win32-x64) dentro del paquete.
  3. Ruta de librerías del sistema — instálala donde LD_LIBRARY_PATH / DYLD_LIBRARY_PATH / PATH puedan encontrarla.

Funciona en Node 18+.

Leer un documento

import { Document } from 'office-oxide';

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

O con TC39 explicit resource management (Node 22+):

import { Document } from 'office-oxide';

using doc = Document.open('report.docx');
console.log(doc.plainText());
// doc.close() se llama automáticamente al salir del ámbito

Helper de un solo paso:

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 ya parseado

  doc.saveAs('file.docx');         // formato destino inferido por la extensión
} finally {
  doc.close();
}

Desde bytes en bruto (Uint8Array o 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 debe ser 'docx' | 'xlsx' | 'pptx' | 'doc' | 'xls' | 'ppt'.

Helpers a nivel de 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"

Edición

Los handles editables conservan al guardar todas las partes OPC sin tocar. Solo DOCX, XLSX y PPTX.

import { EditableDocument } from 'office-oxide';

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

Establecer celdas XLSX

import { EditableDocument } from 'office-oxide';

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

wb.setCell(0, 'A1', 'Total');   // cadena
wb.setCell(0, 'B1', 42.5);      // número
wb.setCell(0, 'C1', true);      // booleano
wb.setCell(0, 'D1', null);      // vacío

wb.save('budget.xlsx');

sheetIndex empieza en cero; cellRef sigue la notación estándar.

IR independiente del 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 basados en 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 heredados

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

Errores

Los fallos lanzan OfficeOxideError con code numérico y 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 error de IO
3 error de parseo
4 falló la extracción
5 error interno
6 formato no soportado

Solución de problemas

Síntoma Solución
office-oxide: failed to load native library Pon OFFICE_OXIDE_LIB con la ruta absoluta o coloca un prebuild válido en el paquete.
koffi: ABI mismatch El prebuild no coincide con la plataforma/arquitectura del proceso Node — reinstala o trae uno nuevo.
TypeError: data must be a Uint8Array or Buffer Document.fromBytes solo acepta tipos binarios. Usa Buffer.from(base64, 'base64').
Document is closed Llamaste a un método tras close() o tras salir de un using. Abre un handle nuevo.
.doc heredado abre, pero se ve corrupto Los Word 97 cifrados no se descifran — descífralo antes con LibreOffice.

Véase también