This closes #1955, refs #119, support to set cell value with an IEEE 754 "not-a-number" value or infinity
This commit is contained in:
parent
68a1704900
commit
4dd34477f7
17
cell.go
17
cell.go
|
@ -15,6 +15,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -385,6 +386,9 @@ func setCellBool(value bool) (t string, v string) {
|
||||||
// var x float32 = 1.325
|
// var x float32 = 1.325
|
||||||
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
|
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
|
||||||
func (f *File) SetCellFloat(sheet, cell string, value float64, precision, bitSize int) error {
|
func (f *File) SetCellFloat(sheet, cell string, value float64, precision, bitSize int) error {
|
||||||
|
if math.IsNaN(value) || math.IsInf(value, 0) {
|
||||||
|
return f.SetCellStr(sheet, cell, fmt.Sprint(value))
|
||||||
|
}
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -399,16 +403,19 @@ func (f *File) SetCellFloat(sheet, cell string, value float64, precision, bitSiz
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.S = ws.prepareCellStyle(col, row, c.S)
|
c.S = ws.prepareCellStyle(col, row, c.S)
|
||||||
c.T, c.V = setCellFloat(value, precision, bitSize)
|
c.setCellFloat(value, precision, bitSize)
|
||||||
c.IS = nil
|
|
||||||
return f.removeFormula(c, ws, sheet)
|
return f.removeFormula(c, ws, sheet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setCellFloat prepares cell type and string type cell value by a given float
|
// setCellFloat prepares cell type and string type cell value by a given float
|
||||||
// value.
|
// value.
|
||||||
func setCellFloat(value float64, precision, bitSize int) (t string, v string) {
|
func (c *xlsxC) setCellFloat(value float64, precision, bitSize int) {
|
||||||
v = strconv.FormatFloat(value, 'f', precision, bitSize)
|
if math.IsNaN(value) || math.IsInf(value, 0) {
|
||||||
return
|
c.setInlineStr(fmt.Sprint(value))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.T, c.V = "", strconv.FormatFloat(value, 'f', precision, bitSize)
|
||||||
|
c.IS = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCellStr provides a function to set string type value of a cell. Total
|
// SetCellStr provides a function to set string type value of a cell. Total
|
||||||
|
|
13
cell_test.go
13
cell_test.go
|
@ -292,6 +292,19 @@ func TestSetCellValue(t *testing.T) {
|
||||||
val, err = f.GetCellValue("Sheet1", "B1")
|
val, err = f.GetCellValue("Sheet1", "B1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "b", val)
|
assert.Equal(t, "b", val)
|
||||||
|
|
||||||
|
f = NewFile()
|
||||||
|
// Test set cell value with an IEEE 754 "not-a-number" value or infinity
|
||||||
|
for num, expected := range map[float64]string{
|
||||||
|
math.NaN(): "NaN",
|
||||||
|
math.Inf(0): "+Inf",
|
||||||
|
math.Inf(-1): "-Inf",
|
||||||
|
} {
|
||||||
|
assert.NoError(t, f.SetCellValue("Sheet1", "A1", num))
|
||||||
|
val, err := f.GetCellValue("Sheet1", "A1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetCellValues(t *testing.T) {
|
func TestSetCellValues(t *testing.T) {
|
||||||
|
|
|
@ -529,9 +529,9 @@ func (sw *StreamWriter) setCellValFunc(c *xlsxC, val interface{}) error {
|
||||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||||
setCellIntFunc(c, val)
|
setCellIntFunc(c, val)
|
||||||
case float32:
|
case float32:
|
||||||
c.T, c.V = setCellFloat(float64(val), -1, 32)
|
c.setCellFloat(float64(val), -1, 32)
|
||||||
case float64:
|
case float64:
|
||||||
c.T, c.V = setCellFloat(val, -1, 64)
|
c.setCellFloat(val, -1, 64)
|
||||||
case string:
|
case string:
|
||||||
c.setCellValue(val)
|
c.setCellValue(val)
|
||||||
case []byte:
|
case []byte:
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -76,6 +77,8 @@ func TestStreamWriter(t *testing.T) {
|
||||||
assert.NoError(t, streamWriter.SetRow("A7", nil, RowOpts{Height: 20, Hidden: true, StyleID: styleID}))
|
assert.NoError(t, streamWriter.SetRow("A7", nil, RowOpts{Height: 20, Hidden: true, StyleID: styleID}))
|
||||||
assert.Equal(t, ErrMaxRowHeight, streamWriter.SetRow("A8", nil, RowOpts{Height: MaxRowHeight + 1}))
|
assert.Equal(t, ErrMaxRowHeight, streamWriter.SetRow("A8", nil, RowOpts{Height: MaxRowHeight + 1}))
|
||||||
|
|
||||||
|
assert.NoError(t, streamWriter.SetRow("A9", []interface{}{math.NaN(), math.Inf(0), math.Inf(-1)}))
|
||||||
|
|
||||||
for rowID := 10; rowID <= 51200; rowID++ {
|
for rowID := 10; rowID <= 51200; rowID++ {
|
||||||
row := make([]interface{}, 50)
|
row := make([]interface{}, 50)
|
||||||
for colID := 0; colID < 50; colID++ {
|
for colID := 0; colID < 50; colID++ {
|
||||||
|
@ -145,7 +148,7 @@ func TestStreamWriter(t *testing.T) {
|
||||||
cells += len(row)
|
cells += len(row)
|
||||||
}
|
}
|
||||||
assert.NoError(t, rows.Close())
|
assert.NoError(t, rows.Close())
|
||||||
assert.Equal(t, 2559559, cells)
|
assert.Equal(t, 2559562, cells)
|
||||||
// Save spreadsheet with password.
|
// Save spreadsheet with password.
|
||||||
assert.NoError(t, file.SaveAs(filepath.Join("test", "EncryptionTestStreamWriter.xlsx"), Options{Password: "password"}))
|
assert.NoError(t, file.SaveAs(filepath.Join("test", "EncryptionTestStreamWriter.xlsx"), Options{Password: "password"}))
|
||||||
assert.NoError(t, file.Close())
|
assert.NoError(t, file.Close())
|
||||||
|
|
Loading…
Reference in New Issue