Expand format recognition for dates
Read in and use DATEMODE (0x22), and recognize more formats as dates (both built-in and user-defined).
This commit is contained in:
parent
6130495e06
commit
80a9dc03c7
63
col.go
63
col.go
@ -3,6 +3,9 @@ package xls
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//content type
|
//content type
|
||||||
@ -43,50 +46,64 @@ type XfRk struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (xf *XfRk) String(wb *WorkBook) string {
|
func (xf *XfRk) String(wb *WorkBook) string {
|
||||||
if len(wb.Xfs) > 21 {
|
idx := int(xf.Index)
|
||||||
switch wb.Xfs[21].formatNo() {
|
if len(wb.Xfs) > idx {
|
||||||
case 27:
|
fNo := wb.Xfs[idx].formatNo()
|
||||||
if f, e := xf.Rk.Float(); e == nil {
|
if fNo >= 164 { // user defined format
|
||||||
t := timeFromExcelTime(f, true)
|
if fmt := wb.Formats[fNo]; fmt != nil && strings.Contains(fmt.str, "YY") {
|
||||||
|
i, f, isFloat := xf.Rk.number()
|
||||||
|
if !isFloat {
|
||||||
|
f = float64(i)
|
||||||
|
}
|
||||||
|
t := timeFromExcelTime(f, wb.dateMode == 1)
|
||||||
|
return t.Format(time.RFC3339) //TODO it should be international
|
||||||
|
}
|
||||||
|
// see http://www.openoffice.org/sc/excelfileformat.pdf
|
||||||
|
} else if 14 <= fNo && fNo <= 17 || fNo == 22 || fNo <= 27 && fNo <= 36 || fNo <= 50 && fNo <= 58 { // jp. date format
|
||||||
|
i, f, isFloat := xf.Rk.number()
|
||||||
|
if !isFloat {
|
||||||
|
f = float64(i)
|
||||||
|
}
|
||||||
|
t := timeFromExcelTime(f, wb.dateMode == 1)
|
||||||
return t.Format("2006.01") //TODO it should be international
|
return t.Format("2006.01") //TODO it should be international
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return xf.Rk.String()
|
||||||
return fmt.Sprintf("%s", xf.Rk.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type RK uint32
|
type RK uint32
|
||||||
|
|
||||||
func (rk RK) String() string {
|
func (rk RK) number() (intNum int64, floatNum float64, isFloat bool) {
|
||||||
multiplied := rk & 1
|
multiplied := rk & 1
|
||||||
isInt := rk & 2
|
isInt := rk & 2
|
||||||
val := rk >> 2
|
val := rk >> 2
|
||||||
if isInt == 0 {
|
if isInt == 0 {
|
||||||
f := math.Float64frombits(uint64(val) << 34)
|
isFloat = true
|
||||||
|
floatNum = math.Float64frombits(uint64(val) << 34)
|
||||||
if multiplied != 0 {
|
if multiplied != 0 {
|
||||||
f = f / 100
|
floatNum = floatNum / 100
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return int64(val), 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rk RK) String() string {
|
||||||
|
i, f, isFloat := rk.number()
|
||||||
|
if isFloat {
|
||||||
return fmt.Sprintf("%.1f", f)
|
return fmt.Sprintf("%.1f", f)
|
||||||
} else {
|
|
||||||
return fmt.Sprint(val)
|
|
||||||
}
|
}
|
||||||
|
return strconv.FormatInt(i, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrIsInt = fmt.Errorf("is int")
|
var ErrIsInt = fmt.Errorf("is int")
|
||||||
|
|
||||||
func (rk RK) Float() (float64, error) {
|
func (rk RK) Float() (float64, error) {
|
||||||
multiplied := rk & 1
|
_, f, isFloat := rk.number()
|
||||||
isInt := rk & 2
|
if !isFloat {
|
||||||
val := rk >> 2
|
return 0, ErrIsInt
|
||||||
if isInt == 0 {
|
|
||||||
f := math.Float64frombits(uint64(val) << 34)
|
|
||||||
if multiplied != 0 {
|
|
||||||
f = f / 100
|
|
||||||
}
|
}
|
||||||
return f, nil
|
return f, nil
|
||||||
} else {
|
|
||||||
return 0.0, ErrIsInt
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MulrkCol struct {
|
type MulrkCol struct {
|
||||||
@ -153,7 +170,7 @@ type RkCol struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *RkCol) String(wb *WorkBook) []string {
|
func (c *RkCol) String(wb *WorkBook) []string {
|
||||||
return []string{c.Xfrk.Rk.String()}
|
return []string{c.Xfrk.String(wb)}
|
||||||
}
|
}
|
||||||
|
|
||||||
type LabelsstCol struct {
|
type LabelsstCol struct {
|
||||||
|
@ -21,6 +21,7 @@ type WorkBook struct {
|
|||||||
rs io.ReadSeeker
|
rs io.ReadSeeker
|
||||||
sst []string
|
sst []string
|
||||||
continue_utf16 uint16
|
continue_utf16 uint16
|
||||||
|
dateMode uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
//read workbook from ole2 file
|
//read workbook from ole2 file
|
||||||
@ -135,6 +136,8 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *bof, pre *bof, offset_pre int
|
|||||||
binary.Read(buf_item, binary.LittleEndian, &f.Head)
|
binary.Read(buf_item, binary.LittleEndian, &f.Head)
|
||||||
f.str = wb.get_string(buf_item, f.Head.Size)
|
f.str = wb.get_string(buf_item, f.Head.Size)
|
||||||
wb.addFormat(f)
|
wb.addFormat(f)
|
||||||
|
case 0x22: //DATEMODE
|
||||||
|
binary.Read(buf_item, binary.LittleEndian, &wb.dateMode)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user