Skip to content

Commit

Permalink
This fixed #1610, support to create a conditional format with number …
Browse files Browse the repository at this point in the history
…format and protection
  • Loading branch information
xuri committed Aug 17, 2023
1 parent a1810aa commit c63ae6d
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 11 deletions.
52 changes: 47 additions & 5 deletions styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,7 @@ func (f *File) NewStyle(style *Style) (int, error) {
return setCellXfs(s, fontID, numFmtID, fillID, borderID, applyAlignment, applyProtection, alignment, protection)
}

// getXfIDFuncs provides a function to get xfID by given style.
var getXfIDFuncs = map[string]func(int, xlsxXf, *Style) bool{
"numFmt": func(numFmtID int, xf xlsxXf, style *Style) bool {
if style.CustomNumFmt == nil && numFmtID == -1 {
Expand Down Expand Up @@ -1121,7 +1122,10 @@ func (f *File) NewConditionalStyle(style *Style) (int, error) {
if err != nil {
return 0, err
}
dxf := dxf{
if fs.DecimalPlaces != nil && (*fs.DecimalPlaces < 0 || *fs.DecimalPlaces > 30) {
fs.DecimalPlaces = intPtr(2)
}
dxf := xlsxDxf{
Fill: newFills(fs, false),
}
if fs.Alignment != nil {
Expand All @@ -1133,17 +1137,55 @@ func (f *File) NewConditionalStyle(style *Style) (int, error) {
if fs.Font != nil {
dxf.Font, _ = f.newFont(fs)
}
dxfStr, _ := xml.Marshal(dxf)
if fs.Protection != nil {
dxf.Protection = newProtection(fs)
}
dxf.NumFmt = newDxfNumFmt(s, style, &dxf)
if s.Dxfs == nil {
s.Dxfs = &xlsxDxfs{}
}
s.Dxfs.Count++
s.Dxfs.Dxfs = append(s.Dxfs.Dxfs, &xlsxDxf{
Dxf: string(dxfStr[5 : len(dxfStr)-6]),
})
s.Dxfs.Dxfs = append(s.Dxfs.Dxfs, &dxf)
return s.Dxfs.Count - 1, nil
}

// newDxfNumFmt provides a function to create number format for conditional
// format styles.
func newDxfNumFmt(styleSheet *xlsxStyleSheet, style *Style, dxf *xlsxDxf) *xlsxNumFmt {
dp, numFmtID := "0", 164 // Default custom number format code from 164.
if style.DecimalPlaces != nil && *style.DecimalPlaces > 0 {
dp += "."
for i := 0; i < *style.DecimalPlaces; i++ {
dp += "0"
}
}
if style.CustomNumFmt != nil {
if styleSheet.Dxfs != nil {
for _, d := range styleSheet.Dxfs.Dxfs {
if d != nil && d.NumFmt != nil && d.NumFmt.NumFmtID > numFmtID {
numFmtID = d.NumFmt.NumFmtID
}
}
}
return &xlsxNumFmt{NumFmtID: numFmtID + 1, FormatCode: *style.CustomNumFmt}
}
numFmtCode, ok := builtInNumFmt[style.NumFmt]
if style.NumFmt > 0 && ok {
return &xlsxNumFmt{NumFmtID: style.NumFmt, FormatCode: numFmtCode}
}
fc, currency := currencyNumFmt[style.NumFmt]
if !currency {
return nil
}
if style.DecimalPlaces != nil {
fc = strings.ReplaceAll(fc, "0.00", dp)
}
if style.NegRed {
fc = fc + ";[Red]" + fc
}
return &xlsxNumFmt{NumFmtID: numFmtID, FormatCode: fc}
}

// GetDefaultFont provides the default font name currently set in the
// workbook. The spreadsheet generated by excelize default font is Calibri.
func (f *File) GetDefaultFont() (string, error) {
Expand Down
18 changes: 17 additions & 1 deletion styles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,26 @@ func TestNewStyle(t *testing.T) {

func TestNewConditionalStyle(t *testing.T) {
f := NewFile()
_, err := f.NewConditionalStyle(&Style{Protection: &Protection{Hidden: true, Locked: true}})
assert.NoError(t, err)
_, err = f.NewConditionalStyle(&Style{DecimalPlaces: intPtr(4), NumFmt: 165, NegRed: true})
assert.NoError(t, err)
_, err = f.NewConditionalStyle(&Style{DecimalPlaces: intPtr(-1)})
assert.NoError(t, err)
_, err = f.NewConditionalStyle(&Style{NumFmt: 1})
assert.NoError(t, err)
_, err = f.NewConditionalStyle(&Style{NumFmt: 27})
assert.NoError(t, err)
numFmt := "general"
_, err = f.NewConditionalStyle(&Style{CustomNumFmt: &numFmt})
assert.NoError(t, err)
numFmt1 := "0.00"
_, err = f.NewConditionalStyle(&Style{CustomNumFmt: &numFmt1})
assert.NoError(t, err)
// Test create conditional style with unsupported charset style sheet
f.Styles = nil
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
_, err := f.NewConditionalStyle(&Style{Font: &Font{Color: "9A0511"}, Fill: Fill{Type: "pattern", Color: []string{"FEC7CE"}, Pattern: 1}})
_, err = f.NewConditionalStyle(&Style{Font: &Font{Color: "9A0511"}, Fill: Fill{Type: "pattern", Color: []string{"FEC7CE"}, Pattern: 1}})
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}

Expand Down
5 changes: 0 additions & 5 deletions xmlStyles.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,6 @@ type xlsxDxfs struct {
// xlsxDxf directly maps the dxf element. A single dxf record, expressing
// incremental formatting to be applied.
type xlsxDxf struct {
Dxf string `xml:",innerxml"`
}

// dxf directly maps the dxf element.
type dxf struct {
Font *xlsxFont `xml:"font"`
NumFmt *xlsxNumFmt `xml:"numFmt"`
Fill *xlsxFill `xml:"fill"`
Expand Down

0 comments on commit c63ae6d

Please sign in to comment.