Skip to content

Commit b65c16b

Browse files
authored
Add set and get Charset and VertAlign to font definitions (#2141)
- Added `Charset` field to `Font` struct - Allows developers to explicitly specify font encodings when generating spreadsheets - Simplify code by combine set and get font from `Font` to `xlsxFont` and `xlsxRPr` - Update unit tests covering different charset values
1 parent c853113 commit b65c16b

File tree

7 files changed

+158
-176
lines changed

7 files changed

+158
-176
lines changed

cell.go

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ func getCellRichText(si *xlsxSI) (runs []RichTextRun) {
11211121
Text: v.T.Val,
11221122
}
11231123
if v.RPr != nil {
1124-
run.Font = newFont(v.RPr)
1124+
run.Font = v.RPr.getFont()
11251125
}
11261126
runs = append(runs, run)
11271127
}
@@ -1162,64 +1162,46 @@ func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err erro
11621162
}
11631163

11641164
// newRpr create run properties for the rich text by given font format.
1165-
func newRpr(fnt *Font) *xlsxRPr {
1166-
rpr := xlsxRPr{}
1167-
trueVal := ""
1168-
if fnt.Bold {
1169-
rpr.B = &trueVal
1170-
}
1171-
if fnt.Italic {
1172-
rpr.I = &trueVal
1173-
}
1174-
if fnt.Strike {
1175-
rpr.Strike = &trueVal
1176-
}
1177-
if fnt.Underline != "" {
1178-
rpr.U = &attrValString{Val: &fnt.Underline}
1179-
}
1180-
if fnt.Family != "" {
1181-
rpr.RFont = &attrValString{Val: &fnt.Family}
1182-
}
1183-
if inStrSlice([]string{"baseline", "superscript", "subscript"}, fnt.VertAlign, true) != -1 {
1184-
rpr.VertAlign = &attrValString{Val: &fnt.VertAlign}
1185-
}
1186-
if fnt.Size > 0 {
1187-
rpr.Sz = &attrValFloat{Val: &fnt.Size}
1188-
}
1189-
rpr.Color = newFontColor(fnt)
1190-
return &rpr
1191-
}
1192-
1193-
// newFont create font format by given run properties for the rich text.
1194-
func newFont(rPr *xlsxRPr) *Font {
1195-
var font Font
1196-
font.Bold = rPr.B != nil
1197-
font.Italic = rPr.I != nil
1198-
if rPr.U != nil {
1199-
font.Underline = "single"
1200-
if rPr.U.Val != nil {
1201-
font.Underline = *rPr.U.Val
1202-
}
1203-
}
1204-
if rPr.RFont != nil && rPr.RFont.Val != nil {
1205-
font.Family = *rPr.RFont.Val
1206-
}
1207-
if rPr.Sz != nil && rPr.Sz.Val != nil {
1208-
font.Size = *rPr.Sz.Val
1209-
}
1210-
if rPr.VertAlign != nil && rPr.VertAlign.Val != nil {
1211-
font.VertAlign = *rPr.VertAlign.Val
1212-
}
1213-
font.Strike = rPr.Strike != nil
1214-
if rPr.Color != nil {
1215-
font.Color = strings.TrimPrefix(rPr.Color.RGB, "FF")
1216-
if rPr.Color.Theme != nil {
1217-
font.ColorTheme = rPr.Color.Theme
1218-
}
1219-
font.ColorIndexed = rPr.Color.Indexed
1220-
font.ColorTint = rPr.Color.Tint
1221-
}
1222-
return &font
1165+
func (fnt *Font) newRpr() *xlsxRPr {
1166+
font := fnt.newFont()
1167+
return &xlsxRPr{
1168+
RFont: font.Name,
1169+
Charset: font.Charset,
1170+
Family: font.Family,
1171+
B: font.B,
1172+
I: font.I,
1173+
Strike: font.Strike,
1174+
Outline: font.Outline,
1175+
Shadow: font.Shadow,
1176+
Condense: font.Condense,
1177+
Extend: font.Extend,
1178+
Color: font.Color,
1179+
Sz: font.Sz,
1180+
U: font.U,
1181+
VertAlign: font.VertAlign,
1182+
Scheme: font.Scheme,
1183+
}
1184+
}
1185+
1186+
// getFont create font format by given internal font properties.
1187+
func (rPr *xlsxRPr) getFont() *Font {
1188+
return extractFont(&xlsxFont{
1189+
Name: rPr.RFont,
1190+
Charset: rPr.Charset,
1191+
Family: rPr.Family,
1192+
B: rPr.B,
1193+
I: rPr.I,
1194+
Strike: rPr.Strike,
1195+
Outline: rPr.Outline,
1196+
Shadow: rPr.Shadow,
1197+
Condense: rPr.Condense,
1198+
Extend: rPr.Extend,
1199+
Color: rPr.Color,
1200+
Sz: rPr.Sz,
1201+
U: rPr.U,
1202+
VertAlign: rPr.VertAlign,
1203+
Scheme: rPr.Scheme,
1204+
})
12231205
}
12241206

12251207
// setRichText provides a function to set rich text of a cell.
@@ -1237,7 +1219,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
12371219
run.T.Val, run.T.Space = trimCellValue(textRun.Text, false)
12381220
fnt := textRun.Font
12391221
if fnt != nil {
1240-
run.RPr = newRpr(fnt)
1222+
run.RPr = fnt.newRpr()
12411223
}
12421224
textRuns = append(textRuns, run)
12431225
}

