From b048fa8aad8d3341d12455805b90ee5e7ddcadbf Mon Sep 17 00:00:00 2001 From: Jeremy Jay Date: Thu, 11 Feb 2021 01:28:46 -0500 Subject: [PATCH] refactor common excel stuff --- xls/formats.go => commonxl/dates.go | 102 ++++------------------------ {xlsx => commonxl}/formats.go | 5 +- xls/sheets.go | 18 ++--- xls/xls.go | 3 +- xlsx/workbook.go | 4 +- 5 files changed, 32 insertions(+), 100 deletions(-) rename xls/formats.go => commonxl/dates.go (55%) rename {xlsx => commonxl}/formats.go (93%) diff --git a/xls/formats.go b/commonxl/dates.go similarity index 55% rename from xls/formats.go rename to commonxl/dates.go index c1fafa5..784845e 100644 --- a/xls/formats.go +++ b/commonxl/dates.go @@ -1,4 +1,4 @@ -package xls +package commonxl import ( "regexp" @@ -6,15 +6,19 @@ import ( "time" ) -func getDateTime(fno uint16, f string, val float64, mode1904 bool) (time.Time, bool) { - if !formatIsDateTime(fno, f) { +// GetDateTime is a wrapper for chained invocation of +// FormatIsDateTime and ConvertToDate. +func GetDateTime(fno uint16, f string, val float64, mode1904 bool) (time.Time, bool) { + if !FormatIsDateTime(fno, f) { return time.Time{}, false } - return convertToDate(val, mode1904), true + return ConvertToDate(val, mode1904), true } -// http://web.archive.org/web/20190808062235/http://aa.usno.navy.mil/faq/docs/JD_Formula.php -func convertToDate(val float64, mode1904 bool) time.Time { +// ConvertToDate converts a floating-point value using the +// Excel date serialization conventions. +func ConvertToDate(val float64, mode1904 bool) time.Time { + // http://web.archive.org/web/20190808062235/http://aa.usno.navy.mil/faq/docs/JD_Formula.php v := int(val) if v < 61 { jdate := val + 0.5 @@ -50,7 +54,9 @@ func convertToDate(val float64, mode1904 bool) time.Time { return date.AddDate(0, 0, v).Add(t) } -func formatIsDateTime(fno uint16, f string) bool { +// FormatIsDateTime returns true if the given format number or +// format string contains a date/time formatting instruction. +func FormatIsDateTime(fno uint16, f string) bool { if _, ok := builtInDateFormats[fno]; ok { return true } @@ -84,87 +90,7 @@ var builtInDateFormats = map[uint16]byte{ 76: 2, 77: 3, 78: 2, 79: 2, 80: 2, 81: 1, } -var builtInFormats = map[uint16]string{ - 0: `General`, - 1: `0`, - 2: `0.00`, - 3: `#,##0`, - 4: `#,##0.00`, - 9: `0%`, - 10: `0.00%`, - - 11: `0.00E+00`, - 12: `# ?/?`, - 13: `# ??/??`, - 14: `mm-dd-yy`, - 15: `d-mmm-yy`, - 16: `d-mmm`, - 17: `mmm-yy`, - 18: `h:mm AM/PM`, - 19: `h:mm:ss AM/PM`, - 20: `h:mm`, - 21: `h:mm:ss`, - 22: `m/d/yy h:mm`, - 37: `#,##0 ;(#,##0)`, - 38: `#,##0 ;[Red](#,##0)`, - 39: `#,##0.00;(#,##0.00)`, - 40: `#,##0.00;[Red](#,##0.00)`, - - 41: `_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)`, - 42: `_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)`, - 43: `_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)`, - 44: `_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)`, - - 45: `mm:ss`, - 46: `[h]:mm:ss`, - 47: `mmss.0`, - 48: `##0.0E+0`, - 49: `@`, - - // zh-cn format codes - 27: `yyyy"年"m"月"`, - 28: `m"月"d"日"`, - 29: `m"月"d"日"`, - 30: `m-d-yy`, - 31: `yyyy"年"m"月"d"日"`, - 32: `h"时"mm"分"`, - 33: `h"时"mm"分"ss"秒"`, - 34: `上午/下午 h"时"mm"分"`, - 35: `上午/下午 h"时"mm"分"ss"秒"`, - 36: `yyyy"年"m"月"`, - 50: `yyyy"年"m"月"`, - 51: `m"月"d"日"`, - 52: `yyyy"年"m"月"`, - 53: `m"月"d"日"`, - 54: `m"月"d"日"`, - 55: `上午/下午 h"时"mm"分"`, - 56: `上午/下午 h"时"mm"分"ss"秒`, - 57: `yyyy"年"m"月"`, - 58: `m"月"d"日"`, - - // th-th format codes - 59: `t0`, - 60: `t0.00`, - 61: `t#,##0`, - 62: `t#,##0.00`, - 67: `t0%`, - 68: `t0.00%`, - 69: `t# ?/?`, - 70: `t# ??/??`, - // th format code, but translated to aid the parser - 71: `d/m/yyyy`, // `ว/ด/ปปปป`, - 72: `d-mmm-yy`, // `ว-ดดด-ปป`, - 73: `d-mmm`, // `ว-ดดด`, - 74: `mmm-yy`, // `ดดด-ปป`, - 75: `h:mm`, // `ช:นน`, - 76: `h:mm:ss`, // `ช:นน:ทท`, - 77: `d/m/yyyy h:mm`, // `ว/ด/ปปปป ช:นน`, - 78: `mm:ss`, // `นน:ทท`, - 79: `[h]:mm:ss`, // `[ช]:นน:ทท`, - 80: `mm:ss.0`, // `นน:ทท.0`, - 81: `d/m/bb`, // `d/m/bb`, -} - +// mapping of standard built-ins to Go date format strings. var builtInGoFormats = map[uint16]string{ 14: `01-02-06`, 15: `2-Jan-06`, diff --git a/xlsx/formats.go b/commonxl/formats.go similarity index 93% rename from xlsx/formats.go rename to commonxl/formats.go index 894d3a0..eaca7b4 100644 --- a/xlsx/formats.go +++ b/commonxl/formats.go @@ -1,6 +1,7 @@ -package xlsx +package commonxl -var builtInFormats = map[uint16]string{ +// BuiltInFormats are all the built-in number formats for XLS/XLSX. +var BuiltInFormats = map[uint16]string{ 0: `General`, 1: `0`, 2: `0.00`, diff --git a/xls/sheets.go b/xls/sheets.go index 1077512..e318223 100644 --- a/xls/sheets.go +++ b/xls/sheets.go @@ -9,6 +9,8 @@ import ( "math" "time" "unicode/utf16" + + "github.com/pbnjay/grate/commonxl" ) func (b *WorkBook) Sheets() []string { @@ -248,8 +250,8 @@ func (s *WorkSheet) parse() error { fno := s.b.xfs[rr.IXFCell] format := s.b.formats[fno] - if formatIsDateTime(fno, format) { - dt, ok := getDateTime(fno, format, rr.Value.Float64(), s.b.dateMode == 1) + if commonxl.FormatIsDateTime(fno, format) { + dt, ok := commonxl.GetDateTime(fno, format, rr.Value.Float64(), s.b.dateMode == 1) if ok { rval = dt } @@ -273,8 +275,8 @@ func (s *WorkSheet) parse() error { fno := s.b.xfs[ixfe] format := s.b.formats[fno] - if formatIsDateTime(fno, format) { - dt, ok := getDateTime(fno, format, value, s.b.dateMode == 1) + if commonxl.FormatIsDateTime(fno, format) { + dt, ok := commonxl.GetDateTime(fno, format, value, s.b.dateMode == 1) if ok { rval = dt } @@ -298,8 +300,8 @@ func (s *WorkSheet) parse() error { fno := s.b.xfs[rr.IXFCell] format := s.b.formats[fno] - if formatIsDateTime(fno, format) { - dt, ok := getDateTime(fno, format, rr.Value.Float64(), s.b.dateMode == 1) + if commonxl.FormatIsDateTime(fno, format) { + dt, ok := commonxl.GetDateTime(fno, format, rr.Value.Float64(), s.b.dateMode == 1) if ok { rval = dt } @@ -346,8 +348,8 @@ func (s *WorkSheet) parse() error { fno := s.b.xfs[ixfe] format := s.b.formats[fno] - if formatIsDateTime(fno, format) { - dt, ok := getDateTime(fno, format, value, s.b.dateMode == 1) + if commonxl.FormatIsDateTime(fno, format) { + dt, ok := commonxl.GetDateTime(fno, format, value, s.b.dateMode == 1) if ok { rval = dt } diff --git a/xls/xls.go b/xls/xls.go index 53f86ec..adfc258 100644 --- a/xls/xls.go +++ b/xls/xls.go @@ -14,6 +14,7 @@ import ( "io" "log" + "github.com/pbnjay/grate/commonxl" "github.com/pbnjay/grate/xls/cfb" "github.com/pbnjay/grate/xls/crypto" ) @@ -60,7 +61,7 @@ func Open(ctx context.Context, filename string) (*WorkBook, error) { xfs: make([]uint16, 0, 128), } - for no, str := range builtInFormats { + for no, str := range commonxl.BuiltInFormats { b.formats[no] = str } diff --git a/xlsx/workbook.go b/xlsx/workbook.go index b769c2a..a37d5ab 100644 --- a/xlsx/workbook.go +++ b/xlsx/workbook.go @@ -6,6 +6,8 @@ import ( "io" "path/filepath" "strconv" + + "github.com/pbnjay/grate/commonxl" ) func (d *Document) parseRels(dec *xml.Decoder, basedir string) error { @@ -110,7 +112,7 @@ func (d *Document) parseStyles(dec *xml.Decoder) error { } nfid, _ := strconv.ParseInt(thisXF, 10, 16) - thisXF = builtInFormats[uint16(nfid)] + thisXF = commonxl.BuiltInFormats[uint16(nfid)] d.xfs = append(d.xfs, thisXF) } else { panic("wheres is this xf??")