21
0
Fork 0

partly support time cell

This commit is contained in:
Liu Ming 2015-03-25 14:47:26 +08:00
parent 7345247a91
commit dff67234df
7 changed files with 151 additions and 56 deletions

30
col.go
View File

@ -41,6 +41,17 @@ type XfRk struct {
Rk RK
}
func (xf *XfRk) String(wb *WorkBook) string {
switch wb.Xfs[21].formatNo() {
case 27:
if f, e := xf.Rk.Float(); e == nil {
t := TimeFromExcelTime(f, true)
return t.Format("2006.01") //TODO it should be international
}
}
return fmt.Sprintf("%s", xf.Rk.String())
}
type RK uint32
func (rk RK) String() string {
@ -58,6 +69,23 @@ func (rk RK) String() string {
}
}
var ErrIsInt = fmt.Errorf("is int")
func (rk RK) Float() (float64, error) {
multiplied := rk & 1
isInt := rk & 2
val := rk >> 2
if isInt == 0 {
f := math.Float64frombits(uint64(val) << 34)
if multiplied != 0 {
f = f / 100
}
return f, nil
} else {
return 0.0, ErrIsInt
}
}
type MulrkCol struct {
Col
Xfrks []XfRk
@ -72,7 +100,7 @@ func (c *MulrkCol) String(wb *WorkBook) []string {
var res = make([]string, len(c.Xfrks))
for i := 0; i < len(c.Xfrks); i++ {
xfrk := c.Xfrks[i]
res[i] = xfrk.Rk.String()
res[i] = xfrk.String(wb)
}
return res
}

98
date.go Normal file
View File

@ -0,0 +1,98 @@
package xls
import (
"math"
"time"
)
const MJD_0 float64 = 2400000.5
const MJD_JD2000 float64 = 51544.5
func shiftJulianToNoon(julianDays, julianFraction float64) (float64, float64) {
switch {
case -0.5 < julianFraction && julianFraction < 0.5:
julianFraction += 0.5
case julianFraction >= 0.5:
julianDays += 1
julianFraction -= 0.5
case julianFraction <= -0.5:
julianDays -= 1
julianFraction += 1.5
}
return julianDays, julianFraction
}
// Return the integer values for hour, minutes, seconds and
// nanoseconds that comprised a given fraction of a day.
func fractionOfADay(fraction float64) (hours, minutes, seconds, nanoseconds int) {
f := 5184000000000000 * fraction
nanoseconds = int(math.Mod(f, 1000000000))
f = f / 1000000000
seconds = int(math.Mod(f, 60))
f = f / 3600
minutes = int(math.Mod(f, 60))
f = f / 60
hours = int(f)
return hours, minutes, seconds, nanoseconds
}
func julianDateToGregorianTime(part1, part2 float64) time.Time {
part1I, part1F := math.Modf(part1)
part2I, part2F := math.Modf(part2)
julianDays := part1I + part2I
julianFraction := part1F + part2F
julianDays, julianFraction = shiftJulianToNoon(julianDays, julianFraction)
day, month, year := doTheFliegelAndVanFlandernAlgorithm(int(julianDays))
hours, minutes, seconds, nanoseconds := fractionOfADay(julianFraction)
return time.Date(year, time.Month(month), day, hours, minutes, seconds, nanoseconds, time.UTC)
}
// By this point generations of programmers have repeated the
// algorithm sent to the editor of "Communications of the ACM" in 1968
// (published in CACM, volume 11, number 10, October 1968, p.657).
// None of those programmers seems to have found it necessary to
// explain the constants or variable names set out by Henry F. Fliegel
// and Thomas C. Van Flandern. Maybe one day I'll buy that jounal and
// expand an explanation here - that day is not today.
func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
l := jd + 68569
n := (4 * l) / 146097
l = l - (146097*n+3)/4
i := (4000 * (l + 1)) / 1461001
l = l - (1461*i)/4 + 31
j := (80 * l) / 2447
d := l - (2447*j)/80
l = j / 11
m := j + 2 - (12 * l)
y := 100*(n-49) + i + l
return d, m, y
}
// Convert an excelTime representation (stored as a floating point number) to a time.Time.
func TimeFromExcelTime(excelTime float64, date1904 bool) time.Time {
var date time.Time
var intPart int64 = int64(excelTime)
// Excel uses Julian dates prior to March 1st 1900, and
// Gregorian thereafter.
if intPart <= 61 {
const OFFSET1900 = 15018.0
const OFFSET1904 = 16480.0
var date time.Time
if date1904 {
date = julianDateToGregorianTime(MJD_0+OFFSET1904, excelTime)
} else {
date = julianDateToGregorianTime(MJD_0+OFFSET1900, excelTime)
}
return date
}
var floatPart float64 = excelTime - float64(intPart)
var dayNanoSeconds float64 = 24 * 60 * 60 * 1000 * 1000 * 1000
if date1904 {
date = time.Date(1904, 1, 1, 0, 0, 0, 0, time.UTC)
} else {
date = time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
}
durationDays := time.Duration(intPart) * time.Hour * 24
durationPart := time.Duration(dayNanoSeconds * floatPart)
return date.Add(durationDays).Add(durationPart)
}

