Skip to content

Commit 7dbf88f

Browse files
committed
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
1 parent e9ae9b4 commit 7dbf88f

File tree

6 files changed

+25
-28
lines changed

6 files changed

+25
-28
lines changed

col.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,10 +439,10 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
439439
for col := start; col <= end; col++ {
440440
from, _ := CoordinatesToCellName(col, 1)
441441
to, _ := CoordinatesToCellName(col, rows)
442-
f.SetCellStyle(sheet, from, to, styleID)
442+
err = f.SetCellStyle(sheet, from, to, styleID)
443443
}
444444
}
445-
return nil
445+
return err
446446
}
447447

448448
// SetColWidth provides a function to set the width of a single column or

datavalidation.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package excelize
1414
import (
1515
"fmt"
1616
"strings"
17+
"unicode/utf16"
1718
)
1819

1920
// DataValidationType defined the type of data validation.
@@ -111,10 +112,10 @@ func (dd *DataValidation) SetInput(title, msg string) {
111112
// SetDropList data validation list.
112113
func (dd *DataValidation) SetDropList(keys []string) error {
113114
formula := "\"" + strings.Join(keys, ",") + "\""
114-
if dataValidationFormulaStrLen < len(formula) {
115+
if dataValidationFormulaStrLen < len(utf16.Encode([]rune(formula))) {
115116
return fmt.Errorf(dataValidationFormulaStrLenErr)
116117
}
117-
dd.Formula1 = fmt.Sprintf("<formula1>%s</formula1>", formula)
118+
dd.Formula1 = formula
118119
dd.Type = convDataValidationType(typeList)
119120
return nil
120121
}
@@ -123,12 +124,12 @@ func (dd *DataValidation) SetDropList(keys []string) error {
123124
func (dd *DataValidation) SetRange(f1, f2 float64, t DataValidationType, o DataValidationOperator) error {
124125
formula1 := fmt.Sprintf("%f", f1)
125126
formula2 := fmt.Sprintf("%f", f2)
126-
if dataValidationFormulaStrLen+21 < len(dd.Formula1) || dataValidationFormulaStrLen+21 < len(dd.Formula2) {
127+
if dataValidationFormulaStrLen < len(utf16.Encode([]rune(dd.Formula1))) || dataValidationFormulaStrLen < len(utf16.Encode([]rune(dd.Formula2))) {
127128
return fmt.Errorf(dataValidationFormulaStrLenErr)
128129
}
129130

130-
dd.Formula1 = fmt.Sprintf("<formula1>%s</formula1>", formula1)
131-
dd.Formula2 = fmt.Sprintf("<formula2>%s</formula2>", formula2)
131+
dd.Formula1 = formula1
132+
dd.Formula2 = formula2
132133
dd.Type = convDataValidationType(t)
133134
dd.Operator = convDataValidationOperatior(o)
134135
return nil
@@ -148,7 +149,7 @@ func (dd *DataValidation) SetRange(f1, f2 float64, t DataValidationType, o DataV
148149
//
149150
func (dd *DataValidation) SetSqrefDropList(sqref string, isCurrentSheet bool) error {
150151
if isCurrentSheet {
151-
dd.Formula1 = fmt.Sprintf("<formula1>%s</formula1>", sqref)
152+
dd.Formula1 = sqref
152153
dd.Type = convDataValidationType(typeList)
153154
return nil
154155
}

date.go

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ import (
1717
)
1818

1919
const (
20+
nanosInADay = float64((24 * time.Hour) / time.Nanosecond)
2021
dayNanoseconds = 24 * time.Hour
2122
maxDuration = 290 * 364 * dayNanoseconds
2223
)
2324

2425
var (
26+
excel1900Epoc = time.Date(1899, time.December, 30, 0, 0, 0, 0, time.UTC)
27+
excel1904Epoc = time.Date(1904, time.January, 1, 0, 0, 0, 0, time.UTC)
2528
excelMinTime1900 = time.Date(1899, time.December, 31, 0, 0, 0, 0, time.UTC)
2629
excelBuggyPeriodStart = time.Date(1900, time.March, 1, 0, 0, 0, 0, time.UTC).Add(-time.Nanosecond)
2730
)
@@ -131,12 +134,11 @@ func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
131134
// timeFromExcelTime provides a function to convert an excelTime
132135
// representation (stored as a floating point number) to a time.Time.
133136
func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
134-
const MDD int64 = 106750 // Max time.Duration Days, aprox. 290 years
135137
var date time.Time
136-
var intPart = int64(excelTime)
138+
var wholeDaysPart = int(excelTime)
137139
// Excel uses Julian dates prior to March 1st 1900, and Gregorian
138140
// thereafter.
139-
if intPart <= 61 {
141+
if wholeDaysPart <= 61 {
140142
const OFFSET1900 = 15018.0
141143
const OFFSET1904 = 16480.0
142144
const MJD0 float64 = 2400000.5
@@ -148,23 +150,14 @@ func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
148150
}
149151
return date
150152
}
151-
var floatPart = excelTime - float64(intPart)
152-
var dayNanoSeconds float64 = 24 * 60 * 60 * 1000 * 1000 * 1000
153+
var floatPart = excelTime - float64(wholeDaysPart)
153154
if date1904 {
154-
date = time.Date(1904, 1, 1, 0, 0, 0, 0, time.UTC)
155+
date = excel1904Epoc
155156
} else {
156-
date = time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
157+
date = excel1900Epoc
157158
}
158-
159-
// Duration is limited to aprox. 290 years
160-
for intPart > MDD {
161-
durationDays := time.Duration(MDD) * time.Hour * 24
162-
date = date.Add(durationDays)
163-
intPart = intPart - MDD
164-
}
165-
durationDays := time.Duration(intPart) * time.Hour * 24
166-
durationPart := time.Duration(dayNanoSeconds * floatPart)
167-
return date.Add(durationDays).Add(durationPart)
159+
durationPart := time.Duration(nanosInADay * floatPart)
160+
return date.AddDate(0, 0, wholeDaysPart).Add(durationPart)
168161
}
169162

170163
// ExcelDateToTime converts a float-based excel date representation to a time.Time.

sheet.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ func (f *File) contentTypesReader() *xlsxTypes {
7272

7373
if f.ContentTypes == nil {
7474
f.ContentTypes = new(xlsxTypes)
75+
f.ContentTypes.Lock()
76+
defer f.ContentTypes.Unlock()
7577
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("[Content_Types].xml")))).
7678
Decode(f.ContentTypes); err != nil && err != io.EOF {
7779
log.Printf("xml decode error: %s", err)
7880
}
7981
}
80-
8182
return f.ContentTypes
8283
}
8384

styles.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ func parseTime(v string, format string) string {
996996
{"mm", "01"},
997997
{"am/pm", "pm"},
998998
{"m/", "1/"},
999+
{"m", "1"},
9991000
{"%%%%", "January"},
10001001
{"&&&&", "Monday"},
10011002
}
@@ -1005,6 +1006,7 @@ func parseTime(v string, format string) string {
10051006
{"\\ ", " "},
10061007
{"\\.", "."},
10071008
{"\\", ""},
1009+
{"\"", ""},
10081010
}
10091011
// It is the presence of the "am/pm" indicator that determines if this is
10101012
// a 12 hour or 24 hours time format, not the number of 'h' characters.

xmlWorksheet.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,8 @@ type DataValidation struct {
436436
ShowInputMessage bool `xml:"showInputMessage,attr,omitempty"`
437437
Sqref string `xml:"sqref,attr"`
438438
Type string `xml:"type,attr,omitempty"`
439-
Formula1 string `xml:",innerxml"`
440-
Formula2 string `xml:",innerxml"`
439+
Formula1 string `xml:"formula1,omitempty"`
440+
Formula2 string `xml:"formula2,omitempty"`
441441
}
442442

443443
// xlsxC collection represents a cell in the worksheet. Information about the

0 commit comments

Comments
 (0)