Skip to content

Convertir PDF y documentos Office en ambas direcciones

Convierte documentos de Microsoft Office (Word, Excel, PowerPoint) a PDF — y convierte un PDF de vuelta a DOCX, PPTX o XLSX — sin tener instalado Microsoft Office ni LibreOffice. PDF Oxide analiza el formato OOXML directamente y genera la salida en PDF, y también renderiza páginas PDF de vuelta en documentos Office editables.

La conversión funciona en dos direcciones:

  • Office → PDF — la clase OfficeConverter (y los constructores open_from_*_bytes) analiza DOCX/XLSX/PPTX y genera un PDF.
  • PDF → Office — los métodos to_docx / to_pptx / to_xlsx en un documento abierto exportan de vuelta a los formatos Office.

Ejemplo rápido

Python

from pdf_oxide import OfficeConverter

# Auto-detect format from extension
pdf = OfficeConverter.convert("report.docx")
pdf.save("report.pdf")

Rust

use pdf_oxide::converters::office::OfficeConverter;

let converter = OfficeConverter::new();
let pdf_bytes = converter.convert("report.docx")?;
std::fs::write("report.pdf", pdf_bytes)?;

C++

#include <pdf_oxide/pdf_oxide.hpp>
#include <fstream>

std::ifstream in("report.docx", std::ios::binary);
std::vector<std::uint8_t> docx((std::istreambuf_iterator<char>(in)), {});

auto doc = pdf_oxide::Document::open_from_docx_bytes(docx);
auto pdf = doc.get_source_bytes();
std::ofstream("report.pdf", std::ios::binary)
    .write(reinterpret_cast<const char*>(pdf.data()), pdf.size());

Dart

import 'dart:io';
import 'package:pdf_oxide/pdf_oxide.dart';

final docx = File('report.docx').readAsBytesSync();
final doc = PdfDocument.openFromDocxBytes(docx);
File('report.pdf').writeAsBytesSync(doc.getSourceBytes());

R

library(pdfoxide)

docx <- readBin("report.docx", "raw", file.info("report.docx")$size)
doc  <- pdf_open_from_docx_bytes(docx)
writeBin(pdf_get_source_bytes(doc), "report.pdf")

Julia

using PdfOxide

docx = read("report.docx")
doc  = open_from_docx_bytes(docx)
write("report.pdf", get_source_bytes(doc))

Zig

const pdf_oxide = @import("pdf_oxide");
const a = std.heap.page_allocator;

const docx = try std.fs.cwd().readFileAlloc("report.docx", a, .unlimited);
var doc = try pdf_oxide.Document.openFromDocxBytes(docx);
const pdf = try doc.sourceBytes(a);
try std.fs.cwd().writeFile(.{ .sub_path = "report.pdf", .data = pdf });

Objective-C

#import "POXPdfOxide.h"
NSError *err = nil;

NSData *docx = [NSData dataWithContentsOfFile:@"report.docx"];
POXDocument *doc = [POXDocument openFromDocxBytes:docx error:&err];
NSData *pdf = [doc sourceBytesWithError:&err];
[pdf writeToFile:@"report.pdf" atomically:YES];

Elixir

docx = File.read!("report.docx")
{:ok, doc} = PdfOxide.open_from_docx_bytes(docx)
{:ok, pdf} = PdfOxide.source_bytes(doc)
File.write!("report.pdf", pdf)

Formatos admitidos

Formato Extensión Descripción
DOCX .docx Documentos Word — párrafos, encabezados, listas, formato de texto
XLSX .xlsx, .xls Hojas de cálculo Excel — múltiples hojas, ancho de columna automático, tipos de celda
PPTX .pptx Presentaciones PowerPoint — diapositivas, títulos, cuadros de texto

Documentos Word (DOCX)

Convierte documentos Word preservando encabezados, párrafos, listas y formato de texto (negrita, cursiva, subrayado, colores, tamaños de fuente).

Python

from pdf_oxide import OfficeConverter

pdf = OfficeConverter.from_docx("document.docx")
pdf.save("document.pdf")

Rust

use pdf_oxide::converters::office::OfficeConverter;

let converter = OfficeConverter::new();
let pdf_bytes = converter.convert_docx("document.docx")?;
std::fs::write("document.pdf", pdf_bytes)?;

C++

#include <pdf_oxide/pdf_oxide.hpp>
#include <fstream>

std::ifstream in("document.docx", std::ios::binary);
std::vector<std::uint8_t> docx((std::istreambuf_iterator<char>(in)), {});

auto doc = pdf_oxide::Document::open_from_docx_bytes(docx);
auto pdf = doc.get_source_bytes();
std::ofstream("document.pdf", std::ios::binary)
    .write(reinterpret_cast<const char*>(pdf.data()), pdf.size());

Dart

import 'dart:io';
import 'package:pdf_oxide/pdf_oxide.dart';

final docx = File('document.docx').readAsBytesSync();
final doc = PdfDocument.openFromDocxBytes(docx);
File('document.pdf').writeAsBytesSync(doc.getSourceBytes());

R

library(pdfoxide)

docx <- readBin("document.docx", "raw", file.info("document.docx")$size)
doc  <- pdf_open_from_docx_bytes(docx)
writeBin(pdf_get_source_bytes(doc), "document.pdf")

Julia

using PdfOxide

docx = read("document.docx")
doc  = open_from_docx_bytes(docx)
write("document.pdf", get_source_bytes(doc))

Zig

const pdf_oxide = @import("pdf_oxide");
const a = std.heap.page_allocator;

