|
|
@@ -80,18 +80,18 @@ type xlsxStyleSheet struct {
|
|
|
CellXfs xlsxCellXfs `xml:"cellXfs,omitempty"`
|
|
|
NumFmts xlsxNumFmts `xml:"numFmts,omitempty"`
|
|
|
|
|
|
- theme *theme
|
|
|
+ theme *theme
|
|
|
+
|
|
|
+ sync.RWMutex // protects the following
|
|
|
styleCache map[int]*Style
|
|
|
numFmtRefTable map[int]xlsxNumFmt
|
|
|
- lock *sync.RWMutex
|
|
|
}
|
|
|
|
|
|
func newXlsxStyleSheet(t *theme) *xlsxStyleSheet {
|
|
|
- stylesheet := new(xlsxStyleSheet)
|
|
|
- stylesheet.theme = t
|
|
|
- stylesheet.styleCache = make(map[int]*Style)
|
|
|
- stylesheet.lock = new(sync.RWMutex)
|
|
|
- return stylesheet
|
|
|
+ return &xlsxStyleSheet{
|
|
|
+ theme: t,
|
|
|
+ styleCache: make(map[int]*Style),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func (styles *xlsxStyleSheet) reset() {
|
|
|
@@ -115,18 +115,17 @@ func (styles *xlsxStyleSheet) reset() {
|
|
|
styles.NumFmts = xlsxNumFmts{}
|
|
|
}
|
|
|
|
|
|
-func (styles *xlsxStyleSheet) getStyle(styleIndex int) (style *Style) {
|
|
|
- styles.lock.RLock()
|
|
|
+func (styles *xlsxStyleSheet) getStyle(styleIndex int) *Style {
|
|
|
+ styles.RLock()
|
|
|
style, ok := styles.styleCache[styleIndex]
|
|
|
- styles.lock.RUnlock()
|
|
|
+ styles.RUnlock()
|
|
|
if ok {
|
|
|
- return
|
|
|
+ return style
|
|
|
}
|
|
|
+
|
|
|
+ style = new(Style)
|
|
|
+
|
|
|
var namedStyleXf xlsxXf
|
|
|
- style = &Style{}
|
|
|
- style.Border = Border{}
|
|
|
- style.Fill = Fill{}
|
|
|
- style.Font = Font{}
|
|
|
|
|
|
xfCount := styles.CellXfs.Count
|
|
|
if styleIndex > -1 && xfCount > 0 && styleIndex <= xfCount {
|
|
|
@@ -189,9 +188,9 @@ func (styles *xlsxStyleSheet) getStyle(styleIndex int) (style *Style) {
|
|
|
if xf.Alignment.Vertical != "" {
|
|
|
style.Alignment.Vertical = xf.Alignment.Vertical
|
|
|
}
|
|
|
- styles.lock.Lock()
|
|
|
+ styles.Lock()
|
|
|
styles.styleCache[styleIndex] = style
|
|
|
- styles.lock.Unlock()
|
|
|
+ styles.Unlock()
|
|
|
}
|
|
|
return style
|
|
|
}
|
|
|
@@ -199,9 +198,8 @@ func (styles *xlsxStyleSheet) getStyle(styleIndex int) (style *Style) {
|
|
|
func (styles *xlsxStyleSheet) argbValue(color xlsxColor) string {
|
|
|
if color.Theme != nil && styles.theme != nil {
|
|
|
return styles.theme.themeColor(int64(*color.Theme), color.Tint)
|
|
|
- } else {
|
|
|
- return color.RGB
|
|
|
}
|
|
|
+ return color.RGB
|
|
|
}
|
|
|
|
|
|
// Excel styles can reference number formats that are built-in, all of which
|
|
|
@@ -241,7 +239,7 @@ func (styles *xlsxStyleSheet) addFont(xFont xlsxFont) (index int) {
|
|
|
}
|
|
|
styles.Fonts.Font = append(styles.Fonts.Font, xFont)
|
|
|
index = styles.Fonts.Count
|
|
|
- styles.Fonts.Count += 1
|
|
|
+ styles.Fonts.Count++
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -254,7 +252,7 @@ func (styles *xlsxStyleSheet) addFill(xFill xlsxFill) (index int) {
|
|
|
}
|
|
|
styles.Fills.Fill = append(styles.Fills.Fill, xFill)
|
|
|
index = styles.Fills.Count
|
|
|
- styles.Fills.Count += 1
|
|
|
+ styles.Fills.Count++
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -268,7 +266,7 @@ func (styles *xlsxStyleSheet) addBorder(xBorder xlsxBorder) (index int) {
|
|
|
styles.Borders.Border = append(styles.Borders.Border, xBorder)
|
|
|
index = styles.Borders.Count
|
|
|
|
|
|
- styles.Borders.Count += 1
|
|
|
+ styles.Borders.Count++
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -284,7 +282,7 @@ func (styles *xlsxStyleSheet) addCellStyleXf(xCellStyleXf xlsxXf) (index int) {
|
|
|
}
|
|
|
styles.CellStyleXfs.Xf = append(styles.CellStyleXfs.Xf, xCellStyleXf)
|
|
|
index = styles.CellStyleXfs.Count
|
|
|
- styles.CellStyleXfs.Count += 1
|
|
|
+ styles.CellStyleXfs.Count++
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -298,7 +296,7 @@ func (styles *xlsxStyleSheet) addCellXf(xCellXf xlsxXf) (index int) {
|
|
|
|
|
|
styles.CellXfs.Xf = append(styles.CellXfs.Xf, xCellXf)
|
|
|
index = styles.CellXfs.Count
|
|
|
- styles.CellXfs.Count += 1
|
|
|
+ styles.CellXfs.Count++
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -326,12 +324,12 @@ func (styles *xlsxStyleSheet) newNumFmt(formatCode string) xlsxNumFmt {
|
|
|
|
|
|
// The user define NumFmtId. The one less than 164 in built in.
|
|
|
numFmtId = builtinNumFmtsCount + 1
|
|
|
- styles.lock.Lock()
|
|
|
- defer styles.lock.Unlock()
|
|
|
+ styles.Lock()
|
|
|
+ defer styles.Unlock()
|
|
|
for {
|
|
|
// get a unused NumFmtId
|
|
|
if _, ok = styles.numFmtRefTable[numFmtId]; ok {
|
|
|
- numFmtId += 1
|
|
|
+ numFmtId++
|
|
|
} else {
|
|
|
styles.addNumFmt(xlsxNumFmt{NumFmtId: numFmtId, FormatCode: formatCode})
|
|
|
break
|
|
|
@@ -353,74 +351,63 @@ func (styles *xlsxStyleSheet) addNumFmt(xNumFmt xlsxNumFmt) {
|
|
|
}
|
|
|
styles.NumFmts.NumFmt = append(styles.NumFmts.NumFmt, xNumFmt)
|
|
|
styles.numFmtRefTable[xNumFmt.NumFmtId] = xNumFmt
|
|
|
- styles.NumFmts.Count += 1
|
|
|
+ styles.NumFmts.Count++
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (styles *xlsxStyleSheet) Marshal() (result string, err error) {
|
|
|
- var xNumFmts string
|
|
|
- var xfonts string
|
|
|
- var xfills string
|
|
|
- var xborders string
|
|
|
- var xcellStyleXfs string
|
|
|
- var xcellXfs string
|
|
|
- var xcellStyles string
|
|
|
-
|
|
|
- var outputFontMap map[int]int = make(map[int]int)
|
|
|
- var outputFillMap map[int]int = make(map[int]int)
|
|
|
- var outputBorderMap map[int]int = make(map[int]int)
|
|
|
+func (styles *xlsxStyleSheet) Marshal() (string, error) {
|
|
|
+ result := xml.Header + `<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`
|
|
|
|
|
|
- result = xml.Header
|
|
|
- result += `<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`
|
|
|
-
|
|
|
- xNumFmts, err = styles.NumFmts.Marshal()
|
|
|
+ xNumFmts, err := styles.NumFmts.Marshal()
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
result += xNumFmts
|
|
|
|
|
|
- xfonts, err = styles.Fonts.Marshal(outputFontMap)
|
|
|
+ outputFontMap := make(map[int]int)
|
|
|
+ xfonts, err := styles.Fonts.Marshal(outputFontMap)
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
result += xfonts
|
|
|
|
|
|
- xfills, err = styles.Fills.Marshal(outputFillMap)
|
|
|
+ outputFillMap := make(map[int]int)
|
|
|
+ xfills, err := styles.Fills.Marshal(outputFillMap)
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
result += xfills
|
|
|
|
|
|
- xborders, err = styles.Borders.Marshal(outputBorderMap)
|
|
|
+ outputBorderMap := make(map[int]int)
|
|
|
+ xborders, err := styles.Borders.Marshal(outputBorderMap)
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
result += xborders
|
|
|
|
|
|
if styles.CellStyleXfs != nil {
|
|
|
- xcellStyleXfs, err = styles.CellStyleXfs.Marshal(outputBorderMap, outputFillMap, outputFontMap)
|
|
|
+ xcellStyleXfs, err := styles.CellStyleXfs.Marshal(outputBorderMap, outputFillMap, outputFontMap)
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
result += xcellStyleXfs
|
|
|
}
|
|
|
|
|
|
- xcellXfs, err = styles.CellXfs.Marshal(outputBorderMap, outputFillMap, outputFontMap)
|
|
|
+ xcellXfs, err := styles.CellXfs.Marshal(outputBorderMap, outputFillMap, outputFontMap)
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
result += xcellXfs
|
|
|
|
|
|
if styles.CellStyles != nil {
|
|
|
- xcellStyles, err = styles.CellStyles.Marshal()
|
|
|
+ xcellStyles, err := styles.CellStyles.Marshal()
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
result += xcellStyles
|
|
|
}
|
|
|
|
|
|
- result += `</styleSheet>`
|
|
|
- return
|
|
|
+ return result + "</styleSheet>", nil
|
|
|
}
|
|
|
|
|
|
// xlsxNumFmts directly maps the numFmts element in the namespace
|
|
|
@@ -484,7 +471,7 @@ func (fonts *xlsxFonts) Marshal(outputFontMap map[int]int) (result string, err e
|
|
|
}
|
|
|
if xfont != "" {
|
|
|
outputFontMap[i] = emittedCount
|
|
|
- emittedCount += 1
|
|
|
+ emittedCount++
|
|
|
subparts += xfont
|
|
|
}
|
|
|
}
|
|
|
@@ -525,7 +512,7 @@ func (font *xlsxFont) Equals(other xlsxFont) bool {
|
|
|
}
|
|
|
|
|
|
func (font *xlsxFont) Marshal() (result string, err error) {
|
|
|
- result = `<font>`
|
|
|
+ result = "<font>"
|
|
|
if font.Sz.Val != "" {
|
|
|
result += fmt.Sprintf(`<sz val="%s"/>`, font.Sz.Val)
|
|
|
}
|
|
|
@@ -550,8 +537,7 @@ func (font *xlsxFont) Marshal() (result string, err error) {
|
|
|
if font.U != nil {
|
|
|
result += "<u/>"
|
|
|
}
|
|
|
- result += `</font>`
|
|
|
- return
|
|
|
+ return result + "</font>", nil
|
|
|
}
|
|
|
|
|
|
// xlsxVal directly maps the val element in the namespace
|
|
|
@@ -575,27 +561,27 @@ type xlsxFills struct {
|
|
|
Fill []xlsxFill `xml:"fill,omitempty"`
|
|
|
}
|
|
|
|
|
|
-func (fills *xlsxFills) Marshal(outputFillMap map[int]int) (result string, err error) {
|
|
|
- emittedCount := 0
|
|
|
- subparts := ""
|
|
|
+func (fills *xlsxFills) Marshal(outputFillMap map[int]int) (string, error) {
|
|
|
+ var subparts string
|
|
|
+ var emittedCount int
|
|
|
for i, fill := range fills.Fill {
|
|
|
- var xfill string
|
|
|
- xfill, err = fill.Marshal()
|
|
|
+ xfill, err := fill.Marshal()
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return "", err
|
|
|
}
|
|
|
if xfill != "" {
|
|
|
outputFillMap[i] = emittedCount
|
|
|
- emittedCount += 1
|
|
|
+ emittedCount++
|
|
|
subparts += xfill
|
|
|
}
|
|
|
}
|
|
|
+ var result string
|
|
|
if emittedCount > 0 {
|
|
|
result = fmt.Sprintf(`<fills count="%d">`, emittedCount)
|
|
|
result += subparts
|
|
|
result += `</fills>`
|
|
|
}
|
|
|
- return
|
|
|
+ return result, nil
|
|
|
}
|
|
|
|
|
|
// xlsxFill directly maps the fill element in the namespace
|
|
|
@@ -696,7 +682,7 @@ func (borders *xlsxBorders) Marshal(outputBorderMap map[int]int) (result string,
|
|
|
}
|
|
|
if xborder != "" {
|
|
|
outputBorderMap[i] = emittedCount
|
|
|
- emittedCount += 1
|
|
|
+ emittedCount++
|
|
|
subparts += xborder
|
|
|
}
|
|
|
}
|
|
|
@@ -891,19 +877,16 @@ func (xf *xlsxXf) Equals(other xlsxXf) bool {
|
|
|
}
|
|
|
|
|
|
func (xf *xlsxXf) Marshal(outputBorderMap, outputFillMap, outputFontMap map[int]int) (result string, err error) {
|
|
|
- var xAlignment string
|
|
|
result = fmt.Sprintf(`<xf applyAlignment="%b" applyBorder="%b" applyFont="%b" applyFill="%b" applyNumberFormat="%b" applyProtection="%b" borderId="%d" fillId="%d" fontId="%d" numFmtId="%d"`, bool2Int(xf.ApplyAlignment), bool2Int(xf.ApplyBorder), bool2Int(xf.ApplyFont), bool2Int(xf.ApplyFill), bool2Int(xf.ApplyNumberFormat), bool2Int(xf.ApplyProtection), outputBorderMap[xf.BorderId], outputFillMap[xf.FillId], outputFontMap[xf.FontId], xf.NumFmtId)
|
|
|
if xf.XfId != nil {
|
|
|
result += fmt.Sprintf(` xfId="%d"`, *xf.XfId)
|
|
|
}
|
|
|
result += ">"
|
|
|
- xAlignment, err = xf.Alignment.Marshal()
|
|
|
+ xAlignment, err := xf.Alignment.Marshal()
|
|
|
if err != nil {
|
|
|
- return
|
|
|
+ return result, err
|
|
|
}
|
|
|
- result += xAlignment
|
|
|
- result += `</xf>`
|
|
|
- return
|
|
|
+ return result + xAlignment + "</xf>", nil
|
|
|
}
|
|
|
|
|
|
type xlsxAlignment struct {
|
|
|
@@ -931,8 +914,7 @@ func (alignment *xlsxAlignment) Marshal() (result string, err error) {
|
|
|
if alignment.Vertical == "" {
|
|
|
alignment.Vertical = "bottom"
|
|
|
}
|
|
|
- result = fmt.Sprintf(`<alignment horizontal="%s" indent="%d" shrinkToFit="%b" textRotation="%d" vertical="%s" wrapText="%b"/>`, alignment.Horizontal, alignment.Indent, bool2Int(alignment.ShrinkToFit), alignment.TextRotation, alignment.Vertical, bool2Int(alignment.WrapText))
|
|
|
- return
|
|
|
+ return fmt.Sprintf(`<alignment horizontal="%s" indent="%d" shrinkToFit="%b" textRotation="%d" vertical="%s" wrapText="%b"/>`, alignment.Horizontal, alignment.Indent, bool2Int(alignment.ShrinkToFit), alignment.TextRotation, alignment.Vertical, bool2Int(alignment.WrapText)), nil
|
|
|
}
|
|
|
|
|
|
func bool2Int(b bool) int {
|