View File

@ -1,11 +1,9 @@
package xls
type FormatB struct {
Index uint16
Size uint16
}
type Format struct {
b *FormatB
Head struct {
Index uint16
Size uint16
}
str string
}

View File

@ -1,17 +0,0 @@
package xls
// type st_xf_data struct {
// Font uint16
// Format uint16
// Type uint16
// Align byte
// Rotation byte
// Ident byte
// Usedattr byte
// Linestyle uint32
// Linecolor uint32
// Groundcolor uint16
// }
type st_xf_data interface {
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"io"
"log"
"unicode/utf16"
)
@ -53,8 +54,8 @@ func (w *WorkBook) addFont(font *FontInfo, buf io.ReadSeeker) {
w.Fonts = append(w.Fonts, Font{Info: font, Name: name})
}
func (w *WorkBook) addFormat(format *FormatB, buf io.ReadSeeker) {
w.Formats[format.Index] = &Format{b: format, str: w.get_string(buf, uint16(format.Size))}
func (w *WorkBook) addFormat(format *Format) {
w.Formats[format.Head.Index] = format
}
func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *BOF, pre *BOF, offset_pre int) (after *BOF, offset int) {
@ -119,21 +120,11 @@ func (wb *WorkBook) parseBof(buf io.ReadSeeker, b *BOF, pre *BOF, offset_pre int
binary.Read(buf_item, binary.LittleEndian, f)
wb.addFont(f, buf_item)
case 0x41E: //FORMAT
// var bts = make([]byte, b.Size)
// binary.Read(buf, binary.LittleEndian, bts)
// buf_item := bytes.NewReader(bts)
f := new(FormatB)
binary.Read(buf_item, binary.LittleEndian, f)
wb.addFormat(f, buf_item)
// case 0x5c:
// var bts = make([]byte, b.Size)
// binary.Read(buf_item, binary.LittleEndian, bts)
// if wb.Is5ver {
// wb.Author = wb.get_string_from_bytes(bts[1:], uint16(bts[1]))
// } else {
// size := binary.LittleEndian.Uint16(bts)
// wb.Author = wb.get_string_from_bytes(bts[2:], size)
// }
f := new(Format)
binary.Read(buf_item, binary.LittleEndian, &f.Head)
f.str = wb.get_string(buf_item, f.Head.Size)
wb.addFormat(f)
log.Println(f.Head.Index, f.str)
}
return
}

View File

@ -133,21 +133,6 @@ func (w *WorkSheet) parseBof(buf io.ReadSeeker, bof *BOF, pre *BOF) *BOF {
}
w.addRange(&hy.CellRange, &hy)
//
// bts := make([]byte, 20)
// binary.Read(buf, binary.LittleEndian, bts)
//
// if flag&0x80 != 0 {
// binary.Read(buf, binary.LittleEndian, &count)
// var bts = make([]uint16, count)
// binary.Read(buf, binary.LittleEndian, &bts)
// runes := utf16.Decode(bts)
// hy.TargetFrame = string(runes)
// }
default:
fmt.Printf("Unknow %X,%d\n", bof.Id, bof.Size)
buf.Seek(int64(bof.Size), 1)

12
xf.go
View File

@ -11,6 +11,10 @@ type Xf5 struct {
Linestyle uint16
}
func (x *Xf5) formatNo() uint16 {
return x.Format
}
type Xf8 struct {
Font uint16
Format uint16
@ -23,3 +27,11 @@ type Xf8 struct {
Linecolor uint32
Groundcolor uint16
}
func (x *Xf8) formatNo() uint16 {
return x.Format
}
type st_xf_data interface {
formatNo() uint16
}