lib.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,12 @@ func float64Ptr(f float64) *float64 { return &f }
447447
// stringPtr returns a pointer to a string with the given value.
448448
func stringPtr(s string) *string { return &s }
449449

450-
// Value extracts string data type text from a attribute value.
451-
func (avb *attrValString) Value() string {
452-
if avb != nil && avb.Val != nil {
453-
return *avb.Val
450+
// Value extracts float64 data type numeric from a attribute value.
451+
func (attr *attrValFloat) Value() float64 {
452+
if attr != nil && attr.Val != nil {
453+
return *attr.Val
454454
}
455-
return ""
455+
return 0
456456
}
457457

458458
// Value extracts boolean data type value from a attribute value.
@@ -463,12 +463,12 @@ func (avb *attrValBool) Value() bool {
463463
return false
464464
}
465465

466-
// Value extracts float64 data type numeric from a attribute value.
467-
func (attr *attrValFloat) Value() float64 {
468-
if attr != nil && attr.Val != nil {
469-
return *attr.Val
466+
// Value extracts string data type text from a attribute value.
467+
func (avb *attrValString) Value() string {
468+
if avb != nil && avb.Val != nil {
469+
return *avb.Val
470470
}
471-
return 0
471+
return ""
472472
}
473473

474474
// MarshalXML convert the boolean data type to literal values 0 or 1 on

styles.go

Lines changed: 58 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,6 @@ func parseFormatStyleSet(style *Style) (*Style, error) {
960960
func (f *File) NewStyle(style *Style) (int, error) {
961961
var (
962962
fs *Style
963-
font *xlsxFont
964963
err error
965964
cellXfsID, fontID, borderID, fillID int
966965
)
@@ -991,11 +990,10 @@ func (f *File) NewStyle(style *Style) (int, error) {
991990
numFmtID := newNumFmt(s, fs)
992991

993992
if fs.Font != nil {
994-
fontID, _ = f.getFontID(s, fs)
993+
fontID = f.getFontID(s, fs)
995994
if fontID == -1 {
996995
s.Fonts.Count++
997-
font, _ = f.newFont(fs)
998-
s.Fonts.Font = append(s.Fonts.Font, font)
996+
s.Fonts.Font = append(s.Fonts.Font, fs.Font.newFont())
999997
fontID = s.Fonts.Count - 1
1000998
}
1001999
}
@@ -1505,37 +1503,32 @@ func (f *File) extractFills(fl *xlsxFill, s *xlsxStyleSheet, style *Style) {
15051503

15061504
// extractFont provides a function to extract font styles settings by given
15071505
// font styles definition.
1508-
func (f *File) extractFont(fnt *xlsxFont, s *xlsxStyleSheet, style *Style) {
1509-
if fnt != nil {
1510-
var font Font
1511-
if fnt.B != nil {
1512-
font.Bold = fnt.B.Value()
1513-
}
1514-
if fnt.I != nil {
1515-
font.Italic = fnt.I.Value()
1516-
}
1517-
if fnt.U != nil {
1518-
if font.Underline = fnt.U.Value(); font.Underline == "" {
1519-
font.Underline = "single"
1520-
}
1521-
}
1522-
if fnt.Name != nil {
1523-
font.Family = fnt.Name.Value()
1524-
}
1525-
if fnt.Sz != nil {
1526-
font.Size = fnt.Sz.Value()
1527-
}
1528-
if fnt.Strike != nil {
1529-
font.Strike = fnt.Strike.Value()
1530-
}
1531-
if fnt.Color != nil {
1532-
font.Color = strings.TrimPrefix(fnt.Color.RGB, "FF")
1533-
font.ColorIndexed = fnt.Color.Indexed
1534-
font.ColorTheme = fnt.Color.Theme
1535-
font.ColorTint = fnt.Color.Tint
1506+
func extractFont(fnt *xlsxFont) *Font {
1507+
if fnt == nil {
1508+
return nil
1509+
}
1510+
var font Font
1511+
if fnt.Charset != nil {
1512+
font.Charset = fnt.Charset.Val
1513+
}
1514+
font.Bold = fnt.B.Value()
1515+
font.Italic = fnt.I.Value()
1516+
if fnt.U != nil {
1517+
if font.Underline = fnt.U.Value(); font.Underline == "" {
1518+
font.Underline = "single"
15361519
}
1537-
style.Font = &font
15381520
}
1521+
font.Family = fnt.Name.Value()
1522+
font.Size = fnt.Sz.Value()
1523+
font.Strike = fnt.Strike.Value()
1524+
if fnt.Color != nil {
1525+
font.Color = strings.TrimPrefix(fnt.Color.RGB, "FF")
1526+
font.ColorIndexed = fnt.Color.Indexed
1527+
font.ColorTheme = fnt.Color.Theme
1528+
font.ColorTint = fnt.Color.Tint
1529+
}
1530+
font.VertAlign = fnt.VertAlign.Value()
1531+
return &font
15391532
}
15401533

15411534
// extractNumFmt provides a function to extract number format by given styles
@@ -1628,7 +1621,7 @@ func (f *File) GetStyle(idx int) (*Style, error) {
16281621
f.extractBorders(s.Borders.Border[*xf.BorderID], s, style)
16291622
}
16301623
if extractStyleCondFuncs["font"](xf, s) {
1631-
f.extractFont(s.Fonts.Font[*xf.FontID], s, style)
1624+
style.Font = extractFont(s.Fonts.Font[*xf.FontID])
16321625
}
16331626
if extractStyleCondFuncs["alignment"](xf, s) {
16341627
f.extractAlignment(xf.Alignment, s, style)
@@ -1645,16 +1638,13 @@ func (f *File) GetStyle(idx int) (*Style, error) {
16451638
func (f *File) getStyleID(ss *xlsxStyleSheet, style *Style) (int, error) {
16461639
var (
16471640
err error
1648-
fontID int
16491641
styleID = -1
16501642
)
16511643
if ss.CellXfs == nil {
16521644
return styleID, err
16531645
}
16541646
numFmtID, borderID, fillID := getNumFmtID(ss, style), getBorderID(ss, style), getFillID(ss, style)
1655-
if fontID, err = f.getFontID(ss, style); err != nil {
1656-
return styleID, err
1657-
}
1647+
fontID := f.getFontID(ss, style)
16581648
if style.CustomNumFmt != nil {
16591649
numFmtID = getCustomNumFmtID(ss, style)
16601650
}
@@ -1700,7 +1690,7 @@ func (f *File) NewConditionalStyle(style *Style) (int, error) {
17001690
dxf.Border = newBorders(fs)
17011691
}
17021692
if fs.Font != nil {
1703-
dxf.Font, _ = f.newFont(fs)
1693+
dxf.Font = fs.Font.newFont()
17041694
}
17051695
if fs.Protection != nil {
17061696
dxf.Protection = newProtection(fs)
@@ -1735,7 +1725,7 @@ func (f *File) GetConditionalStyle(idx int) (*Style, error) {
17351725
}
17361726
f.extractFills(xf.Fill, s, style)
17371727
f.extractBorders(xf.Border, s, style)
1738-
f.extractFont(xf.Font, s, style)
1728+
style.Font = extractFont(xf.Font)
17391729
f.extractAlignment(xf.Alignment, s, style)
17401730
f.extractProtection(xf.Protection, s, style)
17411731
if xf.NumFmt != nil {
@@ -1820,23 +1810,18 @@ func (f *File) readDefaultFont() (*xlsxFont, error) {
18201810

18211811
// getFontID provides a function to get font ID.
18221812
// If given font does not exist, will return -1.
1823-
func (f *File) getFontID(styleSheet *xlsxStyleSheet, style *Style) (int, error) {
1824-
var err error
1813+
func (f *File) getFontID(styleSheet *xlsxStyleSheet, style *Style) int {
18251814
fontID := -1
18261815
if styleSheet.Fonts == nil || style.Font == nil {
1827-
return fontID, err
1816+
return fontID
18281817
}
18291818
for idx, fnt := range styleSheet.Fonts.Font {
1830-
font, err := f.newFont(style)
1831-
if err != nil {
1832-
return fontID, err
1833-
}
1834-
if reflect.DeepEqual(*fnt, *font) {
1819+
if reflect.DeepEqual(*fnt, *style.Font.newFont()) {
18351820
fontID = idx
1836-
return fontID, err
1821+
return fontID
18371822
}
18381823
}
1839-
return fontID, err
1824+
return fontID
18401825
}
18411826

18421827
// newFontColor set font color by given styles.
@@ -1869,35 +1854,37 @@ func newFontColor(font *Font) *xlsxColor {
18691854

18701855
// newFont provides a function to add font style by given cell format
18711856
// settings.
1872-
func (f *File) newFont(style *Style) (*xlsxFont, error) {
1873-
var err error
1874-
if style.Font.Size < MinFontSize {
1875-
style.Font.Size = 11
1857+
func (fnt *Font) newFont() *xlsxFont {
1858+
if fnt.Size < MinFontSize {
1859+
fnt.Size = 11
18761860
}
1877-
fnt := xlsxFont{
1878-
Sz: &attrValFloat{Val: float64Ptr(style.Font.Size)},
1879-
Name: &attrValString{Val: stringPtr(style.Font.Family)},
1861+
font := xlsxFont{
1862+
Sz: &attrValFloat{Val: float64Ptr(fnt.Size)},
18801863
Family: &attrValInt{Val: intPtr(2)},
18811864
}
1882-
fnt.Color = newFontColor(style.Font)
1883-
if style.Font.Bold {
1884-
fnt.B = &attrValBool{Val: &style.Font.Bold}
1865+
if fnt.Family != "" {
1866+
font.Name = &attrValString{Val: stringPtr(fnt.Family)}
18851867
}
1886-
if style.Font.Italic {
1887-
fnt.I = &attrValBool{Val: &style.Font.Italic}
1868+
if fnt.Charset != nil {
1869+
font.Charset = &attrValInt{Val: fnt.Charset}
18881870
}
1889-
if *fnt.Name.Val == "" {
1890-
if *fnt.Name.Val, err = f.GetDefaultFont(); err != nil {
1891-
return &fnt, err
1892-
}
1871+
font.Color = newFontColor(fnt)
1872+
if fnt.Bold {
1873+
font.B = &attrValBool{Val: &fnt.Bold}
1874+
}
1875+
if fnt.Italic {
1876+
font.I = &attrValBool{Val: &fnt.Italic}
1877+
}
1878+
if fnt.Strike {
1879+
font.Strike = &attrValBool{Val: &fnt.Strike}
18931880
}
1894-
if style.Font.Strike {
1895-
fnt.Strike = &attrValBool{Val: &style.Font.Strike}
1881+
if idx := inStrSlice(supportedUnderlineTypes, fnt.Underline, true); idx != -1 {
1882+
font.U = &attrValString{Val: stringPtr(supportedUnderlineTypes[idx])}
18961883
}
1897-
if idx := inStrSlice(supportedUnderlineTypes, style.Font.Underline, true); idx != -1 {
1898-
fnt.U = &attrValString{Val: stringPtr(supportedUnderlineTypes[idx])}
1884+
if inStrSlice([]string{"baseline", "superscript", "subscript"}, fnt.VertAlign, true) != -1 {
1885+
font.VertAlign = &attrValString{Val: &fnt.VertAlign}
18991886
}
1900-
return &fnt, err
1887+
return &font
19011888
}
19021889

19031890
// getNumFmtID provides a function to get number format code ID.

0 commit comments

Comments
 (0)