summaryrefslogtreecommitdiff
path: root/cell.go
diff options
context:
space:
mode:
Diffstat (limited to 'cell.go')
-rw-r--r--cell.go151
1 files changed, 124 insertions, 27 deletions
diff --git a/cell.go b/cell.go
index 3fcbb7b..6ed7f48 100644
--- a/cell.go
+++ b/cell.go
@@ -30,8 +30,10 @@ const (
CellTypeBool
CellTypeDate
CellTypeError
+ CellTypeFormula
+ CellTypeInlineString
CellTypeNumber
- CellTypeString
+ CellTypeSharedString
)
const (
@@ -51,9 +53,9 @@ var cellTypes = map[string]CellType{
"d": CellTypeDate,
"n": CellTypeNumber,
"e": CellTypeError,
- "s": CellTypeString,
- "str": CellTypeString,
- "inlineStr": CellTypeString,
+ "s": CellTypeSharedString,
+ "str": CellTypeFormula,
+ "inlineStr": CellTypeInlineString,
}
// GetCellValue provides a function to get formatted value from cell by given
@@ -235,8 +237,7 @@ func (f *File) setCellTimeFunc(sheet, cell string, value time.Time) error {
date1904 = wb.WorkbookPr.Date1904
}
var isNum bool
- c.T, c.V, isNum, err = setCellTime(value, date1904)
- if err != nil {
+ if isNum, err = c.setCellTime(value, date1904); err != nil {
return err
}
if isNum {
@@ -247,7 +248,7 @@ func (f *File) setCellTimeFunc(sheet, cell string, value time.Time) error {
// setCellTime prepares cell type and Excel time by given Go time.Time type
// timestamp.
-func setCellTime(value time.Time, date1904 bool) (t string, b string, isNum bool, err error) {
+func (c *xlsxC) setCellTime(value time.Time, date1904 bool) (isNum bool, err error) {
var excelTime float64
_, offset := value.In(value.Location()).Zone()
value = value.Add(time.Duration(offset) * time.Second)
@@ -256,9 +257,9 @@ func setCellTime(value time.Time, date1904 bool) (t string, b string, isNum bool
}
isNum = excelTime > 0
if isNum {
- t, b = setCellDefault(strconv.FormatFloat(excelTime, 'f', -1, 64))
+ c.setCellDefault(strconv.FormatFloat(excelTime, 'f', -1, 64))
} else {
- t, b = setCellDefault(value.Format(time.RFC3339Nano))
+ c.setCellDefault(value.Format(time.RFC3339Nano))
}
return
}
@@ -435,14 +436,14 @@ func (f *File) setSharedString(val string) (int, error) {
sst.Count++
sst.UniqueCount++
t := xlsxT{Val: val}
- _, val, t.Space = setCellStr(val)
+ val, t.Space = trimCellValue(val)
sst.SI = append(sst.SI, xlsxSI{T: &t})
f.sharedStringsMap[val] = sst.UniqueCount - 1
return sst.UniqueCount - 1, nil
}
-// setCellStr provides a function to set string type to cell.
-func setCellStr(value string) (t string, v string, ns xml.Attr) {
+// trimCellValue provides a function to set string type to cell.
+func trimCellValue(value string) (v string, ns xml.Attr) {
if len(value) > TotalCellChars {
value = value[:TotalCellChars]
}
@@ -458,10 +459,117 @@ func setCellStr(value string) (t string, v string, ns xml.Attr) {
}
}
}
- t, v = "str", bstrMarshal(value)
+ v = bstrMarshal(value)
return
}
+// setCellValue set cell data type and value for (inline) rich string cell or
+// formula cell.
+func (c *xlsxC) setCellValue(val string) {
+ if c.F != nil {
+ c.setStr(val)
+ return
+ }
+ c.setInlineStr(val)
+}
+
+// setInlineStr set cell data type and value which containing an (inline) rich
+// string.
+func (c *xlsxC) setInlineStr(val string) {
+ c.T, c.V, c.IS = "inlineStr", "", &xlsxSI{T: &xlsxT{}}
+ c.IS.T.Val, c.IS.T.Space = trimCellValue(val)
+}
+
+// setStr set cell data type and value which containing a formula string.
+func (c *xlsxC) setStr(val string) {
+ c.T, c.IS = "str", nil
+ c.V, c.XMLSpace = trimCellValue(val)
+}
+
+// getCellDate parse cell value which containing a boolean.
+func (c *xlsxC) getCellBool(f *File, raw bool) (string, error) {
+ if !raw {
+ if c.V == "1" {
+ return "TRUE", nil
+ }
+ if c.V == "0" {
+ return "FALSE", nil
+ }
+ }
+ return f.formattedValue(c.S, c.V, raw), nil
+}
+
+// setCellDefault prepares cell type and string type cell value by a given
+// string.
+func (c *xlsxC) setCellDefault(value string) {
+ if ok, _, _ := isNumeric(value); !ok {
+ c.setInlineStr(value)
+ c.IS.T.Val = value
+ return
+ }
+ c.V = value
+}
+
+// getCellDate parse cell value which contains a date in the ISO 8601 format.
+func (c *xlsxC) getCellDate(f *File, raw bool) (string, error) {
+ if !raw {
+ layout := "20060102T150405.999"
+ if strings.HasSuffix(c.V, "Z") {
+ layout = "20060102T150405Z"
+ if strings.Contains(c.V, "-") {
+ layout = "2006-01-02T15:04:05Z"
+ }
+ } else if strings.Contains(c.V, "-") {
+ layout = "2006-01-02 15:04:05Z"
+ }
+ if timestamp, err := time.Parse(layout, strings.ReplaceAll(c.V, ",", ".")); err == nil {
+ excelTime, _ := timeToExcelTime(timestamp, false)
+ c.V = strconv.FormatFloat(excelTime, 'G', 15, 64)
+ }
+ }
+ return f.formattedValue(c.S, c.V, raw), nil
+}
+
+// getValueFrom return a value from a column/row cell, this function is
+// intended to be used with for range on rows an argument with the spreadsheet
+// opened file.
+func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
+ f.Lock()
+ defer f.Unlock()
+ switch c.T {
+ case "b":
+ return c.getCellBool(f, raw)
+ case "d":
+ return c.getCellDate(f, raw)
+ case "s":
+ if c.V != "" {
+ xlsxSI := 0
+ xlsxSI, _ = strconv.Atoi(c.V)
+ if _, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok {
+ return f.formattedValue(c.S, f.getFromStringItem(xlsxSI), raw), nil
+ }
+ if len(d.SI) > xlsxSI {
+ return f.formattedValue(c.S, d.SI[xlsxSI].String(), raw), nil
+ }
+ }
+ return f.formattedValue(c.S, c.V, raw), nil
+ case "inlineStr":
+ if c.IS != nil {
+ return f.formattedValue(c.S, c.IS.String(), raw), nil
+ }
+ return f.formattedValue(c.S, c.V, raw), nil
+ default:
+ if isNum, precision, decimal := isNumeric(c.V); isNum && !raw {
+ if precision > 15 {
+ c.V = strconv.FormatFloat(decimal, 'G', 15, 64)
+ } else {
+ c.V = strconv.FormatFloat(decimal, 'f', -1, 64)
+ }
+ }
+ return f.formattedValue(c.S, c.V, raw), nil
+ }
+}
+
// SetCellDefault provides a function to set string type value of a cell as
// default format without escaping the cell.
func (f *File) SetCellDefault(sheet, cell, value string) error {
@@ -476,22 +584,11 @@ func (f *File) SetCellDefault(sheet, cell, value string) error {
ws.Lock()
defer ws.Unlock()
c.S = f.prepareCellStyle(ws, col, row, c.S)
- c.T, c.V = setCellDefault(value)
- c.IS = nil
+ c.setCellDefault(value)
f.removeFormula(c, ws, sheet)
return err
}
-// setCellDefault prepares cell type and string type cell value by a given
-// string.
-func setCellDefault(value string) (t string, v string) {
- if ok, _, _ := isNumeric(value); !ok {
- t = "str"
- }
- v = value
- return
-}
-
// GetCellFormula provides a function to get formula from cell by given
// worksheet name and cell reference in spreadsheet.
func (f *File) GetCellFormula(sheet, cell string) (string, error) {
@@ -625,7 +722,7 @@ func (f *File) SetCellFormula(sheet, cell, formula string, opts ...FormulaOpts)
c.F.Ref = *opt.Ref
}
}
- c.IS = nil
+ c.T, c.IS = "str", nil
return err
}
@@ -900,7 +997,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
return textRuns, ErrCellCharsLength
}
run := xlsxR{T: &xlsxT{}}
- _, run.T.Val, run.T.Space = setCellStr(textRun.Text)
+ run.T.Val, run.T.Space = trimCellValue(textRun.Text)
fnt := textRun.Font
if fnt != nil {
run.RPr = newRpr(fnt)