forked from srinathh/gooxml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
row.go
140 lines (122 loc) · 3.77 KB
/
row.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2017 Baliance. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting [email protected].
package spreadsheet
import (
"fmt"
"baliance.com/gooxml"
"baliance.com/gooxml/measurement"
"baliance.com/gooxml/schema/soo/sml"
"baliance.com/gooxml/spreadsheet/reference"
)
// Row is a row within a spreadsheet.
type Row struct {
w *Workbook
s *sml.Worksheet
x *sml.CT_Row
}
// X returns the inner wrapped XML type.
func (r Row) X() *sml.CT_Row {
return r.x
}
// RowNumber returns the row number (1-N), or zero if it is unset.
func (r Row) RowNumber() uint32 {
if r.x.RAttr != nil {
return *r.x.RAttr
}
return 0
}
// SetHeight sets the row height in points.
func (r Row) SetHeight(d measurement.Distance) {
r.x.HtAttr = gooxml.Float64(float64(d))
}
// SetHeightAuto sets the row height to be automatically determined.
func (r Row) SetHeightAuto() {
r.x.HtAttr = nil
}
// IsHidden returns whether the row is hidden or not.
func (r Row) IsHidden() bool {
return r.x.HiddenAttr != nil && *r.x.HiddenAttr
}
// SetHidden hides or unhides the row
func (r Row) SetHidden(hidden bool) {
if !hidden {
r.x.HiddenAttr = nil
} else {
r.x.HiddenAttr = gooxml.Bool(true)
}
}
// AddCell adds a cell to a spreadsheet.
func (r Row) AddCell() Cell {
numCells := uint32(len(r.x.C))
var nextCellID *string
if numCells > 0 {
prevCellName := gooxml.Stringf("%s%d", reference.IndexToColumn(numCells-1), r.RowNumber())
// previous cell has an expected name
if r.x.C[numCells-1].RAttr != nil && *r.x.C[numCells-1].RAttr == *prevCellName {
nextCellID = gooxml.Stringf("%s%d", reference.IndexToColumn(numCells), r.RowNumber())
}
}
c := sml.NewCT_Cell()
r.x.C = append(r.x.C, c)
// fast path failed, so find the last cell and add another
if nextCellID == nil {
nextIdx := uint32(0)
for _, c := range r.x.C {
if c.RAttr != nil {
cref, _ := reference.ParseCellReference(*c.RAttr)
if cref.ColumnIdx >= nextIdx {
nextIdx = cref.ColumnIdx + 1
}
}
}
nextCellID = gooxml.Stringf("%s%d", reference.IndexToColumn(nextIdx), r.RowNumber())
}
c.RAttr = nextCellID
return Cell{r.w, r.s, r.x, c}
}
// Cells returns a slice of cells. The cells can be manipulated, but appending
// to the slice will have no effect.
func (r Row) Cells() []Cell {
ret := []Cell{}
for _, c := range r.x.C {
ret = append(ret, Cell{r.w, r.s, r.x, c})
}
return ret
}
// AddNamedCell adds a new named cell to a row and returns it. You should
// normally prefer Cell() as it will return the existing cell if the cell
// already exists, while AddNamedCell will duplicate the cell creating an
// invaild spreadsheet.
func (r Row) AddNamedCell(col string) Cell {
c := sml.NewCT_Cell()
r.x.C = append(r.x.C, c)
c.RAttr = gooxml.Stringf("%s%d", col, r.RowNumber())
return Cell{r.w, r.s, r.x, c}
}
// Cell retrieves or adds a new cell to a row. Col is the column (e.g. 'A', 'B')
func (r Row) Cell(col string) Cell {
name := fmt.Sprintf("%s%d", col, r.RowNumber())
for _, c := range r.x.C {
if c.RAttr != nil && *c.RAttr == name {
return Cell{r.w, r.s, r.x, c}
}
}
return r.AddNamedCell(col)
}
// renumberAs assigns a new row number and fixes any cell references within the
// row so they refer to the new row number. This is used when sorting to fix up
// moved rows.
func (r Row) renumberAs(rowNumber uint32) {
r.x.RAttr = gooxml.Uint32(rowNumber)
for _, c := range r.Cells() {
cref, err := reference.ParseCellReference(c.Reference())
if err == nil {
newRef := fmt.Sprintf("%s%d", cref.Column, rowNumber)
c.x.RAttr = gooxml.String(newRef)
}
}
}