forked from tealeg/xlsx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrow.go
161 lines (139 loc) · 4.23 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package xlsx
import (
"fmt"
)
// Row represents a single Row in the current Sheet.
type Row struct {
Hidden bool // Hidden determines whether this Row is hidden or not.
Sheet *Sheet // Sheet is a reference back to the Sheet that this Row is within.
height float64 // Height is the current height of the Row in PostScript Points
outlineLevel uint8 // OutlineLevel contains the outline level of this Row. Used for collapsing.
isCustom bool // isCustom is a flag that is set to true when the Row has been modified
num int // Num hold the positional number of the Row in the Sheet
cellCount int // The current number of cells
cells []*Cell // the cells
}
// SetHeight sets the height of the Row in PostScript points
func (r *Row) SetHeight(ht float64) {
r.height = ht
r.isCustom = true
}
// SetHeightCM sets the height of the Row in centimetres, inherently converting it to PostScript points.
func (r *Row) SetHeightCM(ht float64) {
r.height = ht * 28.3464567 // Convert CM to postscript points
r.isCustom = true
}
// GetHeight returns the height of the Row in PostScript points.
func (r *Row) GetHeight() float64 {
return r.height
}
// SetOutlineLevel sets the outline level of the Row (used for collapsing rows)
func (r *Row) SetOutlineLevel(outlineLevel uint8) {
r.outlineLevel = outlineLevel
if r.Sheet != nil {
if r.outlineLevel > r.Sheet.SheetFormat.OutlineLevelRow {
r.Sheet.SheetFormat.OutlineLevelRow = outlineLevel
}
}
}
// GetOutlineLevel returns the outline level of the Row.
func (r *Row) GetOutlineLevel() uint8 {
return r.outlineLevel
}
// AddCell adds a new Cell to the Row
func (r *Row) AddCell() *Cell {
cell := newCell(r, r.cellCount)
r.cellCount++
r.cells = append(r.cells, cell)
return cell
}
func (r *Row) makeCellKey(colIdx int) string {
return fmt.Sprintf("%s:%06d:%06d", r.Sheet.Name, r.num, colIdx)
}
func (r *Row) key() string {
return r.makeCellKeyRowPrefix()
}
func (r *Row) makeCellKeyRowPrefix() string {
return fmt.Sprintf("%s:%06d", r.Sheet.Name, r.num)
}
func (r *Row) growCellsSlice(newSize int) {
capacity := cap(r.cells)
if newSize >= capacity {
newCap := 2 * capacity
if newSize > newCap {
newCap = newSize
}
newSlice := make([]*Cell, newCap, newCap)
copy(newSlice, r.cells)
r.cells = newSlice
}
}
// GetCell returns the Cell at a given column index, creating it if it doesn't exist.
func (r *Row) GetCell(colIdx int) *Cell {
if colIdx >= len(r.cells) {
cell := newCell(r, colIdx)
r.growCellsSlice(colIdx + 1)
r.cells[colIdx] = cell
return cell
}
cell := r.cells[colIdx]
if cell == nil {
cell = newCell(r, colIdx)
r.cells[colIdx] = cell
}
return cell
}
// cellVisitorFlags contains flags that can be set by CellVisitorOption implementations to modify the behaviour of ForEachCell
type cellVisitorFlags struct {
// skipEmptyCells indicates if we should skip nil cells.
skipEmptyCells bool
}
// CellVisitorOption describes a function that can set values in a
// cellVisitorFlags struct to affect the way ForEachCell operates
type CellVisitorOption func(flags *cellVisitorFlags)
// SkipEmptyCells can be passed as an option to Row.ForEachCell in
// order to make it skip over empty cells in the sheet.
func SkipEmptyCells(flags *cellVisitorFlags) {
flags.skipEmptyCells = true
}
// ForEachCell will call the provided CellVisitorFunc for each
// currently defined cell in the Row. Optionally you may pass one or
// more CellVisitorOption to affect how ForEachCell operates. For
// example you may wish to pass SkipEmptyCells to only visit cells
// which are populated.
func (r *Row) ForEachCell(cvf CellVisitorFunc, option ...CellVisitorOption) error {
flags := &cellVisitorFlags{}
for _, opt := range option {
opt(flags)
}
fn := func(ci int, c *Cell) error {
if c == nil {
if flags.skipEmptyCells {
return nil
}
c = r.GetCell(ci)
}
if c.Value == "" && flags.skipEmptyCells {
return nil
}
c.Row = r
return cvf(c)
}
for ci, cell := range r.cells {
err := fn(ci, cell)
if err != nil {
return err
}
}
cellCount := len(r.cells)
if !flags.skipEmptyCells {
for ci := cellCount; ci < r.Sheet.MaxCol; ci++ {
c := r.GetCell(ci)
err := cvf(c)
if err != nil {
return err
}
}
}
return nil
}