Skip to content

Biblioteca Office para Go — Início Rápido

O pacote Go github.com/yfedoseev/office_oxide/go envolve a FFI C do office_oxide via cgo e oferece tipos Go idiomáticos para ler, converter e editar DOCX / XLSX / PPTX / DOC / XLS / PPT.

Instalação

go get github.com/yfedoseev/office_oxide/go@latest

O binding precisa da biblioteca C office_oxide na hora do link. Duas formas de fornecê-la.

Opção 1 — instalador em uma linha (recomendado):

go run github.com/yfedoseev/office_oxide/go/cmd/install@latest

O instalador baixa o liboffice_oxide prebuilt (e o header) compatível com seu OS/arch e coloca onde o cgo encontra. Rode de novo após upgrade para pegar a nova ABI.

Opção 2 — definir as flags do cgo manualmente se você compilou a partir do source Rust (cargo build --release --lib) ou tem a lib em um prefixo do sistema:

export CGO_CFLAGS="-I/usr/local/include"
export CGO_LDFLAGS="-L/usr/local/lib -loffice_oxide"

Ler um documento

package main

import (
    "fmt"
    "log"

    officeoxide "github.com/yfedoseev/office_oxide/go"
)

func main() {
    doc, err := officeoxide.Open("report.docx")
    if err != nil {
        log.Fatal(err)
    }
    defer doc.Close()

    text, err := doc.PlainText()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(text)
}

Helper de uma só chamada:

text, err := officeoxide.ExtractText("report.docx")

API principal

doc, err := officeoxide.Open("file.xlsx")
if err != nil { log.Fatal(err) }
defer doc.Close()

format, _ := doc.Format()      // "xlsx"
text, _   := doc.PlainText()
md, _     := doc.ToMarkdown()
html, _   := doc.ToHTML()
irJSON, _ := doc.ToIRJSON()

err = doc.SaveAs("file.docx")

Document envolve um handle C; um finalizer libera caso você esqueça Close, mas sempre prefira defer doc.Close() para limpeza determinística.

Abrir a partir de bytes (útil para streaming / serverless):

data, _ := os.ReadFile("report.pptx")
doc, err := officeoxide.OpenFromBytes(data, "pptx")

format precisa ser "docx", "xlsx", "pptx", "doc", "xls" ou "ppt".

Edição

Os handles editáveis preservam todas as partes OPC inalteradas (imagens, gráficos, XML customizado) ao salvar. Apenas DOCX, XLSX e PPTX.

ed, err := officeoxide.OpenEditable("template.docx")
if err != nil { log.Fatal(err) }
defer ed.Close()

n, _ := ed.ReplaceText("{{name}}", "Alice")
fmt.Printf("%d substituições\n", n)

err = ed.Save("out.docx")

Substituir texto em DOCX / PPTX

ed, _ := officeoxide.OpenEditable("slides.pptx")
defer ed.Close()

ed.ReplaceText("Q3", "Q4")
ed.ReplaceText("2024", "2025")

buf, _ := ed.SaveToBytes()   // []byte pronto para upload / stream
_ = os.WriteFile("slides_q4.pptx", buf, 0o644)

Definir células XLSX

ed, _ := officeoxide.OpenEditable("budget.xlsx")
defer ed.Close()

ed.SetCell(0, "A1", officeoxide.NewStringCell("Total"))
ed.SetCell(0, "B1", officeoxide.NewNumberCell(42.5))
ed.SetCell(0, "C1", officeoxide.NewBoolCell(true))
ed.SetCell(0, "D1", officeoxide.NewEmptyCell())

ed.Save("budget.xlsx")

Use NewStringCell, NewNumberCell, NewBoolCell ou NewEmptyCell — o construtor escolhe a variante certa para a chamada FFI.

IR independente de formato

doc.ToIRJSON() devolve JSON que segue o esquema DocumentIR do Rust. Faça o Unmarshal no formato que precisar:

import "encoding/json"

irJSON, _ := doc.ToIRJSON()

var ir struct {
    Sections []struct {
        Title    *string           `json:"title"`
        Elements []json.RawMessage `json:"elements"`
    } `json:"sections"`
}
_ = json.Unmarshal([]byte(irJSON), &ir)
fmt.Printf("%d seções\n", len(ir.Sections))

Detectar formato sem abrir

fmt := officeoxide.DetectFormat("mystery.bin")  // "" se não for suportado

Formatos legados

Abrem como OOXML; SaveAs converte transparentemente via IR:

doc, _ := officeoxide.Open("old.xls")
defer doc.Close()
_ = doc.SaveAs("modern.xlsx")

Erros

Toda chamada falível devolve um *officeoxide.Error com código tipado e a operação de origem:

if _, err := officeoxide.Open("missing.docx"); err != nil {
    var e *officeoxide.Error
    if errors.As(err, &e) {
        fmt.Printf("code=%d op=%s\n", e.Code, e.Op)
    }
}

Usar um handle fechado devolve officeoxide.ErrClosed.

Código Nome Significado
0 OK sucesso
1 INVALID_ARG nil / vazio / string de formato errada
2 IO erro de filesystem
3 PARSE documento corrompido
4 EXTRACTION parsing OK, mas a renderização falhou
5 INTERNAL bug — abra uma issue
6 UNSUPPORTED extensão/feature não suportada

Solução de problemas

Sintoma Solução
could not determine kind of name for C.office_document_open Os headers C não estão visíveis ao cgo. Rode o instalador ou defina CGO_CFLAGS.
cannot find -loffice_oxide no link Defina CGO_LDFLAGS="-L/path/to/lib -loffice_oxide" ou rode o instalador.
Em runtime cannot open shared object file Adicione o diretório da lib em LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (macOS), ou copie a DLL ao lado do binário (Windows).
unsupported format em .doc/.xls Garanta que a extensão esteja em minúsculas, ou chame OpenFromBytes(data, "doc").
Cross-compilation falha cgo precisa de uma toolchain C que case com o alvo. Use zig cc ou CC=aarch64-linux-gnu-gcc.

Veja também