Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-ods

CI Go Reference Go Report Card License: MIT Release

Pure Go library for reading, writing, and evaluating ODS (OpenDocument Spreadsheet) files. Zero external dependencies, no LibreOffice required.

Features

  • Read and write .ods files (OpenDocument Spreadsheet)
  • Cell value management with typed getters/setters (string, int, float, bool, date)
  • Formula evaluation engine with 45+ spreadsheet functions
  • Formula recalculation with dependency graph and circular reference detection
  • Auto-recalc mode: formulas update automatically when cell values change
  • Sheet management (create, copy, rename, delete)
  • Row and column operations (insert, remove, resize, hide/show)
  • Column auto-fit (optimal width)
  • Cell merging and unmerging
  • Cell styling (font, fill, border, alignment)
  • Sheet and cell protection
  • Conditional formatting (calcext namespace)
  • Auto-filter with filter criteria and sort keys
  • Embedded images (PNG, JPEG, GIF, BMP) anchored to cells
  • Streaming row iterator for large files
  • Document properties (title, creator, description)

Requirements

  • Go 1.23+

Installation

go get github.com/mukbeast4/go-ods

Quick Start

package main

import (
	"fmt"
	"log"

	ods "github.com/mukbeast4/go-ods"
)

func main() {
	f := ods.NewFile()

	f.SetCellValue("Sheet1", "A1", "Product")
	f.SetCellValue("Sheet1", "B1", "Price")
	f.SetCellFloat("Sheet1", "A2", 10)
	f.SetCellFloat("Sheet1", "A3", 20)
	f.SetCellFloat("Sheet1", "A4", 30)

	f.SetCellFormula("Sheet1", "A5", "SUM([.A2:.A4])")
	f.RecalcSheet("Sheet1")

	val, _ := f.GetCellFloat("Sheet1", "A5")
	fmt.Println("Sum:", val) // Sum: 60

	if err := f.SaveAs("output.ods"); err != nil {
		log.Fatal(err)
	}
}

Formula Evaluation

The built-in formula engine supports evaluation without LibreOffice:

f := ods.NewFile()

f.SetCellFloat("Sheet1", "A1", 100)
f.SetCellFormula("Sheet1", "B1", "[.A1]*1.2")
f.SetCellFormula("Sheet1", "C1", "IF([.B1]>100;\"over\";\"under\")")

f.RecalcAll()

b1, _ := f.GetCellFloat("Sheet1", "B1")   // 120
c1, _ := f.GetCellValue("Sheet1", "C1")   // "over"

Auto-Recalc

Enable automatic formula recalculation when cell values change:

f.SetAutoRecalc(true)

f.SetCellFloat("Sheet1", "A1", 50)
// All dependent formulas are recalculated immediately

Supported Functions

Category Functions
Math SUM, AVERAGE, MIN, MAX, ABS, ROUND, FLOOR, CEIL, INT, MOD, POWER, SQRT, RAND, RANDBETWEEN
Logic IF, IFS, SWITCH, AND, OR, NOT, IFERROR
Text CONCATENATE, LEN, TRIM, UPPER, LOWER, LEFT, RIGHT, MID, FIND, SEARCH, SUBSTITUTE, REPLACE, TEXT, VALUE
Stats COUNT, COUNTA, COUNTIF, COUNTIFS, MEDIAN, STDEV, STDEVP, VAR, VARP, RANK, LARGE, SMALL, PERCENTILE
Conditional SUMIF, SUMIFS, SUMPRODUCT
Lookup VLOOKUP, HLOOKUP, XLOOKUP, INDEX, MATCH
Date/Time DATE, TODAY, NOW, YEAR, MONTH, DAY

Typed Cell Helpers

Convenience wrappers for the most common number formats:

f.SetCellCurrency("Sheet1", "A1", 1234.5, "$")     // "$1,234.50"
f.SetCellCurrency("Sheet1", "A2", 999.99, "€")     // "€999.99"

f.SetCellPercentage("Sheet1", "B1", 0.25, 0)       // "25%"
f.SetCellPercentage("Sheet1", "B2", 0.3333, 2)     // "33.33%"

t := time.Date(2024, 3, 15, 9, 30, 0, 0, time.UTC)
f.SetCellDateTime("Sheet1", "C1", t, "DD/MM/YYYY")

f.SetCellDuration("Sheet1", "D1", 90*time.Minute)  // stored as PT1H30M0S

Reading ODS Files

f, err := ods.OpenFile("spreadsheet.ods")
if err != nil {
	log.Fatal(err)
}
defer f.Close()

