Skip to content

Commit c63ae6d

Browse files
committed
This fixed qax-os#1610, support to create a conditional format with number format and protection
1 parent a1810aa commit c63ae6d

File tree

3 files changed

+64
-11
lines changed

3 files changed

+64
-11
lines changed

styles.go

+47-5
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,7 @@ func (f *File) NewStyle(style *Style) (int, error) {
10321032
return setCellXfs(s, fontID, numFmtID, fillID, borderID, applyAlignment, applyProtection, alignment, protection)
10331033
}
10341034

1035+
// getXfIDFuncs provides a function to get xfID by given style.
10351036
var getXfIDFuncs = map[string]func(int, xlsxXf, *Style) bool{
10361037
"numFmt": func(numFmtID int, xf xlsxXf, style *Style) bool {
10371038
if style.CustomNumFmt == nil && numFmtID == -1 {
@@ -1121,7 +1122,10 @@ func (f *File) NewConditionalStyle(style *Style) (int, error) {
11211122
if err != nil {
11221123
return 0, err
11231124
}
1124-
dxf := dxf{
1125+
if fs.DecimalPlaces != nil && (*fs.DecimalPlaces < 0 || *fs.DecimalPlaces > 30) {
1126+
fs.DecimalPlaces = intPtr(2)
1127+
}
1128+
dxf := xlsxDxf{
11251129
Fill: newFills(fs, false),
11261130
}
11271131
if fs.Alignment != nil {
@@ -1133,17 +1137,55 @@ func (f *File) NewConditionalStyle(style *Style) (int, error) {
11331137
if fs.Font != nil {
11341138
dxf.Font, _ = f.newFont(fs)
11351139
}
1136-
dxfStr, _ := xml.Marshal(dxf)
1140+
if fs.Protection != nil {
1141+
dxf.Protection = newProtection(fs)
1142+
}
1143+
dxf.NumFmt = newDxfNumFmt(s, style, &dxf)
11371144
if s.Dxfs == nil {
11381145
s.Dxfs = &xlsxDxfs{}
11391146
}
11401147
s.Dxfs.Count++
1141-
s.Dxfs.Dxfs = append(s.Dxfs.Dxfs, &xlsxDxf{
1142-
Dxf: string(dxfStr[5 : len(dxfStr)-6]),
1143-
})
1148+
s.Dxfs.Dxfs = append(s.Dxfs.Dxfs, &dxf)
11441149
return s.Dxfs.Count - 1, nil
11451150
}
11461151

1152+
// newDxfNumFmt provides a function to create number format for conditional
1153+
// format styles.
1154+
func newDxfNumFmt(styleSheet *xlsxStyleSheet, style *Style, dxf *xlsxDxf) *xlsxNumFmt {
1155+
dp, numFmtID := "0", 164 // Default custom number format code from 164.
1156+
if style.DecimalPlaces != nil && *style.DecimalPlaces > 0 {
1157+
dp += "."
1158+
for i := 0; i < *style.DecimalPlaces; i++ {
1159+
dp += "0"
1160+
}
1161+
}
1162+
if style.CustomNumFmt != nil {
1163+
if styleSheet.Dxfs != nil {
1164+
for _, d := range styleSheet.Dxfs.Dxfs {
1165+
if d != nil && d.NumFmt != nil && d.NumFmt.NumFmtID > numFmtID {
1166+
numFmtID = d.NumFmt.NumFmtID
1167+
}
1168+
}
1169+
}
1170+
return &xlsxNumFmt{NumFmtID: numFmtID + 1, FormatCode: *style.CustomNumFmt}
1171+
}
1172+
numFmtCode, ok := builtInNumFmt[style.NumFmt]
1173+
if style.NumFmt > 0 && ok {
1174+
return &xlsxNumFmt{NumFmtID: style.NumFmt, FormatCode: numFmtCode}
1175+
}
1176+
fc, currency := currencyNumFmt[style.NumFmt]
1177+
if !currency {
1178+
return nil
1179+
}
1180+
if style.DecimalPlaces != nil {
1181+
fc = strings.ReplaceAll(fc, "0.00", dp)
1182+
}
1183+
if style.NegRed {
1184+
fc = fc + ";[Red]" + fc
1185+
}
1186+
return &xlsxNumFmt{NumFmtID: numFmtID, FormatCode: fc}
1187+
}
1188+
11471189
// GetDefaultFont provides the default font name currently set in the
11481190
// workbook. The spreadsheet generated by excelize default font is Calibri.
11491191
func (f *File) GetDefaultFont() (string, error) {

styles_test.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,26 @@ func TestNewStyle(t *testing.T) {
355355

356356
func TestNewConditionalStyle(t *testing.T) {
357357
f := NewFile()
358+
_, err := f.NewConditionalStyle(&Style{Protection: &Protection{Hidden: true, Locked: true}})
359+
assert.NoError(t, err)
360+
_, err = f.NewConditionalStyle(&Style{DecimalPlaces: intPtr(4), NumFmt: 165, NegRed: true})
361+
assert.NoError(t, err)
362+
_, err = f.NewConditionalStyle(&Style{DecimalPlaces: intPtr(-1)})
363+
assert.NoError(t, err)
364+
_, err = f.NewConditionalStyle(&Style{NumFmt: 1})
365+
assert.NoError(t, err)
366+
_, err = f.NewConditionalStyle(&Style{NumFmt: 27})
367+
assert.NoError(t, err)
368+
numFmt := "general"
369+
_, err = f.NewConditionalStyle(&Style{CustomNumFmt: &numFmt})
370+
assert.NoError(t, err)
371+
numFmt1 := "0.00"
372+
_, err = f.NewConditionalStyle(&Style{CustomNumFmt: &numFmt1})
373+
assert.NoError(t, err)
358374
// Test create conditional style with unsupported charset style sheet
359375
f.Styles = nil
360376
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
361-
_, err := f.NewConditionalStyle(&Style{Font: &Font{Color: "9A0511"}, Fill: Fill{Type: "pattern", Color: []string{"FEC7CE"}, Pattern: 1}})
377+
_, err = f.NewConditionalStyle(&Style{Font: &Font{Color: "9A0511"}, Fill: Fill{Type: "pattern", Color: []string{"FEC7CE"}, Pattern: 1}})
362378
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
363379
}
364380

xmlStyles.go

-5
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,6 @@ type xlsxDxfs struct {
251251
// xlsxDxf directly maps the dxf element. A single dxf record, expressing
252252
// incremental formatting to be applied.
253253
type xlsxDxf struct {
254-
Dxf string `xml:",innerxml"`
255-
}
256-
257-
// dxf directly maps the dxf element.
258-
type dxf struct {
259254
Font *xlsxFont `xml:"font"`
260255
NumFmt *xlsxNumFmt `xml:"numFmt"`
261256
Fill *xlsxFill `xml:"fill"`

0 commit comments

Comments
 (0)