summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--calc.go336
-rw-r--r--comment.go6
-rw-r--r--datavalidation.go7
-rw-r--r--datavalidation_test.go4
-rw-r--r--errors.go5
-rw-r--r--pivotTable.go4
-rw-r--r--sheet.go5
-rw-r--r--sheet_test.go12
-rw-r--r--styles_test.go4
-rw-r--r--xmlDrawing.go1
10 files changed, 140 insertions, 244 deletions
diff --git a/calc.go b/calc.go
index badd30e..59131d8 100644
--- a/calc.go
+++ b/calc.go
@@ -2849,7 +2849,7 @@ func (fn *formulaFuncs) ARABIC(argsList *list.List) formulaArg {
return newErrorFormulaArg(formulaErrorVALUE, "ARABIC requires 1 numeric argument")
}
text := argsList.Front().Value.(formulaArg).Value()
- if len(text) > 255 {
+ if len(text) > MaxFieldLength {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
text = strings.ToUpper(text)
@@ -7400,47 +7400,12 @@ func (fn *formulaFuncs) DAYS(argsList *list.List) formulaArg {
if argsList.Len() != 2 {
return newErrorFormulaArg(formulaErrorVALUE, "DAYS requires 2 arguments")
}
- var end, start float64
- endArg, startArg := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg)
- switch endArg.Type {
- case ArgNumber:
- end = endArg.Number
- case ArgString:
- endNum := endArg.ToNumber()
- if endNum.Type == ArgNumber {
- end = endNum.Number
- } else {
- args := list.New()
- args.PushBack(endArg)
- endValue := fn.DATEVALUE(args)
- if endValue.Type == ArgError {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- end = endValue.Number
- }
- default:
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- switch startArg.Type {
- case ArgNumber:
- start = startArg.Number
- case ArgString:
- startNum := startArg.ToNumber()
- if startNum.Type == ArgNumber {
- start = startNum.Number
- } else {
- args := list.New()
- args.PushBack(startArg)
- startValue := fn.DATEVALUE(args)
- if startValue.Type == ArgError {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- start = startValue.Number
- }
- default:
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
- return newNumberFormulaArg(end - start)
+ end, start := args.List[0], args.List[1]
+ return newNumberFormulaArg(end.Number - start.Number)
}
// ISOWEEKNUM function returns the ISO week number of a supplied date. The
@@ -7695,28 +7660,18 @@ func (fn *formulaFuncs) YEARFRAC(argsList *list.List) formulaArg {
if argsList.Len() != 2 && argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "YEARFRAC requires 3 or 4 arguments")
}
- var basisArg formulaArg
- startArg, endArg := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Front().Next().Value.(formulaArg).ToNumber()
- args := list.New().Init()
- if startArg.Type != ArgNumber {
- args.PushBack(argsList.Front().Value.(formulaArg))
- if startArg = fn.DATEVALUE(args); startArg.Type != ArgNumber {
- return startArg
- }
- }
- if endArg.Type != ArgNumber {
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- if endArg = fn.DATEVALUE(args); endArg.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ start, end := args.List[0], args.List[1]
+ basis := newNumberFormulaArg(0)
if argsList.Len() == 3 {
- if basisArg = argsList.Back().Value.(formulaArg).ToNumber(); basisArg.Type != ArgNumber {
- return basisArg
+ if basis = argsList.Back().Value.(formulaArg).ToNumber(); basis.Type != ArgNumber {
+ return basis
}
}
- return yearFrac(startArg.Number, endArg.Number, int(basisArg.Number))
+ return yearFrac(start.Number, end.Number, int(basis.Number))
}
// NOW function returns the current date and time. The function receives no
@@ -7859,7 +7814,7 @@ func (fn *formulaFuncs) CHAR(argsList *list.List) formulaArg {
return arg
}
num := int(arg.Number)
- if num < 0 || num > 255 {
+ if num < 0 || num > MaxFieldLength {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
return newStringFormulaArg(fmt.Sprintf("%c", num))
@@ -9413,24 +9368,11 @@ func (fn *formulaFuncs) ACCRINT(argsList *list.List) formulaArg {
if argsList.Len() > 8 {
return newErrorFormulaArg(formulaErrorVALUE, "ACCRINT allows at most 8 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- issue := fn.DATEVALUE(args)
- if issue.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- fi := fn.DATEVALUE(args)
- if fi.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Next().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(3, argsList)
+ if args.Type != ArgList {
+ return args
}
+ issue, settlement := args.List[0], args.List[2]
rate := argsList.Front().Next().Next().Next().Value.(formulaArg).ToNumber()
par := argsList.Front().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
frequency := argsList.Front().Next().Next().Next().Next().Next().Value.(formulaArg).ToNumber()
@@ -9468,18 +9410,11 @@ func (fn *formulaFuncs) ACCRINTM(argsList *list.List) formulaArg {
if argsList.Len() != 4 && argsList.Len() != 5 {
return newErrorFormulaArg(formulaErrorVALUE, "ACCRINTM requires 4 or 5 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- issue := fn.DATEVALUE(args)
- if issue.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ issue, settlement := args.List[0], args.List[1]
if settlement.Number < issue.Number {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
@@ -9644,24 +9579,11 @@ func (fn *formulaFuncs) prepareCouponArgs(name string, argsList *list.List) form
if argsList.Len() != 3 && argsList.Len() != 4 {
return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 or 4 arguments", name))
}
- args := list.New().Init()
- settlement := argsList.Front().Value.(formulaArg).ToNumber()
- if settlement.Type != ArgNumber {
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement = fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- }
- maturity := argsList.Front().Next().Value.(formulaArg).ToNumber()
- if maturity.Type != ArgNumber {
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity = fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
if settlement.Number >= maturity.Number {
return newErrorFormulaArg(formulaErrorNUM, fmt.Sprintf("%s requires maturity > settlement", name))
}
@@ -10048,6 +9970,43 @@ func (fn *formulaFuncs) DDB(argsList *list.List) formulaArg {
return newNumberFormulaArg(depreciation)
}
+// prepareDataValueArgs convert first N arguments to data value for the
+// formula functions.
+func (fn *formulaFuncs) prepareDataValueArgs(n int, argsList *list.List) formulaArg {
+ l := list.New()
+ dataValues := []formulaArg{}
+ getDateValue := func(arg formulaArg, l *list.List) formulaArg {
+ switch arg.Type {
+ case ArgNumber:
+ break
+ case ArgString:
+ num := arg.ToNumber()
+ if num.Type == ArgNumber {
+ arg = num
+ break
+ }
+ l.Init()
+ l.PushBack(arg)
+ arg = fn.DATEVALUE(l)
+ if arg.Type == ArgError {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ default:
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ return arg
+ }
+ for i, arg := 0, argsList.Front(); i < n; arg = arg.Next() {
+ dataValue := getDateValue(arg.Value.(formulaArg), l)
+ if dataValue.Type != ArgNumber {
+ return dataValue
+ }
+ dataValues = append(dataValues, dataValue)
+ i++
+ }
+ return newListFormulaArg(dataValues)
+}
+
// DISC function calculates the Discount Rate for a security. The syntax of
// the function is:
//
@@ -10057,18 +10016,11 @@ func (fn *formulaFuncs) DISC(argsList *list.List) formulaArg {
if argsList.Len() != 4 && argsList.Len() != 5 {
return newErrorFormulaArg(formulaErrorVALUE, "DISC requires 4 or 5 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
if maturity.Number <= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, "DISC requires maturity > settlement")
}
@@ -10253,18 +10205,11 @@ func (fn *formulaFuncs) INTRATE(argsList *list.List) formulaArg {
if argsList.Len() != 4 && argsList.Len() != 5 {
return newErrorFormulaArg(formulaErrorVALUE, "INTRATE requires 4 or 5 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
if maturity.Number <= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, "INTRATE requires maturity > settlement")
}
@@ -10707,18 +10652,11 @@ func (fn *formulaFuncs) PRICEDISC(argsList *list.List) formulaArg {
if argsList.Len() != 4 && argsList.Len() != 5 {
return newErrorFormulaArg(formulaErrorVALUE, "PRICEDISC requires 4 or 5 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
if maturity.Number <= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, "PRICEDISC requires maturity > settlement")
}
@@ -10758,27 +10696,14 @@ func (fn *formulaFuncs) PRICEMAT(argsList *list.List) formulaArg {
if argsList.Len() != 5 && argsList.Len() != 6 {
return newErrorFormulaArg(formulaErrorVALUE, "PRICEMAT requires 5 or 6 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(3, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity, issue := args.List[0], args.List[1], args.List[2]
if settlement.Number >= maturity.Number {
return newErrorFormulaArg(formulaErrorNUM, "PRICEMAT requires maturity > settlement")
}
- args.Init()
- args.PushBack(argsList.Front().Next().Next().Value.(formulaArg))
- issue := fn.DATEVALUE(args)
- if issue.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
if issue.Number >= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, "PRICEMAT requires settlement > issue")
}
@@ -10938,18 +10863,11 @@ func (fn *formulaFuncs) RECEIVED(argsList *list.List) formulaArg {
if argsList.Len() > 5 {
return newErrorFormulaArg(formulaErrorVALUE, "RECEIVED allows at most 5 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
investment := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
if investment.Type != ArgNumber {
return investment
@@ -11061,18 +10979,11 @@ func (fn *formulaFuncs) TBILLEQ(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "TBILLEQ requires 3 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
dsm := maturity.Number - settlement.Number
if dsm > 365 || maturity.Number <= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
@@ -11096,18 +11007,11 @@ func (fn *formulaFuncs) TBILLPRICE(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "TBILLPRICE requires 3 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
dsm := maturity.Number - settlement.Number
if dsm > 365 || maturity.Number <= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
@@ -11131,18 +11035,11 @@ func (fn *formulaFuncs) TBILLYIELD(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "TBILLYIELD requires 3 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
dsm := maturity.Number - settlement.Number
if dsm > 365 || maturity.Number <= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
@@ -11231,18 +11128,11 @@ func (fn *formulaFuncs) YIELDDISC(argsList *list.List) formulaArg {
if argsList.Len() != 4 && argsList.Len() != 5 {
return newErrorFormulaArg(formulaErrorVALUE, "YIELDDISC requires 4 or 5 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
+ settlement, maturity := args.List[0], args.List[1]
pr := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
if pr.Type != ArgNumber {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
@@ -11279,23 +11169,19 @@ func (fn *formulaFuncs) YIELDMAT(argsList *list.List) formulaArg {
if argsList.Len() != 5 && argsList.Len() != 6 {
return newErrorFormulaArg(formulaErrorVALUE, "YIELDMAT requires 5 or 6 arguments")
}
- args := list.New().Init()
- args.PushBack(argsList.Front().Value.(formulaArg))
- settlement := fn.DATEVALUE(args)
- if settlement.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
- }
- args.Init()
- args.PushBack(argsList.Front().Next().Value.(formulaArg))
- maturity := fn.DATEVALUE(args)
- if maturity.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ args := fn.prepareDataValueArgs(2, argsList)
+ if args.Type != ArgList {
+ return args
}
- args.Init()
- args.PushBack(argsList.Front().Next().Next().Value.(formulaArg))
- issue := fn.DATEVALUE(args)
+ settlement, maturity := args.List[0], args.List[1]
+ arg := list.New().Init()
+ issue := argsList.Front().Next().Next().Value.(formulaArg).ToNumber()
if issue.Type != ArgNumber {
- return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ arg.PushBack(argsList.Front().Next().Next().Value.(formulaArg))
+ issue = fn.DATEVALUE(arg)
+ if issue.Type != ArgNumber {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
}
if issue.Number >= settlement.Number {
return newErrorFormulaArg(formulaErrorNUM, "YIELDMAT requires settlement > issue")
diff --git a/comment.go b/comment.go
index a89d2bb..07cd9f2 100644
--- a/comment.go
+++ b/comment.go
@@ -245,11 +245,11 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
a := formatSet.Author
t := formatSet.Text
- if len(a) > 255 {
- a = a[0:255]
+ if len(a) > MaxFieldLength {
+ a = a[:MaxFieldLength]
}
if len(t) > 32512 {
- t = t[0:32512]
+ t = t[:32512]
}
comments := f.commentsReader(commentsXML)
authorID := 0
diff --git a/datavalidation.go b/datavalidation.go
index 047a53c..80a0295 100644
--- a/datavalidation.go
+++ b/datavalidation.go
@@ -35,11 +35,6 @@ const (
DataValidationTypeWhole
)
-const (
- // dataValidationFormulaStrLen 255 characters
- dataValidationFormulaStrLen = 255
-)
-
// DataValidationErrorStyle defined the style of data validation error alert.
type DataValidationErrorStyle int
@@ -120,7 +115,7 @@ func (dd *DataValidation) SetInput(title, msg string) {
// SetDropList data validation list.
func (dd *DataValidation) SetDropList(keys []string) error {
formula := strings.Join(keys, ",")
- if dataValidationFormulaStrLen < len(utf16.Encode([]rune(formula))) {
+ if MaxFieldLength < len(utf16.Encode([]rune(formula))) {
return ErrDataValidationFormulaLenth
}
dd.Formula1 = fmt.Sprintf(`<formula1>"%s"</formula1>`, formulaEscaper.Replace(formula))
diff --git a/datavalidation_test.go b/datavalidation_test.go
index 5986375..c35693c 100644
--- a/datavalidation_test.go
+++ b/datavalidation_test.go
@@ -54,8 +54,8 @@ func TestDataValidation(t *testing.T) {
dvRange.Sqref = "A5:B6"
for _, listValid := range [][]string{
{"1", "2", "3"},
- {strings.Repeat("&", 255)},
- {strings.Repeat("\u4E00", 255)},
+ {strings.Repeat("&", MaxFieldLength)},
+ {strings.Repeat("\u4E00", MaxFieldLength)},
{strings.Repeat("\U0001F600", 100), strings.Repeat("\u4E01", 50), "<&>"},
{`A<`, `B>`, `C"`, "D\t", `E'`, `F`},
} {
diff --git a/errors.go b/errors.go
index 56a2280..f9eedde 100644
--- a/errors.go
+++ b/errors.go
@@ -51,6 +51,11 @@ func newInvalidStyleID(styleID int) error {
return fmt.Errorf("invalid style ID %d, negative values are not supported", styleID)
}
+// newFieldLengthError defined the error message on receiving the field length overflow.
+func newFieldLengthError(name string) error {
+ return fmt.Errorf("field %s must be less or equal than 255 characters", name)
+}
+
var (
// ErrStreamSetColWidth defined the error message on set column width in
// stream writing mode.
diff --git a/pivotTable.go b/pivotTable.go
index 6ce0173..270ee99 100644
--- a/pivotTable.go
+++ b/pivotTable.go
@@ -662,8 +662,8 @@ func (f *File) getPivotTableFieldsSubtotal(fields []PivotTableField) []string {
func (f *File) getPivotTableFieldsName(fields []PivotTableField) []string {
field := make([]string, len(fields))
for idx, fld := range fields {
- if len(fld.Name) > 255 {
- field[idx] = fld.Name[0:255]
+ if len(fld.Name) > MaxFieldLength {
+ field[idx] = fld.Name[:MaxFieldLength]
continue
}
field[idx] = fld.Name
diff --git a/sheet.go b/sheet.go
index 43e277a..5738ced 100644
--- a/sheet.go
+++ b/sheet.go
@@ -27,6 +27,7 @@ import (
"sort"
"strconv"
"strings"
+ "unicode/utf16"
"unicode/utf8"
"github.com/mohae/deepcopy"
@@ -1092,8 +1093,8 @@ func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error
// Check 6 string type fields: OddHeader, OddFooter, EvenHeader, EvenFooter,
// FirstFooter, FirstHeader
for i := 4; i < v.NumField()-1; i++ {
- if v.Field(i).Len() >= 255 {
- return fmt.Errorf("field %s must be less than 255 characters", v.Type().Field(i).Name)
+ if len(utf16.Encode([]rune(v.Field(i).String()))) > MaxFieldLength {
+ return newFieldLengthError(v.Type().Field(i).Name)
}
}
ws.HeaderFooter = &xlsxHeaderFooter{
diff --git a/sheet_test.go b/sheet_test.go
index ef32d79..93a4ab6 100644
--- a/sheet_test.go
+++ b/sheet_test.go
@@ -217,10 +217,18 @@ func TestSetHeaderFooter(t *testing.T) {
assert.EqualError(t, f.SetHeaderFooter("SheetN", nil), "sheet SheetN is not exist")
// Test set header and footer with illegal setting.
assert.EqualError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
- OddHeader: strings.Repeat("c", 256),
- }), "field OddHeader must be less than 255 characters")
+ OddHeader: strings.Repeat("c", MaxFieldLength+1),
+ }), "field OddHeader must be less or equal than 255 characters")
assert.NoError(t, f.SetHeaderFooter("Sheet1", nil))
+ text := strings.Repeat("δΈ€", MaxFieldLength)
+ assert.NoError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
+ OddHeader: text,
+ OddFooter: text,
+ EvenHeader: text,
+ EvenFooter: text,
+ FirstHeader: text,
+ }))
assert.NoError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
DifferentFirst: true,
DifferentOddEven: true,
diff --git a/styles_test.go b/styles_test.go
index a214aaa..9129914 100644
--- a/styles_test.go
+++ b/styles_test.go
@@ -262,10 +262,10 @@ func TestGetDefaultFont(t *testing.T) {
func TestSetDefaultFont(t *testing.T) {
f := NewFile()
- f.SetDefaultFont("Ariel")
+ f.SetDefaultFont("Arial")
styles := f.stylesReader()
s := f.GetDefaultFont()
- assert.Equal(t, s, "Ariel", "Default font should change to Ariel")
+ assert.Equal(t, s, "Arial", "Default font should change to Arial")
assert.Equal(t, *styles.CellStyles.CellStyle[0].CustomBuiltIn, true)
}
diff --git a/xmlDrawing.go b/xmlDrawing.go
index 0bb11ac..dabb34a 100644
--- a/xmlDrawing.go
+++ b/xmlDrawing.go
@@ -99,6 +99,7 @@ const (
MaxFontFamilyLength = 31
MaxFontSize = 409
MaxFileNameLength = 207
+ MaxFieldLength = 255
MaxColumnWidth = 255
MaxRowHeight = 409
TotalRows = 1048576