This closes #2004, support apply number format for time and duration cell value
- Add unit tests - Update dependencies modules
This commit is contained in:
parent
b23e5a26df
commit
f1d1a5dc2b
4
cell.go
4
cell.go
|
@ -144,7 +144,7 @@ func (f *File) SetCellValue(sheet, cell string, value interface{}) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = f.setDefaultTimeStyle(sheet, cell, 21)
|
||||
err = f.setDefaultTimeStyle(sheet, cell, getDurationNumFmt(v))
|
||||
case time.Time:
|
||||
err = f.setCellTimeFunc(sheet, cell, v)
|
||||
case bool:
|
||||
|
@ -256,7 +256,7 @@ func (f *File) setCellTimeFunc(sheet, cell string, value time.Time) error {
|
|||
return err
|
||||
}
|
||||
if isNum {
|
||||
_ = f.setDefaultTimeStyle(sheet, cell, 22)
|
||||
_ = f.setDefaultTimeStyle(sheet, cell, getTimeNumFmt(value))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
25
cell_test.go
25
cell_test.go
|
@ -305,6 +305,29 @@ func TestSetCellValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, val)
|
||||
}
|
||||
// Test set cell value with time duration
|
||||
for val, expected := range map[time.Duration]string{
|
||||
time.Hour*21 + time.Minute*51 + time.Second*44: "21:51:44",
|
||||
time.Hour*21 + time.Minute*50: "21:50",
|
||||
time.Hour*24 + time.Minute*51 + time.Second*44: "24:51:44",
|
||||
time.Hour*24 + time.Minute*50: "24:50:00",
|
||||
} {
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "A1", val))
|
||||
val, err := f.GetCellValue("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, val)
|
||||
}
|
||||
// Test set cell value with time
|
||||
for val, expected := range map[time.Time]string{
|
||||
time.Date(2024, time.October, 1, 0, 0, 0, 0, time.UTC): "Oct-24",
|
||||
time.Date(2024, time.October, 10, 0, 0, 0, 0, time.UTC): "10-10-24",
|
||||
time.Date(2024, time.October, 10, 12, 0, 0, 0, time.UTC): "10/10/24 12:00",
|
||||
} {
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "A1", val))
|
||||
val, err := f.GetCellValue("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetCellValues(t *testing.T) {
|
||||
|
@ -314,7 +337,7 @@ func TestSetCellValues(t *testing.T) {
|
|||
|
||||
v, err := f.GetCellValue("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, v, "12/31/10 00:00")
|
||||
assert.Equal(t, v, "12-31-10")
|
||||
|
||||
// Test date value lower than min date supported by Excel
|
||||
err = f.SetCellValue("Sheet1", "A1", time.Date(1600, time.December, 31, 0, 0, 0, 0, time.UTC))
|
||||
|
|
28
date.go
28
date.go
|
@ -214,3 +214,31 @@ func formatYear(y int) int {
|
|||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// getDurationNumFmt returns most simplify numbers format code for time
|
||||
// duration type cell value by given worksheet name, cell reference and number.
|
||||
func getDurationNumFmt(d time.Duration) int {
|
||||
if d >= time.Hour*24 {
|
||||
return 46
|
||||
}
|
||||
// Whole minutes
|
||||
if d.Minutes() == float64(int(d.Minutes())) {
|
||||
return 20
|
||||
}
|
||||
return 21
|
||||
}
|
||||
|
||||
// getTimeNumFmt returns most simplify numbers format code for time type cell
|
||||
// value by given worksheet name, cell reference and number.
|
||||
func getTimeNumFmt(t time.Time) int {
|
||||
nextMonth := t.AddDate(0, 1, 0)
|
||||
// Whole months
|
||||
if t.Day() == 1 && nextMonth.Day() == 1 {
|
||||
return 17
|
||||
}
|
||||
// Whole days
|
||||
if t.Hour() == 0 && t.Minute() == 0 && t.Second() == 0 && t.Nanosecond() == 0 {
|
||||
return 14
|
||||
}
|
||||
return 22
|
||||
}
|
||||
|
|
13
excelize.go
13
excelize.go
|
@ -242,15 +242,18 @@ func (f *File) xmlNewDecoder(rdr io.Reader) (ret *xml.Decoder) {
|
|||
// time.Time type cell value by given worksheet name, cell reference and
|
||||
// number format code.
|
||||
func (f *File) setDefaultTimeStyle(sheet, cell string, format int) error {
|
||||
s, err := f.GetCellStyle(sheet, cell)
|
||||
styleIdx, err := f.GetCellStyle(sheet, cell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s == 0 {
|
||||
style, _ := f.NewStyle(&Style{NumFmt: format})
|
||||
err = f.SetCellStyle(sheet, cell, cell, style)
|
||||
if styleIdx == 0 {
|
||||
styleIdx, _ = f.NewStyle(&Style{NumFmt: format})
|
||||
} else {
|
||||
style, _ := f.GetStyle(styleIdx)
|
||||
style.NumFmt = format
|
||||
styleIdx, _ = f.NewStyle(style)
|
||||
}
|
||||
return err
|
||||
return f.SetCellStyle(sheet, cell, cell, styleIdx)
|
||||
}
|
||||
|
||||
// workSheetReader provides a function to get the pointer to the structure
|
||||
|
|
6
go.mod
6
go.mod
|
@ -8,10 +8,10 @@ require (
|
|||
github.com/stretchr/testify v1.8.4
|
||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7
|
||||
golang.org/x/crypto v0.27.0
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/image v0.18.0
|
||||
golang.org/x/net v0.29.0
|
||||
golang.org/x/text v0.18.0
|
||||
golang.org/x/net v0.30.0
|
||||
golang.org/x/text v0.19.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
12
go.sum
12
go.sum
|
@ -15,14 +15,14 @@ github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7
|
|||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
|
Loading…
Reference in New Issue