val, _ := f.GetCellValue("Sheet1", "A1")
rows, _ := f.GetRows("Sheet1")

for _, row := range rows {
	fmt.Println(row)
}

Sheet Operations

f.NewSheet("Data")
f.SetSheetName("Sheet1", "Summary")
f.CopySheet("Data", "DataBackup")
f.DeleteSheet("DataBackup")

sheets := f.GetSheetList() // ["Summary", "Data"]

Cell Styling

style := &ods.Style{
	Font: &ods.Font{
		Family:             "Arial",
		Size:               "12pt",
		Bold:               "bold",
		Color:              "#FF0000",
		Strikethrough:      true,
		StrikethroughColor: "#000000",
		VerticalAlign:      "super", // or "sub"
	},
	Fill: &ods.Fill{Color: "#FFFF00"},
	Alignment: &ods.Alignment{
		Horizontal: "center",
		Rotation:   45,  // degrees (0-360, negatives are normalized)
		Indent:     2,   // 0.25cm increments
	},
}

styleID, _ := f.NewStyle(style)
f.SetCellStyle("Sheet1", "A1", "A1", styleID)

Row and Column Operations

f.InsertRows("Sheet1", 3, 2)       // Insert 2 rows at row 3
f.RemoveRow("Sheet1", 5)           // Remove row 5
f.SetColWidth("Sheet1", "B", 5.0)  // Set column B width

f.SetRowVisible("Sheet1", 2, false)  // Hide row 2
f.SetColVisible("Sheet1", "C", false) // Hide column C
f.SetColAutoFit("Sheet1", "A", true)  // Auto-fit column A width
f.SetRowAutoFit("Sheet1", 1, true)    // Auto-fit row 1 height

Sheet Protection

f.SetSheetProtection("Sheet1", true)

protected, _ := f.IsSheetProtected("Sheet1") // true

locked := true
styleID, _ := f.NewStyle(&ods.Style{
	Protected: &locked,
})
f.SetCellStyle("Sheet1", "A1", "A1", styleID)

Conditional Formatting

rules := []ods.ConditionalRule{
	{Value: "of:cell-content()>90", StyleName: "good", BaseCellAddress: "Sheet1.A1"},
	{Value: "of:cell-content()<50", StyleName: "bad", BaseCellAddress: "Sheet1.A1"},
}
f.SetConditionalFormat("Sheet1", "A1:A100", rules)

formats, _ := f.GetConditionalFormats("Sheet1")
f.RemoveConditionalFormat("Sheet1", "A1:A100")

Auto-Filter, Filter Criteria and Sort

f.SetAutoFilter("Sheet1", "A1", "D100")

f.SetFilterCriteria("Sheet1", []ods.FilterCriteria{
	{Column: 0, Values: []string{"Alice"}},
})

f.SetSort("Sheet1", []ods.SortKey{
	{Column: 1, Descending: true},
})

criteria, _ := f.GetFilterCriteria("Sheet1")
sortKeys, _ := f.GetSort("Sheet1")

f.ClearFilterCriteria("Sheet1")
f.RemoveSort("Sheet1")

Embedded Images

Anchor images (PNG, JPEG, GIF, BMP) to any cell. Format is auto-detected, dimensions are in centimeters, identical binaries are deduplicated.

f.AddImage("Sheet1", "B2", "logo.png", &ods.ImageOptions{Width: 4, Height: 3})

data, _ := os.ReadFile("chart.jpg")
f.AddImageFromBytes("Sheet1", "D5", data, &ods.ImageOptions{
	Width: 6, Height: 4, OffsetX: 0.5, OffsetY: 0.25,
})

images, _ := f.GetImages("Sheet1")
for _, img := range images {
	fmt.Printf("%s: %s %vx%vcm\n", img.CellRef, img.Format, img.Width, img.Height)
}

f.RemoveImages("Sheet1", "B2")

Examples

A collection of runnable samples lives under examples/. Each sub-directory is a standalone main package:

go run ./examples/quickstart   # cells, formula, save
go run ./examples/formulas     # aggregation functions
go run ./examples/styling      # fonts, fills, borders, rotation
go run ./examples/autofilter   # filter + sort
go run ./examples/streaming    # 10k rows via AppendRows + RowIterator
go run ./examples/roundtrip    # open -> mutate -> save
go run ./examples/images       # embed a PNG

See examples/README.md for a breakdown of each sample.

Contributing

We welcome contributions! Please read our Contributing Guide and Code of Conduct before submitting a pull request.

Security

To report a security vulnerability, please see our Security Policy.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Pure Go library for reading, writing, and evaluating ODS (OpenDocument Spreadsheet) files

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages