cat / 012
clone

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

Fit new pivot sheets' columns and list a pivot filter's values

Dami committed a40bf99
A pivot created on its own sheet widens its columns to the results
until a width is set by hand. PivotFilterValues lists a source column's
values the way a filter's values list does, sharing its code. XLSX
downloads write pivot results as values.
commit
a40bf99103deef78ff6da878ff8b4b7b16a4e177
parent
901e837a5e952f9058fbe6edc4c1e869b3083643
author
Dami <dami.etoile@gmail.com>
7 files changed, +113 -8
Minternal/fileio/xlsx_test.go31++++++++++++++++++++++++++++++
Minternal/sheet/filter.go14++++++++++----
Minternal/sheet/pivot.go29+++++++++++++++++++++++++---
Minternal/sheet/pivot_test.go26+++++++++++++++++++++++++
Minternal/sheet/pivotlayout.go18+++++++++++++++++
Minternal/sheet/sheet.go1+
Minternal/sheet/workbook.go2+-
M internal/fileio/xlsx_test.go +31 -0
@@ -251,6 +251,37 @@ func TestExcelFormulas(t *testing.T) {
251251 }252252 }253253 254+// A pivot table goes out as the values it shows: Excel gets no pivot255+// cache, and its results read back as plain cells.256+func TestXLSXPivotAsValues(t *testing.T) {257+ src := build(t, map[string]string{"A1": "Item", "B1": "Qty", "A2": "Pen", "B2": "3", "A3": "Ink", "B3": "4", "A4": "Pen", "B4": "5"})258+ r := sheet.NewRect(addr(t, "A1"), addr(t, "B4"))259+ p := sheet.NewPivot(src, r)260+ p.Rows = []sheet.PivotGroup{{Col: 0}}261+ p.Values = []sheet.PivotValue{{Col: 1, Summarize: sheet.SumBy}}262+ pv, err := src.Book().CreatePivot(src, r, "", p)263+ if err != nil {264+ t.Fatal(err)265+ }266+ name := filepath.Join(t.TempDir(), "pivot.xlsx")267+ if _, err := Export(context.Background(), name, XLSX, SnapBook(pv), ExportOptions{}); err != nil {268+ t.Fatal(err)269+ }270+ x, err := excelize.OpenFile(name)271+ if err != nil {272+ t.Fatal(err)273+ }274+ defer x.Close()275+ for cell, want := range map[string]string{"A1": "Item", "B1": "SUM of Qty", "A3": "Pen", "B3": "8", "B4": "12"} {276+ if got, _ := x.GetCellValue("Pivot Table 1", cell); got != want {277+ t.Errorf("%s = %q, want %q", cell, got, want)278+ }279+ if f, _ := x.GetCellFormula("Pivot Table 1", cell); f != "" {280+ t.Errorf("%s has formula %q", cell, f)281+ }282+ }283+}284+254285 // Every sheet goes out to Excel and comes back, with references between255286 // sheets, the sheet shown and named ranges.256287 func TestXLSXWorkbookRoundTrip(t *testing.T) {
M internal/sheet/filter.go +10 -4
M internal/sheet/pivot.go +26 -3
@@ -105,6 +105,11 @@ type pivotState struct {
105105 stale bool // recompute at the end of the current change106106 out Rect // what the last result covered, from A1107107 err string // why the pivot shows #REF!, or ""108+ // fit has the result's columns widened to fit, while the sheet is109+ // the pivot's own: from its creation until a width is set by hand.110+ // The widths aren't undo steps; undoing the creation removes them111+ // with the sheet.112+ fit bool108113 }109114 110115 // clone returns a deep copy, so a stored pivot never shares slices.
@@ -195,9 +200,7 @@ func (w *Workbook) CreatePivot(src *Sheet, r Rect, name string, p Pivot) (*Sheet
195200 w.change(s, "create "+name, Rect{}, func() {196201 w.recordSheets()197202 w.insert(s, w.Index(src)+1)198- s.pivot.def = p.clone()199- s.pivot.stale = true200- s.pivot.out = Rect{}203+ s.pivot = pivotState{def: p.clone(), stale: true, fit: true}201204 })202205 return s, nil203206 }
@@ -356,6 +359,26 @@ func (w *Workbook) DefaultSummarize(p Pivot, col int) Summarize {
356359 return CountABy357360 }358361 362+// PivotFilterValues lists the distinct values of column col of the363+// pivot's source, among the rows its other filters let through, as a364+// filter's values list does.365+func (w *Workbook) PivotFilterValues(p Pivot, col int) []FilterValue {366+ src := w.Lookup(p.Source)367+ if src == nil || p.Lost {368+ return nil369+ }370+ var others []PivotFilter371+ var hidden []string372+ for _, f := range p.Filters {373+ if f.Col == col {374+ hidden = f.Criteria.Hidden375+ } else {376+ others = append(others, f)377+ }378+ }379+ return src.valuesList(p.Range, col, pivotTests(others), hidden, true)380+}381+359382 // NewPivot starts a pivot over r on src with nothing chosen yet and both360383 // grand totals on, as Sheets' new pivot tables.361384 func NewPivot(src *Sheet, r Rect) Pivot {
M internal/sheet/pivot_test.go +26 -0
M internal/sheet/pivotlayout.go +18 -0
M internal/sheet/sheet.go +1 -0
M internal/sheet/workbook.go +1 -1