const docx = try std.fs.cwd().readFileAlloc("document.docx", a, .unlimited);
var doc = try pdf_oxide.Document.openFromDocxBytes(docx);
const pdf = try doc.sourceBytes(a);
try std.fs.cwd().writeFile(.{ .sub_path = "document.pdf", .data = pdf });

Objective-C

#import "POXPdfOxide.h"
NSError *err = nil;

NSData *docx = [NSData dataWithContentsOfFile:@"document.docx"];
POXDocument *doc = [POXDocument openFromDocxBytes:docx error:&err];
NSData *pdf = [doc sourceBytesWithError:&err];
[pdf writeToFile:@"document.pdf" atomically:YES];

Elixir

docx = File.read!("document.docx")
{:ok, doc} = PdfOxide.open_from_docx_bytes(docx)
{:ok, pdf} = PdfOxide.source_bytes(doc)
File.write!("document.pdf", pdf)

Desde bytes

Python

from pdf_oxide import OfficeConverter

with open("document.docx", "rb") as f:
    pdf = OfficeConverter.from_docx_bytes(f.read())
pdf.save("document.pdf")

Rust

let docx_bytes = std::fs::read("document.docx")?;
let converter = OfficeConverter::new();
let pdf_bytes = converter.convert_docx_bytes(&docx_bytes)?;
std::fs::write("document.pdf", pdf_bytes)?;

C++

std::ifstream in("document.docx", std::ios::binary);
std::vector<std::uint8_t> docx_bytes((std::istreambuf_iterator<char>(in)), {});

auto doc = pdf_oxide::Document::open_from_docx_bytes(docx_bytes);
auto pdf_bytes = doc.get_source_bytes();
std::ofstream("document.pdf", std::ios::binary)
    .write(reinterpret_cast<const char*>(pdf_bytes.data()), pdf_bytes.size());

Dart

final docxBytes = File('document.docx').readAsBytesSync();
final doc = PdfDocument.openFromDocxBytes(docxBytes);
File('document.pdf').writeAsBytesSync(doc.getSourceBytes());

R

docx_bytes <- readBin("document.docx", "raw", file.info("document.docx")$size)
doc <- pdf_open_from_docx_bytes(docx_bytes)
writeBin(pdf_get_source_bytes(doc), "document.pdf")

Julia

docx_bytes = read("document.docx")
doc = open_from_docx_bytes(docx_bytes)
write("document.pdf", get_source_bytes(doc))

Zig

const docx_bytes = try std.fs.cwd().readFileAlloc("document.docx", a, .unlimited);
var doc = try pdf_oxide.Document.openFromDocxBytes(docx_bytes);
const pdf_bytes = try doc.sourceBytes(a);
try std.fs.cwd().writeFile(.{ .sub_path = "document.pdf", .data = pdf_bytes });

Objective-C

NSData *docxBytes = [NSData dataWithContentsOfFile:@"document.docx"];
POXDocument *doc = [POXDocument openFromDocxBytes:docxBytes error:&err];
NSData *pdfBytes = [doc sourceBytesWithError:&err];
[pdfBytes writeToFile:@"document.pdf" atomically:YES];

Elixir

docx_bytes = File.read!("document.docx")
{:ok, doc} = PdfOxide.open_from_docx_bytes(docx_bytes)
{:ok, pdf_bytes} = PdfOxide.source_bytes(doc)
File.write!("document.pdf", pdf_bytes)

Funciones DOCX admitidas

  • Párrafos con alineación (izquierda, centro, derecha, justificado)
  • Encabezados (estilos Encabezado 1–9)
  • Formato de texto: negrita, cursiva, subrayado, tachado
  • Tamaños y colores de fuente
  • Listas numeradas y con viñetas, con anidamiento
  • Extracción de metadatos (título y autor de docProps/core.xml)

Hojas de cálculo Excel (XLSX)

Convierte hojas de cálculo a PDF con cálculo automático del ancho de columnas y compatibilidad con múltiples hojas. Cada hoja se renderiza como una sección separada.

Python

from pdf_oxide import OfficeConverter

pdf = OfficeConverter.from_xlsx("data.xlsx")
pdf.save("data.pdf")

Rust

let converter = OfficeConverter::new();
let pdf_bytes = converter.convert_xlsx("data.xlsx")?;
std::fs::write("data.pdf", pdf_bytes)?;

C++

std::ifstream in("data.xlsx", std::ios::binary);
std::vector<std::uint8_t> xlsx((std::istreambuf_iterator<char>(in)), {});

auto doc = pdf_oxide::Document::open_from_xlsx_bytes(xlsx);
auto pdf = doc.get_source_bytes();
std::ofstream("data.pdf", std::ios::binary)
    .write(reinterpret_cast<const char*>(pdf.data()), pdf.size());

Dart

final xlsx = File('data.xlsx').readAsBytesSync();
final doc = PdfDocument.openFromXlsxBytes(xlsx);
File('data.pdf').writeAsBytesSync(doc.getSourceBytes());

R

xlsx <- readBin("data.xlsx", "raw", file.info("data.xlsx")$size)
doc  <- pdf_open_from_xlsx_bytes(xlsx)
writeBin(pdf_get_source_bytes(doc), "data.pdf")

Julia

xlsx = read("data.xlsx")
doc  = open_from_xlsx_bytes(xlsx)
write("data.pdf", get_source_bytes(doc))

Zig

