Skip to content

Commit

Permalink
spreadsheet: use ParseCellReference from reference package
Browse files Browse the repository at this point in the history
Drop the old cell reference parsing code and use the new code
that parses to a struct and identifies absolute references
  • Loading branch information
tbaliance committed Oct 2, 2017
1 parent 988f2e3 commit 968e4ba
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 157 deletions.
11 changes: 5 additions & 6 deletions spreadsheet/cell.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,10 @@ func (c Cell) SetFormulaShared(formula string, rows, cols uint32) error {
c.x.F = sml.NewCT_CellFormula()
c.x.F.TAttr = sml.ST_CellFormulaTypeShared
c.x.F.Content = formula
col, rowIdx, err := ParseCellReference(c.Reference())
cref, err := reference.ParseCellReference(c.Reference())
if err != nil {
return err
}
colIdx := reference.ColumnToIndex(col)

sid := uint32(0)
for _, r := range c.s.SheetData.Row {
Expand All @@ -119,13 +118,13 @@ func (c Cell) SetFormulaShared(formula string, rows, cols uint32) error {
}
}

ref := fmt.Sprintf("%s%d:%s%d", col, rowIdx, reference.IndexToColumn(colIdx+cols), rowIdx+rows)
ref := fmt.Sprintf("%s%d:%s%d", cref.Column, cref.RowIdx, reference.IndexToColumn(cref.ColumnIdx+cols), cref.RowIdx+rows)
c.x.F.RefAttr = gooxml.String(ref)
c.x.F.SiAttr = gooxml.Uint32(sid)
sheet := Sheet{c.w, nil, c.s}
for row := rowIdx; row <= rowIdx+rows; row++ {
for col := colIdx; col <= colIdx+cols; col++ {
if row == rowIdx && col == colIdx {
for row := cref.RowIdx; row <= cref.RowIdx+rows; row++ {
for col := cref.ColumnIdx; col <= cref.ColumnIdx+cols; col++ {
if row == cref.RowIdx && col == cref.ColumnIdx {
continue
}
ref := fmt.Sprintf("%s%d", reference.IndexToColumn(col), row)
Expand Down
11 changes: 7 additions & 4 deletions spreadsheet/comments.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (c Comments) AddComment(cellRef string, author string) RichText {
}

// AddCommentWithStyle adds a new comment styled in a default way
func (c Comments) AddCommentWithStyle(cellRef string, author string, comment string) {
func (c Comments) AddCommentWithStyle(cellRef string, author string, comment string) error {
rt := c.AddComment(cellRef, author)
run := rt.AddRun()
run.SetBold(true)
Expand All @@ -80,7 +80,10 @@ func (c Comments) AddCommentWithStyle(cellRef string, author string, comment str
run.SetColor(color.Black)
run.SetText("\r\n" + comment + "\r\n")

col, rowIdx, _ := ParseCellReference(cellRef)
colIdx := reference.ColumnToIndex(col)
c.w.vmlDrawings[0].Shape = append(c.w.vmlDrawings[0].Shape, vmldrawing.NewCommentShape(int64(colIdx), int64(rowIdx-1)))
cref, err := reference.ParseCellReference(cellRef)
if err != nil {
return err
}
c.w.vmlDrawings[0].Shape = append(c.w.vmlDrawings[0].Shape, vmldrawing.NewCommentShape(int64(cref.ColumnIdx), int64(cref.RowIdx-1)))
return nil
}
10 changes: 6 additions & 4 deletions spreadsheet/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ package spreadsheet

import (
"strconv"

"baliance.com/gooxml/spreadsheet/reference"
)

// SortOrder is a column sort order.
Expand All @@ -32,16 +34,16 @@ type Comparer struct {
func (c Comparer) LessRows(column string, lhs, rhs Row) bool {
var lhsCell, rhsCell Cell
for _, c := range lhs.Cells() {
cellCol, _, _ := ParseCellReference(c.Reference())
if cellCol == column {
cref, _ := reference.ParseCellReference(c.Reference())
if cref.Column == column {
lhsCell = c
break
}
}

for _, c := range rhs.Cells() {
cellCol, _, _ := ParseCellReference(c.Reference())
if cellCol == column {
cref, _ := reference.ParseCellReference(c.Reference())
if cref.Column == column {
rhsCell = c
break
}
Expand Down
50 changes: 0 additions & 50 deletions spreadsheet/parse.go

This file was deleted.

47 changes: 0 additions & 47 deletions spreadsheet/parse_test.go

This file was deleted.

10 changes: 5 additions & 5 deletions spreadsheet/row.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ func (r Row) AddCell() Cell {
nextIdx := uint32(0)
for _, c := range r.x.C {
if c.RAttr != nil {
col, _, _ := ParseCellReference(*c.RAttr)
if col := reference.ColumnToIndex(col); col >= nextIdx {
nextIdx = col + 1
cref, _ := reference.ParseCellReference(*c.RAttr)
if cref.ColumnIdx >= nextIdx {
nextIdx = cref.ColumnIdx + 1
}
}
}
Expand Down Expand Up @@ -131,9 +131,9 @@ func (r Row) Cell(col string) Cell {
func (r Row) renumberAs(rowNumber uint32) {
r.x.RAttr = gooxml.Uint32(rowNumber)
for _, c := range r.Cells() {
col, _, err := ParseCellReference(c.Reference())
cref, err := reference.ParseCellReference(c.Reference())
if err == nil {
newRef := fmt.Sprintf("%s%d", col, rowNumber)
newRef := fmt.Sprintf("%s%d", cref.Column, rowNumber)
c.x.RAttr = gooxml.String(newRef)
}
}
Expand Down
69 changes: 28 additions & 41 deletions spreadsheet/sheet.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ func (s Sheet) Row(rowNum uint32) Row {

// Cell creates or returns a cell given a cell reference of the form 'A10'
func (s Sheet) Cell(cellRef string) Cell {
col, row, err := ParseCellReference(cellRef)
cref, err := reference.ParseCellReference(cellRef)
if err != nil {
gooxml.Log("error parsing cell reference: %s", err)
return s.AddRow().AddCell()
}
return s.Row(row).Cell(col)
return s.Row(cref.RowIdx).Cell(cref.Column)
}

// AddNumberedRow adds a row with a given row number. If you reuse a row number
Expand Down Expand Up @@ -183,22 +183,12 @@ func (s Sheet) validateRowCellNumbers() error {
func (s Sheet) validateMergedCells() error {
mergedCells := map[uint64]struct{}{}
for _, mc := range s.MergedCells() {
from, to, err := ParseRangeReference(mc.Reference())
from, to, err := reference.ParseRangeReference(mc.Reference())
if err != nil {
return fmt.Errorf("sheet name '%s' has invalid merged cell reference %s", s.Name(), mc.Reference())
}
fc, frIdx, err := ParseCellReference(from)
if err != nil {
return fmt.Errorf("sheet name '%s' has invalid merged cell reference %s", s.Name(), mc.Reference())
}
tc, trIdx, err := ParseCellReference(to)
if err != nil {
return fmt.Errorf("sheet name '%s' has invalid merged cell reference %s", s.Name(), mc.Reference())
}
fcIdx := reference.ColumnToIndex(fc)
tcIdx := reference.ColumnToIndex(tc)
for r := frIdx; r <= trIdx; r++ {
for c := fcIdx; c <= tcIdx; c++ {
for r := from.RowIdx; r <= to.RowIdx; r++ {
for c := from.ColumnIdx; c <= to.ColumnIdx; c++ {
idx := uint64(r)<<32 | uint64(c)
if _, ok := mergedCells[idx]; ok {
return fmt.Errorf("sheet name '%s' has overlapping merged cell range", s.Name())
Expand Down Expand Up @@ -270,13 +260,13 @@ func (s Sheet) AddHyperlink(url string) common.Hyperlink {
// invalidate the reference.
func (s Sheet) RangeReference(n string) string {
sp := strings.Split(n, ":")
fc, fr, _ := ParseCellReference(sp[0])
from := fmt.Sprintf("$%s$%d", fc, fr)
cref, _ := reference.ParseCellReference(sp[0])
from := fmt.Sprintf("$%s$%d", cref.Column, cref.RowIdx)
if len(sp) == 1 {
return fmt.Sprintf(`'%s'!%s`, s.Name(), from)
}
tc, tr, _ := ParseCellReference(sp[1])
to := fmt.Sprintf("$%s$%d", tc, tr)
tref, _ := reference.ParseCellReference(sp[1])
to := fmt.Sprintf("$%s$%d", tref.Column, tref.RowIdx)
return fmt.Sprintf(`'%s'!%s:%s`, s.Name(), from, to)
}

Expand Down Expand Up @@ -386,14 +376,13 @@ func (s Sheet) ExtentsIndex() (string, uint32, string, uint32) {
}

for _, c := range r.Cells() {
col, _, err := ParseCellReference(c.Reference())
cref, err := reference.ParseCellReference(c.Reference())
if err == nil {
// column index is zero based here
colIdx := reference.ColumnToIndex(col)
if colIdx < minCol {
minCol = colIdx
} else if colIdx > maxCol {
maxCol = colIdx
if cref.ColumnIdx < minCol {
minCol = cref.ColumnIdx
} else if cref.ColumnIdx > maxCol {
maxCol = cref.ColumnIdx
}
}
}
Expand Down Expand Up @@ -485,20 +474,10 @@ func (s Sheet) Comments() Comments {
// breaks apart a single border into its components and applies it to cells as
// needed to give the effect of a border applying to multiple cells.
func (s Sheet) SetBorder(cellRange string, border Border) error {
from, to, err := ParseRangeReference(cellRange)
if err != nil {
return err
}
tlCol, tlRowIdx, err := ParseCellReference(from)
from, to, err := reference.ParseRangeReference(cellRange)
if err != nil {
return err
}
brCol, brRowIdx, err := ParseCellReference(to)
if err != nil {
return err
}
tlColIdx := reference.ColumnToIndex(tlCol)
brColIdx := reference.ColumnToIndex(brCol)

topLeftStyle := s.w.StyleSheet.AddCellStyle()
topLeftBorder := s.w.StyleSheet.AddBorder()
Expand Down Expand Up @@ -544,6 +523,11 @@ func (s Sheet) SetBorder(cellRange string, border Border) error {
bottomRightBorder.x.Bottom = border.x.Bottom
bottomRightBorder.x.Right = border.x.Right

tlRowIdx := from.RowIdx
tlColIdx := from.ColumnIdx
brRowIdx := to.RowIdx
brColIdx := to.ColumnIdx

for row := tlRowIdx; row <= brRowIdx; row++ {
for col := tlColIdx; col <= brColIdx; col++ {
ref := fmt.Sprintf("%s%d", reference.IndexToColumn(col), row)
Expand Down Expand Up @@ -642,16 +626,19 @@ func (s *Sheet) RecalculateFormulas() {
// setArray expands an array into cached values starting at the origin which
// should be a cell reference of the type "A1". This is used when evaluating
// array type formulas.
func (s *Sheet) setArray(origin string, arr formula.Result) {
colStr, rowIdx, _ := ParseCellReference(origin)
colIdx := reference.ColumnToIndex(colStr)
func (s *Sheet) setArray(origin string, arr formula.Result) error {
cref, err := reference.ParseCellReference(origin)
if err != nil {
return err
}
for ir, row := range arr.ValueArray {
sr := s.Row(rowIdx + uint32(ir))
sr := s.Row(cref.RowIdx + uint32(ir))
for ic, val := range row {
cell := sr.Cell(reference.IndexToColumn(colIdx + uint32(ic)))
cell := sr.Cell(reference.IndexToColumn(cref.ColumnIdx + uint32(ic)))
cell.SetCachedFormulaResult(val.String())
}
}
return nil
}

// SheetViews returns the sheet views defined. This is where splits and frozen
Expand Down

0 comments on commit 968e4ba

Please sign in to comment.