已验证 提交 79265655 编写于 作者: xurime's avatar xurime

This closes #1777, fix the GetStyle or GetConditionalStyle function to returns...

This closes #1777, fix the GetStyle or GetConditionalStyle function to returns incorrect DecimalPlaces field value

- Update documentation for the NewStyle function
- Update unit tests
- Update dependencies Go module
- Update GitHub workflow dependencies package version
- Update copyright agreement statement
上级 f4e39513
......@@ -24,12 +24,12 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
......@@ -14,7 +14,7 @@ jobs:
steps:
- name: Install Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
......
BSD 3-Clause License
Copyright (c) 2016-2023 The excelize Authors.
Copyright (c) 2016-2024 The excelize Authors.
Copyright (c) 2011-2017 Geoffrey J. Teale
All rights reserved.
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
......@@ -8,9 +8,9 @@ require (
github.com/stretchr/testify v1.8.4
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05
golang.org/x/crypto v0.17.0
golang.org/x/crypto v0.18.0
golang.org/x/image v0.14.0
golang.org/x/net v0.19.0
golang.org/x/net v0.20.0
golang.org/x/text v0.14.0
)
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......@@ -4680,6 +4680,67 @@ func (f *File) checkDateTimePattern() error {
return nil
}
// extractNumFmtDecimal returns decimal places, if has a decimal point token and
// zero place holder token from a number format code token list.
func extractNumFmtDecimal(tokens []nfp.Token) (int, bool, bool) {
decimal, point, zero := 0, false, false
for _, token := range tokens {
if token.TType == nfp.TokenTypeDecimalPoint {
point = true
}
if token.TType == nfp.TokenTypeZeroPlaceHolder {
if point {
decimal = len(token.TValue)
}
zero = true
}
}
return decimal, point, zero
}
// extractNumFmtDecimal returns decimal places from a number format code that
// has the same decimal places in positive part negative part or only positive
// part, if the given number format code is not suitable for numeric this
// function will return -1.
func (f *File) extractNumFmtDecimal(fmtCode string) int {
var (
p = nfp.NumberFormatParser()
pos, neg, posPoint, negPoint, posZero, negZero bool
posDecimal, negDecimal int
)
for i, section := range p.Parse(fmtCode) {
if i == 0 {
pos = true
posDecimal, posPoint, posZero = extractNumFmtDecimal(section.Items)
}
if i == 1 {
neg = true
negDecimal, negPoint, negZero = extractNumFmtDecimal(section.Items)
}
}
if !pos {
return -1
}
equalPosNegDecimal := posPoint && negPoint && posDecimal == negDecimal
equalPosNegZero := !posPoint && !negPoint && posZero && negZero
if neg {
if equalPosNegDecimal {
return posDecimal
}
if equalPosNegZero {
return 0
}
return -1
}
if posPoint {
return posDecimal
}
if posZero {
return 0
}
return -1
}
// langNumFmtFuncZhCN returns number format code by given date and time pattern
// for country code zh-cn.
func (f *File) langNumFmtFuncZhCN(numFmtID int) string {
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......@@ -278,6 +278,14 @@ func parseFormatStyleSet(style *Style) (*Style, error) {
// single
// double
//
// NumFmt is used to set the built-in all languages formats index, built-in
// language formats index, or built-in currency formats index, it doesn't work
// when you specify the custom number format by CustomNumFmt. When you get
// style definition by the GetStyle or GetConditionalStyle function, the NumFmt
// only works if the number format code is exactly equal with any built-in all
// languages format code, built-in language formats code, or built-in currency
// format code.
//
// Excel's built-in all languages formats are shown in the following table:
//
// Index | Format String
......@@ -919,8 +927,8 @@ func parseFormatStyleSet(style *Style) (*Style, error) {
// 633 | ZWN
// 634 | ZWR
//
// Excelize support set custom number format for cell. For example, set number
// as date type in Uruguay (Spanish) format for Sheet1!A6:
// Excelize support set custom number format for cell by CustomNumFmt field. For
// example, set number as date type in Uruguay (Spanish) format for Sheet1!A6:
//
// f := excelize.NewFile()
// defer func() {
......@@ -940,7 +948,15 @@ func parseFormatStyleSet(style *Style) (*Style, error) {
// }
// err = f.SetCellStyle("Sheet1", "A6", "A6", style)
//
// Cell Sheet1!A6 in the Excel Application: martes, 04 de Julio de 2017
// Cell Sheet1!A6 in the spreadsheet application: martes, 04 de Julio de 2017
//
// DecimalPlaces is used to set the decimal places for built-in currency
// formats, it doesn't work if you have specified the built-in all languages
// formats or built-in language formats by NumFmt field, or specify the custom
// number format by CustomNumFmt. When you get style definition by the GetStyle
// or GetConditionalStyle function, the DecimalPlaces only doesn't nil if a
// number format code has the same decimal places in the positive part negative
// part, or only the positive part.
func (f *File) NewStyle(style *Style) (int, error) {
var (
fs *Style
......@@ -1498,12 +1514,21 @@ func (f *File) extractFont(fnt *xlsxFont, s *xlsxStyleSheet, style *Style) {
func (f *File) extractNumFmt(n *int, s *xlsxStyleSheet, style *Style) {
if n != nil {
numFmtID := *n
if _, ok := builtInNumFmt[numFmtID]; ok || isLangNumFmt(numFmtID) {
if builtInFmtCode, ok := builtInNumFmt[numFmtID]; ok || isLangNumFmt(numFmtID) {
style.NumFmt = numFmtID
if decimalPlaces := f.extractNumFmtDecimal(builtInFmtCode); decimalPlaces != -1 {
style.DecimalPlaces = &decimalPlaces
}
return
}
if s.NumFmts != nil {
for _, numFmt := range s.NumFmts.NumFmt {
if numFmt.NumFmtID != numFmtID {
continue
}
if decimalPlaces := f.extractNumFmtDecimal(numFmt.FormatCode); decimalPlaces != -1 {
style.DecimalPlaces = &decimalPlaces
}
style.CustomNumFmt = &numFmt.FormatCode
if strings.Contains(numFmt.FormatCode, ";[Red]") {
style.NegRed = true
......
......@@ -443,7 +443,8 @@ func TestConditionalStyle(t *testing.T) {
assert.NoError(t, err)
style, err = f.GetConditionalStyle(idx)
assert.NoError(t, err)
assert.Equal(t, expected, style)
assert.Equal(t, expected.NumFmt, style.NumFmt)
assert.Zero(t, *style.DecimalPlaces)
_, err = f.NewConditionalStyle(&Style{NumFmt: 27})
assert.NoError(t, err)
numFmt := "general"
......@@ -641,6 +642,7 @@ func TestGetStyle(t *testing.T) {
assert.Equal(t, expected.Alignment, style.Alignment)
assert.Equal(t, expected.Protection, style.Protection)
assert.Equal(t, expected.NumFmt, style.NumFmt)
assert.Nil(t, style.DecimalPlaces)
expected = &Style{
Fill: Fill{Type: "pattern", Pattern: 1, Color: []string{"0000FF"}},
......@@ -650,6 +652,15 @@ func TestGetStyle(t *testing.T) {
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Equal(t, expected.Fill, style.Fill)
assert.Nil(t, style.DecimalPlaces)
expected = &Style{NumFmt: 2}
styleID, err = f.NewStyle(expected)
assert.NoError(t, err)
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Equal(t, expected.NumFmt, style.NumFmt)
assert.Equal(t, 2, *style.DecimalPlaces)
expected = &Style{NumFmt: 27}
styleID, err = f.NewStyle(expected)
......@@ -657,6 +668,7 @@ func TestGetStyle(t *testing.T) {
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Equal(t, expected.NumFmt, style.NumFmt)
assert.Nil(t, style.DecimalPlaces)
expected = &Style{NumFmt: 165}
styleID, err = f.NewStyle(expected)
......@@ -664,13 +676,50 @@ func TestGetStyle(t *testing.T) {
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Equal(t, expected.NumFmt, style.NumFmt)
assert.Equal(t, 2, *style.DecimalPlaces)
expected = &Style{NumFmt: 165, NegRed: true}
decimal := 4
expected = &Style{NumFmt: 165, DecimalPlaces: &decimal, NegRed: true}
styleID, err = f.NewStyle(expected)
assert.NoError(t, err)
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Equal(t, expected.NumFmt, style.NumFmt)
assert.Equal(t, 0, style.NumFmt)
assert.Equal(t, *expected.DecimalPlaces, *style.DecimalPlaces)
assert.Equal(t, "[$$-409]#,##0.0000;[Red][$$-409]#,##0.0000", *style.CustomNumFmt)
for _, val := range [][]interface{}{
{"$#,##0", 0},
{"$#,##0.0", 1},
{"_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(@_)", 0},
{"_($* #,##000_);_($* (#,##000);_($* \"-\"_);_(@_)", 0},
{"_($* #,##0.0000_);_($* (#,##0.0000);_($* \"-\"????_);_(@_)", 4},
} {
numFmtCode := val[0].(string)
expected = &Style{CustomNumFmt: &numFmtCode}
styleID, err = f.NewStyle(expected)
assert.NoError(t, err)
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Equal(t, val[1].(int), *style.DecimalPlaces, numFmtCode)
}
for _, val := range []string{
";$#,##0",
";$#,##0;",
";$#,##0.0",
";$#,##0.0;",
"$#,##0;0.0",
"_($* #,##0_);;_($* \"-\"_);_(@_)",
"_($* #,##0.0_);_($* (#,##0.00);_($* \"-\"_);_(@_)",
} {
expected = &Style{CustomNumFmt: &val}
styleID, err = f.NewStyle(expected)
assert.NoError(t, err)
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Nil(t, style.DecimalPlaces)
}
// Test get style with custom color index
f.Styles.Colors = &xlsxStyleColors{
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
// Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册