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) + args := fn.prepareDataValueArgs(2, argsList) + if args.Type != ArgList { + return args } - 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) - } - 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 := fn.prepareDataValueArgs(2, argsList) + if args.Type != ArgList { + return args } - args.Init() - args.PushBack(argsList.Front().Next().Value.(formulaArg)) - maturity := fn.DATEVALUE(args) - if maturity.Type != ArgNumber { - return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) - } - 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(`"%s"`, 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