const xlsx = try std.fs.cwd().readFileAlloc("data.xlsx", a, .unlimited);
var doc = try pdf_oxide.Document.openFromXlsxBytes(xlsx);
const pdf = try doc.sourceBytes(a);
try std.fs.cwd().writeFile(.{ .sub_path = "data.pdf", .data = pdf });

Objective-C

NSData *xlsx = [NSData dataWithContentsOfFile:@"data.xlsx"];
POXDocument *doc = [POXDocument openFromXlsxBytes:xlsx error:&err];
NSData *pdf = [doc sourceBytesWithError:&err];
[pdf writeToFile:@"data.pdf" atomically:YES];

Elixir

xlsx = File.read!("data.xlsx")
{:ok, doc} = PdfOxide.open_from_xlsx_bytes(xlsx)
{:ok, pdf} = PdfOxide.source_bytes(doc)
File.write!("data.pdf", pdf)

Funciones XLSX admitidas

  • Renderizado de múltiples hojas con títulos
  • Tipos de celda: cadenas, enteros, decimales, booleanos, fechas, errores
  • Cálculo automático del ancho de columnas
  • Saltos de página automáticos cuando el contenido supera el espacio disponible

Presentaciones PowerPoint (PPTX)

Convierte presentaciones a PDF. Cada diapositiva se convierte en una página con títulos y cuadros de texto extraídos.

Python

from pdf_oxide import OfficeConverter

pdf = OfficeConverter.from_pptx("slides.pptx")
pdf.save("slides.pdf")

Rust

let converter = OfficeConverter::new();
let pdf_bytes = converter.convert_pptx("slides.pptx")?;
std::fs::write("slides.pdf", pdf_bytes)?;

C++

std::ifstream in("slides.pptx", std::ios::binary);
std::vector<std::uint8_t> pptx((std::istreambuf_iterator<char>(in)), {});

auto doc = pdf_oxide::Document::open_from_pptx_bytes(pptx);
auto pdf = doc.get_source_bytes();
std::ofstream("slides.pdf", std::ios::binary)
    .write(reinterpret_cast<const char*>(pdf.data()), pdf.size());

Dart

final pptx = File('slides.pptx').readAsBytesSync();
final doc = PdfDocument.openFromPptxBytes(pptx);
File('slides.pdf').writeAsBytesSync(doc.getSourceBytes());

R

pptx <- readBin("slides.pptx", "raw", file.info("slides.pptx")$size)
doc  <- pdf_open_from_pptx_bytes(pptx)
writeBin(pdf_get_source_bytes(doc), "slides.pdf")

Julia

pptx = read("slides.pptx")
doc  = open_from_pptx_bytes(pptx)
write("slides.pdf", get_source_bytes(doc))

Zig

const pptx = try std.fs.cwd().readFileAlloc("slides.pptx", a, .unlimited);
var doc = try pdf_oxide.Document.openFromPptxBytes(pptx);
const pdf = try doc.sourceBytes(a);
try std.fs.cwd().writeFile(.{ .sub_path = "slides.pdf", .data = pdf });

Objective-C

NSData *pptx = [NSData dataWithContentsOfFile:@"slides.pptx"];
POXDocument *doc = [POXDocument openFromPptxBytes:pptx error:&err];
NSData *pdf = [doc sourceBytesWithError:&err];
[pdf writeToFile:@"slides.pdf" atomically:YES];

Elixir

pptx = File.read!("slides.pptx")
{:ok, doc} = PdfOxide.open_from_pptx_bytes(pptx)
{:ok, pdf} = PdfOxide.source_bytes(doc)
File.write!("slides.pdf", pdf)

¿Cómo convierto un PDF a DOCX, PPTX o XLSX?

