Compare commits
3 Commits
9c278365f2
...
d81b4c8661
Author | SHA1 | Date |
---|---|---|
xuri | d81b4c8661 | |
xuri | 4dd34477f7 | |
pjh591029530 | 68a1704900 |
17
cell.go
17
cell.go
|
@ -15,6 +15,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
@ -385,6 +386,9 @@ func setCellBool(value bool) (t string, v string) {
|
|||
// var x float32 = 1.325
|
||||
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
|
||||
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()
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
|
@ -399,16 +403,19 @@ func (f *File) SetCellFloat(sheet, cell string, value float64, precision, bitSiz
|
|||
return err
|
||||
}
|
||||
c.S = ws.prepareCellStyle(col, row, c.S)
|
||||
c.T, c.V = setCellFloat(value, precision, bitSize)
|
||||
c.IS = nil
|
||||
c.setCellFloat(value, precision, bitSize)
|
||||
return f.removeFormula(c, ws, sheet)
|
||||
}
|
||||
|
||||
// setCellFloat prepares cell type and string type cell value by a given float
|
||||
// value.
|
||||
func setCellFloat(value float64, precision, bitSize int) (t string, v string) {
|
||||
v = strconv.FormatFloat(value, 'f', precision, bitSize)
|
||||
return
|
||||
func (c *xlsxC) setCellFloat(value float64, precision, bitSize int) {
|
||||
if math.IsNaN(value) || math.IsInf(value, 0) {
|
||||
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
|
||||
|
|
13
cell_test.go
13
cell_test.go
|
@ -292,6 +292,19 @@ func TestSetCellValue(t *testing.T) {
|
|||
val, err = f.GetCellValue("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
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) {
|
||||
|
|
|
@ -598,8 +598,7 @@ func (f *File) drawScatterChart(pa *cPlotArea, opts *Chart) *cPlotArea {
|
|||
DLbls: f.drawChartDLbls(opts),
|
||||
AxID: f.genAxID(opts),
|
||||
},
|
||||
CatAx: f.drawPlotAreaCatAx(pa, opts),
|
||||
ValAx: f.drawPlotAreaValAx(pa, opts),
|
||||
ValAx: append(f.drawPlotAreaCatAx(pa, opts), f.drawPlotAreaValAx(pa, opts)...),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -659,7 +658,7 @@ func (f *File) drawBubbleChart(pa *cPlotArea, opts *Chart) *cPlotArea {
|
|||
DLbls: f.drawChartDLbls(opts),
|
||||
AxID: f.genAxID(opts),
|
||||
},
|
||||
ValAx: []*cAxs{f.drawPlotAreaCatAx(pa, opts)[0], f.drawPlotAreaValAx(pa, opts)[0]},
|
||||
ValAx: append(f.drawPlotAreaCatAx(pa, opts), f.drawPlotAreaValAx(pa, opts)...),
|
||||
}
|
||||
if opts.BubbleSize > 0 && opts.BubbleSize <= 300 {
|
||||
plotArea.BubbleChart.BubbleScale = &attrValFloat{Val: float64Ptr(float64(opts.BubbleSize))}
|
||||
|
|
|
@ -529,9 +529,9 @@ func (sw *StreamWriter) setCellValFunc(c *xlsxC, val interface{}) error {
|
|||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||
setCellIntFunc(c, val)
|
||||
case float32:
|
||||
c.T, c.V = setCellFloat(float64(val), -1, 32)
|
||||
c.setCellFloat(float64(val), -1, 32)
|
||||
case float64:
|
||||
c.T, c.V = setCellFloat(val, -1, 64)
|
||||
c.setCellFloat(val, -1, 64)
|
||||
case string:
|
||||
c.setCellValue(val)
|
||||
case []byte:
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"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.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++ {
|
||||
row := make([]interface{}, 50)
|
||||
for colID := 0; colID < 50; colID++ {
|
||||
|
@ -145,7 +148,7 @@ func TestStreamWriter(t *testing.T) {
|
|||
cells += len(row)
|
||||
}
|
||||
assert.NoError(t, rows.Close())
|
||||
assert.Equal(t, 2559559, cells)
|
||||
assert.Equal(t, 2559562, cells)
|
||||
// Save spreadsheet with password.
|
||||
assert.NoError(t, file.SaveAs(filepath.Join("test", "EncryptionTestStreamWriter.xlsx"), Options{Password: "password"}))
|
||||
assert.NoError(t, file.Close())
|
||||
|
|
|
@ -36,7 +36,7 @@ type decodeCellAnchorPos struct {
|
|||
To *xlsxTo `xml:"to"`
|
||||
Pos *xlsxInnerXML `xml:"pos"`
|
||||
Ext *xlsxInnerXML `xml:"ext"`
|
||||
Sp *xlsxInnerXML `xml:"sp"`
|
||||
Sp *xlsxSp `xml:"sp"`
|
||||
GrpSp *xlsxInnerXML `xml:"grpSp"`
|
||||
GraphicFrame *xlsxInnerXML `xml:"graphicFrame"`
|
||||
CxnSp *xlsxInnerXML `xml:"cxnSp"`
|
||||
|
@ -46,16 +46,14 @@ type decodeCellAnchorPos struct {
|
|||
ClientData *xlsxInnerXML `xml:"clientData"`
|
||||
}
|
||||
|
||||
// xdrSp (Shape) directly maps the sp element. This element specifies the
|
||||
// existence of a single shape. A shape can either be a preset or a custom
|
||||
// geometry, defined using the SpreadsheetDrawingML framework. In addition to
|
||||
// a geometry each shape can have both visual and non-visual properties
|
||||
// attached. Text and corresponding styling information can also be attached
|
||||
// to a shape. This shape is specified along with all other shapes within
|
||||
// either the shape tree or group shape elements.
|
||||
// decodeSp defines the structure used to deserialize the sp element.
|
||||
type decodeSp struct {
|
||||
NvSpPr *decodeNvSpPr `xml:"nvSpPr"`
|
||||
SpPr *decodeSpPr `xml:"spPr"`
|
||||
Macro string `xml:"macro,attr,omitempty"`
|
||||
TextLink string `xml:"textlink,attr,omitempty"`
|
||||
FLocksText bool `xml:"fLocksText,attr,omitempty"`
|
||||
FPublished *bool `xml:"fPublished,attr"`
|
||||
NvSpPr *decodeNvSpPr `xml:"nvSpPr"`
|
||||
SpPr *decodeSpPr `xml:"spPr"`
|
||||
}
|
||||
|
||||
// decodeSp (Non-Visual Properties for a Shape) directly maps the nvSpPr
|
||||
|
|
|
@ -238,7 +238,7 @@ type xlsxCellAnchorPos struct {
|
|||
To *xlsxTo `xml:"xdr:to"`
|
||||
Pos *xlsxInnerXML `xml:"xdr:pos"`
|
||||
Ext *xlsxInnerXML `xml:"xdr:ext"`
|
||||
Sp *xlsxInnerXML `xml:"xdr:sp"`
|
||||
Sp *xlsxSp `xml:"xdr:sp"`
|
||||
GrpSp *xlsxInnerXML `xml:"xdr:grpSp"`
|
||||
GraphicFrame *xlsxInnerXML `xml:"xdr:graphicFrame"`
|
||||
CxnSp *xlsxInnerXML `xml:"xdr:cxnSp"`
|
||||
|
@ -248,6 +248,21 @@ type xlsxCellAnchorPos struct {
|
|||
ClientData *xlsxInnerXML `xml:"xdr:clientData"`
|
||||
}
|
||||
|
||||
// xdrSp (Shape) directly maps the sp element. This element specifies the
|
||||
// existence of a single shape. A shape can either be a preset or a custom
|
||||
// geometry, defined using the SpreadsheetDrawingML framework. In addition to
|
||||
// a geometry each shape can have both visual and non-visual properties
|
||||
// attached. Text and corresponding styling information can also be attached
|
||||
// to a shape. This shape is specified along with all other shapes within
|
||||
// either the shape tree or group shape elements.
|
||||
type xlsxSp struct {
|
||||
Macro string `xml:"macro,attr,omitempty"`
|
||||
TextLink string `xml:"textlink,attr,omitempty"`
|
||||
FLocksText bool `xml:"fLocksText,attr,omitempty"`
|
||||
FPublished *bool `xml:"fPublished,attr"`
|
||||
Content string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxPoint2D describes the position of a drawing element within a spreadsheet.
|
||||
type xlsxPoint2D struct {
|
||||
XMLName xml.Name `xml:"xdr:pos"`
|
||||
|
|
|
@ -56,15 +56,15 @@ type xlsxPivotTableDefinition struct {
|
|||
EnableDrill bool `xml:"enableDrill,attr,omitempty"`
|
||||
EnableFieldProperties bool `xml:"enableFieldProperties,attr,omitempty"`
|
||||
PreserveFormatting bool `xml:"preserveFormatting,attr,omitempty"`
|
||||
UseAutoFormatting *bool `xml:"useAutoFormatting,attr,omitempty"`
|
||||
UseAutoFormatting *bool `xml:"useAutoFormatting,attr"`
|
||||
PageWrap int `xml:"pageWrap,attr,omitempty"`
|
||||
PageOverThenDown *bool `xml:"pageOverThenDown,attr,omitempty"`
|
||||
PageOverThenDown *bool `xml:"pageOverThenDown,attr"`
|
||||
SubtotalHiddenItems bool `xml:"subtotalHiddenItems,attr,omitempty"`
|
||||
RowGrandTotals *bool `xml:"rowGrandTotals,attr,omitempty"`
|
||||
ColGrandTotals *bool `xml:"colGrandTotals,attr,omitempty"`
|
||||
RowGrandTotals *bool `xml:"rowGrandTotals,attr"`
|
||||
ColGrandTotals *bool `xml:"colGrandTotals,attr"`
|
||||
FieldPrintTitles bool `xml:"fieldPrintTitles,attr,omitempty"`
|
||||
ItemPrintTitles bool `xml:"itemPrintTitles,attr,omitempty"`
|
||||
MergeItem *bool `xml:"mergeItem,attr,omitempty"`
|
||||
MergeItem *bool `xml:"mergeItem,attr"`
|
||||
ShowDropZones bool `xml:"showDropZones,attr,omitempty"`
|
||||
CreatedVersion int `xml:"createdVersion,attr,omitempty"`
|
||||
Indent int `xml:"indent,attr,omitempty"`
|
||||
|
@ -74,7 +74,7 @@ type xlsxPivotTableDefinition struct {
|
|||
Compact *bool `xml:"compact,attr"`
|
||||
Outline *bool `xml:"outline,attr"`
|
||||
OutlineData bool `xml:"outlineData,attr,omitempty"`
|
||||
CompactData *bool `xml:"compactData,attr,omitempty"`
|
||||
CompactData *bool `xml:"compactData,attr"`
|
||||
Published bool `xml:"published,attr,omitempty"`
|
||||
GridDropZones bool `xml:"gridDropZones,attr,omitempty"`
|
||||
Immersive bool `xml:"immersive,attr,omitempty"`
|
||||
|
@ -150,7 +150,7 @@ type xlsxPivotField struct {
|
|||
DataSourceSort bool `xml:"dataSourceSort,attr,omitempty"`
|
||||
NonAutoSortDefault bool `xml:"nonAutoSortDefault,attr,omitempty"`
|
||||
RankBy int `xml:"rankBy,attr,omitempty"`
|
||||
DefaultSubtotal *bool `xml:"defaultSubtotal,attr,omitempty"`
|
||||
DefaultSubtotal *bool `xml:"defaultSubtotal,attr"`
|
||||
SumSubtotal bool `xml:"sumSubtotal,attr,omitempty"`
|
||||
CountASubtotal bool `xml:"countASubtotal,attr,omitempty"`
|
||||
AvgSubtotal bool `xml:"avgSubtotal,attr,omitempty"`
|
||||
|
|
Loading…
Reference in New Issue