xls

package module
v0.0.0-...-0d2c7ae Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2025 License: Apache-2.0 Imports: 14 Imported by: 0

README

xls

GoDoc

A pure Go library for reading Microsoft Excel .xls (BIFF8) files.

This is a maintained and modernized fork of the original library by Rongshu Tech (Chinese), based on libxls.
Special thanks to original contributors including @tgulacsi and @flyin9.

Forked from


✨ What's New in This Fork

  • ✅ Added OpenStream function to read .xls files from any io.Reader
  • ✅ Refactored core internals for clarity and maintainability
  • ✅ Added detailed inline documentation and comments
  • ✅ Improved test coverage and modernized test suite
  • ✅ Workbook Stream tag in some xls files came as WORKBOOK

📦 Basic Usage

import "github.com/augcampos/xls"

// Open from file (auto-closes on error)
wb, err := xls.Open("example.xls")
if err != nil {
	log.Fatal(err)
}

// Open from file with manual control over closing
wb, closer, err := xls.OpenWithCloser("example.xls")
if err != nil {
	log.Fatal(err)
}
defer closer.Close()

// Open from an io.Reader (fully buffered into memory)
f, _ := os.Open("example.xls")
defer f.Close()
wb, err := xls.OpenStream(f)

See GoDoc for full API documentation and examples.


📁 Features

  • Reads .xls (BIFF8) files
  • Supports cell values, formats, dates, and SST (shared string table)
  • Minimal dependencies
  • Zero C bindings – pure Go implementation

🛠 Limitations

  • Write support (.xls export) is not available
  • Formula evaluation is not yet implemented

Documentation

Overview

xls package use to parse the 97 -2004 microsoft xls file(".xls" suffix, NOT ".xlsx" suffix )

there are some example in godoc, please follow them.

Index

Examples

Constants

View Source
const (
	MJD_0      float64 = 2400000.5
	MJD_JD2000 float64 = 51544.5
)

Variables

View Source
var ErrIsInt = fmt.Errorf("is int")
View Source
var ErrWorkbookNotFound = errors.New("xls: no Workbook or Book stream found")

ErrWorkbookNotFound is returned when neither "Workbook" nor "Book" stream could be found in the OLE2 directory structure.

Functions

func CompareXlsXlsx

func CompareXlsXlsx(xlsFilePath, xlsxFilePath string) string

CompareXlsXlsx compares the content of an XLS file against an XLSX file. It returns an empty string if the files are considered equivalent, or a string describing the first encountered mismatch.

Types

type BlankCol

type BlankCol struct {
	Col
	Xf uint16 // Format index (XF)
}

BlankCol represents a cell that is visually empty but may still have formatting applied. This is common in sparse worksheets or cells with just borders/colors and no content.

func (*BlankCol) String

func (c *BlankCol) String(_ *WorkBook) []string

String returns an empty string for a blank cell.

type CellRange

type CellRange struct {
	FirstRowB uint16
	LastRowB  uint16
	FristColB uint16
	LastColB  uint16
}

range type of multi cells in multi rows.

func (*CellRange) FirstCol

func (c *CellRange) FirstCol() uint16

func (*CellRange) FirstRow

func (c *CellRange) FirstRow() uint16

func (*CellRange) LastCol

func (c *CellRange) LastCol() uint16

func (*CellRange) LastRow

func (c *CellRange) LastRow() uint16

type Col

type Col struct {
	RowB      uint16
	FirstColB uint16
}

func (*Col) FirstCol

func (c *Col) FirstCol() uint16

FirstCol returns the starting column index (0-based) for this cell or cell range. In most cases, FirstCol == LastCol for a single-cell value.

func (*Col) LastCol

func (c *Col) LastCol() uint16

LastCol returns the ending column index for this cell or cell range. By default, it equals FirstCol unless overridden in a derived type.

func (*Col) Row

func (c *Col) Row() uint16

Row returns the row index (0-based) where this column's data is located. This is used to identify the row number in the Excel sheet.

func (*Col) String

func (c *Col) String(_ *WorkBook) []string

String returns a string slice representation of the column's contents. This default implementation returns a single placeholder value and is meant to be overridden by concrete column types (e.g. NumberCol, RkCol).

type Coler

type Coler interface {
	Row() uint16
}

type Font

type Font struct {
	Info *FontInfo
	Name string
}

type FontInfo

type FontInfo struct {
	Height     uint16
	Flag       uint16
	Color      uint16
	Bold       uint16
	Escapement uint16
	Underline  byte
	Family     byte
	Charset    byte
	Notused    byte
	NameB      byte
}

type Format

type Format struct {
	Head struct {
		Index uint16
		Size  uint16
	}
	// contains filtered or unexported fields
}

type FormulaCol

