2016-08-30 11:51:31 +08:00
|
|
|
package excelize
|
|
|
|
|
|
|
|
import (
|
2019-06-27 21:58:14 +08:00
|
|
|
"bytes"
|
2019-12-22 00:02:09 +08:00
|
|
|
"compress/gzip"
|
|
|
|
"encoding/xml"
|
2017-08-11 23:15:33 +08:00
|
|
|
"fmt"
|
2018-07-07 15:59:48 +08:00
|
|
|
"image/color"
|
2017-01-22 16:16:03 +08:00
|
|
|
_ "image/gif"
|
|
|
|
_ "image/jpeg"
|
|
|
|
_ "image/png"
|
2017-03-28 21:18:06 +08:00
|
|
|
"io/ioutil"
|
2019-09-22 20:52:01 +08:00
|
|
|
"math"
|
2018-12-27 18:51:44 +08:00
|
|
|
"os"
|
2018-12-27 22:28:28 +08:00
|
|
|
"path/filepath"
|
2016-08-30 14:00:21 +08:00
|
|
|
"strconv"
|
2017-09-11 15:53:25 +08:00
|
|
|
"strings"
|
2016-08-30 11:51:31 +08:00
|
|
|
"testing"
|
2017-05-05 14:40:28 +08:00
|
|
|
"time"
|
2018-12-26 13:33:40 +08:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2016-08-30 11:51:31 +08:00
|
|
|
)
|
|
|
|
|
2017-01-18 14:47:23 +08:00
|
|
|
func TestOpenFile(t *testing.T) {
|
2020-07-09 01:24:11 +08:00
|
|
|
// Test update the spreadsheet file.
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, err)
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2017-09-13 22:00:33 +08:00
|
|
|
// Test get all the rows in a not exists worksheet.
|
2019-12-24 01:09:28 +08:00
|
|
|
_, err = f.GetRows("Sheet4")
|
|
|
|
assert.EqualError(t, err, "sheet Sheet4 is not exist")
|
2017-09-13 22:00:33 +08:00
|
|
|
// Test get all the rows in a worksheet.
|
2019-04-21 00:04:42 +08:00
|
|
|
rows, err := f.GetRows("Sheet2")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
2016-11-02 12:58:51 +08:00
|
|
|
for _, row := range rows {
|
|
|
|
for _, cell := range row {
|
|
|
|
t.Log(cell, "\t")
|
|
|
|
}
|
|
|
|
t.Log("\r\n")
|
|
|
|
}
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.UpdateLinkedValue())
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32)))
|
|
|
|
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)))
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2017-09-19 11:59:33 +08:00
|
|
|
// Test set cell value with illegal row number.
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)),
|
2021-12-07 00:26:53 +08:00
|
|
|
newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-12-23 00:07:40 +08:00
|
|
|
assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100))
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2017-09-19 11:59:33 +08:00
|
|
|
// Test set cell integer value with illegal row number.
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, f.SetCellInt("Sheet2", "A", 100), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet2", "C11", "Knowns"))
|
2017-01-19 14:05:32 +08:00
|
|
|
// Test max characters in a cell.
|
2021-04-30 00:14:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet2", "D11", strings.Repeat("c", TotalCellChars+2)))
|
2019-04-21 00:04:42 +08:00
|
|
|
f.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.")
|
2017-09-13 22:00:33 +08:00
|
|
|
// Test set worksheet name with illegal name.
|
2019-04-21 00:04:42 +08:00
|
|
|
f.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.EqualError(t, f.SetCellInt("Sheet3", "A23", 10), "sheet Sheet3 is not exist")
|
|
|
|
assert.EqualError(t, f.SetCellStr("Sheet3", "b230", "10"), "sheet Sheet3 is not exist")
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.SetCellStr("Sheet10", "b230", "10"), "sheet Sheet10 is not exist")
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2017-09-19 11:59:33 +08:00
|
|
|
// Test set cell string value with illegal row number.
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, f.SetCellStr("Sheet1", "A", "10"), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
f.SetActiveSheet(2)
|
2017-09-19 11:59:33 +08:00
|
|
|
// Test get cell formula with given rows number.
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.GetCellFormula("Sheet1", "B19")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
2017-10-31 16:33:36 +08:00
|
|
|
// Test get cell formula with illegal worksheet name.
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.GetCellFormula("Sheet2", "B20")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.GetCellFormula("Sheet1", "B20")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
|
|
|
// Test get cell formula with illegal rows number.
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.GetCellFormula("Sheet1", "B")
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, err, newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
|
2018-05-26 16:23:15 +08:00
|
|
|
// Test get shared cell formula
|
2019-12-23 00:07:40 +08:00
|
|
|
_, err = f.GetCellFormula("Sheet2", "H11")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
_, err = f.GetCellFormula("Sheet2", "I11")
|
|
|
|
assert.NoError(t, err)
|
2022-01-09 00:20:42 +08:00
|
|
|
getSharedFormula(&xlsxWorksheet{}, 0, "")
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2016-10-19 18:42:29 +08:00
|
|
|
// Test read cell value with given illegal rows number.
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.GetCellValue("Sheet2", "a-1")
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, err, newCellNameToCoordinatesError("A-1", newInvalidCellNameError("A-1")).Error())
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.GetCellValue("Sheet2", "A")
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2016-10-19 18:42:29 +08:00
|
|
|
// Test read cell value with given lowercase column number.
|
2019-12-23 00:07:40 +08:00
|
|
|
_, err = f.GetCellValue("Sheet2", "a5")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
_, err = f.GetCellValue("Sheet2", "C11")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
_, err = f.GetCellValue("Sheet2", "D11")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
_, err = f.GetCellValue("Sheet2", "D12")
|
|
|
|
assert.NoError(t, err)
|
2016-10-19 18:42:29 +08:00
|
|
|
// Test SetCellValue function.
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F1", " Hello"))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "G1", []byte("World")))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F2", 42))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F3", int8(1<<8/2-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F4", int16(1<<16/2-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F5", int32(1<<32/2-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F6", int64(1<<32/2-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F7", float32(42.65418)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F8", float64(-42.65418)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F9", float32(42)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F10", float64(42)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F11", uint(1<<32-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F12", uint8(1<<8-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F13", uint16(1<<16-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F14", uint32(1<<32-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F15", uint64(1<<32-1)))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F16", true))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F17", complex64(5+10i)))
|
2019-04-16 10:57:21 +08:00
|
|
|
|
|
|
|
// Test on not exists worksheet.
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.SetCellDefault("SheetN", "A1", ""), "sheet SheetN is not exist")
|
|
|
|
assert.EqualError(t, f.SetCellFloat("SheetN", "A1", 42.65418, 2, 32), "sheet SheetN is not exist")
|
|
|
|
assert.EqualError(t, f.SetCellBool("SheetN", "A1", true), "sheet SheetN is not exist")
|
|
|
|
assert.EqualError(t, f.SetCellFormula("SheetN", "A1", ""), "sheet SheetN is not exist")
|
|
|
|
assert.EqualError(t, f.SetCellHyperLink("SheetN", "A1", "Sheet1!A40", "Location"), "sheet SheetN is not exist")
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2018-01-26 01:06:40 +08:00
|
|
|
// Test boolean write
|
|
|
|
booltest := []struct {
|
|
|
|
value bool
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{false, "0"},
|
|
|
|
{true, "1"},
|
|
|
|
}
|
|
|
|
for _, test := range booltest {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "F16", test.value))
|
2019-04-21 00:04:42 +08:00
|
|
|
val, err := f.GetCellValue("Sheet2", "F16")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, test.expected, val)
|
2018-01-26 01:06:40 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "G2", nil))
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2021-06-04 23:06:58 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "G4", time.Now()))
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "G4", time.Now().UTC()))
|
2022-01-27 22:37:32 +08:00
|
|
|
assert.EqualError(t, f.SetCellValue("SheetN", "A1", time.Now()), "sheet SheetN is not exist")
|
2018-01-05 09:39:31 +08:00
|
|
|
// 02:46:40
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "G5", time.Duration(1e13)))
|
2016-10-23 16:07:57 +08:00
|
|
|
// Test completion column.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", "M2", nil))
|
2016-10-19 18:42:29 +08:00
|
|
|
// Test read cell value with given axis large than exists row.
|
2019-12-23 00:07:40 +08:00
|
|
|
_, err = f.GetCellValue("Sheet2", "E231")
|
|
|
|
assert.NoError(t, err)
|
2020-07-09 01:24:11 +08:00
|
|
|
// Test get active worksheet of spreadsheet and get worksheet name of spreadsheet by given worksheet index.
|
2019-04-21 00:04:42 +08:00
|
|
|
f.GetSheetName(f.GetActiveSheetIndex())
|
2020-07-09 01:24:11 +08:00
|
|
|
// Test get worksheet index of spreadsheet by given worksheet name.
|
2019-04-21 00:04:42 +08:00
|
|
|
f.GetSheetIndex("Sheet1")
|
2020-07-09 01:24:11 +08:00
|
|
|
// Test get worksheet name of spreadsheet by given invalid worksheet index.
|
2019-04-21 00:04:42 +08:00
|
|
|
f.GetSheetName(4)
|
2019-12-24 01:09:28 +08:00
|
|
|
// Test get worksheet map of workbook.
|
2019-04-21 00:04:42 +08:00
|
|
|
f.GetSheetMap()
|
2016-09-05 16:37:15 +08:00
|
|
|
for i := 1; i <= 300; i++ {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet2", "c"+strconv.Itoa(i), strconv.Itoa(i)))
|
2017-01-19 14:05:32 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestOpenFile.xlsx")))
|
2021-05-10 00:09:24 +08:00
|
|
|
assert.EqualError(t, f.SaveAs(filepath.Join("test", strings.Repeat("c", 199), ".xlsx")), ErrMaxFileNameLength.Error())
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2018-12-27 18:51:44 +08:00
|
|
|
}
|
|
|
|
|
2019-01-01 13:20:14 +08:00
|
|
|
func TestSaveFile(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2019-01-01 13:20:14 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2022-01-23 00:32:34 +08:00
|
|
|
assert.EqualError(t, f.SaveAs(filepath.Join("test", "TestSaveFile.xlsb")), ErrWorkbookExt.Error())
|
|
|
|
for _, ext := range []string{".xlam", ".xlsm", ".xlsx", ".xltm", ".xltx"} {
|
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", fmt.Sprintf("TestSaveFile%s", ext))))
|
|
|
|
}
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err = OpenFile(filepath.Join("test", "TestSaveFile.xlsx"))
|
2019-01-01 13:20:14 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.Save())
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2019-01-01 13:20:14 +08:00
|
|
|
}
|
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
func TestSaveAsWrongPath(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2021-08-15 00:06:40 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
// Test write file to not exist directory.
|
2022-01-23 00:32:34 +08:00
|
|
|
assert.Error(t, f.SaveAs(filepath.Join("x", "Book1.xlsx")))
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2017-01-19 14:05:32 +08:00
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
func TestCharsetTranscoder(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
f.CharsetTranscoder(*new(charsetTranscoderFn))
|
|
|
|
}
|
|
|
|
|
2019-06-18 23:07:44 +08:00
|
|
|
func TestOpenReader(t *testing.T) {
|
|
|
|
_, err := OpenReader(strings.NewReader(""))
|
|
|
|
assert.EqualError(t, err, "zip: not a valid zip file")
|
2021-12-27 23:34:14 +08:00
|
|
|
_, err = OpenReader(bytes.NewReader(oleIdentifier), Options{Password: "password", UnzipXMLSizeLimit: UnzipSizeLimit + 1})
|
2020-09-01 00:40:56 +08:00
|
|
|
assert.EqualError(t, err, "decrypted file failed")
|
|
|
|
|
2021-08-15 00:06:40 +08:00
|
|
|
// Test open spreadsheet with unzip size limit.
|
|
|
|
_, err = OpenFile(filepath.Join("test", "Book1.xlsx"), Options{UnzipSizeLimit: 100})
|
|
|
|
assert.EqualError(t, err, newUnzipSizeLimitError(100).Error())
|
|
|
|
|
2020-09-02 23:14:19 +08:00
|
|
|
// Test open password protected spreadsheet created by Microsoft Office Excel 2010.
|
2020-09-01 00:40:56 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "encryptSHA1.xlsx"), Options{Password: "password"})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
val, err := f.GetCellValue("Sheet1", "A1")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "SECRET", val)
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2019-12-22 00:02:09 +08:00
|
|
|
|
2020-09-02 23:14:19 +08:00
|
|
|
// Test open password protected spreadsheet created by LibreOffice 7.0.0.3.
|
|
|
|
f, err = OpenFile(filepath.Join("test", "encryptAES.xlsx"), Options{Password: "password"})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
val, err = f.GetCellValue("Sheet1", "A1")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "SECRET", val)
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
|
|
|
|
2022-01-09 00:20:42 +08:00
|
|
|
// Test open spreadsheet with invalid options.
|
2021-12-27 23:34:14 +08:00
|
|
|
_, err = OpenReader(bytes.NewReader(oleIdentifier), Options{UnzipSizeLimit: 1, UnzipXMLSizeLimit: 2})
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.EqualError(t, err, ErrOptionsUnzipSizeLimit.Error())
|
2020-09-02 23:14:19 +08:00
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
// Test unexpected EOF.
|
|
|
|
var b bytes.Buffer
|
|
|
|
w := gzip.NewWriter(&b)
|
|
|
|
defer w.Close()
|
|
|
|
w.Flush()
|
|
|
|
|
|
|
|
r, _ := gzip.NewReader(&b)
|
|
|
|
defer r.Close()
|
|
|
|
|
|
|
|
_, err = OpenReader(r)
|
|
|
|
assert.EqualError(t, err, "unexpected EOF")
|
2020-05-23 13:29:51 +08:00
|
|
|
|
|
|
|
_, err = OpenReader(bytes.NewReader([]byte{
|
|
|
|
0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x09, 0x00, 0x63, 0x00, 0x47, 0xa3, 0xb6, 0x50, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x70, 0x61,
|
|
|
|
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x99, 0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00,
|
|
|
|
0x00, 0x21, 0x06, 0x59, 0xc0, 0x12, 0xf3, 0x19, 0xc7, 0x51, 0xd1, 0xc9, 0x31, 0xcb, 0xcc, 0x8a,
|
|
|
|
0xe1, 0x44, 0xe1, 0x56, 0x20, 0x24, 0x1f, 0xba, 0x09, 0xda, 0x53, 0xd5, 0xef, 0x50, 0x4b, 0x07,
|
|
|
|
0x08, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x01,
|
|
|
|
0x02, 0x1f, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x63, 0x00, 0x47, 0xa3, 0xb6, 0x50, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x73, 0x73, 0x77,
|
|
|
|
0x6f, 0x72, 0x64, 0x01, 0x99, 0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00, 0x50, 0x4b,
|
|
|
|
0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00, 0x5d, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
}))
|
|
|
|
assert.EqualError(t, err, "zip: unsupported compression algorithm")
|
2019-06-18 23:07:44 +08:00
|
|
|
}
|
|
|
|
|
2017-01-18 16:05:01 +08:00
|
|
|
func TestBrokenFile(t *testing.T) {
|
2016-10-19 18:42:29 +08:00
|
|
|
// Test write file with broken file struct.
|
2019-04-21 00:04:42 +08:00
|
|
|
f := File{}
|
2016-10-19 18:42:29 +08:00
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
t.Run("SaveWithoutName", func(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.Save(), "no path defined for file, consider File.WriteTo or File.Write")
|
2018-12-27 18:51:44 +08:00
|
|
|
})
|
2017-01-18 16:05:01 +08:00
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
t.Run("SaveAsEmptyStruct", func(t *testing.T) {
|
|
|
|
// Test write file with broken file struct with given path.
|
2020-10-04 21:07:39 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "BadWorkbook.SaveAsEmptyStruct.xlsx")))
|
2018-12-27 18:51:44 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("OpenBadWorkbook", func(t *testing.T) {
|
|
|
|
// Test set active sheet without BookViews and Sheets maps in xl/workbook.xml.
|
2018-12-27 22:28:28 +08:00
|
|
|
f3, err := OpenFile(filepath.Join("test", "BadWorkbook.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
f3.GetActiveSheetIndex()
|
2020-04-23 02:01:14 +08:00
|
|
|
f3.SetActiveSheet(1)
|
2018-12-27 18:51:44 +08:00
|
|
|
assert.NoError(t, err)
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f3.Close())
|
2018-12-27 18:51:44 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("OpenNotExistsFile", func(t *testing.T) {
|
2020-07-09 01:24:11 +08:00
|
|
|
// Test open a spreadsheet file with given illegal path.
|
2018-12-27 22:28:28 +08:00
|
|
|
_, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if assert.Error(t, err) {
|
|
|
|
assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
|
|
|
|
}
|
|
|
|
})
|
2017-01-18 16:05:01 +08:00
|
|
|
}
|
|
|
|
|
2017-06-28 17:03:20 +08:00
|
|
|
func TestNewFile(t *testing.T) {
|
2020-07-09 01:24:11 +08:00
|
|
|
// Test create a spreadsheet file.
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
|
|
|
f.NewSheet("Sheet1")
|
|
|
|
f.NewSheet("XLSXSheet2")
|
|
|
|
f.NewSheet("XLSXSheet3")
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellInt("XLSXSheet2", "A23", 56))
|
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "B20", "42"))
|
2019-04-21 00:04:42 +08:00
|
|
|
f.SetActiveSheet(0)
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2018-04-26 11:41:13 +08:00
|
|
|
// Test add picture to sheet with scaling and positioning.
|
2019-04-21 00:04:42 +08:00
|
|
|
err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
|
2018-12-27 22:28:28 +08:00
|
|
|
`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2016-08-30 11:51:31 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2018-09-14 00:24:49 +08:00
|
|
|
// Test add picture to worksheet without formatset.
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2018-09-14 00:24:49 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2018-09-14 00:24:49 +08:00
|
|
|
// Test add picture to worksheet with invalid formatset.
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), `{`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.Error(t, err) {
|
|
|
|
t.FailNow()
|
2016-09-06 21:20:24 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewFile.xlsx")))
|
2021-07-09 00:04:58 +08:00
|
|
|
assert.NoError(t, f.Save())
|
2016-08-30 11:51:31 +08:00
|
|
|
}
|
2017-01-18 14:47:23 +08:00
|
|
|
|
2019-03-24 13:08:32 +08:00
|
|
|
func TestAddDrawingVML(t *testing.T) {
|
|
|
|
// Test addDrawingVML with illegal cell coordinates.
|
|
|
|
f := NewFile()
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, f.addDrawingVML(0, "", "*", 0, 0), newCellNameToCoordinatesError("*", newInvalidCellNameError("*")).Error())
|
2019-03-24 13:08:32 +08:00
|
|
|
}
|
|
|
|
|
2017-01-19 14:05:32 +08:00
|
|
|
func TestSetCellHyperLink(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2017-01-19 14:05:32 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
// Test set cell hyperlink in a work sheet already have hyperlinks.
|
2021-07-28 00:38:09 +08:00
|
|
|
assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/xuri/excelize", "External"))
|
2017-01-19 14:05:32 +08:00
|
|
|
// Test add first hyperlink in a work sheet.
|
2021-07-28 00:38:09 +08:00
|
|
|
assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/xuri/excelize", "External"))
|
2017-07-30 15:46:04 +08:00
|
|
|
// Test add Location hyperlink in a work sheet.
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
|
2021-03-03 20:30:31 +08:00
|
|
|
// Test add Location hyperlink with display & tooltip in a work sheet.
|
|
|
|
display := "Display value"
|
|
|
|
tooltip := "Hover text"
|
|
|
|
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D7", "Sheet1!D9", "Location", HyperlinkOpts{
|
|
|
|
Display: &display,
|
|
|
|
Tooltip: &tooltip,
|
|
|
|
}))
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.SetCellHyperLink("Sheet2", "C3", "Sheet1!D8", ""), `invalid link type ""`)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.SetCellHyperLink("Sheet2", "", "Sheet1!D60", "Location"), `invalid cell name ""`)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx")))
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2019-04-21 00:04:42 +08:00
|
|
|
|
2019-12-23 00:07:40 +08:00
|
|
|
f = NewFile()
|
2019-12-24 01:09:28 +08:00
|
|
|
_, err = f.workSheetReader("Sheet1")
|
|
|
|
assert.NoError(t, err)
|
2021-07-05 00:03:56 +08:00
|
|
|
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
|
|
|
assert.True(t, ok)
|
|
|
|
ws.(*xlsxWorksheet).Hyperlinks = &xlsxHyperlinks{Hyperlink: make([]xlsxHyperlink, 65530)}
|
2021-07-28 00:38:09 +08:00
|
|
|
assert.EqualError(t, f.SetCellHyperLink("Sheet1", "A65531", "https://github.com/xuri/excelize", "External"), ErrTotalSheetHyperlinks.Error())
|
2019-12-14 19:57:37 +08:00
|
|
|
|
|
|
|
f = NewFile()
|
2019-12-24 01:09:28 +08:00
|
|
|
_, err = f.workSheetReader("Sheet1")
|
|
|
|
assert.NoError(t, err)
|
2021-07-05 00:03:56 +08:00
|
|
|
ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml")
|
|
|
|
assert.True(t, ok)
|
|
|
|
ws.(*xlsxWorksheet).MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
|
2021-07-28 00:38:09 +08:00
|
|
|
err = f.SetCellHyperLink("Sheet1", "A1", "https://github.com/xuri/excelize", "External")
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
2017-01-19 14:05:32 +08:00
|
|
|
}
|
|
|
|
|
2017-08-08 20:08:54 +08:00
|
|
|
func TestGetCellHyperLink(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-08-08 20:08:54 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
_, _, err = f.GetCellHyperLink("Sheet1", "")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.EqualError(t, err, `invalid cell name ""`)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
link, target, err := f.GetCellHyperLink("Sheet1", "A22")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
2017-08-08 20:08:54 +08:00
|
|
|
t.Log(link, target)
|
2019-04-21 00:04:42 +08:00
|
|
|
link, target, err = f.GetCellHyperLink("Sheet2", "D6")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
2017-08-08 20:08:54 +08:00
|
|
|
t.Log(link, target)
|
2019-04-21 00:04:42 +08:00
|
|
|
link, target, err = f.GetCellHyperLink("Sheet3", "H3")
|
2019-04-16 10:57:21 +08:00
|
|
|
assert.EqualError(t, err, "sheet Sheet3 is not exist")
|
2017-08-08 20:08:54 +08:00
|
|
|
t.Log(link, target)
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2019-12-14 19:57:37 +08:00
|
|
|
|
|
|
|
f = NewFile()
|
2019-12-24 01:09:28 +08:00
|
|
|
_, err = f.workSheetReader("Sheet1")
|
|
|
|
assert.NoError(t, err)
|
2021-07-05 00:03:56 +08:00
|
|
|
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
|
|
|
assert.True(t, ok)
|
|
|
|
ws.(*xlsxWorksheet).Hyperlinks = &xlsxHyperlinks{
|
2019-12-14 19:57:37 +08:00
|
|
|
Hyperlink: []xlsxHyperlink{{Ref: "A1"}},
|
|
|
|
}
|
|
|
|
link, target, err = f.GetCellHyperLink("Sheet1", "A1")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, link, true)
|
|
|
|
assert.Equal(t, target, "")
|
|
|
|
|
2021-07-05 00:03:56 +08:00
|
|
|
ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml")
|
|
|
|
assert.True(t, ok)
|
|
|
|
ws.(*xlsxWorksheet).MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
|
2019-12-14 19:57:37 +08:00
|
|
|
link, target, err = f.GetCellHyperLink("Sheet1", "A1")
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
2019-12-14 19:57:37 +08:00
|
|
|
assert.Equal(t, link, false)
|
|
|
|
assert.Equal(t, target, "")
|
2017-08-08 20:08:54 +08:00
|
|
|
}
|
|
|
|
|
2017-01-24 18:29:02 +08:00
|
|
|
func TestSetSheetBackground(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-01-24 18:29:02 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-01-24 18:29:02 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-01-24 18:29:02 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetBackground.xlsx")))
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2018-12-27 18:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetSheetBackgroundErrors(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-01-24 18:29:02 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.SetSheetBackground("Sheet2", filepath.Join("test", "not_exists", "not_exists.png"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if assert.Error(t, err) {
|
|
|
|
assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.SetSheetBackground("Sheet2", filepath.Join("test", "Book1.xlsx"))
|
2021-05-10 00:09:24 +08:00
|
|
|
assert.EqualError(t, err, ErrImgExt.Error())
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2017-01-24 18:29:02 +08:00
|
|
|
}
|
2017-01-25 15:44:18 +08:00
|
|
|
|
2019-09-22 20:52:01 +08:00
|
|
|
// TestWriteArrayFormula tests the extended options of SetCellFormula by writing an array function
|
|
|
|
// to a workbook. In the resulting file, the lines 2 and 3 as well as 4 and 5 should have matching
|
|
|
|
// contents.
|
|
|
|
func TestWriteArrayFormula(t *testing.T) {
|
|
|
|
cell := func(col, row int) string {
|
|
|
|
c, err := CoordinatesToCellName(col, row)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
f := NewFile()
|
|
|
|
|
|
|
|
sample := []string{"Sample 1", "Sample 2", "Sample 3"}
|
|
|
|
values := []int{1855, 1709, 1462, 1115, 1524, 625, 773, 126, 1027, 1696, 1078, 1917, 1109, 1753, 1884, 659, 994, 1911, 1925, 899, 196, 244, 1488, 1056, 1986, 66, 784, 725, 767, 1722, 1541, 1026, 1455, 264, 1538, 877, 1581, 1098, 383, 762, 237, 493, 29, 1923, 474, 430, 585, 688, 308, 200, 1259, 622, 798, 1048, 996, 601, 582, 332, 377, 805, 250, 1860, 1360, 840, 911, 1346, 1651, 1651, 665, 584, 1057, 1145, 925, 1752, 202, 149, 1917, 1398, 1894, 818, 714, 624, 1085, 1566, 635, 78, 313, 1686, 1820, 494, 614, 1913, 271, 1016, 338, 1301, 489, 1733, 1483, 1141}
|
|
|
|
assoc := []int{2, 0, 0, 0, 0, 1, 1, 0, 0, 1, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 2, 0, 2, 1, 2, 2, 2, 1, 0, 1, 0, 1, 1, 2, 0, 2, 1, 0, 2, 1, 0, 1, 0, 0, 2, 0, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 0, 1, 0, 2, 0, 0, 1, 2, 1, 0, 1, 0, 0, 2, 1, 1, 2, 0, 2, 1, 0, 2, 2, 2, 1, 0, 0, 1, 1, 1, 2, 0, 2, 0, 1, 1}
|
|
|
|
if len(values) != len(assoc) {
|
|
|
|
t.Fatal("values and assoc must be of same length")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Average calculates the average of the n-th sample (0 <= n < len(sample)).
|
|
|
|
average := func(n int) int {
|
|
|
|
sum := 0
|
|
|
|
count := 0
|
|
|
|
for i := 0; i != len(values); i++ {
|
|
|
|
if assoc[i] == n {
|
|
|
|
sum += values[i]
|
|
|
|
count++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return int(math.Round(float64(sum) / float64(count)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stdev calculates the standard deviation of the n-th sample (0 <= n < len(sample)).
|
|
|
|
stdev := func(n int) int {
|
|
|
|
avg := average(n)
|
|
|
|
|
|
|
|
sum := 0
|
|
|
|
count := 0
|
|
|
|
for i := 0; i != len(values); i++ {
|
|
|
|
if assoc[i] == n {
|
|
|
|
sum += (values[i] - avg) * (values[i] - avg)
|
|
|
|
count++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return int(math.Round(math.Sqrt(float64(sum) / float64(count))))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Line 2 contains the results of AVERAGEIF
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "A2", "Average"))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
// Line 3 contains the average that was calculated in Go
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "A3", "Average (calculated)"))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
// Line 4 contains the results of the array function that calculates the standard deviation
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "A4", "Std. deviation"))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
// Line 5 contains the standard deviations calculated in Go
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "A5", "Std. deviation (calculated)"))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "B1", sample[0]))
|
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "C1", sample[1]))
|
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", "D1", sample[2]))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
firstResLine := 8
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", cell(1, firstResLine-1), "Result Values"))
|
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", cell(2, firstResLine-1), "Sample"))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
for i := 0; i != len(values); i++ {
|
|
|
|
valCell := cell(1, i+firstResLine)
|
|
|
|
assocCell := cell(2, i+firstResLine)
|
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellInt("Sheet1", valCell, values[i]))
|
|
|
|
assert.NoError(t, f.SetCellStr("Sheet1", assocCell, sample[assoc[i]]))
|
2019-09-22 20:52:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
valRange := fmt.Sprintf("$A$%d:$A$%d", firstResLine, len(values)+firstResLine-1)
|
|
|
|
assocRange := fmt.Sprintf("$B$%d:$B$%d", firstResLine, len(values)+firstResLine-1)
|
|
|
|
|
|
|
|
for i := 0; i != len(sample); i++ {
|
|
|
|
nameCell := cell(i+2, 1)
|
|
|
|
avgCell := cell(i+2, 2)
|
|
|
|
calcAvgCell := cell(i+2, 3)
|
|
|
|
stdevCell := cell(i+2, 4)
|
|
|
|
calcStdevCell := cell(i+2, 5)
|
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellInt("Sheet1", calcAvgCell, average(i)))
|
|
|
|
assert.NoError(t, f.SetCellInt("Sheet1", calcStdevCell, stdev(i)))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
// Average can be done with AVERAGEIF
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellFormula("Sheet1", avgCell, fmt.Sprintf("ROUND(AVERAGEIF(%s,%s,%s),0)", assocRange, nameCell, valRange)))
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
ref := stdevCell + ":" + stdevCell
|
2021-02-15 00:09:35 +08:00
|
|
|
arr := STCellFormulaTypeArray
|
2019-09-22 20:52:01 +08:00
|
|
|
// Use an array formula for standard deviation
|
2021-02-15 00:09:35 +08:00
|
|
|
assert.NoError(t, f.SetCellFormula("Sheet1", stdevCell, fmt.Sprintf("ROUND(STDEVP(IF(%s=%s,%s)),0)", assocRange, nameCell, valRange),
|
|
|
|
FormulaOpts{}, FormulaOpts{Type: &arr}, FormulaOpts{Ref: &ref}))
|
2019-09-22 20:52:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestWriteArrayFormula.xlsx")))
|
|
|
|
}
|
|
|
|
|
2017-03-26 15:27:04 +08:00
|
|
|
func TestSetCellStyleAlignment(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-26 15:27:04 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2017-06-29 19:41:00 +08:00
|
|
|
var style int
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"alignment":{"horizontal":"center","ident":1,"justify_last_line":true,"reading_order":0,"relative_indent":1,"shrink_to_fit":true,"text_rotation":45,"vertical":"top","wrap_text":true}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-06-29 19:41:00 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A22", "A22", style))
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2017-09-19 11:59:33 +08:00
|
|
|
// Test set cell style with given illegal rows number.
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, f.SetCellStyle("Sheet1", "A", "A22", style), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
|
|
|
assert.EqualError(t, f.SetCellStyle("Sheet1", "A22", "A", style), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2017-09-19 11:59:33 +08:00
|
|
|
// Test get cell style with given illegal rows number.
|
2019-04-21 00:04:42 +08:00
|
|
|
index, err := f.GetCellStyle("Sheet1", "A")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.Equal(t, 0, index)
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleAlignment.xlsx")))
|
2017-03-26 15:27:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetCellStyleBorder(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-06 12:05:41 +08:00
|
|
|
}
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
var style int
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2017-03-19 17:14:40 +08:00
|
|
|
// Test set border on overlapping area with vertical variants shading styles gradient fill.
|
2021-12-25 21:51:09 +08:00
|
|
|
style, err = f.NewStyle(&Style{
|
|
|
|
Border: []Border{
|
|
|
|
{Type: "left", Color: "0000FF", Style: 3},
|
|
|
|
{Type: "top", Color: "00FF00", Style: 4},
|
|
|
|
{Type: "bottom", Color: "FFFF00", Style: 5},
|
|
|
|
{Type: "right", Color: "FF0000", Style: 6},
|
|
|
|
{Type: "diagonalDown", Color: "A020F0", Style: 7},
|
|
|
|
{Type: "diagonalUp", Color: "A020F0", Style: 8},
|
|
|
|
},
|
|
|
|
})
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-06 12:05:41 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "J21", "L25", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-06 12:05:41 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":4}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-06-29 19:41:00 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2017-03-19 17:14:40 +08:00
|
|
|
// Test set border and solid style pattern fill for a single cell.
|
2020-03-10 00:04:23 +08:00
|
|
|
style, err = f.NewStyle(&Style{
|
|
|
|
Border: []Border{
|
|
|
|
{
|
|
|
|
Type: "left",
|
|
|
|
Color: "0000FF",
|
|
|
|
Style: 8,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: "top",
|
|
|
|
Color: "00FF00",
|
|
|
|
Style: 9,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: "bottom",
|
|
|
|
Color: "FFFF00",
|
|
|
|
Style: 10,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: "right",
|
|
|
|
Color: "FF0000",
|
|
|
|
Style: 11,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: "diagonalDown",
|
|
|
|
Color: "A020F0",
|
|
|
|
Style: 12,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: "diagonalUp",
|
|
|
|
Color: "A020F0",
|
|
|
|
Style: 13,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Fill: Fill{
|
|
|
|
Type: "pattern",
|
|
|
|
Color: []string{"#E0EBF5"},
|
|
|
|
Pattern: 1,
|
|
|
|
},
|
|
|
|
})
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-19 17:14:40 +08:00
|
|
|
}
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "O22", "O22", style))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleBorder.xlsx")))
|
2018-12-27 18:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetCellStyleBorderErrors(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set border with invalid style parameter.
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.NewStyle("")
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.EqualError(t, err, "unexpected end of JSON input") {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set border with invalid style index number.
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":-1},{"type":"top","color":"00FF00","style":14},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":9},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-19 17:14:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-05 14:40:28 +08:00
|
|
|
func TestSetCellStyleNumberFormat(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-19 17:14:40 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2017-04-07 17:32:14 +08:00
|
|
|
// Test only set fill and number format for a cell.
|
2017-05-05 14:40:28 +08:00
|
|
|
col := []string{"L", "M", "N", "O", "P"}
|
|
|
|
data := []int{0, 1, 2, 3, 4, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
|
|
|
|
value := []string{"37947.7500001", "-37947.7500001", "0.007", "2.1", "String"}
|
|
|
|
for i, v := range value {
|
|
|
|
for k, d := range data {
|
|
|
|
c := col[i] + strconv.Itoa(k+1)
|
|
|
|
var val float64
|
|
|
|
val, err = strconv.ParseFloat(v, 64)
|
|
|
|
if err != nil {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", c, v))
|
2017-05-05 14:40:28 +08:00
|
|
|
} else {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet2", c, val))
|
2017-05-05 14:40:28 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format": ` + strconv.Itoa(d) + `}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-05-05 14:40:28 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", c, c, style))
|
|
|
|
t.Log(f.GetCellValue("Sheet2", c))
|
2017-05-05 14:40:28 +08:00
|
|
|
}
|
|
|
|
}
|
2017-06-29 19:41:00 +08:00
|
|
|
var style int
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"number_format":-1}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-06-29 19:41:00 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", "L33", "L33", style))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleNumberFormat.xlsx")))
|
2017-05-05 14:40:28 +08:00
|
|
|
}
|
|
|
|
|
2017-07-14 21:15:44 +08:00
|
|
|
func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
|
2018-12-27 18:51:44 +08:00
|
|
|
t.Run("TestBook3", func(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook3()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2017-07-14 21:15:44 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", "A1", 56))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", "A2", -32.3))
|
2018-12-27 18:51:44 +08:00
|
|
|
var style int
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"number_format": 188, "decimal_places": -1}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2017-07-14 21:15:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
|
|
|
|
style, err = f.NewStyle(`{"number_format": 188, "decimal_places": 31, "negred": true}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2017-07-14 21:15:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
|
2017-07-14 21:15:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook3.xlsx")))
|
2018-12-27 18:51:44 +08:00
|
|
|
})
|
2017-07-14 21:15:44 +08:00
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
t.Run("TestBook4", func(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook4()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err := f.NewStyle(`{"number_format": 27}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
|
|
|
|
style, err = f.NewStyle(`{"number_format": 31, "lang": "ko-kr"}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"number_format": 71, "lang": "th-th"}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook4.xlsx")))
|
2018-12-27 18:51:44 +08:00
|
|
|
})
|
2017-07-14 21:15:44 +08:00
|
|
|
}
|
|
|
|
|
2017-07-27 11:46:04 +08:00
|
|
|
func TestSetCellStyleCustomNumberFormat(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5))
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5))
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err := f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
|
2020-05-24 20:20:22 +08:00
|
|
|
assert.NoError(t, err)
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
|
2020-05-24 20:20:22 +08:00
|
|
|
style, err = f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@","font":{"color":"#9A0511"}}`)
|
|
|
|
assert.NoError(t, err)
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2020-05-24 20:20:22 +08:00
|
|
|
_, err = f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yy;@"}`)
|
|
|
|
assert.NoError(t, err)
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCustomNumberFormat.xlsx")))
|
2017-07-27 11:46:04 +08:00
|
|
|
}
|
|
|
|
|
2017-05-05 14:40:28 +08:00
|
|
|
func TestSetCellStyleFill(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-19 17:14:40 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2017-06-29 19:41:00 +08:00
|
|
|
var style int
|
2017-03-19 17:14:40 +08:00
|
|
|
// Test set fill for cell with invalid parameter.
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":6}}`)
|
2020-05-24 20:20:22 +08:00
|
|
|
assert.NoError(t, err)
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF"],"shading":1}}`)
|
2020-05-24 20:20:22 +08:00
|
|
|
assert.NoError(t, err)
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"fill":{"type":"pattern","color":[],"pattern":1}}`)
|
2020-05-24 20:20:22 +08:00
|
|
|
assert.NoError(t, err)
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
|
2017-04-07 17:32:14 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":19}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-03-06 12:05:41 +08:00
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFill.xlsx")))
|
2017-04-25 18:43:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetCellStyleFont(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-25 18:43:10 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2017-06-29 19:41:00 +08:00
|
|
|
var style int
|
2019-08-21 23:03:34 +08:00
|
|
|
style, err = f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-25 18:43:10 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", "A1", "A1", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"font":{"italic":true,"underline":"double"}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-25 18:43:10 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", "A2", "A2", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"font":{"bold":true}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-25 18:43:10 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", "A3", "A3", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"font":{"bold":true,"family":"","size":0,"color":"","underline":""}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-25 18:43:10 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", "A4", "A4", style))
|
2017-06-29 19:41:00 +08:00
|
|
|
|
2019-09-23 21:50:03 +08:00
|
|
|
style, err = f.NewStyle(`{"font":{"color":"#777777","strike":true}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-25 18:43:10 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", "A5", "A5", style))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFont.xlsx")))
|
2017-03-06 12:05:41 +08:00
|
|
|
}
|
2017-03-22 18:51:18 +08:00
|
|
|
|
2018-03-07 12:56:18 +08:00
|
|
|
func TestSetCellStyleProtection(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2018-03-07 12:56:18 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2018-03-07 12:56:18 +08:00
|
|
|
var style int
|
2019-04-21 00:04:42 +08:00
|
|
|
style, err = f.NewStyle(`{"protection":{"hidden":true, "locked":true}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2018-03-07 12:56:18 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SetCellStyle("Sheet2", "A6", "A6", style))
|
|
|
|
err = f.SaveAs(filepath.Join("test", "TestSetCellStyleProtection.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2018-03-07 12:56:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
func TestSetDeleteSheet(t *testing.T) {
|
|
|
|
t.Run("TestBook3", func(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook3()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
f.DeleteSheet("XLSXSheet3")
|
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook3.xlsx")))
|
2018-12-27 18:51:44 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("TestBook4", func(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook4()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
f.DeleteSheet("Sheet1")
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.EqualError(t, f.AddComment("Sheet1", "A1", ""), "unexpected end of JSON input")
|
|
|
|
assert.NoError(t, f.AddComment("Sheet1", "A1", `{"author":"Excelize: ","text":"This is a comment."}`))
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook4.xlsx")))
|
2018-12-27 18:51:44 +08:00
|
|
|
})
|
2017-03-22 18:51:18 +08:00
|
|
|
}
|
2017-03-28 21:18:06 +08:00
|
|
|
|
2017-04-26 11:43:39 +08:00
|
|
|
func TestSheetVisibility(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-26 11:43:39 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetSheetVisible("Sheet2", false))
|
|
|
|
assert.NoError(t, f.SetSheetVisible("Sheet1", false))
|
|
|
|
assert.NoError(t, f.SetSheetVisible("Sheet1", true))
|
|
|
|
assert.Equal(t, true, f.GetSheetVisible("Sheet1"))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSheetVisibility.xlsx")))
|
2017-04-26 11:43:39 +08:00
|
|
|
}
|
|
|
|
|
2017-04-04 19:12:35 +08:00
|
|
|
func TestCopySheet(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-04-04 19:12:35 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
idx := f.NewSheet("CopySheet")
|
2020-04-23 02:01:14 +08:00
|
|
|
assert.NoError(t, f.CopySheet(0, idx))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("CopySheet", "F1", "Hello"))
|
2019-04-21 00:04:42 +08:00
|
|
|
val, err := f.GetCellValue("Sheet1", "F1")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotEqual(t, "Hello", val)
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheet.xlsx")))
|
2018-12-27 18:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCopySheetError(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := prepareTestBook1()
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-08-19 13:37:15 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2020-04-23 02:01:14 +08:00
|
|
|
assert.EqualError(t, f.copySheet(-1, -2), "sheet is not exist")
|
|
|
|
if !assert.EqualError(t, f.CopySheet(-1, -2), "invalid worksheet index") {
|
2018-12-27 18:51:44 +08:00
|
|
|
t.FailNow()
|
2017-04-04 19:12:35 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx")))
|
2017-04-04 19:12:35 +08:00
|
|
|
}
|
2017-04-23 00:10:23 +08:00
|
|
|
|
2019-03-24 13:08:32 +08:00
|
|
|
func TestGetSheetComments(t *testing.T) {
|
|
|
|
f := NewFile()
|
2020-03-31 00:02:00 +08:00
|
|
|
assert.Equal(t, "", f.getSheetComments("sheet0"))
|
2019-03-24 13:08:32 +08:00
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
func TestSetSheetVisible(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
f.WorkBook.Sheets.Sheet[0].Name = "SheetN"
|
|
|
|
assert.EqualError(t, f.SetSheetVisible("Sheet1", false), "sheet SheetN is not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetActiveSheetIndex(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
f.WorkBook.BookViews = nil
|
2020-04-23 02:01:14 +08:00
|
|
|
assert.Equal(t, 0, f.GetActiveSheetIndex())
|
2019-12-22 00:02:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestRelsWriter(t *testing.T) {
|
|
|
|
f := NewFile()
|
2021-07-04 12:13:06 +08:00
|
|
|
f.Relationships.Store("xl/worksheets/sheet/rels/sheet1.xml.rel", &xlsxRelationships{})
|
2019-12-22 00:02:09 +08:00
|
|
|
f.relsWriter()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetSheetView(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
2019-12-22 00:02:09 +08:00
|
|
|
_, err := f.getSheetView("SheetN", 0)
|
|
|
|
assert.EqualError(t, err, "sheet SheetN is not exist")
|
2017-07-30 12:40:59 +08:00
|
|
|
}
|
|
|
|
|
2017-08-11 23:15:33 +08:00
|
|
|
func TestConditionalFormat(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
2020-04-23 02:01:14 +08:00
|
|
|
sheet1 := f.GetSheetName(0)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
fillCells(f, sheet1, 10, 15)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2020-03-16 00:13:01 +08:00
|
|
|
var format1, format2, format3, format4 int
|
2017-08-11 23:15:33 +08:00
|
|
|
var err error
|
|
|
|
// Rose format for bad conditional.
|
2019-04-21 00:04:42 +08:00
|
|
|
format1, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2017-08-11 23:15:33 +08:00
|
|
|
// Light yellow format for neutral conditional.
|
2019-04-21 00:04:42 +08:00
|
|
|
format2, err = f.NewConditionalStyle(`{"fill":{"type":"pattern","color":["#FEEAA0"],"pattern":1}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2017-08-11 23:15:33 +08:00
|
|
|
// Light green format for good conditional.
|
2019-04-21 00:04:42 +08:00
|
|
|
format3, err = f.NewConditionalStyle(`{"font":{"color":"#09600B"},"fill":{"type":"pattern","color":["#C7EECF"],"pattern":1}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2020-03-16 00:13:01 +08:00
|
|
|
// conditional style with align and left border.
|
|
|
|
format4, err = f.NewConditionalStyle(`{"alignment":{"wrap_text":true},"border":[{"type":"left","color":"#000000","style":1}]}`)
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2017-08-11 23:15:33 +08:00
|
|
|
// Color scales: 2 color.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "A1:A10", `[{"type":"2_color_scale","criteria":"=","min_type":"min","max_type":"max","min_color":"#F8696B","max_color":"#63BE7B"}]`))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Color scales: 3 color.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "B1:B10", `[{"type":"3_color_scale","criteria":"=","min_type":"min","mid_type":"percentile","max_type":"max","min_color":"#F8696B","mid_color":"#FFEB84","max_color":"#63BE7B"}]`))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Hightlight cells rules: between...
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Hightlight cells rules: Greater Than...
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format3)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Hightlight cells rules: Equal To...
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "E1:E10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d}]`, format3)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Hightlight cells rules: Not Equal To...
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format2)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Hightlight cells rules: Duplicate Values...
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format2)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Top/Bottom rules: Top 10%.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Top/Bottom rules: Above Average...
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Top/Bottom rules: Below Average...
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1)))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Data Bars: Gradient Fill.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
|
2017-08-18 20:55:27 +08:00
|
|
|
// Use a formula to determine which cells to format.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1)))
|
2020-03-16 00:13:01 +08:00
|
|
|
// Alignment/Border cells rules.
|
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "M1:M10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"0"}]`, format4)))
|
|
|
|
|
|
|
|
// Test set invalid format set in conditional format.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.EqualError(t, f.SetConditionalFormat(sheet1, "L1:L10", ""), "unexpected end of JSON input")
|
2020-03-16 00:13:01 +08:00
|
|
|
// Set conditional format on not exists worksheet.
|
|
|
|
assert.EqualError(t, f.SetConditionalFormat("SheetN", "L1:L10", "[]"), "sheet SheetN is not exist")
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2017-08-11 23:15:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set conditional format with illegal valid type.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
|
2017-08-11 23:15:33 +08:00
|
|
|
// Set conditional format with illegal criteria type.
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2022-01-09 00:20:42 +08:00
|
|
|
// Set conditional format with file without dxfs element should not return error.
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err = OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2017-08-11 23:15:33 +08:00
|
|
|
}
|
2017-09-06 13:15:25 +08:00
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
func TestConditionalFormatError(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
2020-04-23 02:01:14 +08:00
|
|
|
sheet1 := f.GetSheetName(0)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
fillCells(f, sheet1, 10, 15)
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2020-03-16 00:13:01 +08:00
|
|
|
// Set conditional format with illegal JSON string should return error.
|
2019-04-21 00:04:42 +08:00
|
|
|
_, err := f.NewConditionalStyle("")
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.EqualError(t, err, "unexpected end of JSON input") {
|
|
|
|
t.FailNow()
|
2017-09-06 13:15:25 +08:00
|
|
|
}
|
|
|
|
}
|
2018-03-02 10:19:40 +08:00
|
|
|
|
|
|
|
func TestSharedStrings(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2018-03-02 10:19:40 +08:00
|
|
|
}
|
2019-08-07 05:43:56 +08:00
|
|
|
rows, err := f.GetRows("Sheet1")
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
assert.Equal(t, "A", rows[0][0])
|
2019-08-08 05:26:13 +08:00
|
|
|
rows, err = f.GetRows("Sheet2")
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
assert.Equal(t, "Test Weight (Kgs)", rows[0][0])
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2018-03-02 10:19:40 +08:00
|
|
|
}
|
2018-03-12 20:14:39 +08:00
|
|
|
|
|
|
|
func TestSetSheetRow(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2018-03-12 20:14:39 +08:00
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetSheetRow("Sheet1", "B27", &[]interface{}{"cell", nil, int32(42), float64(42), time.Now().UTC()}))
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.SetSheetRow("Sheet1", "", &[]interface{}{"cell", nil, 2}),
|
2021-12-07 00:26:53 +08:00
|
|
|
newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2021-07-05 00:03:56 +08:00
|
|
|
assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", []interface{}{}), ErrParameterInvalid.Error())
|
|
|
|
assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", &f), ErrParameterInvalid.Error())
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetRow.xlsx")))
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2018-03-12 20:14:39 +08:00
|
|
|
}
|
2018-05-07 16:14:35 +08:00
|
|
|
|
2018-07-07 15:59:48 +08:00
|
|
|
func TestHSL(t *testing.T) {
|
|
|
|
var hsl HSL
|
2020-10-23 00:01:52 +08:00
|
|
|
r, g, b, a := hsl.RGBA()
|
|
|
|
assert.Equal(t, uint32(0), r)
|
|
|
|
assert.Equal(t, uint32(0), g)
|
|
|
|
assert.Equal(t, uint32(0), b)
|
|
|
|
assert.Equal(t, uint32(0xffff), a)
|
|
|
|
assert.Equal(t, HSL{0, 0, 0}, hslModel(hsl))
|
|
|
|
assert.Equal(t, HSL{0, 0, 0}, hslModel(color.Gray16{Y: uint16(1)}))
|
|
|
|
R, G, B := HSLToRGB(0, 1, 0.4)
|
|
|
|
assert.Equal(t, uint8(204), R)
|
|
|
|
assert.Equal(t, uint8(0), G)
|
|
|
|
assert.Equal(t, uint8(0), B)
|
|
|
|
R, G, B = HSLToRGB(0, 1, 0.6)
|
|
|
|
assert.Equal(t, uint8(255), R)
|
|
|
|
assert.Equal(t, uint8(51), G)
|
|
|
|
assert.Equal(t, uint8(51), B)
|
|
|
|
assert.Equal(t, 0.0, hueToRGB(0, 0, -1))
|
|
|
|
assert.Equal(t, 0.0, hueToRGB(0, 0, 2))
|
|
|
|
assert.Equal(t, 0.0, hueToRGB(0, 0, 1.0/7))
|
|
|
|
assert.Equal(t, 0.0, hueToRGB(0, 0, 0.4))
|
|
|
|
assert.Equal(t, 0.0, hueToRGB(0, 0, 2.0/4))
|
2018-07-07 15:59:48 +08:00
|
|
|
t.Log(RGBToHSL(255, 255, 0))
|
2020-10-23 00:01:52 +08:00
|
|
|
h, s, l := RGBToHSL(0, 255, 255)
|
|
|
|
assert.Equal(t, float64(0.5), h)
|
|
|
|
assert.Equal(t, float64(1), s)
|
|
|
|
assert.Equal(t, float64(0.5), l)
|
2018-07-07 15:59:48 +08:00
|
|
|
t.Log(RGBToHSL(250, 100, 50))
|
|
|
|
t.Log(RGBToHSL(50, 100, 250))
|
|
|
|
t.Log(RGBToHSL(250, 50, 100))
|
|
|
|
}
|
|
|
|
|
2018-11-02 23:08:31 +08:00
|
|
|
func TestProtectSheet(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
2022-01-08 10:32:13 +08:00
|
|
|
sheetName := f.GetSheetName(0)
|
|
|
|
assert.NoError(t, f.ProtectSheet(sheetName, nil))
|
|
|
|
// Test protect worksheet with XOR hash algorithm
|
|
|
|
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
2018-11-02 23:08:31 +08:00
|
|
|
Password: "password",
|
|
|
|
EditScenarios: false,
|
2019-12-24 01:09:28 +08:00
|
|
|
}))
|
2022-01-08 10:32:13 +08:00
|
|
|
ws, err := f.workSheetReader(sheetName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "83AF", ws.SheetProtection.Password)
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx")))
|
2022-01-08 10:32:13 +08:00
|
|
|
// Test protect worksheet with SHA-512 hash algorithm
|
|
|
|
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
|
|
|
AlgorithmName: "SHA-512",
|
|
|
|
Password: "password",
|
|
|
|
}))
|
|
|
|
ws, err = f.workSheetReader(sheetName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, 24, len(ws.SheetProtection.SaltValue))
|
|
|
|
assert.Equal(t, 88, len(ws.SheetProtection.HashValue))
|
|
|
|
assert.Equal(t, int(sheetProtectionSpinCount), ws.SheetProtection.SpinCount)
|
|
|
|
// Test remove sheet protection with an incorrect password
|
|
|
|
assert.EqualError(t, f.UnprotectSheet(sheetName, "wrongPassword"), ErrUnprotectSheetPassword.Error())
|
|
|
|
// Test remove sheet protection with password verification
|
|
|
|
assert.NoError(t, f.UnprotectSheet(sheetName, "password"))
|
|
|
|
// Test protect worksheet with empty password
|
|
|
|
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{}))
|
|
|
|
assert.Equal(t, "", ws.SheetProtection.Password)
|
|
|
|
// Test protect worksheet with password exceeds the limit length
|
|
|
|
assert.EqualError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
|
|
|
AlgorithmName: "MD4",
|
|
|
|
Password: strings.Repeat("s", MaxFieldLength+1),
|
|
|
|
}), ErrPasswordLengthInvalid.Error())
|
|
|
|
// Test protect worksheet with unsupported hash algorithm
|
|
|
|
assert.EqualError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
|
|
|
AlgorithmName: "RIPEMD-160",
|
|
|
|
Password: "password",
|
|
|
|
}), ErrUnsupportedHashAlgorithm.Error())
|
2019-04-16 10:57:21 +08:00
|
|
|
// Test protect not exists worksheet.
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.ProtectSheet("SheetN", nil), "sheet SheetN is not exist")
|
2018-11-02 23:08:31 +08:00
|
|
|
}
|
|
|
|
|
2018-11-04 23:14:43 +08:00
|
|
|
func TestUnprotectSheet(t *testing.T) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
2018-11-04 23:14:43 +08:00
|
|
|
}
|
2022-01-08 10:32:13 +08:00
|
|
|
// Test remove protection on not exists worksheet.
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.EqualError(t, f.UnprotectSheet("SheetN"), "sheet SheetN is not exist")
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.UnprotectSheet("Sheet1"))
|
2022-01-08 10:32:13 +08:00
|
|
|
assert.EqualError(t, f.UnprotectSheet("Sheet1", "password"), ErrUnprotectSheet.Error())
|
2019-04-21 00:04:42 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnprotectSheet.xlsx")))
|
2021-09-18 23:20:24 +08:00
|
|
|
assert.NoError(t, f.Close())
|
2022-01-08 10:32:13 +08:00
|
|
|
|
|
|
|
f = NewFile()
|
|
|
|
sheetName := f.GetSheetName(0)
|
|
|
|
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{Password: "password"}))
|
|
|
|
// Test remove sheet protection with an incorrect password
|
|
|
|
assert.EqualError(t, f.UnprotectSheet(sheetName, "wrongPassword"), ErrUnprotectSheetPassword.Error())
|
|
|
|
// Test remove sheet protection with password verification
|
|
|
|
assert.NoError(t, f.UnprotectSheet(sheetName, "password"))
|
|
|
|
// Test with invalid salt value
|
|
|
|
assert.NoError(t, f.ProtectSheet(sheetName, &FormatSheetProtection{
|
|
|
|
AlgorithmName: "SHA-512",
|
|
|
|
Password: "password",
|
|
|
|
}))
|
|
|
|
ws, err := f.workSheetReader(sheetName)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
ws.SheetProtection.SaltValue = "YWJjZA====="
|
|
|
|
assert.EqualError(t, f.UnprotectSheet(sheetName, "wrongPassword"), "illegal base64 data at input byte 8")
|
2018-11-04 23:14:43 +08:00
|
|
|
}
|
2019-04-16 10:57:21 +08:00
|
|
|
|
|
|
|
func TestSetDefaultTimeStyle(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
// Test set default time style on not exists worksheet.
|
|
|
|
assert.EqualError(t, f.setDefaultTimeStyle("SheetN", "", 0), "sheet SheetN is not exist")
|
2020-10-04 21:07:39 +08:00
|
|
|
|
|
|
|
// Test set default time style on invalid cell
|
2021-12-07 00:26:53 +08:00
|
|
|
assert.EqualError(t, f.setDefaultTimeStyle("Sheet1", "", 42), newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
2018-11-04 23:14:43 +08:00
|
|
|
|
2019-07-21 12:56:36 +08:00
|
|
|
func TestAddVBAProject(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
assert.NoError(t, f.SetSheetPrOptions("Sheet1", CodeName("Sheet1")))
|
|
|
|
assert.EqualError(t, f.AddVBAProject("macros.bin"), "stat macros.bin: no such file or directory")
|
2021-05-10 00:09:24 +08:00
|
|
|
assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "Book1.xlsx")), ErrAddVBAProject.Error())
|
2019-07-21 12:56:36 +08:00
|
|
|
assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
|
|
|
|
// Test add VBA project twice.
|
|
|
|
assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
|
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddVBAProject.xlsm")))
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
func TestContentTypesReader(t *testing.T) {
|
2021-03-30 23:02:22 +08:00
|
|
|
// Test unsupported charset.
|
2019-12-22 00:02:09 +08:00
|
|
|
f := NewFile()
|
|
|
|
f.ContentTypes = nil
|
2021-12-27 23:34:14 +08:00
|
|
|
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
2019-12-22 00:02:09 +08:00
|
|
|
f.contentTypesReader()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWorkbookReader(t *testing.T) {
|
2021-03-30 23:02:22 +08:00
|
|
|
// Test unsupported charset.
|
2019-12-22 00:02:09 +08:00
|
|
|
f := NewFile()
|
|
|
|
f.WorkBook = nil
|
2021-12-27 23:34:14 +08:00
|
|
|
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
2019-12-22 00:02:09 +08:00
|
|
|
f.workbookReader()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWorkSheetReader(t *testing.T) {
|
2021-03-30 23:02:22 +08:00
|
|
|
// Test unsupported charset.
|
2019-12-22 00:02:09 +08:00
|
|
|
f := NewFile()
|
2021-07-05 00:03:56 +08:00
|
|
|
f.Sheet.Delete("xl/worksheets/sheet1.xml")
|
|
|
|
f.Pkg.Store("xl/worksheets/sheet1.xml", MacintoshCyrillicCharset)
|
2019-12-22 00:02:09 +08:00
|
|
|
_, err := f.workSheetReader("Sheet1")
|
|
|
|
assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
|
2021-08-15 00:06:40 +08:00
|
|
|
assert.EqualError(t, f.UpdateLinkedValue(), "xml decode error: XML syntax error on line 1: invalid UTF-8")
|
2019-12-22 00:02:09 +08:00
|
|
|
|
|
|
|
// Test on no checked worksheet.
|
|
|
|
f = NewFile()
|
2021-07-05 00:03:56 +08:00
|
|
|
f.Sheet.Delete("xl/worksheets/sheet1.xml")
|
|
|
|
f.Pkg.Store("xl/worksheets/sheet1.xml", []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData/></worksheet>`))
|
2019-12-22 00:02:09 +08:00
|
|
|
f.checked = nil
|
|
|
|
_, err = f.workSheetReader("Sheet1")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRelsReader(t *testing.T) {
|
2021-03-30 23:02:22 +08:00
|
|
|
// Test unsupported charset.
|
2019-12-22 00:02:09 +08:00
|
|
|
f := NewFile()
|
|
|
|
rels := "xl/_rels/workbook.xml.rels"
|
2021-07-04 12:13:06 +08:00
|
|
|
f.Relationships.Store(rels, nil)
|
2021-07-05 00:03:56 +08:00
|
|
|
f.Pkg.Store(rels, MacintoshCyrillicCharset)
|
2019-12-22 00:02:09 +08:00
|
|
|
f.relsReader(rels)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteSheetFromWorkbookRels(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
rels := "xl/_rels/workbook.xml.rels"
|
2021-07-04 12:13:06 +08:00
|
|
|
f.Relationships.Store(rels, nil)
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.Equal(t, f.deleteSheetFromWorkbookRels("rID"), "")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAttrValToInt(t *testing.T) {
|
|
|
|
_, err := attrValToInt("r", []xml.Attr{
|
2022-01-23 00:32:34 +08:00
|
|
|
{Name: xml.Name{Local: "r"}, Value: "s"},
|
|
|
|
})
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.EqualError(t, err, `strconv.Atoi: parsing "s": invalid syntax`)
|
|
|
|
}
|
|
|
|
|
2018-12-27 18:51:44 +08:00
|
|
|
func prepareTestBook1() (*File, error) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.AddPicture("Sheet2", "I9", filepath.Join("test", "images", "excel.jpg"),
|
2018-12-27 18:51:44 +08:00
|
|
|
`{"x_offset": 140, "y_offset": 120, "hyperlink": "#Sheet2!D8", "hyperlink_type": "Location"}`)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test add picture to worksheet with offset, external hyperlink and positioning.
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.png"),
|
2021-07-28 00:38:09 +08:00
|
|
|
`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/xuri/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-12-27 22:28:28 +08:00
|
|
|
file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.jpg"))
|
2018-12-27 18:51:44 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file)
|
2018-12-27 18:51:44 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
return f, nil
|
2018-12-27 18:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func prepareTestBook3() (*File, error) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
|
|
|
f.NewSheet("Sheet1")
|
|
|
|
f.NewSheet("XLSXSheet2")
|
|
|
|
f.NewSheet("XLSXSheet3")
|
2019-12-24 01:09:28 +08:00
|
|
|
if err := f.SetCellInt("XLSXSheet2", "A23", 56); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := f.SetCellStr("Sheet1", "B20", "42"); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-04-21 00:04:42 +08:00
|
|
|
f.SetActiveSheet(0)
|
|
|
|
|
|
|
|
err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
|
2018-12-27 22:28:28 +08:00
|
|
|
`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
|
2018-12-27 18:51:44 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
|
2018-12-27 18:51:44 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
return f, nil
|
2018-12-27 18:51:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func prepareTestBook4() (*File, error) {
|
2019-04-21 00:04:42 +08:00
|
|
|
f := NewFile()
|
2019-12-24 01:09:28 +08:00
|
|
|
if err := f.SetColWidth("Sheet1", "B", "A", 12); err != nil {
|
|
|
|
return f, err
|
|
|
|
}
|
|
|
|
if err := f.SetColWidth("Sheet1", "A", "B", 12); err != nil {
|
|
|
|
return f, err
|
|
|
|
}
|
|
|
|
if _, err := f.GetColWidth("Sheet1", "A"); err != nil {
|
|
|
|
return f, err
|
|
|
|
}
|
|
|
|
if _, err := f.GetColWidth("Sheet1", "C"); err != nil {
|
|
|
|
return f, err
|
|
|
|
}
|
2018-12-27 18:51:44 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
return f, nil
|
2018-12-27 18:51:44 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
2019-04-21 00:04:42 +08:00
|
|
|
func fillCells(f *File, sheet string, colCount, rowCount int) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
for col := 1; col <= colCount; col++ {
|
|
|
|
for row := 1; row <= rowCount; row++ {
|
2019-03-23 20:08:06 +08:00
|
|
|
cell, _ := CoordinatesToCellName(col, row)
|
2019-12-24 01:09:28 +08:00
|
|
|
if err := f.SetCellStr(sheet, cell, cell); err != nil {
|
2020-02-19 00:08:10 +08:00
|
|
|
fmt.Println(err)
|
2019-12-24 01:09:28 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-24 22:14:33 +08:00
|
|
|
|
|
|
|
func BenchmarkOpenFile(b *testing.B) {
|
|
|
|
for i := 0; i < b.N; i++ {
|
2021-09-18 23:20:24 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
|
|
|
if err != nil {
|
|
|
|
b.Error(err)
|
|
|
|
}
|
|
|
|
if err := f.Close(); err != nil {
|
2019-12-24 01:09:28 +08:00
|
|
|
b.Error(err)
|
|
|
|
}
|
2019-10-24 22:14:33 +08:00
|
|
|
}
|
|
|
|
}
|