cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

main
012 / internal / sheet / tablefile.go
tablefile.go 2.5K
1package sheet23import (4 "fmt"5)67// Tables in the file (version 6): a sheet's tables are a list in its8// view, each with its name, its range, header row included, its9// columns' names and its style:10//11// "tables": [{"name":"Sales","range":"A1:C20","columns":["Region","Month","Amount"],"banded":true,"header":true}],12//13// They need a version: a build without tables can't read the formulas14// that read them.15type fileTable struct {16 Name string `json:"name"`17 Range string `json:"range"`18 Columns []string `json:"columns,omitempty"`19 Banded bool `json:"banded,omitempty"`20 Header bool `json:"header,omitempty"`21}2223// hasTables reports whether any sheet has a table.24func (w *Workbook) hasTables() bool {25 for _, s := range w.sheets {26 if s.HasTables() {27 return true28 }29 }30 return false31}3233// encodeTables is the sheet's tables as the file holds them.34func encodeTables(ts []Table) []fileTable {35 out := make([]fileTable, len(ts))36 for i, t := range ts {37 out[i] = fileTable{Name: t.Name, Range: t.Range.String(), Columns: t.Cols, Banded: t.Banded, Header: t.Header}38 }39 return out40}4142// readTables restores a sheet's tables from a file, its cells already43// read.44func (s *Sheet) readTables(fts []fileTable) error {45 for _, ft := range fts {46 r, ok := ParseRange(ft.Range)47 if !ok {48 return fmt.Errorf("table %q: invalid range %q", ft.Name, ft.Range)49 }50 if err := s.LoadTable(Table{Name: ft.Name, Range: r, Cols: ft.Columns, Banded: ft.Banded, Header: ft.Header}); err != nil {51 return fmt.Errorf("table %q: %w", ft.Name, err)52 }53 }54 return nil55}5657// LoadTable adds t to the sheet as a loader does, without recording58// undo, its cells loaded. Columns t doesn't name, or names in a number59// other than its range's width, are named from its header row, and the60// names are made unique. Its range isn't checked against what else the61// sheet holds: edits since it was made (a region sent over it, a table62// moved onto another) may overlap them, and the file opens as it was63// saved.64func (s *Sheet) LoadTable(t Table) error {65 if err := s.wb.checkTableName(t.Name, ""); err != nil {66 return err67 }68 if t.Range.To.Row == t.Range.From.Row || !t.Range.To.Valid() {69 return fmt.Errorf("the range %s has no row below its header", t.Range)70 }71 t.Cols = columnNames(t.Cols, nil)72 if len(t.Cols) != t.Range.To.Col-t.Range.From.Col+1 {73 t.Cols = columnNames(s.rowTexts(Rect{From: t.Range.From, To: Addr{Col: t.Range.To.Col, Row: t.Range.From.Row}}), nil)74 }75 s.view.tables = append(s.view.tables, t)76 return nil77}