type FormulaCol struct {
	Header struct {
		Col
		IndexXf uint16  // Format index (XF)
		Result  [8]byte // Raw result of formula evaluation
		Flags   uint16  // Evaluation flags (e.g. result type)
		// contains filtered or unexported fields
	}
	Bts []byte // Additional payload or expression data (currently unused)
}

FormulaCol represents a cell that contains a formula, but whose result is not a string and must be interpreted from raw bytes.

The Result field may contain the precomputed value as 8 bytes, but decoding it properly is left for future implementation (TODO).

func (*FormulaCol) String

func (c *FormulaCol) String(_ *WorkBook) []string

String returns a placeholder indicating that formula result parsing is not yet implemented.

type FormulaStringCol

type FormulaStringCol struct {
	Col
	RenderedValue string
}

FormulaStringCol represents a formula whose result is a string literal. The result has already been rendered and is stored in RenderedValue.

func (*FormulaStringCol) String

func (c *FormulaStringCol) String(_ *WorkBook) []string

String returns the already-rendered string result of a formula cell.

type HyperLink struct {
	CellRange
	Description      string
	TextMark         string
	TargetFrame      string
	URL              string
	ShortedFilePath  string
	ExtendedFilePath string
	IsURL            bool
}

hyperlink type's content.

func (*HyperLink) String

func (h *HyperLink) String(_ *WorkBook) []string

get the hyperlink string, use the public variable Url to get the original Url.

type LabelsstCol

type LabelsstCol struct {
	Col
	Xf  uint16 // Format index (XF)
	Sst uint32 // Index into the shared string table (wb.sst)
}

LabelsstCol represents a cell that refers to the shared string table (SST).

func (*LabelsstCol) String

func (c *LabelsstCol) String(wb *WorkBook) []string

String returns the resolved string from the SST at the given index.

type MulBlankCol

type MulBlankCol struct {
	Col
	Xfs      []uint16
	LastColB uint16
}

func (*MulBlankCol) LastCol

func (c *MulBlankCol) LastCol() uint16

LastCol returns the last column index represented by this MulBlankCol. This is used when a row contains a sequence of adjacent blank cells, each with its own formatting (XF) index.

func (*MulBlankCol) String

func (c *MulBlankCol) String(_ *WorkBook) []string

String returns a slice of empty strings, one for each blank cell in the group.

Even though these cells are visually empty, they may have distinct formatting information stored in the XF index (available via c.Xfs).

type MulrkCol

type MulrkCol struct {
	Col
	Xfrks    []XfRk
	LastColB uint16
}

func (*MulrkCol) LastCol

func (c *MulrkCol) LastCol() uint16

LastCol returns the last column index represented by this MulrkCol. This allows the caller to know how many adjacent cells are included.

func (*MulrkCol) String

func (c *MulrkCol) String(wb *WorkBook) []string

String returns a string slice with formatted values for each cell in the multi-column RK group.

Each entry in Xfrks corresponds to a cell, and the XfRk's String method is used to format its value according to the workbook's formatting rules.

type NumberCol

type NumberCol struct {
	Col
	Index uint16
	Float float64
}

func (*NumberCol) String

func (c *NumberCol) String(_ *WorkBook) []string

String returns the floating-point value of the NumberCol as a string.

This corresponds to the BIFF `NUMBER` record, which stores an IEEE 754 float.

type RK

type RK uint32

func (RK) Float

func (rk RK) Float() (float64, error)

Float attempts to return the RK value as a float64.

The RK format can encode either an integer or a float. If the RK value represents an integer, this method returns an error (ErrIsInt).

func (RK) String

func (rk RK) String() string

String returns the RK value formatted as either a float or int string.

type Ranger

type Ranger interface {
	FirstRow() uint16
	LastRow() uint16
}

range type of multi rows.

type RkCol

type RkCol struct {
	Col
	Xfrk XfRk
}

RkCol represents a single cell that stores a value in RK format (compact int/float).

func (*RkCol) String

func (c *RkCol) String(wb *WorkBook) []string

String returns the formatted string representation of the RK value, respecting any number/date formatting rules from the workbook.

type Row

type Row struct {
	// contains filtered or unexported fields
}

Row the data of one row

func (*Row) Col

func (r *Row) Col(i int) string

Col Get the Nth Col from the Row, if has not, return nil. Suggest use Has function to test it.

func (*Row) ColExact

func (r *Row) ColExact(i int) string

ColExact Get the Nth Col from the Row, if has not, return nil. For merged cells value is returned for first cell only

func (*Row) FirstCol

func (r *Row) FirstCol() int

FirstCol Get the number of First Col of the Row.

func (*Row) LastCol

func (r *Row) LastCol() int

LastCol Get the number of Last Col of the Row.

type SstInfo

type SstInfo struct {
	Total uint32
	Count uint32
}

type TWorkSheetVisibility

