summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxuri <xuri.me@gmail.com>2021-07-29 00:03:57 +0800
committerxuri <xuri.me@gmail.com>2021-07-29 00:03:57 +0800
commit7dbf88f221f278075d4ff9e153b21236d0826c33 (patch)
tree508e171a8702bb52f017239d1f210cad076c19c4
parente9ae9b45b20a5df7e3aa15afcfac83ecb13394c6 (diff)
This closes #971, closes #972 and closes #974
- Escape XML character in the drop list - Fix incorrect character count limit in the drop list - Fix Excel time parse issue in some case - Fix custom number format month parse issue in some case - Fix corrupted file generated caused by concurrency adding pictures
-rw-r--r--col.go4
-rw-r--r--datavalidation.go13
-rw-r--r--date.go27
-rw-r--r--sheet.go3
-rw-r--r--styles.go2
-rw-r--r--xmlWorksheet.go4
6 files changed, 25 insertions, 28 deletions
diff --git a/col.go b/col.go
index 5171f34..088fac9 100644
--- a/col.go
+++ b/col.go
@@ -439,10 +439,10 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
for col := start; col <= end; col++ {
from, _ := CoordinatesToCellName(col, 1)
to, _ := CoordinatesToCellName(col, rows)
- f.SetCellStyle(sheet, from, to, styleID)
+ err = f.SetCellStyle(sheet, from, to, styleID)
}
}
- return nil
+ return err
}
// SetColWidth provides a function to set the width of a single column or
diff --git a/datavalidation.go b/datavalidation.go
index 0f8508b..a95f4d0 100644
--- a/datavalidation.go
+++ b/datavalidation.go
@@ -14,6 +14,7 @@ package excelize
import (
"fmt"
"strings"
+ "unicode/utf16"
)
// DataValidationType defined the type of data validation.
@@ -111,10 +112,10 @@ 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(formula) {
+ if dataValidationFormulaStrLen < len(utf16.Encode([]rune(formula))) {
return fmt.Errorf(dataValidationFormulaStrLenErr)
}
- dd.Formula1 = fmt.Sprintf("<formula1>%s</formula1>", formula)
+ dd.Formula1 = formula
dd.Type = convDataValidationType(typeList)
return nil
}
@@ -123,12 +124,12 @@ func (dd *DataValidation) SetDropList(keys []string) error {
func (dd *DataValidation) SetRange(f1, f2 float64, t DataValidationType, o DataValidationOperator) error {
formula1 := fmt.Sprintf("%f", f1)
formula2 := fmt.Sprintf("%f", f2)
- if dataValidationFormulaStrLen+21 < len(dd.Formula1) || dataValidationFormulaStrLen+21 < len(dd.Formula2) {
+ if dataValidationFormulaStrLen < len(utf16.Encode([]rune(dd.Formula1))) || dataValidationFormulaStrLen < len(utf16.Encode([]rune(dd.Formula2))) {
return fmt.Errorf(dataValidationFormulaStrLenErr)
}
- dd.Formula1 = fmt.Sprintf("<formula1>%s</formula1>", formula1)
- dd.Formula2 = fmt.Sprintf("<formula2>%s</formula2>", formula2)
+ dd.Formula1 = formula1
+ dd.Formula2 = formula2
dd.Type = convDataValidationType(t)
dd.Operator = convDataValidationOperatior(o)
return nil
@@ -148,7 +149,7 @@ func (dd *DataValidation) SetRange(f1, f2 float64, t DataValidationType, o DataV
//
func (dd *DataValidation) SetSqrefDropList(sqref string, isCurrentSheet bool) error {
if isCurrentSheet {
- dd.Formula1 = fmt.Sprintf("<formula1>%s</formula1>", sqref)
+ dd.Formula1 = sqref
dd.Type = convDataValidationType(typeList)
return nil
}
diff --git a/date.go b/date.go
index 0531b6c..a5edcf8 100644
--- a/date.go
+++ b/date.go
@@ -17,11 +17,14 @@ import (
)
const (
+ nanosInADay = float64((24 * time.Hour) / time.Nanosecond)
dayNanoseconds = 24 * time.Hour
maxDuration = 290 * 364 * dayNanoseconds
)
var (
+ excel1900Epoc = time.Date(1899, time.December, 30, 0, 0, 0, 0, time.UTC)
+ excel1904Epoc = time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC)
excelMinTime1900 = time.Date(1899, time.December, 31, 0, 0, 0, 0, time.UTC)
excelBuggyPeriodStart = time.Date(1900, time.March, 1, 0, 0, 0, 0, time.UTC).Add(-time.Nanosecond)
)
@@ -131,12 +134,11 @@ func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
// timeFromExcelTime provides a function to convert an excelTime
// representation (stored as a floating point number) to a time.Time.
func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
- const MDD int64 = 106750 // Max time.Duration Days, aprox. 290 years
var date time.Time
- var intPart = int64(excelTime)
+ var wholeDaysPart = int(excelTime)
// Excel uses Julian dates prior to March 1st 1900, and Gregorian
// thereafter.
- if intPart <= 61 {
+ if wholeDaysPart <= 61 {
const OFFSET1900 = 15018.0
const OFFSET1904 = 16480.0
const MJD0 float64 = 2400000.5
@@ -148,23 +150,14 @@ func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
}
return date
}
- var floatPart = excelTime - float64(intPart)
- var dayNanoSeconds float64 = 24 * 60 * 60 * 1000 * 1000 * 1000
+ var floatPart = excelTime - float64(wholeDaysPart)
if date1904 {
- date = time.Date(1904, 1, 1, 0, 0, 0, 0, time.UTC)
+ date = excel1904Epoc
} else {
- date = time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
+ date = excel1900Epoc
}
-
- // Duration is limited to aprox. 290 years
- for intPart > MDD {
- durationDays := time.Duration(MDD) * time.Hour * 24
- date = date.Add(durationDays)
- intPart = intPart - MDD
- }
- durationDays := time.Duration(intPart) * time.Hour * 24
- durationPart := time.Duration(dayNanoSeconds * floatPart)
- return date.Add(durationDays).Add(durationPart)
+ durationPart := time.Duration(nanosInADay * floatPart)
+ return date.AddDate(0, 0, wholeDaysPart).Add(durationPart)
}
// ExcelDateToTime converts a float-based excel date representation to a time.Time.
diff --git a/sheet.go b/sheet.go
index 7a1fff3..756eb81 100644
--- a/sheet.go
+++ b/sheet.go
@@ -72,12 +72,13 @@ func (f *File) contentTypesReader() *xlsxTypes {
if f.ContentTypes == nil {
f.ContentTypes = new(xlsxTypes)
+ f.ContentTypes.Lock()
+ defer f.ContentTypes.Unlock()
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("[Content_Types].xml")))).
Decode(f.ContentTypes); err != nil && err != io.EOF {
log.Printf("xml decode error: %s", err)
}
}
-
return f.ContentTypes
}
diff --git a/styles.go b/styles.go
index 07ccab1..2a99a4d 100644
--- a/styles.go
+++ b/styles.go
@@ -996,6 +996,7 @@ func parseTime(v string, format string) string {
{"mm", "01"},
{"am/pm", "pm"},
{"m/", "1/"},
+ {"m", "1"},
{"%%%%", "January"},
{"&&&&", "Monday"},
}
@@ -1005,6 +1006,7 @@ func parseTime(v string, format string) string {
{"\\ ", " "},
{"\\.", "."},
{"\\", ""},
+ {"\"", ""},
}
// It is the presence of the "am/pm" indicator that determines if this is
// a 12 hour or 24 hours time format, not the number of 'h' characters.
diff --git a/xmlWorksheet.go b/xmlWorksheet.go
index 4499546..a54d51b 100644
--- a/xmlWorksheet.go
+++ b/xmlWorksheet.go
@@ -436,8 +436,8 @@ type DataValidation struct {
ShowInputMessage bool `xml:"showInputMessage,attr,omitempty"`
Sqref string `xml:"sqref,attr"`
Type string `xml:"type,attr,omitempty"`
- Formula1 string `xml:",innerxml"`
- Formula2 string `xml:",innerxml"`
+ Formula1 string `xml:"formula1,omitempty"`
+ Formula2 string `xml:"formula2,omitempty"`
}
// xlsxC collection represents a cell in the worksheet. Information about the