La dirección inversa — PDF → Office — opera sobre un documento PDF abierto, no sobre OfficeConverter. Abre un PDF con PdfDocument (Python/Rust), OpenFromBytes/Open (Go/C#) o Document.open (Swift) y llama a to_docx / to_pptx / to_xlsx para exportar a los formatos Office.

PDF Oxide elige la estrategia de salida automáticamente según el número de páginas: los documentos iguales o inferiores al umbral de maquetación (30 páginas para DOCX/PPTX, 200 para XLSX) usan el camino de preservación de maquetación, que mantiene cada fragmento de texto cerca de su posición original como elemento posicionado y editable; los documentos más grandes recurren al camino de flujo, que redistribuye el contenido para que Word/PowerPoint/Excel los abra al instante. Cada página PDF se convierte en una sección DOCX, una diapositiva PPTX o una hoja de cálculo XLSX, y se preservan las dimensiones de página originales y las fuentes incrustadas, de modo que una conversión de ida y vuelta PDF → Office → PDF mantiene el diseño original.

PDF a Word (DOCX)

Rust

use pdf_oxide::document::PdfDocument;

let doc = PdfDocument::open("report.pdf")?;

// Write straight to disk
doc.to_docx("report.docx")?;

// Or get the bytes in memory
let docx_bytes: Vec<u8> = doc.to_docx_bytes()?;
std::fs::write("report.docx", docx_bytes)?;

Python

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")

# Write straight to disk
doc.to_docx("report.docx")

# Or get the bytes in memory
docx_bytes = doc.to_docx_bytes()
with open("report.docx", "wb") as f:
    f.write(docx_bytes)

Go

doc, err := pdfoxide.Open("report.pdf")
if err != nil {
    log.Fatal(err)
}
defer doc.Close()

docxBytes, err := doc.ToDocxBytes()
if err != nil {
    log.Fatal(err)
}
os.WriteFile("report.docx", docxBytes, 0o644)

C#

using PdfOxide.Core;

using var doc = PdfDocument.Open("report.pdf");
byte[] docxBytes = doc.ToDocxBytes();
File.WriteAllBytes("report.docx", docxBytes);

Swift

import PdfOxide

let doc = try Document.open("report.pdf")
let docxBytes = try doc.toDocx()
try Data(docxBytes).write(to: URL(fileURLWithPath: "report.docx"))

C++

#include <pdf_oxide/pdf_oxide.hpp>
#include <fstream>

auto doc = pdf_oxide::Document::open("report.pdf");
auto docx_bytes = doc.to_docx();
std::ofstream("report.docx", std::ios::binary)
    .write(reinterpret_cast<const char*>(docx_bytes.data()), docx_bytes.size());

Dart

import 'dart:io';
import 'package:pdf_oxide/pdf_oxide.dart';

final doc = PdfDocument.open('report.pdf');
File('report.docx').writeAsBytesSync(doc.toDocx());

R

library(pdfoxide)

doc <- pdf_open("report.pdf")
writeBin(pdf_to_docx(doc), "report.docx")

Julia

using PdfOxide

doc = open_document("report.pdf")
write("report.docx", to_docx(doc))

Zig

const pdf_oxide = @import("pdf_oxide");
const a = std.heap.page_allocator;

var doc = try pdf_oxide.Document.open("report.pdf");
const docx_bytes = try doc.toDocx(a);
try std.fs.cwd().writeFile(.{ .sub_path = "report.docx", .data = docx_bytes });

Objective-C

#import "POXPdfOxide.h"
NSError *err = nil;

POXDocument *doc = [POXDocument openPath:@"report.pdf" error:&err];
NSData *docxBytes = [doc toDocxWithError:&err];
[docxBytes writeToFile:@"report.docx" atomically:YES];

Elixir

{:ok, doc} = PdfOxide.open("report.pdf")
{:ok, docx_bytes} = PdfOxide.to_docx(doc)
File.write!("report.docx", docx_bytes)

PDF a PowerPoint (PPTX)

Rust

use pdf_oxide::document::PdfDocument;

let doc = PdfDocument::open("deck.pdf")?;
doc.to_pptx("deck.pptx")?;            // to disk
let pptx_bytes = doc.to_pptx_bytes()?; // or in memory

Python

from pdf_oxide import PdfDocument

doc = PdfDocument("deck.pdf")
doc.to_pptx("deck.pptx")           # to disk
pptx_bytes = doc.to_pptx_bytes()   # or in memory

Go

doc, _ := pdfoxide.Open("deck.pdf")
defer doc.Close()
pptxBytes, err := doc.ToPptxBytes()
if err != nil {
    log.Fatal(err)
}
os.WriteFile("deck.pptx", pptxBytes, 0o644)

C#

using var doc = PdfDocument.Open("deck.pdf");
File.WriteAllBytes("deck.pptx", doc.ToPptxBytes());

Swift

let doc = try Document.open("deck.pdf")
let pptxBytes = try doc.toPptx()
try Data(pptxBytes).write(to: URL(fileURLWithPath: "deck.pptx"))

C++

auto doc = pdf_oxide::Document::open("deck.pdf");
auto pptx_bytes = doc.to_pptx();
std::ofstream("deck.pptx", std::ios::binary)
    .write(reinterpret_cast<const char*>(pptx_bytes.data()), pptx_bytes.size());

Dart

final doc = PdfDocument.open('deck.pdf');
File('deck.pptx').writeAsBytesSync(doc.toPptx());

R

doc <- pdf_open("deck.pdf")
writeBin(pdf_to_pptx(doc), "deck.pptx")

Julia

doc = open_document("deck.pdf")
write("deck.pptx", to_pptx(doc))

Zig

var doc = try pdf_oxide.Document.open("deck.pdf");
const pptx_bytes = try doc.toPptx(a);
try std.fs.cwd().writeFile(.{ .sub_path = "deck.pptx", .data = pptx_bytes });

Objective-C

POXDocument *doc = [POXDocument openPath:@"deck.pdf" error:&err];
NSData *pptxBytes = [doc toPptxWithError:&err];
[pptxBytes writeToFile:@"deck.pptx" atomically:YES];

Elixir

{:ok, doc} = PdfOxide.open("deck.pdf")
{:ok, pptx_bytes} = PdfOxide.to_pptx(doc)
File.write!("deck.pptx", pptx_bytes)

PDF a Excel (XLSX)

Rust

use pdf_oxide::document::PdfDocument;

let doc = PdfDocument::open("table.pdf")?;
doc.to_xlsx("table.xlsx")?;            // to disk
let xlsx_bytes = doc.to_xlsx_bytes()?; // or in memory

Python

from pdf_oxide import PdfDocument

doc = PdfDocument("table.pdf")
doc.to_xlsx("table.xlsx")          # to disk
xlsx_bytes = doc.to_xlsx_bytes()   # or in memory

Go

doc, _ := pdfoxide.Open("table.pdf")
defer doc.Close()
xlsxBytes, err := doc.ToXlsxBytes()
if err != nil {
    log.Fatal(err)
}
os.WriteFile("table.xlsx", xlsxBytes, 0o644)

C#

using var doc = PdfDocument.Open("table.pdf");
File.WriteAllBytes("table.xlsx", doc.ToXlsxBytes());

Swift

let doc = try Document.open("table.pdf")
let xlsxBytes = try doc.toXlsx()
try Data(xlsxBytes).write(to: URL(fileURLWithPath: "table.xlsx"))

C++

auto doc = pdf_oxide::Document::open("table.pdf");
auto xlsx_bytes = doc.to_xlsx();
std::ofstream("table.xlsx", std::ios::binary)
    .write(reinterpret_cast<const char*>(xlsx_bytes.data()), xlsx_bytes.size());

Dart

final doc = PdfDocument.open('table.pdf');
File('table.xlsx').writeAsBytesSync(doc.toXlsx());

R

doc <- pdf_open("table.pdf")
writeBin(pdf_to_xlsx(doc), "table.xlsx")

Julia

doc = open_document("table.pdf")
write("table.xlsx", to_xlsx(doc))

Zig

var doc = try pdf_oxide.Document.open("table.pdf");
const xlsx_bytes = try doc.toXlsx(a);
try std.fs.cwd().writeFile(.{ .sub_path = "table.xlsx", .data = xlsx_bytes });

Objective-C

POXDocument *doc = [POXDocument openPath:@"table.pdf" error:&err];
NSData *xlsxBytes = [doc toXlsxWithError:&err];
[xlsxBytes writeToFile:@"table.xlsx" atomically:YES];

Elixir

{:ok, doc} = PdfOxide.open("table.pdf")
{:ok, xlsx_bytes} = PdfOxide.to_xlsx(doc)
File.write!("table.xlsx", xlsx_bytes)

Nota para Python: to_docx/to_pptx/to_xlsx están disponibles en PdfDocument (la clase de extracción e inspección), no en el constructor OfficeConverter/Pdf que se usa para la dirección Office → PDF. Usa PdfDocument("file.pdf") para abrir el PDF de origen.


¿Cómo abro un archivo Office directamente como documento PDF?

Los bindings nativos (Go, C#, Swift y el ABI de C) exponen constructores open_from_*_bytes que convierten bytes DOCX/PPTX/XLSX y devuelven un PdfDocument ya abierto — práctico cuando quieres extraer texto, renderizar o reexportar de inmediato sin guardar el PDF intermedio. Cada constructor ejecuta OfficeConverter internamente y abre el PDF resultante en una sola llamada.

Go

data, err := os.ReadFile("contract.docx")
if err != nil {
    log.Fatal(err)
}

doc, err := pdfoxide.OpenFromDocxBytes(data)
if err != nil {
    log.Fatal(err)
}
defer doc.Close()

// Now work with it as a normal PDF document
text, _ := doc.ExtractText(0)
fmt.Println(text)

C#

using PdfOxide.Core;

byte[] data = File.ReadAllBytes("contract.docx");
using var doc = PdfDocument.OpenFromDocxBytes(data);

// Use it like any other open PDF — extract, render, or re-export
byte[] pdfBytes = doc.ToDocxBytes(); // round-trip if you like

Swift

import PdfOxide
import Foundation

let data = try Data(contentsOf: URL(fileURLWithPath: "contract.docx"))
let doc = try Document.openFromDocxBytes([UInt8](data))
let pageCount = try doc.pageCount()
print("Converted DOCX has \(pageCount) page(s)")

C++

#include <pdf_oxide/pdf_oxide.hpp>
#include <fstream>

std::ifstream in("contract.docx", std::ios::binary);
std::vector<std::uint8_t> data((std::istreambuf_iterator<char>(in)), {});

auto doc = pdf_oxide::Document::open_from_docx_bytes(data);
// Now work with it as a normal PDF document
auto text = doc.extract_text(0);

Dart

import 'dart:io';
import 'package:pdf_oxide/pdf_oxide.dart';

final data = File('contract.docx').readAsBytesSync();
final doc = PdfDocument.openFromDocxBytes(data);
final text = doc.extractText(0);

R

library(pdfoxide)

data <- readBin("contract.docx", "raw", file.info("contract.docx")$size)
doc  <- pdf_open_from_docx_bytes(data)
text <- pdf_extract_text(doc, 0)

Julia

using PdfOxide

data = read("contract.docx")
doc  = open_from_docx_bytes(data)
text = extract_text(doc, 0)

Zig

const pdf_oxide = @import("pdf_oxide");
const a = std.heap.page_allocator;

const data = try std.fs.cwd().readFileAlloc("contract.docx", a, .unlimited);
var doc = try pdf_oxide.Document.openFromDocxBytes(data);
const text = try doc.extractText(a, 0);

Objective-C

#import "POXPdfOxide.h"
NSError *err = nil;

NSData *data = [NSData dataWithContentsOfFile:@"contract.docx"];
POXDocument *doc = [POXDocument openFromDocxBytes:data error:&err];
NSString *text = [doc extractText:0 error:&err];

Elixir

data = File.read!("contract.docx")
{:ok, doc} = PdfOxide.open_from_docx_bytes(data)
{:ok, text} = PdfOxide.extract_text(doc, 0)

Para PPTX y XLSX se usan los constructores correspondientes:

Formato de origen Go C# Swift
DOCX OpenFromDocxBytes(data) PdfDocument.OpenFromDocxBytes(data) Document.openFromDocxBytes(bytes)
PPTX OpenFromPptxBytes(data) PdfDocument.OpenFromPptxBytes(data) Document.openFromPptxBytes(bytes)
XLSX OpenFromXlsxBytes(data) PdfDocument.OpenFromXlsxBytes(data) Document.openFromXlsxBytes(bytes)

Rust / Python: el PdfDocument central no tiene el constructor open_from_docx_bytes. En Rust, convierte primero con OfficeConverter::new().convert_docx_bytes(&data)? y luego abre con PdfDocument::from_bytes(pdf_bytes)?. En Python, usa OfficeConverter.from_docx_bytes(data) (documentado arriba), que devuelve un Pdf.

use pdf_oxide::converters::office::OfficeConverter;
use pdf_oxide::document::PdfDocument;

let data = std::fs::read("contract.docx")?;
let pdf_bytes = OfficeConverter::new().convert_docx_bytes(&data)?;
let doc = PdfDocument::from_bytes(pdf_bytes)?;
println!("{} pages", doc.page_count()?);

Configuración (Rust)

Personaliza el tamaño de página, los márgenes y las fuentes con OfficeConfig:

use pdf_oxide::converters::office::{OfficeConverter, OfficeConfig};

let config = OfficeConfig::a4(); // A4 page size
let converter = OfficeConverter::with_config(config);
let pdf_bytes = converter.convert_docx("document.docx")?;

Campos de OfficeConfig

Campo Tipo Valor predeterminado Descripción
page_size PageSize Letter Dimensiones de la página
margins Margins 1 pulgada en todos los lados Márgenes de página en puntos (72pt = 1 pulgada)
embed_fonts bool false Si se deben incrustar fuentes
default_font String "Helvetica" Fuente de reserva
default_font_size f32 11.0 Tamaño de texto predeterminado en puntos
line_height f32 1.2 Multiplicador de altura de línea
include_images bool true Si se deben incluir imágenes incrustadas

Tamaños de página predefinidos

let config = OfficeConfig::letter(); // 8.5 × 11 inches (default)
let config = OfficeConfig::a4();     // 210 × 297 mm

Márgenes personalizados

use pdf_oxide::converters::office::Margins;

let mut config = OfficeConfig::letter();
config.margins = Margins::uniform(36.0);  // 0.5 inch margins
config.margins = Margins::none();          // No margins

Conversión por lotes

Python

from pdf_oxide import OfficeConverter
from pathlib import Path

office_dir = Path("documents/")
output_dir = Path("pdfs/")
output_dir.mkdir(exist_ok=True)

extensions = {".docx", ".xlsx", ".pptx"}

for doc_path in office_dir.iterdir():
    if doc_path.suffix.lower() in extensions:
        pdf = OfficeConverter.convert(str(doc_path))
        pdf.save(str(output_dir / doc_path.with_suffix(".pdf").name))
        print(f"Converted: {doc_path.name}")

Rust

use pdf_oxide::converters::office::OfficeConverter;
use std::fs;

let converter = OfficeConverter::new();

for entry in fs::read_dir("documents/")? {
    let path = entry?.path();
    match path.extension().and_then(|e| e.to_str()) {
        Some("docx" | "xlsx" | "pptx") => {
            let pdf_bytes = converter.convert(&path)?;
            let out = format!("pdfs/{}.pdf", path.file_stem().unwrap().to_str().unwrap());
            fs::write(&out, pdf_bytes)?;
            println!("Converted: {}", path.display());
        }
        _ => {}
    }
}

C++

#include <pdf_oxide/pdf_oxide.hpp>
#include <filesystem>
#include <fstream>
namespace fs = std::filesystem;

for (const auto& entry : fs::directory_iterator("documents/")) {
    auto path = entry.path();
    auto ext = path.extension().string();

    if (ext != ".docx" && ext != ".xlsx" && ext != ".pptx") continue;

    std::ifstream in(path, std::ios::binary);
    std::vector<std::uint8_t> bytes((std::istreambuf_iterator<char>(in)), {});

    auto doc =
        ext == ".docx" ? pdf_oxide::Document::open_from_docx_bytes(bytes)
        : ext == ".xlsx" ? pdf_oxide::Document::open_from_xlsx_bytes(bytes)
                         : pdf_oxide::Document::open_from_pptx_bytes(bytes);

    auto pdf = doc.get_source_bytes();
    auto out = "pdfs/" + path.stem().string() + ".pdf";
    std::ofstream(out, std::ios::binary)
        .write(reinterpret_cast<const char*>(pdf.data()), pdf.size());
}

Dart

import 'dart:io';
import 'package:pdf_oxide/pdf_oxide.dart';

Directory('pdfs').createSync(recursive: true);

for (final entry in Directory('documents').listSync()) {
  if (entry is! File) continue;
  final ext = entry.path.split('.').last.toLowerCase();
  final bytes = entry.readAsBytesSync();

  final doc = switch (ext) {
    'docx' => PdfDocument.openFromDocxBytes(bytes),
    'xlsx' => PdfDocument.openFromXlsxBytes(bytes),
    'pptx' => PdfDocument.openFromPptxBytes(bytes),
    _ => null,
  };
  if (doc == null) continue;

  final name = entry.uri.pathSegments.last.replaceAll(RegExp(r'\.\w+$'), '');
  File('pdfs/$name.pdf').writeAsBytesSync(doc.getSourceBytes());
}

R

library(pdfoxide)

dir.create("pdfs", showWarnings = FALSE)

for (path in list.files("documents", full.names = TRUE)) {
  ext   <- tolower(tools::file_ext(path))
  bytes <- readBin(path, "raw", file.info(path)$size)

  doc <- switch(ext,
    docx = pdf_open_from_docx_bytes(bytes),
    xlsx = pdf_open_from_xlsx_bytes(bytes),
    pptx = pdf_open_from_pptx_bytes(bytes),
    next)

  out <- file.path("pdfs", paste0(tools::file_path_sans_ext(basename(path)), ".pdf"))
  writeBin(pdf_get_source_bytes(doc), out)
}

Julia

using PdfOxide

mkpath("pdfs")

for path in readdir("documents"; join = true)
    ext   = lowercase(splitext(path)[2])
    bytes = read(path)

    doc = if ext == ".docx"
        open_from_docx_bytes(bytes)
    elseif ext == ".xlsx"
        open_from_xlsx_bytes(bytes)
    elseif ext == ".pptx"
        open_from_pptx_bytes(bytes)
    else
        continue
    end

    name = first(splitext(basename(path)))
    write(joinpath("pdfs", name * ".pdf"), get_source_bytes(doc))
end

Zig

const pdf_oxide = @import("pdf_oxide");
const a = std.heap.page_allocator;

try std.fs.cwd().makePath("pdfs");
var dir = try std.fs.cwd().openDir("documents", .{ .iterate = true });
var it = dir.iterate();
while (try it.next()) |entry| {
    const bytes = try dir.readFileAlloc(entry.name, a, .unlimited);

    var doc = if (std.mem.endsWith(u8, entry.name, ".docx"))
        try pdf_oxide.Document.openFromDocxBytes(bytes)
    else if (std.mem.endsWith(u8, entry.name, ".xlsx"))
        try pdf_oxide.Document.openFromXlsxBytes(bytes)
    else if (std.mem.endsWith(u8, entry.name, ".pptx"))
        try pdf_oxide.Document.openFromPptxBytes(bytes)
    else
        continue;

    const pdf = try doc.sourceBytes(a);
    const stem = entry.name[0 .. std.mem.lastIndexOfScalar(u8, entry.name, '.').?];
    const out = try std.fmt.allocPrint(a, "pdfs/{s}.pdf", .{stem});
    try std.fs.cwd().writeFile(.{ .sub_path = out, .data = pdf });
}

Objective-C

#import "POXPdfOxide.h"
NSError *err = nil;
NSFileManager *fm = [NSFileManager defaultManager];
[fm createDirectoryAtPath:@"pdfs" withIntermediateDirectories:YES attributes:nil error:&err];

for (NSString *name in [fm contentsOfDirectoryAtPath:@"documents" error:&err]) {
    NSString *path = [@"documents" stringByAppendingPathComponent:name];
    NSData *bytes = [NSData dataWithContentsOfFile:path];
    NSString *ext = name.pathExtension.lowercaseString;

    POXDocument *doc;
    if ([ext isEqualToString:@"docx"])      doc = [POXDocument openFromDocxBytes:bytes error:&err];
    else if ([ext isEqualToString:@"xlsx"]) doc = [POXDocument openFromXlsxBytes:bytes error:&err];
    else if ([ext isEqualToString:@"pptx"]) doc = [POXDocument openFromPptxBytes:bytes error:&err];
    else continue;

    NSData *pdf = [doc sourceBytesWithError:&err];
    NSString *out = [@"pdfs" stringByAppendingPathComponent:
        [name.stringByDeletingPathExtension stringByAppendingPathExtension:@"pdf"]];
    [pdf writeToFile:out atomically:YES];
}

Elixir

File.mkdir_p!("pdfs")

for name <- File.ls!("documents") do
  bytes = File.read!(Path.join("documents", name))

  result =
    case Path.extname(name) |> String.downcase() do
      ".docx" -> PdfOxide.open_from_docx_bytes(bytes)
      ".xlsx" -> PdfOxide.open_from_xlsx_bytes(bytes)
      ".pptx" -> PdfOxide.open_from_pptx_bytes(bytes)
      _ -> :skip
    end

  with {:ok, doc} <- result,
       {:ok, pdf} <- PdfOxide.source_bytes(doc) do
    out = Path.join("pdfs", Path.rootname(name) <> ".pdf")
    File.write!(out, pdf)
  end
end

Referencia de API

<a id=“office-pdf-officeconverter”></a>

Python — OfficeConverter

Método Devuelve Descripción
OfficeConverter.convert(path) Pdf Detectar formato automáticamente y convertir
OfficeConverter.from_docx(path) Pdf Convertir archivo DOCX
OfficeConverter.from_docx_bytes(data) Pdf Convertir DOCX desde bytes
OfficeConverter.from_xlsx(path) Pdf Convertir archivo XLSX
OfficeConverter.from_xlsx_bytes(data) Pdf Convertir XLSX desde bytes
OfficeConverter.from_pptx(path) Pdf Convertir archivo PPTX
OfficeConverter.from_pptx_bytes(data) Pdf Convertir PPTX desde bytes

Todos los métodos devuelven un objeto Pdf. Llama a pdf.save("output.pdf") o pdf.to_bytes() para obtener el resultado.

Rust — OfficeConverter

Método Devuelve Descripción
OfficeConverter::new() OfficeConverter Crear con configuración predeterminada
OfficeConverter::with_config(config) OfficeConverter Crear con configuración personalizada
convert(path) Result<Vec<u8>> Detectar formato automáticamente y convertir
convert_docx(path) Result<Vec<u8>> Convertir archivo DOCX
convert_docx_bytes(bytes) Result<Vec<u8>> Convertir DOCX desde bytes
convert_xlsx(path) Result<Vec<u8>> Convertir archivo XLSX
convert_xlsx_bytes(bytes) Result<Vec<u8>> Convertir XLSX desde bytes
convert_pptx(path) Result<Vec<u8>> Convertir archivo PPTX
convert_pptx_bytes(bytes) Result<Vec<u8>> Convertir PPTX desde bytes

PDF → Office — to_docx / to_pptx / to_xlsx

Exportado desde un documento PDF abierto. Disponible en Rust, Python, Go, C# y Swift.

Lenguaje Método Devuelve Descripción
Rust PdfDocument::to_docx(path) Result<()> Exportar PDF a archivo DOCX en disco
Rust PdfDocument::to_docx_bytes() Result<Vec<u8>> Exportar PDF a bytes DOCX
Rust PdfDocument::to_pptx(path) / to_pptx_bytes() Result<()> / Result<Vec<u8>> Exportar PDF a PPTX
Rust PdfDocument::to_xlsx(path) / to_xlsx_bytes() Result<()> / Result<Vec<u8>> Exportar PDF a XLSX
Python PdfDocument.to_docx(path) / to_docx_bytes() None / bytes Exportar PDF a DOCX
Python PdfDocument.to_pptx(path) / to_pptx_bytes() None / bytes Exportar PDF a PPTX
Python PdfDocument.to_xlsx(path) / to_xlsx_bytes() None / bytes Exportar PDF a XLSX
Go (*PdfDocument).ToDocxBytes() ([]byte, error) Exportar PDF a bytes DOCX
Go (*PdfDocument).ToPptxBytes() ([]byte, error) Exportar PDF a bytes PPTX
Go (*PdfDocument).ToXlsxBytes() ([]byte, error) Exportar PDF a bytes XLSX
C# PdfDocument.ToDocxBytes() byte[] Exportar PDF a bytes DOCX
C# PdfDocument.ToPptxBytes() byte[] Exportar PDF a bytes PPTX
C# PdfDocument.ToXlsxBytes() byte[] Exportar PDF a bytes XLSX
Swift Document.toDocx() [UInt8] Exportar PDF a bytes DOCX
Swift Document.toPptx() [UInt8] Exportar PDF a bytes PPTX
Swift Document.toXlsx() [UInt8] Exportar PDF a bytes XLSX

Office → documento PDF — open_from_*_bytes

Constructores de conveniencia de los bindings nativos que convierten bytes Office y devuelven un documento PDF abierto. Disponibles en Go, C#, Swift y el ABI de C. No disponibles en el PdfDocument central de Rust ni en Python — usa OfficeConverter en esos casos (ver tabla arriba).

Lenguaje Constructor Devuelve Descripción
Go OpenFromDocxBytes(data) (*PdfDocument, error) Abrir documento PDF desde bytes DOCX
Go OpenFromPptxBytes(data) (*PdfDocument, error) Abrir documento PDF desde bytes PPTX
Go OpenFromXlsxBytes(data) (*PdfDocument, error) Abrir documento PDF desde bytes XLSX
C# PdfDocument.OpenFromDocxBytes(data) PdfDocument Abrir documento PDF desde bytes DOCX
C# PdfDocument.OpenFromPptxBytes(data) PdfDocument Abrir documento PDF desde bytes PPTX
C# PdfDocument.OpenFromXlsxBytes(data) PdfDocument Abrir documento PDF desde bytes XLSX
Swift Document.openFromDocxBytes(bytes) Document Abrir documento PDF desde bytes DOCX
Swift Document.openFromPptxBytes(bytes) Document Abrir documento PDF desde bytes PPTX
Swift Document.openFromXlsxBytes(bytes) Document Abrir documento PDF desde bytes XLSX
C ABI pdf_document_open_from_docx_bytes(data, len, error_code) PdfDocument * Abrir documento PDF desde bytes DOCX
C ABI pdf_document_open_from_pptx_bytes(data, len, error_code) PdfDocument * Abrir documento PDF desde bytes PPTX
C ABI pdf_document_open_from_xlsx_bytes(data, len, error_code) PdfDocument * Abrir documento PDF desde bytes XLSX

Preguntas frecuentes

¿Se conserva el diseño al convertir un PDF a DOCX?

Sí, dentro de ciertos límites. Para documentos por debajo del umbral de maquetación (30 páginas para DOCX/PPTX, 200 para XLSX), to_docx_bytes / to_pptx_bytes / to_xlsx_bytes usan el camino de preservación de maquetación, que emite cada fragmento de texto PDF como un elemento posicionado y editable e incrusta las fuentes del PDF de origen, de modo que una conversión de ida y vuelta PDF → Office → PDF mantiene las dimensiones originales de la página. Los documentos más grandes recurren al camino de flujo, que redistribuye el texto en párrafos reales para que Word/PowerPoint/Excel los abra instantáneamente.

¿Puedo convertir un PDF de vuelta a PowerPoint o Excel, no solo a Word?

Sí. to_pptx/to_pptx_bytes mapean cada página PDF a una diapositiva con el tamaño del MediaBox de origen, y to_xlsx/to_xlsx_bytes mapean cada página a una hoja de cálculo. Ambos están disponibles en Rust, Python, Go, C# y Swift.

¿Por qué no existe open_from_docx_bytes en Python?

Python expone la dirección Office → PDF a través de la clase de nivel superior OfficeConverter (OfficeConverter.from_docx_bytes(data) devuelve un Pdf). Los constructores open_from_*_bytes son envoltorios de conveniencia añadidos en la capa FFI nativa (Go, C#, Swift, ABI de C), donde no existe una clase conversora separada.

¿Necesito tener Microsoft Office o LibreOffice instalado?

No. PDF Oxide lee y escribe el formato OOXML (DOCX/XLSX/PPTX) directamente en Rust puro. No hay llamadas a procesos externos, automatización COM ni instancias de Office sin interfaz gráfica — la conversión funciona igual en Linux, macOS y Windows.


Páginas relacionadas