type TWorkSheetVisibility byte
const (
	WorkSheetVisible    TWorkSheetVisibility = 0
	WorkSheetHidden     TWorkSheetVisibility = 1
	WorkSheetVeryHidden TWorkSheetVisibility = 2
)

type WorkBook

type WorkBook struct {
	Is5ver   bool
	Type     uint16
	Codepage uint16
	Xfs      []st_xf_data
	Fonts    []Font
	Formats  map[uint16]*Format

	Author string
	// contains filtered or unexported fields
}

xls workbook type

func Open

func Open(file string) (*WorkBook, error)

Open opens an XLS file from the given file path. It returns a parsed WorkBook object, or an error if the file could not be opened or parsed successfully.

Example

ExampleOpen demonstrates how to open an XLS file and access basic metadata.

xlFile, err := Open("testdata/Table.xls")
if err != nil {
	fmt.Println("failed to open XLS:", err)
	return
}

// Print workbook author metadata
fmt.Println("Author:", xlFile.Author)

func OpenReader

func OpenReader(reader io.ReadSeeker) (*WorkBook, error)

OpenReader parses an XLS workbook from a seekable input stream (e.g., file, bytes.Reader). The reader must implement io.ReadSeeker as the underlying OLE2 format requires random access.

func OpenStream

func OpenStream(r io.Reader) (*WorkBook, error)

OpenStream loads an XLS workbook from any io.Reader (e.g., network stream, compressed archive). Since the XLS format requires seeking, the entire input is buffered into memory. Not recommended for very large XLS files due to memory usage.

func OpenWithCloser

func OpenWithCloser(file string) (*WorkBook, io.Closer, error)

OpenWithCloser is similar to Open, but also returns the file handle (as io.Closer). This allows the caller to manually close the file when done. Useful when you want to avoid leaking file descriptors.

func (*WorkBook) GetFirstSheet

func (wb *WorkBook) GetFirstSheet() *WorkSheet

func (*WorkBook) GetSheet

func (wb *WorkBook) GetSheet(num int) *WorkSheet

Get one sheet by its number

Example

ExampleWorkBook_GetSheet reads the first sheet and prints the first two columns of each row.

xlFile, err := Open("testdata/Table.xls")
if err != nil {
	fmt.Println("failed to open XLS:", err)
	return
}

sheet := xlFile.GetSheet(0)
if sheet == nil {
	fmt.Println("sheet not found")
	return
}

fmt.Printf("Total Lines: %d (%s)", sheet.MaxRow, sheet.Name)

// Iterate over all rows and print values from the first two columns
for i := 0; i <= int(sheet.MaxRow); i++ {
	row := sheet.Row(i)
	col1 := row.Col(0)
	col2 := row.Col(1)
	fmt.Printf("\n%s, %s", col1, col2)
}

func (*WorkBook) GetSheetByName

func (wb *WorkBook) GetSheetByName(sheetName string) *WorkSheet

func (*WorkBook) NumSheets

func (wb *WorkBook) NumSheets() int

Get the number of all sheets, look into example

Example

ExampleWorkBook_NumberSheets shows how to list all sheet names in the workbook.

xlFile, err := Open("testdata/Table.xls")
if err != nil {
	fmt.Println("failed to open XLS:", err)
	return
}

// Iterate over all sheets and print their names
for i := 0; i < xlFile.NumSheets(); i++ {
	sheet := xlFile.GetSheet(i)
	fmt.Println("Sheet:", sheet.Name)
}

func (*WorkBook) Parse

func (wb *WorkBook) Parse(buf io.ReadSeeker)

func (*WorkBook) ReadAllCells

func (wb *WorkBook) ReadAllCells(maxRowsTotal int) [][]string

ReadAllCells reads all cell data from the workbook up to a maximum number of rows. Note: This may consume significant memory for large files.

type WorkSheet

type WorkSheet struct {
	Name       string
	Selected   bool
	Visibility TWorkSheetVisibility

	// NOTICE: this is the max row number of the sheet, so it should be count -1
	MaxRow uint16
	// contains filtered or unexported fields
}

WorkSheet in one WorkBook

func (*WorkSheet) Row

func (w *WorkSheet) Row(i int) *Row

type Xf5

type Xf5 struct {
	Font      uint16
	Format    uint16
	Type      uint16
	Align     uint16
	Color     uint16
	Fill      uint16
	Border    uint16
	LineStyle uint16
}

type Xf8

type Xf8 struct {
	Font        uint16
	Format      uint16
	Type        uint16
	Align       byte
	Rotation    byte
	Ident       byte
	UsedAttr    byte
	LineStyle   uint32
	LineColor   uint32
	GroundColor uint16
}

type XfRk

type XfRk struct {
	Index uint16
	Rk    RK
}

func (*XfRk) String

func (xf *XfRk) String(workBook *WorkBook) string

String converts the RK value to its formatted string representation, depending on the associated cell format (Xf) and number format definition.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL