diff --git a/README.md b/README.md
index 89d2d00..6ab549e 100644
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ func main() {
fmt.Println(err)
}
}()
- // Get value from cell by given worksheet name and axis.
+ // Get value from cell by given worksheet name and cell reference.
cell, err := f.GetCellValue("Sheet1", "B2")
if err != nil {
fmt.Println(err)
diff --git a/adjust.go b/adjust.go
index 3a0271d..92efcd0 100644
--- a/adjust.go
+++ b/adjust.go
@@ -185,7 +185,7 @@ func (f *File) adjustTable(ws *xlsxWorksheet, sheet string, dir adjustDirection,
Decode(&t); err != nil && err != io.EOF {
return
}
- coordinates, err := areaRefToCoordinates(t.Ref)
+ coordinates, err := rangeRefToCoordinates(t.Ref)
if err != nil {
return
}
@@ -204,7 +204,7 @@ func (f *File) adjustTable(ws *xlsxWorksheet, sheet string, dir adjustDirection,
idx--
continue
}
- t.Ref, _ = f.coordinatesToAreaRef([]int{x1, y1, x2, y2})
+ t.Ref, _ = f.coordinatesToRangeRef([]int{x1, y1, x2, y2})
if t.AutoFilter != nil {
t.AutoFilter.Ref = t.Ref
}
@@ -221,7 +221,7 @@ func (f *File) adjustAutoFilter(ws *xlsxWorksheet, dir adjustDirection, num, off
return nil
}
- coordinates, err := areaRefToCoordinates(ws.AutoFilter.Ref)
+ coordinates, err := rangeRefToCoordinates(ws.AutoFilter.Ref)
if err != nil {
return err
}
@@ -241,7 +241,7 @@ func (f *File) adjustAutoFilter(ws *xlsxWorksheet, dir adjustDirection, num, off
coordinates = f.adjustAutoFilterHelper(dir, coordinates, num, offset)
x1, y1, x2, y2 = coordinates[0], coordinates[1], coordinates[2], coordinates[3]
- if ws.AutoFilter.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
+ if ws.AutoFilter.Ref, err = f.coordinatesToRangeRef([]int{x1, y1, x2, y2}); err != nil {
return err
}
return nil
@@ -277,8 +277,8 @@ func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, off
}
for i := 0; i < len(ws.MergeCells.Cells); i++ {
- areaData := ws.MergeCells.Cells[i]
- coordinates, err := areaRefToCoordinates(areaData.Ref)
+ mergedCells := ws.MergeCells.Cells[i]
+ coordinates, err := rangeRefToCoordinates(mergedCells.Ref)
if err != nil {
return err
}
@@ -305,8 +305,8 @@ func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, off
i--
continue
}
- areaData.rect = []int{x1, y1, x2, y2}
- if areaData.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
+ mergedCells.rect = []int{x1, y1, x2, y2}
+ if mergedCells.Ref, err = f.coordinatesToRangeRef([]int{x1, y1, x2, y2}); err != nil {
return err
}
}
diff --git a/calc.go b/calc.go
index f7b3a63..b19dba7 100644
--- a/calc.go
+++ b/calc.go
@@ -789,10 +789,14 @@ func (f *File) calcCellValue(ctx *calcContext, sheet, cell string) (result strin
return
}
result = token.Value()
- isNum, precision := isNumeric(result)
- if isNum && (precision > 15 || precision == 0) {
- num := roundPrecision(result, -1)
- result = strings.ToUpper(num)
+ if isNum, precision, decimal := isNumeric(result); isNum {
+ if precision > 15 {
+ result = strings.ToUpper(strconv.FormatFloat(decimal, 'G', 15, 64))
+ return
+ }
+ if !strings.HasPrefix(result, "0") {
+ result = strings.ToUpper(strconv.FormatFloat(decimal, 'f', -1, 64))
+ }
}
return
}
@@ -2089,13 +2093,13 @@ func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
// cmplx2str replace complex number string characters.
func cmplx2str(num complex128, suffix string) string {
realPart, imagPart := fmt.Sprint(real(num)), fmt.Sprint(imag(num))
- isNum, i := isNumeric(realPart)
+ isNum, i, decimal := isNumeric(realPart)
if isNum && i > 15 {
- realPart = roundPrecision(realPart, -1)
+ realPart = strconv.FormatFloat(decimal, 'G', 15, 64)
}
- isNum, i = isNumeric(imagPart)
+ isNum, i, decimal = isNumeric(imagPart)
if isNum && i > 15 {
- imagPart = roundPrecision(imagPart, -1)
+ imagPart = strconv.FormatFloat(decimal, 'G', 15, 64)
}
c := realPart
if imag(num) > 0 {
diff --git a/calc_test.go b/calc_test.go
index ef196dc..df86f90 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -1736,7 +1736,7 @@ func TestCalcCellValue(t *testing.T) {
"=UPPER(\"TEST 123\")": "TEST 123",
// VALUE
"=VALUE(\"50\")": "50",
- "=VALUE(\"1.0E-07\")": "1E-07",
+ "=VALUE(\"1.0E-07\")": "0.0000001",
"=VALUE(\"5,000\")": "5000",
"=VALUE(\"20%\")": "0.2",
"=VALUE(\"12:00:00\")": "0.5",
diff --git a/cell.go b/cell.go
index b97c410..6beb3b2 100644
--- a/cell.go
+++ b/cell.go
@@ -485,7 +485,7 @@ func (f *File) SetCellDefault(sheet, cell, value string) error {
// 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 {
+ if ok, _, _ := isNumeric(value); !ok {
t = "str"
}
v = value
@@ -631,7 +631,7 @@ func (f *File) SetCellFormula(sheet, cell, formula string, opts ...FormulaOpts)
// setSharedFormula set shared formula for the cells.
func (ws *xlsxWorksheet) setSharedFormula(ref string) error {
- coordinates, err := areaRefToCoordinates(ref)
+ coordinates, err := rangeRefToCoordinates(ref)
if err != nil {
return err
}
@@ -1098,7 +1098,7 @@ func (f *File) setSheetCells(sheet, cell string, slice interface{}, dir adjustDi
return err
}
-// getCellInfo does common preparation for all SetCell* methods.
+// getCellInfo does common preparation for all set cell value functions.
func (f *File) prepareCell(ws *xlsxWorksheet, cell string) (*xlsxC, int, int, error) {
var err error
cell, err = f.mergeCellsParser(ws, cell)
@@ -1116,8 +1116,9 @@ func (f *File) prepareCell(ws *xlsxWorksheet, cell string) (*xlsxC, int, int, er
return &ws.SheetData.Row[row-1].C[col-1], col, row, err
}
-// getCellStringFunc does common value extraction workflow for all GetCell*
-// methods. Passed function implements specific part of required logic.
+// getCellStringFunc does common value extraction workflow for all get cell
+// value function. Passed function implements specific part of required
+// logic.
func (f *File) getCellStringFunc(sheet, cell string, fn func(x *xlsxWorksheet, c *xlsxC) (string, bool, error)) (string, error) {
ws, err := f.workSheetReader(sheet)
if err != nil {
@@ -1235,7 +1236,7 @@ func (f *File) mergeCellsParser(ws *xlsxWorksheet, cell string) (string, error)
i--
continue
}
- ok, err := f.checkCellInArea(cell, ws.MergeCells.Cells[i].Ref)
+ ok, err := f.checkCellInRangeRef(cell, ws.MergeCells.Cells[i].Ref)
if err != nil {
return cell, err
}
@@ -1247,18 +1248,18 @@ func (f *File) mergeCellsParser(ws *xlsxWorksheet, cell string) (string, error)
return cell, nil
}
-// checkCellInArea provides a function to determine if a given cell reference
+// checkCellInRangeRef provides a function to determine if a given cell reference
// in a range.
-func (f *File) checkCellInArea(cell, area string) (bool, error) {
+func (f *File) checkCellInRangeRef(cell, reference string) (bool, error) {
col, row, err := CellNameToCoordinates(cell)
if err != nil {
return false, err
}
- if rng := strings.Split(area, ":"); len(rng) != 2 {
+ if rng := strings.Split(reference, ":"); len(rng) != 2 {
return false, err
}
- coordinates, err := areaRefToCoordinates(area)
+ coordinates, err := rangeRefToCoordinates(reference)
if err != nil {
return false, err
}
@@ -1333,7 +1334,7 @@ func parseSharedFormula(dCol, dRow int, orig []byte) (res string, start int) {
// R1C1-reference notation, are the same.
//
// Note that this function not validate ref tag to check the cell whether in
-// allow area, and always return origin shared formula.
+// allow range reference, and always return origin shared formula.
func getSharedFormula(ws *xlsxWorksheet, si int, cell string) string {
for _, r := range ws.SheetData.Row {
for _, c := range r.C {
diff --git a/cell_test.go b/cell_test.go
index 9c8b511..0205705 100644
--- a/cell_test.go
+++ b/cell_test.go
@@ -95,43 +95,43 @@ func TestConcurrency(t *testing.T) {
assert.NoError(t, f.Close())
}
-func TestCheckCellInArea(t *testing.T) {
+func TestCheckCellInRangeRef(t *testing.T) {
f := NewFile()
- expectedTrueCellInAreaList := [][2]string{
+ expectedTrueCellInRangeRefList := [][2]string{
{"c2", "A1:AAZ32"},
{"B9", "A1:B9"},
{"C2", "C2:C2"},
}
- for _, expectedTrueCellInArea := range expectedTrueCellInAreaList {
- cell := expectedTrueCellInArea[0]
- area := expectedTrueCellInArea[1]
- ok, err := f.checkCellInArea(cell, area)
+ for _, expectedTrueCellInRangeRef := range expectedTrueCellInRangeRefList {
+ cell := expectedTrueCellInRangeRef[0]
+ reference := expectedTrueCellInRangeRef[1]
+ ok, err := f.checkCellInRangeRef(cell, reference)
assert.NoError(t, err)
assert.Truef(t, ok,
- "Expected cell %v to be in area %v, got false\n", cell, area)
+ "Expected cell %v to be in range reference %v, got false\n", cell, reference)
}
- expectedFalseCellInAreaList := [][2]string{
+ expectedFalseCellInRangeRefList := [][2]string{
{"c2", "A4:AAZ32"},
{"C4", "D6:A1"}, // weird case, but you never know
{"AEF42", "BZ40:AEF41"},
}
- for _, expectedFalseCellInArea := range expectedFalseCellInAreaList {
- cell := expectedFalseCellInArea[0]
- area := expectedFalseCellInArea[1]
- ok, err := f.checkCellInArea(cell, area)
+ for _, expectedFalseCellInRangeRef := range expectedFalseCellInRangeRefList {
+ cell := expectedFalseCellInRangeRef[0]
+ reference := expectedFalseCellInRangeRef[1]
+ ok, err := f.checkCellInRangeRef(cell, reference)
assert.NoError(t, err)
assert.Falsef(t, ok,
- "Expected cell %v not to be inside of area %v, but got true\n", cell, area)
+ "Expected cell %v not to be inside of range reference %v, but got true\n", cell, reference)
}
- ok, err := f.checkCellInArea("A1", "A:B")
+ ok, err := f.checkCellInRangeRef("A1", "A:B")
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
assert.False(t, ok)
- ok, err = f.checkCellInArea("AA0", "Z0:AB1")
+ ok, err = f.checkCellInRangeRef("AA0", "Z0:AB1")
assert.EqualError(t, err, newCellNameToCoordinatesError("AA0", newInvalidCellNameError("AA0")).Error())
assert.False(t, ok)
}
@@ -326,8 +326,10 @@ func TestGetCellValue(t *testing.T) {
275.39999999999998
68.900000000000006
1.1000000000000001
- 1234567890123_4
- 123456789_0123_4
+ 1234567890123_4
+ 123456789_0123_4
+ +0.0000000000000000002399999999999992E-4
+ 7.2399999999999992E-2
`)))
f.checked = nil
rows, err = f.GetRows("Sheet1")
@@ -361,6 +363,8 @@ func TestGetCellValue(t *testing.T) {
"1.1",
"1234567890123_4",
"123456789_0123_4",
+ "2.39999999999999E-23",
+ "0.0724",
}}, rows)
assert.NoError(t, err)
}
diff --git a/col.go b/col.go
index adc7f85..964cb97 100644
--- a/col.go
+++ b/col.go
@@ -560,7 +560,7 @@ func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol)
// | | | (x2,y2)|
// +-----+------------+------------+
//
-// Example of an object that covers some area from cell A1 to B2.
+// Example of an object that covers some range reference from cell A1 to B2.
//
// Based on the width and height of the object we need to calculate 8 vars:
//
diff --git a/datavalidation.go b/datavalidation.go
index 3d82f7c..5ae5f65 100644
--- a/datavalidation.go
+++ b/datavalidation.go
@@ -333,7 +333,7 @@ func (f *File) squashSqref(cells [][]int) []string {
l, r := 0, 0
for i := 1; i < len(cells); i++ {
if cells[i][0] == cells[r][0] && cells[i][1]-cells[r][1] > 1 {
- curr, _ := f.coordinatesToAreaRef(append(cells[l], cells[r]...))
+ curr, _ := f.coordinatesToRangeRef(append(cells[l], cells[r]...))
if l == r {
curr, _ = CoordinatesToCellName(cells[l][0], cells[l][1])
}
@@ -343,7 +343,7 @@ func (f *File) squashSqref(cells [][]int) []string {
r++
}
}
- curr, _ := f.coordinatesToAreaRef(append(cells[l], cells[r]...))
+ curr, _ := f.coordinatesToRangeRef(append(cells[l], cells[r]...))
if l == r {
curr, _ = CoordinatesToCellName(cells[l][0], cells[l][1])
}
diff --git a/excelize_test.go b/excelize_test.go
index 5756e6e..9bb6fa8 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -615,7 +615,7 @@ func TestSetCellStyleBorder(t *testing.T) {
var style int
- // Test set border on overlapping area with vertical variants shading styles gradient fill.
+ // Test set border on overlapping range with vertical variants shading styles gradient fill.
style, err = f.NewStyle(&Style{
Border: []Border{
{Type: "left", Color: "0000FF", Style: 3},
diff --git a/lib.go b/lib.go
index 5feb7d5..21ce7d2 100644
--- a/lib.go
+++ b/lib.go
@@ -19,6 +19,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "math/big"
"os"
"regexp"
"strconv"
@@ -273,19 +274,19 @@ func CoordinatesToCellName(col, row int, abs ...bool) (string, error) {
return sign + colName + sign + strconv.Itoa(row), err
}
-// areaRefToCoordinates provides a function to convert range reference to a
+// rangeRefToCoordinates provides a function to convert range reference to a
// pair of coordinates.
-func areaRefToCoordinates(ref string) ([]int, error) {
+func rangeRefToCoordinates(ref string) ([]int, error) {
rng := strings.Split(strings.ReplaceAll(ref, "$", ""), ":")
if len(rng) < 2 {
return nil, ErrParameterInvalid
}
- return areaRangeToCoordinates(rng[0], rng[1])
+ return cellRefsToCoordinates(rng[0], rng[1])
}
-// areaRangeToCoordinates provides a function to convert cell range to a
+// cellRefsToCoordinates provides a function to convert cell range to a
// pair of coordinates.
-func areaRangeToCoordinates(firstCell, lastCell string) ([]int, error) {
+func cellRefsToCoordinates(firstCell, lastCell string) ([]int, error) {
coordinates := make([]int, 4)
var err error
coordinates[0], coordinates[1], err = CellNameToCoordinates(firstCell)
@@ -311,9 +312,9 @@ func sortCoordinates(coordinates []int) error {
return nil
}
-// coordinatesToAreaRef provides a function to convert a pair of coordinates
-// to area reference.
-func (f *File) coordinatesToAreaRef(coordinates []int) (string, error) {
+// coordinatesToRangeRef provides a function to convert a pair of coordinates
+// to range reference.
+func (f *File) coordinatesToRangeRef(coordinates []int) (string, error) {
if len(coordinates) != 4 {
return "", ErrCoordinates
}
@@ -364,7 +365,7 @@ func (f *File) flatSqref(sqref string) (cells map[int][][]int, err error) {
}
cells[col] = append(cells[col], []int{col, row})
case 2:
- if coordinates, err = areaRefToCoordinates(ref); err != nil {
+ if coordinates, err = rangeRefToCoordinates(ref); err != nil {
return
}
_ = sortCoordinates(coordinates)
@@ -691,34 +692,16 @@ func (f *File) addSheetNameSpace(sheet string, ns xml.Attr) {
// isNumeric determines whether an expression is a valid numeric type and get
// the precision for the numeric.
-func isNumeric(s string) (bool, int) {
- dot, e, n, p := false, false, false, 0
- for i, v := range s {
- if v == '.' {
- if dot {
- return false, 0
- }
- dot = true
- } else if v == 'E' || v == 'e' {
- e = true
- } else if v < '0' || v > '9' {
- if i == 0 && v == '-' {
- continue
- }
- if e && v == '-' {
- return true, 0
- }
- if e && v == '+' {
- p = 15
- continue
- }
- return false, 0
- } else {
- p++
- }
- n = true
+func isNumeric(s string) (bool, int, float64) {
+ var decimal big.Float
+ _, ok := decimal.SetString(s)
+ if !ok {
+ return false, 0, 0
}
- return n, p
+ var noScientificNotation string
+ flt, _ := decimal.Float64()
+ noScientificNotation = strconv.FormatFloat(flt, 'f', -1, 64)
+ return true, len(strings.ReplaceAll(noScientificNotation, ".", "")), flt
}
var (
diff --git a/lib_test.go b/lib_test.go
index c42914d..e96704f 100644
--- a/lib_test.go
+++ b/lib_test.go
@@ -217,15 +217,15 @@ func TestCoordinatesToCellName_Error(t *testing.T) {
}
}
-func TestCoordinatesToAreaRef(t *testing.T) {
+func TestCoordinatesToRangeRef(t *testing.T) {
f := NewFile()
- _, err := f.coordinatesToAreaRef([]int{})
+ _, err := f.coordinatesToRangeRef([]int{})
assert.EqualError(t, err, ErrCoordinates.Error())
- _, err = f.coordinatesToAreaRef([]int{1, -1, 1, 1})
+ _, err = f.coordinatesToRangeRef([]int{1, -1, 1, 1})
assert.EqualError(t, err, "invalid cell reference [1, -1]")
- _, err = f.coordinatesToAreaRef([]int{1, 1, 1, -1})
+ _, err = f.coordinatesToRangeRef([]int{1, 1, 1, -1})
assert.EqualError(t, err, "invalid cell reference [1, -1]")
- ref, err := f.coordinatesToAreaRef([]int{1, 1, 1, 1})
+ ref, err := f.coordinatesToRangeRef([]int{1, 1, 1, 1})
assert.NoError(t, err)
assert.EqualValues(t, ref, "A1:A1")
}
diff --git a/merge.go b/merge.go
index ac7fb04..04dc493 100644
--- a/merge.go
+++ b/merge.go
@@ -17,7 +17,7 @@ import "strings"
func (mc *xlsxMergeCell) Rect() ([]int, error) {
var err error
if mc.rect == nil {
- mc.rect, err = areaRefToCoordinates(mc.Ref)
+ mc.rect, err = rangeRefToCoordinates(mc.Ref)
}
return mc.rect, err
}
@@ -46,7 +46,7 @@ func (mc *xlsxMergeCell) Rect() ([]int, error) {
// |A8(x3,y4) C8(x4,y4)|
// +------------------------+
func (f *File) MergeCell(sheet, hCell, vCell string) error {
- rect, err := areaRefToCoordinates(hCell + ":" + vCell)
+ rect, err := rangeRefToCoordinates(hCell + ":" + vCell)
if err != nil {
return err
}
@@ -73,11 +73,11 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error {
}
// UnmergeCell provides a function to unmerge a given range reference.
-// For example unmerge area D3:E9 on Sheet1:
+// For example unmerge range reference D3:E9 on Sheet1:
//
// err := f.UnmergeCell("Sheet1", "D3", "E9")
//
-// Attention: overlapped areas will also be unmerged.
+// Attention: overlapped range will also be unmerged.
func (f *File) UnmergeCell(sheet, hCell, vCell string) error {
ws, err := f.workSheetReader(sheet)
if err != nil {
@@ -85,7 +85,7 @@ func (f *File) UnmergeCell(sheet, hCell, vCell string) error {
}
ws.Lock()
defer ws.Unlock()
- rect1, err := areaRefToCoordinates(hCell + ":" + vCell)
+ rect1, err := rangeRefToCoordinates(hCell + ":" + vCell)
if err != nil {
return err
}
@@ -105,7 +105,7 @@ func (f *File) UnmergeCell(sheet, hCell, vCell string) error {
if mergeCell == nil {
continue
}
- rect2, _ := areaRefToCoordinates(mergeCell.Ref)
+ rect2, _ := rangeRefToCoordinates(mergeCell.Ref)
if isOverlap(rect1, rect2) {
continue
}
diff --git a/merge_test.go b/merge_test.go
index f4d5f7e..6977c5a 100644
--- a/merge_test.go
+++ b/merge_test.go
@@ -169,7 +169,7 @@ func TestUnmergeCell(t *testing.T) {
f = NewFile()
assert.NoError(t, f.MergeCell("Sheet1", "A2", "B3"))
- // Test unmerged area on not exists worksheet.
+ // Test unmerged range reference on not exists worksheet.
assert.EqualError(t, f.UnmergeCell("SheetN", "A1", "A1"), "sheet SheetN does not exist")
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
diff --git a/numfmt.go b/numfmt.go
index fd99240..09e64c9 100644
--- a/numfmt.go
+++ b/numfmt.go
@@ -279,7 +279,7 @@ var (
// prepareNumberic split the number into two before and after parts by a
// decimal point.
func (nf *numberFormat) prepareNumberic(value string) {
- if nf.isNumeric, _ = isNumeric(value); !nf.isNumeric {
+ if nf.isNumeric, _, _ = isNumeric(value); !nf.isNumeric {
return
}
}
@@ -338,13 +338,13 @@ func (nf *numberFormat) positiveHandler() (result string) {
continue
}
if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == strings.Repeat("0", len(token.TValue)) {
- if isNum, precision := isNumeric(nf.value); isNum {
+ if isNum, precision, decimal := isNumeric(nf.value); isNum {
if nf.number < 1 {
nf.result += "0"
continue
}
if precision > 15 {
- nf.result += roundPrecision(nf.value, 15)
+ nf.result += strconv.FormatFloat(decimal, 'f', -1, 64)
} else {
nf.result += fmt.Sprintf("%.f", nf.number)
}
@@ -902,13 +902,13 @@ func (nf *numberFormat) negativeHandler() (result string) {
continue
}
if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == strings.Repeat("0", len(token.TValue)) {
- if isNum, precision := isNumeric(nf.value); isNum {
+ if isNum, precision, decimal := isNumeric(nf.value); isNum {
if math.Abs(nf.number) < 1 {
nf.result += "0"
continue
}
if precision > 15 {
- nf.result += strings.TrimLeft(roundPrecision(nf.value, 15), "-")
+ nf.result += strings.TrimLeft(strconv.FormatFloat(decimal, 'f', -1, 64), "-")
} else {
nf.result += fmt.Sprintf("%.f", math.Abs(nf.number))
}
@@ -941,7 +941,7 @@ func (nf *numberFormat) textHandler() (result string) {
// getValueSectionType returns its applicable number format expression section
// based on the given value.
func (nf *numberFormat) getValueSectionType(value string) (float64, string) {
- isNum, _ := isNumeric(value)
+ isNum, _, _ := isNumeric(value)
if !isNum {
return 0, nfp.TokenSectionText
}
diff --git a/picture.go b/picture.go
index 3b6d821..e1c62f2 100644
--- a/picture.go
+++ b/picture.go
@@ -652,11 +652,11 @@ func (f *File) drawingResize(sheet, cell string, width, height float64, formatSe
if inMergeCell {
continue
}
- if inMergeCell, err = f.checkCellInArea(cell, mergeCell[0]); err != nil {
+ if inMergeCell, err = f.checkCellInRangeRef(cell, mergeCell[0]); err != nil {
return
}
if inMergeCell {
- rng, _ = areaRangeToCoordinates(mergeCell.GetStartAxis(), mergeCell.GetEndAxis())
+ rng, _ = cellRefsToCoordinates(mergeCell.GetStartAxis(), mergeCell.GetEndAxis())
_ = sortCoordinates(rng)
}
}
diff --git a/pivotTable.go b/pivotTable.go
index af30a0b..8e16e06 100644
--- a/pivotTable.go
+++ b/pivotTable.go
@@ -81,8 +81,9 @@ type PivotTableField struct {
// options. Note that the same fields can not in Columns, Rows and Filter
// fields at the same time.
//
-// For example, create a pivot table on the Sheet1!$G$2:$M$34 area with the
-// region Sheet1!$A$1:$E$31 as the data source, summarize by sum for sales:
+// For example, create a pivot table on the Sheet1!$G$2:$M$34 range reference
+// with the region Sheet1!$A$1:$E$31 as the data source, summarize by sum for
+// sales:
//
// package main
//
@@ -205,7 +206,7 @@ func (f *File) adjustRange(rangeStr string) (string, []int, error) {
return "", []int{}, ErrParameterInvalid
}
trimRng := strings.ReplaceAll(rng[1], "$", "")
- coordinates, err := areaRefToCoordinates(trimRng)
+ coordinates, err := rangeRefToCoordinates(trimRng)
if err != nil {
return rng[0], []int{}, err
}
diff --git a/rows.go b/rows.go
index 561f64b..2960aa4 100644
--- a/rows.go
+++ b/rows.go
@@ -19,7 +19,6 @@ import (
"io/ioutil"
"log"
"math"
- "math/big"
"os"
"strconv"
@@ -486,32 +485,17 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
}
return f.formattedValue(c.S, c.V, raw), nil
default:
- if isNum, precision := isNumeric(c.V); isNum && !raw {
- if precision == 0 {
- c.V = roundPrecision(c.V, 15)
+ if isNum, precision, decimal := isNumeric(c.V); isNum && !raw {
+ if precision > 15 {
+ c.V = strconv.FormatFloat(decimal, 'G', 15, 64)
} else {
- c.V = roundPrecision(c.V, -1)
+ c.V = strconv.FormatFloat(decimal, 'f', -1, 64)
}
}
return f.formattedValue(c.S, c.V, raw), nil
}
}
-// roundPrecision provides a function to format floating-point number text
-// with precision, if the given text couldn't be parsed to float, this will
-// return the original string.
-func roundPrecision(text string, prec int) string {
- decimal := big.Float{}
- if _, ok := decimal.SetString(text); ok {
- flt, _ := decimal.Float64()
- if prec == -1 {
- return strconv.FormatFloat(flt, 'G', 15, 64)
- }
- return strconv.FormatFloat(flt, 'f', -1, 64)
- }
- return text
-}
-
// SetRowVisible provides a function to set visible of a single row by given
// worksheet name and Excel row number. For example, hide row 2 in Sheet1:
//
@@ -732,7 +716,7 @@ func (f *File) duplicateMergeCells(sheet string, ws *xlsxWorksheet, row, row2 in
row++
}
for _, rng := range ws.MergeCells.Cells {
- coordinates, err := areaRefToCoordinates(rng.Ref)
+ coordinates, err := rangeRefToCoordinates(rng.Ref)
if err != nil {
return err
}
@@ -741,8 +725,8 @@ func (f *File) duplicateMergeCells(sheet string, ws *xlsxWorksheet, row, row2 in
}
}
for i := 0; i < len(ws.MergeCells.Cells); i++ {
- areaData := ws.MergeCells.Cells[i]
- coordinates, _ := areaRefToCoordinates(areaData.Ref)
+ mergedCells := ws.MergeCells.Cells[i]
+ coordinates, _ := rangeRefToCoordinates(mergedCells.Ref)
x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
if y1 == y2 && y1 == row {
from, _ := CoordinatesToCellName(x1, row2)
diff --git a/rows_test.go b/rows_test.go
index d51e256..8ce007f 100644
--- a/rows_test.go
+++ b/rows_test.go
@@ -995,10 +995,6 @@ func TestNumberFormats(t *testing.T) {
assert.NoError(t, f.Close())
}
-func TestRoundPrecision(t *testing.T) {
- assert.Equal(t, "text", roundPrecision("text", 0))
-}
-
func BenchmarkRows(b *testing.B) {
f, _ := OpenFile(filepath.Join("test", "Book1.xlsx"))
for i := 0; i < b.N; i++ {
diff --git a/sheet.go b/sheet.go
index ee4f667..fe24b18 100644
--- a/sheet.go
+++ b/sheet.go
@@ -39,6 +39,9 @@ import (
// `Sheet1` will be created.
func (f *File) NewSheet(sheet string) int {
// Check if the worksheet already exists
+ if trimSheetName(sheet) == "" {
+ return -1
+ }
index := f.GetSheetIndex(sheet)
if index != -1 {
return index
diff --git a/sheet_test.go b/sheet_test.go
index 324d626..87c36d4 100644
--- a/sheet_test.go
+++ b/sheet_test.go
@@ -90,6 +90,8 @@ func TestNewSheet(t *testing.T) {
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewSheet.xlsx")))
// create new worksheet with already exists name
assert.Equal(t, f.GetSheetIndex("Sheet2"), f.NewSheet("Sheet2"))
+ // create new worksheet with empty sheet name
+ assert.Equal(t, -1, f.NewSheet(":\\/?*[]"))
}
func TestSetPane(t *testing.T) {
diff --git a/stream.go b/stream.go
index 84299cb..019731f 100644
--- a/stream.go
+++ b/stream.go
@@ -145,7 +145,7 @@ func (sw *StreamWriter) AddTable(hCell, vCell, format string) error {
return err
}
- coordinates, err := areaRangeToCoordinates(hCell, vCell)
+ coordinates, err := cellRefsToCoordinates(hCell, vCell)
if err != nil {
return err
}
@@ -157,7 +157,7 @@ func (sw *StreamWriter) AddTable(hCell, vCell, format string) error {
}
// Correct table reference range, such correct C1:B3 to B1:C3.
- ref, err := sw.File.coordinatesToAreaRef(coordinates)
+ ref, err := sw.File.coordinatesToRangeRef(coordinates)
if err != nil {
return err
}
@@ -412,7 +412,7 @@ func (sw *StreamWriter) SetColWidth(min, max int, width float64) error {
// the StreamWriter. Don't create a merged cell that overlaps with another
// existing merged cell.
func (sw *StreamWriter) MergeCell(hCell, vCell string) error {
- _, err := areaRangeToCoordinates(hCell, vCell)
+ _, err := cellRefsToCoordinates(hCell, vCell)
if err != nil {
return err
}
diff --git a/styles.go b/styles.go
index 587fd74..a4f5dc4 100644
--- a/styles.go
+++ b/styles.go
@@ -2486,11 +2486,14 @@ func (f *File) GetCellStyle(sheet, cell string) (int, error) {
if err != nil {
return 0, err
}
- c, col, row, err := f.prepareCell(ws, cell)
+ col, row, err := CellNameToCoordinates(cell)
if err != nil {
return 0, err
}
- return f.prepareCellStyle(ws, col, row, c.S), err
+ prepareSheetXML(ws, col, row)
+ ws.Lock()
+ defer ws.Unlock()
+ return f.prepareCellStyle(ws, col, row, ws.SheetData.Row[row-1].C[col-1].S), err
}
// SetCellStyle provides a function to add style attribute for cells by given
@@ -2856,7 +2859,7 @@ func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error {
// max_color - Same as min_color, see above.
//
// bar_color - Used for data_bar. Same as min_color, see above.
-func (f *File) SetConditionalFormat(sheet, area, formatSet string) error {
+func (f *File) SetConditionalFormat(sheet, reference, formatSet string) error {
var format []*formatConditional
err := json.Unmarshal([]byte(formatSet), &format)
if err != nil {
@@ -2897,7 +2900,7 @@ func (f *File) SetConditionalFormat(sheet, area, formatSet string) error {
}
ws.ConditionalFormatting = append(ws.ConditionalFormatting, &xlsxConditionalFormatting{
- SQRef: area,
+ SQRef: reference,
CfRule: cfRule,
})
return err
diff --git a/table.go b/table.go
index 66ba729..7ef7562 100644
--- a/table.go
+++ b/table.go
@@ -48,7 +48,7 @@ func parseFormatTableSet(formatSet string) (*formatTable, error) {
// Note that the table must be at least two lines including the header. The
// header cells must contain strings and must be unique, and must set the
// header row data of the table before calling the AddTable function. Multiple
-// tables coordinate areas that can't have an intersection.
+// tables range reference that can't have an intersection.
//
// table_name: The name of the table, in the same worksheet name of the table should be unique
//
@@ -167,7 +167,7 @@ func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, formatSet
}
// Correct table range reference, such correct C1:B3 to B1:C3.
- ref, err := f.coordinatesToAreaRef([]int{x1, y1, x2, y2})
+ ref, err := f.coordinatesToRangeRef([]int{x1, y1, x2, y2})
if err != nil {
return err
}