2019-03-06 21:40:45 +08:00
|
|
|
package excelize
|
|
|
|
|
|
|
|
import (
|
2019-12-22 00:02:09 +08:00
|
|
|
"bytes"
|
2019-03-06 21:40:45 +08:00
|
|
|
"fmt"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2019-10-18 14:57:35 +08:00
|
|
|
"github.com/stretchr/testify/require"
|
2019-03-06 21:40:45 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestRows(t *testing.T) {
|
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
|
|
|
const sheet2 = "Sheet2"
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
rows, err := f.Rows(sheet2)
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-10-24 23:18:02 +08:00
|
|
|
var collectedRows [][]string
|
2019-03-06 21:40:45 +08:00
|
|
|
for rows.Next() {
|
2019-03-23 20:08:06 +08:00
|
|
|
columns, err := rows.Columns()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
collectedRows = append(collectedRows, trimSliceSpace(columns))
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
|
|
|
if !assert.NoError(t, rows.Error()) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
returnedRows, err := f.GetRows(sheet2)
|
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
|
|
|
for i := range returnedRows {
|
|
|
|
returnedRows[i] = trimSliceSpace(returnedRows[i])
|
2019-03-06 21:40:45 +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
|
|
|
if !assert.Equal(t, collectedRows, returnedRows) {
|
|
|
|
t.FailNow()
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
2019-12-22 00:02:09 +08:00
|
|
|
|
|
|
|
f = NewFile()
|
|
|
|
f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<worksheet><sheetData><row r="1"><c r="A1" t="s"><v>1</v></c></row><row r="A"><c r="2" t="str"><v>B</v></c></row></sheetData></worksheet>`)
|
|
|
|
_, err = f.Rows("Sheet1")
|
|
|
|
assert.EqualError(t, err, `strconv.Atoi: parsing "A": invalid syntax`)
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
|
|
|
|
2019-10-18 14:57:35 +08:00
|
|
|
func TestRowsIterator(t *testing.T) {
|
|
|
|
const (
|
|
|
|
sheet2 = "Sheet2"
|
|
|
|
expectedNumRow = 11
|
|
|
|
)
|
2019-11-23 04:13:59 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2019-10-18 14:57:35 +08:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-11-23 04:13:59 +08:00
|
|
|
rows, err := f.Rows(sheet2)
|
2019-10-18 14:57:35 +08:00
|
|
|
require.NoError(t, err)
|
|
|
|
var rowCount int
|
|
|
|
for rows.Next() {
|
|
|
|
rowCount++
|
|
|
|
require.True(t, rowCount <= expectedNumRow, "rowCount is greater than expected")
|
|
|
|
}
|
|
|
|
assert.Equal(t, expectedNumRow, rowCount)
|
2019-10-26 20:55:24 +08:00
|
|
|
|
2019-11-23 04:13:59 +08:00
|
|
|
// Valued cell sparse distribution test
|
|
|
|
f = NewFile()
|
|
|
|
cells := []string{"C1", "E1", "A3", "B3", "C3", "D3", "E3"}
|
|
|
|
for _, cell := range cells {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", cell, 1))
|
2019-11-23 04:13:59 +08:00
|
|
|
}
|
|
|
|
rows, err = f.Rows("Sheet1")
|
|
|
|
require.NoError(t, err)
|
|
|
|
rowCount = 0
|
|
|
|
for rows.Next() {
|
|
|
|
rowCount++
|
|
|
|
require.True(t, rowCount <= 3, "rowCount is greater than expected")
|
|
|
|
}
|
|
|
|
assert.Equal(t, 3, rowCount)
|
2019-10-18 14:57:35 +08:00
|
|
|
}
|
|
|
|
|
2019-03-06 21:40:45 +08:00
|
|
|
func TestRowsError(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
_, err = f.Rows("SheetN")
|
2019-04-16 10:57:21 +08:00
|
|
|
assert.EqualError(t, err, "sheet SheetN is not exist")
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestRowHeight(t *testing.T) {
|
2020-09-18 22:20:58 +08:00
|
|
|
f := NewFile()
|
|
|
|
sheet1 := f.GetSheetName(0)
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-09-18 22:20:58 +08:00
|
|
|
assert.EqualError(t, f.SetRowHeight(sheet1, 0, defaultRowHeightPixels+1.0), "invalid row number 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
|
|
|
|
2020-09-18 22:20:58 +08:00
|
|
|
_, err := f.GetRowHeight("Sheet1", 0)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.EqualError(t, err, "invalid row number 0")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-09-18 22:20:58 +08:00
|
|
|
assert.NoError(t, f.SetRowHeight(sheet1, 1, 111.0))
|
|
|
|
height, err := f.GetRowHeight(sheet1, 1)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, 111.0, height)
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-09-18 22:20:58 +08:00
|
|
|
// Test set row height overflow max row height limit.
|
|
|
|
assert.EqualError(t, f.SetRowHeight(sheet1, 4, MaxRowHeight+1), "the height of the row must be smaller than or equal to 409 points")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2019-03-24 13:08:32 +08:00
|
|
|
// Test get row height that rows index over exists rows.
|
2020-09-18 22:20:58 +08:00
|
|
|
height, err = f.GetRowHeight(sheet1, 5)
|
2019-03-24 13:08:32 +08:00
|
|
|
assert.NoError(t, err)
|
2020-08-22 18:58:43 +08:00
|
|
|
assert.Equal(t, defaultRowHeight, height)
|
2019-03-24 13:08:32 +08:00
|
|
|
|
|
|
|
// Test get row height that rows heights haven't changed.
|
2020-09-18 22:20:58 +08:00
|
|
|
height, err = f.GetRowHeight(sheet1, 3)
|
2019-03-24 13:08:32 +08:00
|
|
|
assert.NoError(t, err)
|
2020-08-22 18:58:43 +08:00
|
|
|
assert.Equal(t, defaultRowHeight, height)
|
2019-03-24 13:08:32 +08:00
|
|
|
|
2019-04-16 10:57:21 +08:00
|
|
|
// Test set and get row height on not exists worksheet.
|
2020-09-18 22:20:58 +08:00
|
|
|
assert.EqualError(t, f.SetRowHeight("SheetN", 1, 111.0), "sheet SheetN is not exist")
|
|
|
|
_, err = f.GetRowHeight("SheetN", 3)
|
2019-04-16 10:57:21 +08:00
|
|
|
assert.EqualError(t, err, "sheet SheetN is not exist")
|
|
|
|
|
2020-09-18 22:20:58 +08:00
|
|
|
err = f.SaveAs(filepath.Join("test", "TestRowHeight.xlsx"))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
convertColWidthToPixels(0)
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
func TestColumns(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
rows, err := f.Rows("Sheet1")
|
|
|
|
assert.NoError(t, err)
|
2019-12-31 01:01:16 +08:00
|
|
|
|
|
|
|
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="2"><c r="A1" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
|
|
|
|
_, err = rows.Columns()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="2"><c r="A1" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
|
|
|
|
rows.curRow = 1
|
|
|
|
_, err = rows.Columns()
|
2020-01-03 23:57:25 +08:00
|
|
|
assert.NoError(t, err)
|
2019-12-31 01:01:16 +08:00
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="A"><c r="A1" t="s"><v>1</v></c></row><row r="A"><c r="2" t="str"><v>B</v></c></row></sheetData></worksheet>`)))
|
2019-12-31 01:01:16 +08:00
|
|
|
rows.stashRow, rows.curRow = 0, 1
|
2019-12-22 00:02:09 +08:00
|
|
|
_, err = rows.Columns()
|
|
|
|
assert.EqualError(t, err, `strconv.Atoi: parsing "A": invalid syntax`)
|
|
|
|
|
|
|
|
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="1"><c r="A1" t="s"><v>1</v></c></row><row r="A"><c r="2" t="str"><v>B</v></c></row></sheetData></worksheet>`)))
|
|
|
|
_, err = rows.Columns()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
rows.curRow = 3
|
|
|
|
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="1"><c r="A" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
|
|
|
|
_, err = rows.Columns()
|
|
|
|
assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
|
|
|
|
|
|
|
|
// Test token is nil
|
|
|
|
rows.decoder = f.xmlNewDecoder(bytes.NewReader(nil))
|
|
|
|
_, err = rows.Columns()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSharedStringsReader(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
f.XLSX["xl/sharedStrings.xml"] = MacintoshCyrillicCharset
|
|
|
|
f.sharedStringsReader()
|
2020-07-11 02:31:02 +08:00
|
|
|
si := xlsxSI{}
|
|
|
|
assert.EqualValues(t, "", si.String())
|
2019-12-22 00:02:09 +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
|
|
|
func TestRowVisibility(t *testing.T) {
|
2019-10-26 20:55:24 +08:00
|
|
|
f, err := prepareTestBook1()
|
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
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
2019-10-26 20:55:24 +08:00
|
|
|
f.NewSheet("Sheet3")
|
|
|
|
assert.NoError(t, f.SetRowVisible("Sheet3", 2, false))
|
|
|
|
assert.NoError(t, f.SetRowVisible("Sheet3", 2, true))
|
2019-12-24 01:09:28 +08:00
|
|
|
visiable, err := f.GetRowVisible("Sheet3", 2)
|
|
|
|
assert.Equal(t, true, visiable)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
visiable, err = f.GetRowVisible("Sheet3", 25)
|
|
|
|
assert.Equal(t, false, visiable)
|
|
|
|
assert.NoError(t, err)
|
2019-10-26 20:55:24 +08:00
|
|
|
assert.EqualError(t, f.SetRowVisible("Sheet3", 0, true), "invalid row number 0")
|
|
|
|
assert.EqualError(t, f.SetRowVisible("SheetN", 2, false), "sheet SheetN is not exist")
|
|
|
|
|
|
|
|
visible, err := f.GetRowVisible("Sheet3", 0)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.Equal(t, false, visible)
|
|
|
|
assert.EqualError(t, err, "invalid row number 0")
|
2019-10-26 20:55:24 +08:00
|
|
|
_, err = f.GetRowVisible("SheetN", 1)
|
|
|
|
assert.EqualError(t, err, "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
|
|
|
|
2019-10-26 20:55:24 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRowVisibility.xlsx")))
|
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-03-06 21:40:45 +08:00
|
|
|
func TestRemoveRow(t *testing.T) {
|
2019-12-22 00:02:09 +08:00
|
|
|
f := NewFile()
|
2020-04-23 02:01:14 +08:00
|
|
|
sheet1 := f.GetSheetName(0)
|
2019-12-22 00:02:09 +08:00
|
|
|
r, err := f.workSheetReader(sheet1)
|
2019-04-15 11:22:57 +08:00
|
|
|
assert.NoError(t, err)
|
2019-03-06 21:40:45 +08:00
|
|
|
const (
|
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
|
|
|
colCount = 10
|
|
|
|
rowCount = 10
|
2019-03-06 21:40:45 +08:00
|
|
|
)
|
2019-12-22 00:02:09 +08:00
|
|
|
fillCells(f, sheet1, colCount, rowCount)
|
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.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.EqualError(t, f.RemoveRow(sheet1, -1), "invalid row number -1")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.EqualError(t, f.RemoveRow(sheet1, 0), "invalid row number 0")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.NoError(t, f.RemoveRow(sheet1, 4))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount-1) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.MergeCell(sheet1, "B3", "B5"))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.NoError(t, f.RemoveRow(sheet1, 2))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount-2) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.NoError(t, f.RemoveRow(sheet1, 4))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount-3) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
err = f.AutoFilter(sheet1, "A2", "A2", `{"column":"A","expression":"x != blanks"}`)
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.NoError(t, f.RemoveRow(sheet1, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount-4) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.NoError(t, f.RemoveRow(sheet1, 2))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount-5) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.NoError(t, f.RemoveRow(sheet1, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount-6) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2019-12-22 00:02:09 +08:00
|
|
|
assert.NoError(t, f.RemoveRow(sheet1, 10))
|
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRemoveRow.xlsx")))
|
|
|
|
|
|
|
|
// Test remove row on not exist worksheet
|
|
|
|
assert.EqualError(t, f.RemoveRow("SheetN", 1), `sheet SheetN is not exist`)
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestInsertRow(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
|
|
|
sheet1 := f.GetSheetName(0)
|
|
|
|
r, err := f.workSheetReader(sheet1)
|
2019-04-15 11:22:57 +08:00
|
|
|
assert.NoError(t, err)
|
2019-03-06 21:40:45 +08:00
|
|
|
const (
|
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
|
|
|
colCount = 10
|
|
|
|
rowCount = 10
|
2019-03-06 21:40:45 +08:00
|
|
|
)
|
2020-11-10 23:48:09 +08:00
|
|
|
fillCells(f, sheet1, colCount, rowCount)
|
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-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.EqualError(t, f.InsertRow(sheet1, -1), "invalid row number -1")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.EqualError(t, f.InsertRow(sheet1, 0), "invalid row number 0")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.InsertRow(sheet1, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount+1) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.InsertRow(sheet1, 4))
|
2019-03-06 21:40:45 +08:00
|
|
|
if !assert.Len(t, r.SheetData.Row, rowCount+2) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertRow.xlsx")))
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Testing internal sructure state after insert operations.
|
|
|
|
// It is important for insert workflow to be constant to avoid side effect with functions related to internal structure.
|
|
|
|
func TestInsertRowInEmptyFile(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
|
|
|
sheet1 := f.GetSheetName(0)
|
|
|
|
r, err := f.workSheetReader(sheet1)
|
2019-04-15 11:22:57 +08:00
|
|
|
assert.NoError(t, err)
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.InsertRow(sheet1, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
assert.Len(t, r.SheetData.Row, 0)
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.InsertRow(sheet1, 2))
|
2019-03-06 21:40:45 +08:00
|
|
|
assert.Len(t, r.SheetData.Row, 0)
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.InsertRow(sheet1, 99))
|
2019-03-06 21:40:45 +08:00
|
|
|
assert.Len(t, r.SheetData.Row, 0)
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
|
|
|
|
2019-04-16 10:57:21 +08:00
|
|
|
func TestDuplicateRowFromSingleRow(t *testing.T) {
|
2019-03-06 21:40:45 +08:00
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("FromSingleRow", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
|
|
|
assert.NoError(t, f.SetCellStr(sheet, "A1", cells["A1"]))
|
|
|
|
assert.NoError(t, f.SetCellStr(sheet, "B1", cells["B1"]))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRow(sheet, 1))
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "FromSingleRow_1"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
expect := map[string]string{
|
|
|
|
"A1": cells["A1"], "B1": cells["B1"],
|
|
|
|
"A2": cells["A1"], "B2": cells["B1"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRow(sheet, 2))
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "FromSingleRow_2"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
expect = map[string]string{
|
|
|
|
"A1": cells["A1"], "B1": cells["B1"],
|
|
|
|
"A2": cells["A1"], "B2": cells["B1"],
|
|
|
|
"A3": cells["A1"], "B3": cells["B1"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("UpdateDuplicatedRows", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
|
|
|
assert.NoError(t, f.SetCellStr(sheet, "A1", cells["A1"]))
|
|
|
|
assert.NoError(t, f.SetCellStr(sheet, "B1", cells["B1"]))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRow(sheet, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, "A2", cells["A2"]))
|
|
|
|
assert.NoError(t, f.SetCellStr(sheet, "B2", cells["B2"]))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "UpdateDuplicatedRows"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
expect := map[string]string{
|
|
|
|
"A1": cells["A1"], "B1": cells["B1"],
|
|
|
|
"A2": cells["A2"], "B2": cells["B2"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowFirstOfMultipleRows(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
|
|
|
newFileWithDefaults := func() *File {
|
|
|
|
f := NewFile()
|
|
|
|
for cell, val := range cells {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, cell, val))
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("FirstOfMultipleRows", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := newFileWithDefaults()
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRow(sheet, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "FirstOfMultipleRows"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
expect := map[string]string{
|
|
|
|
"A1": cells["A1"], "B1": cells["B1"],
|
|
|
|
"A2": cells["A1"], "B2": cells["B1"],
|
|
|
|
"A3": cells["A2"], "B3": cells["B2"],
|
|
|
|
"A4": cells["A3"], "B4": cells["B3"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowZeroWithNoRows(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("ZeroWithNoRows", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.EqualError(t, f.DuplicateRow(sheet, 0), "invalid row number 0")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "ZeroWithNoRows"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
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-11-10 23:48:09 +08:00
|
|
|
val, err := f.GetCellValue(sheet, "A1")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "", val)
|
2020-11-10 23:48:09 +08:00
|
|
|
val, err = f.GetCellValue(sheet, "B1")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "", val)
|
2020-11-10 23:48:09 +08:00
|
|
|
val, err = f.GetCellValue(sheet, "A2")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "", val)
|
2020-11-10 23:48:09 +08:00
|
|
|
val, err = f.GetCellValue(sheet, "B2")
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "", val)
|
|
|
|
|
|
|
|
assert.NoError(t, err)
|
2019-03-06 21:40:45 +08:00
|
|
|
expect := map[string]string{
|
|
|
|
"A1": "", "B1": "",
|
|
|
|
"A2": "", "B2": "",
|
|
|
|
}
|
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-03-06 21:40:45 +08:00
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("MiddleRowOfEmptyFile", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRow(sheet, 99))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "MiddleRowOfEmptyFile"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
expect := map[string]string{
|
|
|
|
"A98": "",
|
|
|
|
"A99": "",
|
|
|
|
"A100": "",
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
|
|
|
newFileWithDefaults := func() *File {
|
|
|
|
f := NewFile()
|
|
|
|
for cell, val := range cells {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, cell, val))
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("WithLargeOffsetToMiddleOfData", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := newFileWithDefaults()
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 3))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "WithLargeOffsetToMiddleOfData"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
expect := map[string]string{
|
|
|
|
"A1": cells["A1"], "B1": cells["B1"],
|
|
|
|
"A2": cells["A2"], "B2": cells["B2"],
|
|
|
|
"A3": cells["A1"], "B3": cells["B1"],
|
|
|
|
"A4": cells["A3"], "B4": cells["B3"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
|
|
|
newFileWithDefaults := func() *File {
|
|
|
|
f := NewFile()
|
|
|
|
for cell, val := range cells {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, cell, val))
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("WithLargeOffsetToEmptyRows", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := newFileWithDefaults()
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 7))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "WithLargeOffsetToEmptyRows"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
expect := map[string]string{
|
|
|
|
"A1": cells["A1"], "B1": cells["B1"],
|
|
|
|
"A2": cells["A2"], "B2": cells["B2"],
|
|
|
|
"A3": cells["A3"], "B3": cells["B3"],
|
|
|
|
"A7": cells["A1"], "B7": cells["B1"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowInsertBefore(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
|
|
|
newFileWithDefaults := func() *File {
|
|
|
|
f := NewFile()
|
|
|
|
for cell, val := range cells {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, cell, val))
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("InsertBefore", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := newFileWithDefaults()
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "InsertBefore"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
expect := map[string]string{
|
|
|
|
"A1": cells["A2"], "B1": cells["B2"],
|
|
|
|
"A2": cells["A1"], "B2": cells["B1"],
|
|
|
|
"A3": cells["A2"], "B3": cells["B2"],
|
|
|
|
"A4": cells["A3"], "B4": cells["B3"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v, cell) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
|
|
|
newFileWithDefaults := func() *File {
|
|
|
|
f := NewFile()
|
|
|
|
for cell, val := range cells {
|
2019-12-24 01:09:28 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, cell, val))
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := newFileWithDefaults()
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRowTo(sheet, 3, 1))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "InsertBeforeWithLargeOffset"))) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
expect := map[string]string{
|
|
|
|
"A1": cells["A3"], "B1": cells["B3"],
|
|
|
|
"A2": cells["A1"], "B2": cells["B1"],
|
|
|
|
"A3": cells["A2"], "B3": cells["B2"],
|
|
|
|
"A4": cells["A3"], "B4": cells["B3"],
|
|
|
|
}
|
|
|
|
for cell, val := range expect {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-02-25 00:19:22 +08:00
|
|
|
func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) {
|
|
|
|
const sheet = "Sheet1"
|
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
|
|
|
newFileWithDefaults := func() *File {
|
|
|
|
f := NewFile()
|
|
|
|
for cell, val := range cells {
|
|
|
|
assert.NoError(t, f.SetCellStr(sheet, cell, val))
|
|
|
|
}
|
|
|
|
assert.NoError(t, f.MergeCell(sheet, "B2", "C2"))
|
|
|
|
assert.NoError(t, f.MergeCell(sheet, "C6", "C8"))
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := newFileWithDefaults()
|
2020-02-25 00:19:22 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1))
|
|
|
|
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 8))
|
2020-02-25 00:19:22 +08:00
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "InsertBeforeWithMergeCells"))) {
|
2020-02-25 00:19:22 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
expect := []MergeCell{
|
|
|
|
{"B3:C3", "B2 Value"},
|
|
|
|
{"C7:C10", ""},
|
|
|
|
{"B1:C1", "B2 Value"},
|
|
|
|
}
|
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
mergeCells, err := f.GetMergeCells(sheet)
|
2020-02-25 00:19:22 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
for idx, val := range expect {
|
|
|
|
if !assert.Equal(t, val, mergeCells[idx]) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-12-22 08:47:46 +08:00
|
|
|
func TestDuplicateRowInvalidRowNum(t *testing.T) {
|
2019-03-06 21:40:45 +08:00
|
|
|
const sheet = "Sheet1"
|
2020-12-22 08:47:46 +08:00
|
|
|
outFile := filepath.Join("test", "TestDuplicateRow.InvalidRowNum.%s.xlsx")
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
cells := map[string]string{
|
|
|
|
"A1": "A1 Value",
|
|
|
|
"A2": "A2 Value",
|
|
|
|
"A3": "A3 Value",
|
|
|
|
"B1": "B1 Value",
|
|
|
|
"B2": "B2 Value",
|
|
|
|
"B3": "B3 Value",
|
|
|
|
}
|
|
|
|
|
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
|
|
|
invalidIndexes := []int{-100, -2, -1, 0}
|
2019-03-06 21:40:45 +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
|
|
|
for _, row := range invalidIndexes {
|
|
|
|
name := fmt.Sprintf("%d", row)
|
2019-03-06 21:40:45 +08:00
|
|
|
t.Run(name, func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
2019-03-06 21:40:45 +08:00
|
|
|
for col, val := range cells {
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, col, val))
|
2019-03-06 21:40:45 +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
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.EqualError(t, f.DuplicateRow(sheet, row), fmt.Sprintf("invalid row number %d", row))
|
2019-03-06 21:40:45 +08:00
|
|
|
|
|
|
|
for col, val := range cells {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, col)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v) {
|
2019-03-06 21:40:45 +08:00
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, name)))
|
2019-03-06 21:40:45 +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
|
|
|
for _, row1 := range invalidIndexes {
|
|
|
|
for _, row2 := range invalidIndexes {
|
|
|
|
name := fmt.Sprintf("[%d,%d]", row1, row2)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2020-11-10 23:48:09 +08:00
|
|
|
f := NewFile()
|
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, val := range cells {
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SetCellStr(sheet, col, val))
|
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-03-06 21:40:45 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.EqualError(t, f.DuplicateRowTo(sheet, row1, row2), fmt.Sprintf("invalid row number %d", row1))
|
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, val := range cells {
|
2020-11-10 23:48:09 +08:00
|
|
|
v, err := f.GetCellValue(sheet, col)
|
2019-03-23 20:08:06 +08:00
|
|
|
assert.NoError(t, err)
|
|
|
|
if !assert.Equal(t, val, v) {
|
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
|
|
|
t.FailNow()
|
|
|
|
}
|
2019-03-06 21:40:45 +08:00
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, 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-03-06 21:40:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-25 00:19:22 +08:00
|
|
|
func TestDuplicateRowTo(t *testing.T) {
|
|
|
|
f := File{}
|
|
|
|
assert.EqualError(t, f.DuplicateRowTo("SheetN", 1, 2), "sheet SheetN is not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDuplicateMergeCells(t *testing.T) {
|
|
|
|
f := File{}
|
2020-11-10 23:48:09 +08:00
|
|
|
ws := &xlsxWorksheet{MergeCells: &xlsxMergeCells{
|
2020-02-26 18:53:50 +08:00
|
|
|
Cells: []*xlsxMergeCell{{Ref: "A1:-"}},
|
2020-02-25 00:19:22 +08:00
|
|
|
}}
|
2020-11-10 23:48:09 +08:00
|
|
|
assert.EqualError(t, f.duplicateMergeCells("Sheet1", ws, 0, 0), `cannot convert cell "-" to coordinates: invalid cell name "-"`)
|
|
|
|
ws.MergeCells.Cells[0].Ref = "A1:B1"
|
|
|
|
assert.EqualError(t, f.duplicateMergeCells("SheetN", ws, 1, 2), "sheet SheetN is not exist")
|
2020-02-25 00:19:22 +08:00
|
|
|
}
|
|
|
|
|
2020-10-04 21:07:39 +08:00
|
|
|
func TestGetValueFromInlineStr(t *testing.T) {
|
2019-12-11 00:02:33 +08:00
|
|
|
c := &xlsxC{T: "inlineStr"}
|
|
|
|
f := NewFile()
|
|
|
|
d := &xlsxSST{}
|
|
|
|
val, err := c.getValueFrom(f, d)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "", val)
|
|
|
|
}
|
|
|
|
|
2020-10-04 21:07:39 +08:00
|
|
|
func TestGetValueFromNumber(t *testing.T) {
|
|
|
|
c := &xlsxC{T: "n", V: "2.2200000000000002"}
|
|
|
|
f := NewFile()
|
|
|
|
d := &xlsxSST{}
|
|
|
|
val, err := c.getValueFrom(f, d)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "2.22", val)
|
|
|
|
|
|
|
|
c = &xlsxC{T: "n", V: "2.220000ddsf0000000002-r"}
|
2021-01-27 13:51:47 +08:00
|
|
|
val, err = c.getValueFrom(f, d)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "2.220000ddsf0000000002-r", val)
|
|
|
|
|
|
|
|
c = &xlsxC{T: "n", V: "2.2."}
|
|
|
|
val, err = c.getValueFrom(f, d)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "2.2.", val)
|
2020-10-04 21:07:39 +08:00
|
|
|
}
|
|
|
|
|
2019-10-16 01:03:29 +08:00
|
|
|
func TestErrSheetNotExistError(t *testing.T) {
|
|
|
|
err := ErrSheetNotExist{SheetName: "Sheet1"}
|
2019-11-23 04:13:59 +08:00
|
|
|
assert.EqualValues(t, err.Error(), "sheet Sheet1 is not exist")
|
2019-10-16 01:03:29 +08:00
|
|
|
}
|
|
|
|
|
2020-04-24 08:26:16 +08:00
|
|
|
func TestCheckRow(t *testing.T) {
|
|
|
|
f := NewFile()
|
|
|
|
f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" ><sheetData><row r="2"><c><v>1</v></c><c r="F2"><v>2</v></c><c><v>3</v></c><c><v>4</v></c><c r="M2"><v>5</v></c></row></sheetData></worksheet>`)
|
|
|
|
_, err := f.GetRows("Sheet1")
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NoError(t, f.SetCellValue("Sheet1", "A1", false))
|
|
|
|
f = NewFile()
|
|
|
|
f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" ><sheetData><row r="2"><c><v>1</v></c><c r="-"><v>2</v></c><c><v>3</v></c><c><v>4</v></c><c r="M2"><v>5</v></c></row></sheetData></worksheet>`)
|
|
|
|
assert.EqualError(t, f.SetCellValue("Sheet1", "A1", false), `cannot convert cell "-" to coordinates: invalid cell name "-"`)
|
|
|
|
}
|
|
|
|
|
2020-10-04 21:07:39 +08:00
|
|
|
func TestNumberFormats(t *testing.T) {
|
|
|
|
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
cells := make([][]string, 0)
|
|
|
|
cols, err := f.Cols("Sheet2")
|
|
|
|
if !assert.NoError(t, err) {
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
for cols.Next() {
|
|
|
|
col, err := cols.Rows()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
cells = append(cells, col)
|
|
|
|
}
|
|
|
|
assert.Equal(t, []string{"", "200", "450", "200", "510", "315", "127", "89", "348", "53", "37"}, cells[3])
|
|
|
|
}
|
|
|
|
|
2019-08-05 06:23:42 +08:00
|
|
|
func BenchmarkRows(b *testing.B) {
|
2019-10-24 22:14:33 +08:00
|
|
|
f, _ := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
2019-08-05 06:23:42 +08:00
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
rows, _ := f.Rows("Sheet2")
|
|
|
|
for rows.Next() {
|
|
|
|
row, _ := rows.Columns()
|
|
|
|
for i := range row {
|
|
|
|
if i >= 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-06 21:40:45 +08:00
|
|
|
func trimSliceSpace(s []string) []string {
|
|
|
|
for {
|
|
|
|
if len(s) > 0 && s[len(s)-1] == "" {
|
|
|
|
s = s[:len(s)-1]
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|