-
Notifications
You must be signed in to change notification settings - Fork 1
/
styles.go
213 lines (193 loc) · 4.47 KB
/
styles.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package streamxlsx
import (
"encoding/xml"
"io"
)
const DefaultDatetimeFormat = "m/d/yy h:mm"
// A Stylesheet has all used formats and styles. There is exactly one per document.
// It's recommended to use `Format()` to work with styles, since that hides all the details.
//
// note: this could have support for fonts, fills, and borders.
type Stylesheet struct {
NumFmts []NumFmt
CellXfs []Xf
CellStyleXfs []Xf
}
type stylesheetXML struct {
XMLName string `xml:"styleSheet"`
XMLNS string `xml:"xmlns,attr"`
NumFmts numFmtsXML `xml:"numFmts"`
Fonts fontsXML `xml:"fonts"`
Fills fillsXML `xml:"fills"`
Borders bordersXML `xml:"borders"`
CellStyleXfs xfsXML `xml:"cellStyleXfs"`
CellXfs xfsXML `xml:"cellXfs"`
}
type numFmtsXML struct {
Count int `xml:"count,attr"`
NumFmts []NumFmt `xml:"numFmt"`
}
type fontsXML struct {
Count int `xml:"count,attr"`
Fonts []font `xml:"font"`
}
/*
type FontSZ struct {
Val int `xml:"val,attr"`
}
type FontColor struct {
Theme int `xml:"theme,attr"`
}
type FontName struct {
Val string `xml:"val,attr"`
}
type FontFamily struct {
Val int `xml:"val,attr"`
}
type FontScheme struct {
Val string `xml:"val,attr"`
}
*/
// not implemented
type font struct {
// SZ FontSZ `xml:"sz"`
// Color FontColor `xml:"color"`
// Name FontName `xml:"name"`
// Family FontFamily `xml:"family"`
// Scheme FontScheme `xml:"scheme"`
}
type fillPattern struct {
Type string `xml:"patternType,attr"`
}
// not implemented
type fill struct {
PatternFill fillPattern `xml:"patternFill"`
}
type fillsXML struct {
Count int `xml:"count,attr"`
Fills []fill `xml:"fill"`
}
type bordersXML struct {
Count int `xml:"count,attr"`
Borders []border `xml:"border"`
}
// not implemented
type border struct {
// <borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>
}
type xfsXML struct {
Count int `xml:"count,attr"`
Xfs []Xf `xml:"xf"`
}
// Xf is either a CellXF or a CellStyleXf.
// <xf numFmtId="0" fontId="8" fillId="4" borderId="0" xfId="3"/>
type Xf struct {
NumFmtID int `xml:"numFmtId,attr"`
FontID int `xml:"fontId,attr"`
FillID int `xml:"fillId,attr"`
BorderID int `xml:"borderId,attr"`
ApplyNumberFormat int `xml:"applyNumberFormat,attr,omitempty"`
XfID *int `xml:"xfId,attr,omitempty"`
}
type NumFmt struct {
ID int `xml:"numFmtId,attr"`
Code string `xml:"formatCode,attr"`
}
// Get or create the ID for a numfmt. It can return a "default" ID, or create a
// custom ID.
// Example of a code is "0.00".
func (s *Stylesheet) GetNumFmtID(code string) int {
// see builtInNumFmt in tealeg
switch code {
case "0":
return 1
case "0.00":
return 2
case "#.##0":
return 3
case "m/d/yy h:mm":
return 22
default:
// FIXME &c.
}
max := 163 // custom IDs start here+1, according to tealeg
for _, nf := range s.NumFmts {
if nf.Code == code {
return nf.ID
}
if nf.ID > max {
max = nf.ID
}
}
newID := max + 1
s.NumFmts = append(s.NumFmts, NumFmt{
ID: newID,
Code: code,
})
return newID
}
// makes a CellXF ID
// The ID is the entry in the array, 0-based
func (s *Stylesheet) GetCellID(xf Xf) int {
for i, x := range s.CellXfs {
if x == xf {
return i
}
}
s.CellXfs = append(s.CellXfs, xf)
return len(s.CellXfs) - 1
}
// makes a CellStyleXf ID
// The ID is the entry in the array, 0-based
func (s *Stylesheet) GetCellStyleID(xf Xf) int {
for i, x := range s.CellStyleXfs {
if x == xf {
return i
}
}
s.CellStyleXfs = append(s.CellStyleXfs, xf)
return len(s.CellStyleXfs) - 1
}
func writeStylesheet(fh io.Writer, s *Stylesheet) error {
fh.Write([]byte(xml.Header))
enc := xml.NewEncoder(fh)
return enc.Encode(stylesheetXML{
XMLNS: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
NumFmts: numFmtsXML{
Count: len(s.NumFmts),
NumFmts: s.NumFmts,
},
Fonts: fontsXML{
Count: 1,
Fonts: []font{
{
// SZ: FontSZ{11},
// Color: FontColor{1},
// Name: FontName{"Calibri"},
// Family: FontFamily{2},
// Scheme: FontScheme{"minor"},
},
},
},
Fills: fillsXML{
Count: 1,
Fills: []fill{
{PatternFill: fillPattern{Type: "none"}},
},
},
Borders: bordersXML{
Count: 1,
Borders: []border{
{},
},
},
CellStyleXfs: xfsXML{
Count: len(s.CellStyleXfs),
Xfs: s.CellStyleXfs,
},
CellXfs: xfsXML{
Count: len(s.CellXfs),
Xfs: s.CellXfs,
},
})
}