- Checking and return error for invalid sheet name instead of trim invalid characters - Add error return for the 4 functions: `DeleteSheet`, `GetSheetIndex`, `GetSheetVisible` and `SetSheetName` - Export new error 4 constants: `ErrSheetNameBlank`, `ErrSheetNameInvalid`, `ErrSheetNameLength` and `ErrSheetNameSingleQuote` - Rename exported error constant `ErrExistsWorksheet` to `ErrExistsSheet` - Update unit tests for 90 functions: `AddChart`, `AddChartSheet`, `AddComment`, `AddDataValidation`, `AddPicture`, `AddPictureFromBytes`, `AddPivotTable`, `AddShape`, `AddSparkline`, `AddTable`, `AutoFilter`, `CalcCellValue`, `Cols`, `DeleteChart`, `DeleteComment`, `DeleteDataValidation`, `DeletePicture`, `DeleteSheet`, `DuplicateRow`, `DuplicateRowTo`, `GetCellFormula`, `GetCellHyperLink`, `GetCellRichText`, `GetCellStyle`, `GetCellType`, `GetCellValue`, `GetColOutlineLevel`, `GetCols`, `GetColStyle`, `GetColVisible`, `GetColWidth`, `GetConditionalFormats`, `GetDataValidations`, `GetMergeCells`, `GetPageLayout`, `GetPageMargins`, `GetPicture`, `GetRowHeight`, `GetRowOutlineLevel`, `GetRows`, `GetRowVisible`, `GetSheetIndex`, `GetSheetProps`, `GetSheetVisible`, `GroupSheets`, `InsertCol`, `InsertPageBreak`, `InsertRows`, `MergeCell`, `NewSheet`, `NewStreamWriter`, `ProtectSheet`, `RemoveCol`, `RemovePageBreak`, `RemoveRow`, `Rows`, `SearchSheet`, `SetCellBool`, `SetCellDefault`, `SetCellFloat`, `SetCellFormula`, `SetCellHyperLink`, `SetCellInt`, `SetCellRichText`, `SetCellStr`, `SetCellStyle`, `SetCellValue`, `SetColOutlineLevel`, `SetColStyle`, `SetColVisible`, `SetColWidth`, `SetConditionalFormat`, `SetHeaderFooter`, `SetPageLayout`, `SetPageMargins`, `SetPanes`, `SetRowHeight`, `SetRowOutlineLevel`, `SetRowStyle`, `SetRowVisible`, `SetSheetBackground`, `SetSheetBackgroundFromBytes`, `SetSheetCol`, `SetSheetName`, `SetSheetProps`, `SetSheetRow`, `SetSheetVisible`, `UnmergeCell`, `UnprotectSheet` and `UnsetConditionalFormat` - Update documentation of the set style functions Co-authored-by: guoweikuang <weikuang.guo@shopee.com>
This commit is contained in:
parent
ce4f7a25c9
commit
6a5ee811ba
11
calc.go
11
calc.go
|
@ -11460,19 +11460,20 @@ func (fn *formulaFuncs) SHEET(argsList *list.List) formulaArg {
|
|||
return newErrorFormulaArg(formulaErrorVALUE, "SHEET accepts at most 1 argument")
|
||||
}
|
||||
if argsList.Len() == 0 {
|
||||
return newNumberFormulaArg(float64(fn.f.GetSheetIndex(fn.sheet) + 1))
|
||||
idx, _ := fn.f.GetSheetIndex(fn.sheet)
|
||||
return newNumberFormulaArg(float64(idx + 1))
|
||||
}
|
||||
arg := argsList.Front().Value.(formulaArg)
|
||||
if sheetIdx := fn.f.GetSheetIndex(arg.Value()); sheetIdx != -1 {
|
||||
if sheetIdx, _ := fn.f.GetSheetIndex(arg.Value()); sheetIdx != -1 {
|
||||
return newNumberFormulaArg(float64(sheetIdx + 1))
|
||||
}
|
||||
if arg.cellRanges != nil && arg.cellRanges.Len() > 0 {
|
||||
if sheetIdx := fn.f.GetSheetIndex(arg.cellRanges.Front().Value.(cellRange).From.Sheet); sheetIdx != -1 {
|
||||
if sheetIdx, _ := fn.f.GetSheetIndex(arg.cellRanges.Front().Value.(cellRange).From.Sheet); sheetIdx != -1 {
|
||||
return newNumberFormulaArg(float64(sheetIdx + 1))
|
||||
}
|
||||
}
|
||||
if arg.cellRefs != nil && arg.cellRefs.Len() > 0 {
|
||||
if sheetIdx := fn.f.GetSheetIndex(arg.cellRefs.Front().Value.(cellRef).Sheet); sheetIdx != -1 {
|
||||
if sheetIdx, _ := fn.f.GetSheetIndex(arg.cellRefs.Front().Value.(cellRef).Sheet); sheetIdx != -1 {
|
||||
return newNumberFormulaArg(float64(sheetIdx + 1))
|
||||
}
|
||||
}
|
||||
|
@ -13960,7 +13961,7 @@ func (fn *formulaFuncs) ADDRESS(argsList *list.List) formulaArg {
|
|||
}
|
||||
var sheetText string
|
||||
if argsList.Len() == 5 {
|
||||
sheetText = fmt.Sprintf("%s!", trimSheetName(argsList.Back().Value.(formulaArg).Value()))
|
||||
sheetText = fmt.Sprintf("%s!", argsList.Back().Value.(formulaArg).Value())
|
||||
}
|
||||
formatter := addressFmtMaps[fmt.Sprintf("%d_%s", int(absNum.Number), a1.Value())]
|
||||
addr, err := formatter(int(colNum.Number), int(rowNum.Number))
|
||||
|
|
|
@ -4389,16 +4389,19 @@ func TestCalcCellValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// Test get calculated cell value on not formula cell.
|
||||
// Test get calculated cell value on not formula cell
|
||||
f := prepareCalcData(cellData)
|
||||
result, err := f.CalcCellValue("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", result)
|
||||
// Test get calculated cell value on not exists worksheet.
|
||||
// Test get calculated cell value on not exists worksheet
|
||||
f = prepareCalcData(cellData)
|
||||
_, err = f.CalcCellValue("SheetN", "A1")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get calculated cell value with not support formula.
|
||||
// Test get calculated cell value with invalid sheet name
|
||||
_, err = f.CalcCellValue("Sheet:1", "A1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
// Test get calculated cell value with not support formula
|
||||
f = prepareCalcData(cellData)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=UNSUPPORT(A1)"))
|
||||
_, err = f.CalcCellValue("Sheet1", "A1")
|
||||
|
|
92
cell_test.go
92
cell_test.go
|
@ -167,13 +167,15 @@ func TestSetCellFloat(t *testing.T) {
|
|||
})
|
||||
f := NewFile()
|
||||
assert.EqualError(t, f.SetCellFloat(sheet, "A", 123.42, -1, 64), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test set cell float data type value with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellFloat("Sheet:1", "A1", 123.42, -1, 64), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestSetCellValue(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.EqualError(t, f.SetCellValue("Sheet1", "A", time.Now().UTC()), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
assert.EqualError(t, f.SetCellValue("Sheet1", "A", time.Duration(1e13)), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test set cell value with column and row style inherit.
|
||||
// Test set cell value with column and row style inherit
|
||||
style1, err := f.NewStyle(&Style{NumFmt: 2})
|
||||
assert.NoError(t, err)
|
||||
style2, err := f.NewStyle(&Style{NumFmt: 9})
|
||||
|
@ -189,11 +191,13 @@ func TestSetCellValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, "0.50", B2)
|
||||
|
||||
// Test set cell value with unsupported charset shared strings table.
|
||||
// Test set cell value with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellValue("Sheet:1", "A1", "A1"), ErrSheetNameInvalid.Error())
|
||||
// Test set cell value with unsupported charset shared strings table
|
||||
f.SharedStrings = nil
|
||||
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetCellValue("Sheet1", "A1", "A1"), "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test set cell value with unsupported charset workbook.
|
||||
// Test set cell value with unsupported charset workbook
|
||||
f.WorkBook = nil
|
||||
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetCellValue("Sheet1", "A1", time.Now().UTC()), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
@ -208,7 +212,7 @@ func TestSetCellValues(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, v, "12/31/10 00:00")
|
||||
|
||||
// Test date value lower than min date supported by Excel.
|
||||
// Test date value lower than min date supported by Excel
|
||||
err = f.SetCellValue("Sheet1", "A1", time.Date(1600, time.December, 31, 0, 0, 0, 0, time.UTC))
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
@ -220,6 +224,8 @@ func TestSetCellValues(t *testing.T) {
|
|||
func TestSetCellBool(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.EqualError(t, f.SetCellBool("Sheet1", "A", true), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test set cell boolean data type value with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellBool("Sheet:1", "A1", true), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestSetCellTime(t *testing.T) {
|
||||
|
@ -242,7 +248,7 @@ func TestSetCellTime(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetCellValue(t *testing.T) {
|
||||
// Test get cell value without r attribute of the row.
|
||||
// Test get cell value without r attribute of the row
|
||||
f := NewFile()
|
||||
sheetData := `<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>%s</sheetData></worksheet>`
|
||||
|
||||
|
@ -387,11 +393,14 @@ func TestGetCellValue(t *testing.T) {
|
|||
}, rows[0])
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test get cell value with unsupported charset shared strings table.
|
||||
// Test get cell value with unsupported charset shared strings table
|
||||
f.SharedStrings = nil
|
||||
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
|
||||
_, value := f.GetCellValue("Sheet1", "A1")
|
||||
assert.EqualError(t, value, "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test get cell value with invalid sheet name
|
||||
_, err = f.GetCellValue("Sheet:1", "A1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestGetCellType(t *testing.T) {
|
||||
|
@ -405,6 +414,9 @@ func TestGetCellType(t *testing.T) {
|
|||
assert.Equal(t, CellTypeSharedString, cellType)
|
||||
_, err = f.GetCellType("Sheet1", "A")
|
||||
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test get cell type with invalid sheet name
|
||||
_, err = f.GetCellType("Sheet:1", "A1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestGetValueFrom(t *testing.T) {
|
||||
|
@ -418,12 +430,16 @@ func TestGetValueFrom(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetCellFormula(t *testing.T) {
|
||||
// Test get cell formula on not exist worksheet.
|
||||
// Test get cell formula on not exist worksheet
|
||||
f := NewFile()
|
||||
_, err := f.GetCellFormula("SheetN", "A1")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
|
||||
// Test get cell formula on no formula cell.
|
||||
// Test get cell formula with invalid sheet name
|
||||
_, err = f.GetCellFormula("Sheet:1", "A1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
// Test get cell formula on no formula cell
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "A1", true))
|
||||
_, err = f.GetCellFormula("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
|
@ -497,7 +513,10 @@ func TestSetCellFormula(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)"))
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)"))
|
||||
|
||||
// Test set cell formula with illegal rows number.
|
||||
// Test set cell formula with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellFormula("Sheet:1", "A1", "SUM(1,2)"), ErrSheetNameInvalid.Error())
|
||||
|
||||
// Test set cell formula with illegal rows number
|
||||
assert.EqualError(t, f.SetCellFormula("Sheet1", "C", "SUM(Sheet2!D2,Sheet2!D9)"), newCellNameToCoordinatesError("C", newInvalidCellNameError("C")).Error())
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula1.xlsx")))
|
||||
|
@ -507,15 +526,15 @@ func TestSetCellFormula(t *testing.T) {
|
|||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Test remove cell formula.
|
||||
// Test remove cell formula
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", ""))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula2.xlsx")))
|
||||
// Test remove all cell formula.
|
||||
// Test remove all cell formula
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", ""))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula3.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test set shared formula for the cells.
|
||||
// Test set shared formula for the cells
|
||||
f = NewFile()
|
||||
for r := 1; r <= 5; r++ {
|
||||
assert.NoError(t, f.SetSheetRow("Sheet1", fmt.Sprintf("A%d", r), &[]interface{}{r, r + 1}))
|
||||
|
@ -533,7 +552,7 @@ func TestSetCellFormula(t *testing.T) {
|
|||
assert.EqualError(t, f.SetCellFormula("Sheet1", "D1", "=A1+C1", FormulaOpts{Ref: &ref, Type: &formulaType}), ErrParameterInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula5.xlsx")))
|
||||
|
||||
// Test set table formula for the cells.
|
||||
// Test set table formula for the cells
|
||||
f = NewFile()
|
||||
for idx, row := range [][]interface{}{{"A", "B", "C"}, {1, 2}} {
|
||||
assert.NoError(t, f.SetSheetRow("Sheet1", fmt.Sprintf("A%d", idx+1), &row))
|
||||
|
@ -583,46 +602,49 @@ func TestGetCellRichText(t *testing.T) {
|
|||
runsSource[1].Font.Color = strings.ToUpper(runsSource[1].Font.Color)
|
||||
assert.True(t, reflect.DeepEqual(runsSource[1].Font, runs[1].Font), "should get the same font")
|
||||
|
||||
// Test get cell rich text when string item index overflow.
|
||||
// Test get cell rich text when string item index overflow
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).SheetData.Row[0].C[0].V = "2"
|
||||
runs, err = f.GetCellRichText("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(runs))
|
||||
// Test get cell rich text when string item index is negative.
|
||||
// Test get cell rich text when string item index is negative
|
||||
ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).SheetData.Row[0].C[0].V = "-1"
|
||||
runs, err = f.GetCellRichText("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(runs))
|
||||
// Test get cell rich text on invalid string item index.
|
||||
// Test get cell rich text on invalid string item index
|
||||
ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).SheetData.Row[0].C[0].V = "x"
|
||||
_, err = f.GetCellRichText("Sheet1", "A1")
|
||||
assert.EqualError(t, err, "strconv.Atoi: parsing \"x\": invalid syntax")
|
||||
// Test set cell rich text on not exists worksheet.
|
||||
// Test set cell rich text on not exists worksheet
|
||||
_, err = f.GetCellRichText("SheetN", "A1")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test set cell rich text with illegal cell reference.
|
||||
// Test set cell rich text with illegal cell reference
|
||||
_, err = f.GetCellRichText("Sheet1", "A")
|
||||
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test set rich text color theme without tint.
|
||||
// Test set rich text color theme without tint
|
||||
assert.NoError(t, f.SetCellRichText("Sheet1", "A1", []RichTextRun{{Font: &Font{ColorTheme: &theme}}}))
|
||||
// Test set rich text color tint without theme.
|
||||
// Test set rich text color tint without theme
|
||||
assert.NoError(t, f.SetCellRichText("Sheet1", "A1", []RichTextRun{{Font: &Font{ColorTint: 0.5}}}))
|
||||
|
||||
// Test set cell rich text with unsupported charset shared strings table.
|
||||
// Test set cell rich text with unsupported charset shared strings table
|
||||
f.SharedStrings = nil
|
||||
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetCellRichText("Sheet1", "A1", runsSource), "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test get cell rich text with unsupported charset shared strings table.
|
||||
// Test get cell rich text with unsupported charset shared strings table
|
||||
f.SharedStrings = nil
|
||||
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
|
||||
_, err = f.GetCellRichText("Sheet1", "A1")
|
||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test get cell rich text with invalid sheet name
|
||||
_, err = f.GetCellRichText("Sheet:1", "A1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestSetCellRichText(t *testing.T) {
|
||||
|
@ -716,12 +738,14 @@ func TestSetCellRichText(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellRichText.xlsx")))
|
||||
// Test set cell rich text on not exists worksheet.
|
||||
// Test set cell rich text on not exists worksheet
|
||||
assert.EqualError(t, f.SetCellRichText("SheetN", "A1", richTextRun), "sheet SheetN does not exist")
|
||||
// Test set cell rich text with illegal cell reference.
|
||||
// Test set cell rich text with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellRichText("Sheet:1", "A1", richTextRun), ErrSheetNameInvalid.Error())
|
||||
// Test set cell rich text with illegal cell reference
|
||||
assert.EqualError(t, f.SetCellRichText("Sheet1", "A", richTextRun), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
richTextRun = []RichTextRun{{Text: strings.Repeat("s", TotalCellChars+1)}}
|
||||
// Test set cell rich text with characters over the maximum limit.
|
||||
// Test set cell rich text with characters over the maximum limit
|
||||
assert.EqualError(t, f.SetCellRichText("Sheet1", "A1", richTextRun), ErrCellCharsLength.Error())
|
||||
}
|
||||
|
||||
|
@ -747,7 +771,7 @@ func TestFormattedValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, "03/04/2019", result)
|
||||
|
||||
// Test format value with no built-in number format ID.
|
||||
// Test format value with no built-in number format ID
|
||||
numFmtID := 5
|
||||
f.Styles.CellXfs.Xf = append(f.Styles.CellXfs.Xf, xlsxXf{
|
||||
NumFmtID: &numFmtID,
|
||||
|
@ -756,7 +780,7 @@ func TestFormattedValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, "43528", result)
|
||||
|
||||
// Test format value with invalid number format ID.
|
||||
// Test format value with invalid number format ID
|
||||
f.Styles.CellXfs.Xf = append(f.Styles.CellXfs.Xf, xlsxXf{
|
||||
NumFmtID: nil,
|
||||
})
|
||||
|
@ -764,7 +788,7 @@ func TestFormattedValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, "43528", result)
|
||||
|
||||
// Test format value with empty number format.
|
||||
// Test format value with empty number format
|
||||
f.Styles.NumFmts = nil
|
||||
f.Styles.CellXfs.Xf = append(f.Styles.CellXfs.Xf, xlsxXf{
|
||||
NumFmtID: &numFmtID,
|
||||
|
@ -773,7 +797,7 @@ func TestFormattedValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, "43528", result)
|
||||
|
||||
// Test format decimal value with build-in number format ID.
|
||||
// Test format decimal value with build-in number format ID
|
||||
styleID, err := f.NewStyle(&Style{
|
||||
NumFmt: 1,
|
||||
})
|
||||
|
@ -786,13 +810,13 @@ func TestFormattedValue(t *testing.T) {
|
|||
assert.Equal(t, "0_0", fn("0_0", "", false))
|
||||
}
|
||||
|
||||
// Test format value with unsupported charset workbook.
|
||||
// Test format value with unsupported charset workbook
|
||||
f.WorkBook = nil
|
||||
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||
_, err = f.formattedValue(1, "43528", false)
|
||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
|
||||
// Test format value with unsupported charset style sheet.
|
||||
// Test format value with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
_, err = f.formattedValue(1, "43528", false)
|
||||
|
@ -800,7 +824,7 @@ func TestFormattedValue(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFormattedValueNilXfs(t *testing.T) {
|
||||
// Set the CellXfs to nil and verify that the formattedValue function does not crash.
|
||||
// Set the CellXfs to nil and verify that the formattedValue function does not crash
|
||||
f := NewFile()
|
||||
f.Styles.CellXfs = nil
|
||||
result, err := f.formattedValue(3, "43528", false)
|
||||
|
@ -809,7 +833,7 @@ func TestFormattedValueNilXfs(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFormattedValueNilNumFmts(t *testing.T) {
|
||||
// Set the NumFmts value to nil and verify that the formattedValue function does not crash.
|
||||
// Set the NumFmts value to nil and verify that the formattedValue function does not crash
|
||||
f := NewFile()
|
||||
f.Styles.NumFmts = nil
|
||||
result, err := f.formattedValue(3, "43528", false)
|
||||
|
@ -818,7 +842,7 @@ func TestFormattedValueNilNumFmts(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFormattedValueNilWorkbook(t *testing.T) {
|
||||
// Set the Workbook value to nil and verify that the formattedValue function does not crash.
|
||||
// Set the Workbook value to nil and verify that the formattedValue function does not crash
|
||||
f := NewFile()
|
||||
f.WorkBook = nil
|
||||
result, err := f.formattedValue(3, "43528", false)
|
||||
|
|
10
chart.go
10
chart.go
|
@ -941,8 +941,12 @@ func (f *File) AddChart(sheet, cell, opts string, combo ...string) error {
|
|||
// a chart.
|
||||
func (f *File) AddChartSheet(sheet, opts string, combo ...string) error {
|
||||
// Check if the worksheet already exists
|
||||
if f.GetSheetIndex(sheet) != -1 {
|
||||
return ErrExistsWorksheet
|
||||
idx, err := f.GetSheetIndex(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if idx != -1 {
|
||||
return ErrExistsSheet
|
||||
}
|
||||
options, comboCharts, err := f.getChartOptions(opts, combo)
|
||||
if err != nil {
|
||||
|
@ -963,7 +967,7 @@ func (f *File) AddChartSheet(sheet, opts string, combo ...string) error {
|
|||
}
|
||||
sheetID++
|
||||
path := "xl/chartsheets/sheet" + strconv.Itoa(sheetID) + ".xml"
|
||||
f.sheetMap[trimSheetName(sheet)] = path
|
||||
f.sheetMap[sheet] = path
|
||||
f.Sheet.Store(path, nil)
|
||||
drawingID := f.countDrawings() + 1
|
||||
chartID := f.countCharts() + 1
|
||||
|
|
|
@ -217,6 +217,8 @@ func TestAddChart(t *testing.T) {
|
|||
assert.NoError(t, f.AddChart("Combo Charts", axis, fmt.Sprintf(`{"type":"areaStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"%s"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true}}`, props[1]), fmt.Sprintf(`{"type":"%s","series":[{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true}}`, props[0])))
|
||||
}
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChart.xlsx")))
|
||||
// Test with invalid sheet name
|
||||
assert.EqualError(t, f.AddChart("Sheet:1", "A1", `{"type":"col","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"}]}`), ErrSheetNameInvalid.Error())
|
||||
// Test with illegal cell reference
|
||||
assert.EqualError(t, f.AddChart("Sheet2", "A", `{"type":"col","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"2D Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test with unsupported chart type
|
||||
|
@ -257,14 +259,16 @@ func TestAddChartSheet(t *testing.T) {
|
|||
// Test cell value on chartsheet
|
||||
assert.EqualError(t, f.SetCellValue("Chart1", "A1", true), "sheet Chart1 is not a worksheet")
|
||||
// Test add chartsheet on already existing name sheet
|
||||
assert.EqualError(t, f.AddChartSheet("Sheet1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`), ErrExistsWorksheet.Error())
|
||||
assert.EqualError(t, f.AddChartSheet("Sheet1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`), ErrExistsSheet.Error())
|
||||
// Test add chartsheet with invalid sheet name
|
||||
assert.EqualError(t, f.AddChartSheet("Sheet:1", "A1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`), ErrSheetNameInvalid.Error())
|
||||
// Test with unsupported chart type
|
||||
assert.EqualError(t, f.AddChartSheet("Chart2", `{"type":"unknown","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column Chart"}}`), "unsupported chart type unknown")
|
||||
|
||||
assert.NoError(t, f.UpdateLinkedValue())
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChartSheet.xlsx")))
|
||||
// Test add chart sheet with unsupported charset content types.
|
||||
// Test add chart sheet with unsupported charset content types
|
||||
f = NewFile()
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
|
@ -278,11 +282,13 @@ func TestDeleteChart(t *testing.T) {
|
|||
assert.NoError(t, f.AddChart("Sheet1", "P1", `{"type":"col","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"2D Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`))
|
||||
assert.NoError(t, f.DeleteChart("Sheet1", "P1"))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDeleteChart.xlsx")))
|
||||
// Test delete chart on not exists worksheet.
|
||||
// Test delete chart with invalid sheet name
|
||||
assert.EqualError(t, f.DeleteChart("Sheet:1", "P1"), ErrSheetNameInvalid.Error())
|
||||
// Test delete chart on not exists worksheet
|
||||
assert.EqualError(t, f.DeleteChart("SheetN", "A1"), "sheet SheetN does not exist")
|
||||
// Test delete chart with invalid coordinates.
|
||||
// Test delete chart with invalid coordinates
|
||||
assert.EqualError(t, f.DeleteChart("Sheet1", ""), newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
|
||||
// Test delete chart on no chart worksheet.
|
||||
// Test delete chart on no chart worksheet
|
||||
assert.NoError(t, NewFile().DeleteChart("Sheet1", "A1"))
|
||||
assert.NoError(t, f.Close())
|
||||
}
|
||||
|
|
5
col.go
5
col.go
|
@ -208,6 +208,9 @@ func (cols *Cols) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.Sta
|
|||
// fmt.Println()
|
||||
// }
|
||||
func (f *File) Cols(sheet string) (*Cols, error) {
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name, ok := f.getSheetXMLPath(sheet)
|
||||
if !ok {
|
||||
return nil, ErrSheetNotExist{sheet}
|
||||
|
@ -236,7 +239,7 @@ func (f *File) Cols(sheet string) (*Cols, error) {
|
|||
case xml.EndElement:
|
||||
if xmlElement.Name.Local == "sheetData" {
|
||||
colIterator.cols.f = f
|
||||
colIterator.cols.sheet = trimSheetName(sheet)
|
||||
colIterator.cols.sheet = sheet
|
||||
return &colIterator.cols, nil
|
||||
}
|
||||
}
|
||||
|
|
81
col_test.go
81
col_test.go
|
@ -57,7 +57,13 @@ func TestCols(t *testing.T) {
|
|||
_, err = f.Rows("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test columns iterator with unsupported charset shared strings table.
|
||||
// Test columns iterator with invalid sheet name
|
||||
_, err = f.Cols("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
// Test get columns cells with invalid sheet name
|
||||
_, err = f.GetCols("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
// Test columns iterator with unsupported charset shared strings table
|
||||
f.SharedStrings = nil
|
||||
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
|
||||
cols, err = f.Cols("Sheet1")
|
||||
|
@ -212,14 +218,18 @@ func TestColumnVisibility(t *testing.T) {
|
|||
assert.Equal(t, true, visible)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test get column visible on an inexistent worksheet.
|
||||
// Test get column visible on an inexistent worksheet
|
||||
_, err = f.GetColVisible("SheetN", "F")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
|
||||
// Test get column visible with illegal cell reference.
|
||||
// Test get column visible with invalid sheet name
|
||||
_, err = f.GetColVisible("Sheet:1", "F")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
// Test get column visible with illegal cell reference
|
||||
_, err = f.GetColVisible("Sheet1", "*")
|
||||
assert.EqualError(t, err, newInvalidColumnNameError("*").Error())
|
||||
assert.EqualError(t, f.SetColVisible("Sheet1", "*", false), newInvalidColumnNameError("*").Error())
|
||||
// Test set column visible with invalid sheet name
|
||||
assert.EqualError(t, f.SetColVisible("Sheet:1", "A", false), ErrSheetNameInvalid.Error())
|
||||
|
||||
f.NewSheet("Sheet3")
|
||||
assert.NoError(t, f.SetColVisible("Sheet3", "E", false))
|
||||
|
@ -254,25 +264,35 @@ func TestOutlineLevel(t *testing.T) {
|
|||
assert.Equal(t, uint8(0), level)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
|
||||
// Test column outline level with invalid sheet name
|
||||
_, err = f.GetColOutlineLevel("Sheet:1", "A")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SetColWidth("Sheet2", "A", "D", 13))
|
||||
assert.EqualError(t, f.SetColWidth("Sheet2", "A", "D", MaxColumnWidth+1), ErrColumnWidth.Error())
|
||||
// Test set column width with invalid sheet name
|
||||
assert.EqualError(t, f.SetColWidth("Sheet:1", "A", "D", 13), ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SetColOutlineLevel("Sheet2", "B", 2))
|
||||
assert.NoError(t, f.SetRowOutlineLevel("Sheet1", 2, 7))
|
||||
assert.EqualError(t, f.SetColOutlineLevel("Sheet1", "D", 8), ErrOutlineLevel.Error())
|
||||
assert.EqualError(t, f.SetRowOutlineLevel("Sheet1", 2, 8), ErrOutlineLevel.Error())
|
||||
// Test set row outline level on not exists worksheet.
|
||||
// Test set row outline level on not exists worksheet
|
||||
assert.EqualError(t, f.SetRowOutlineLevel("SheetN", 1, 4), "sheet SheetN does not exist")
|
||||
// Test get row outline level on not exists worksheet.
|
||||
// Test set row outline level with invalid sheet name
|
||||
assert.EqualError(t, f.SetRowOutlineLevel("Sheet:1", 1, 4), ErrSheetNameInvalid.Error())
|
||||
// Test get row outline level on not exists worksheet
|
||||
_, err = f.GetRowOutlineLevel("SheetN", 1)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
|
||||
// Test set and get column outline level with illegal cell reference.
|
||||
// Test get row outline level with invalid sheet name
|
||||
_, err = f.GetRowOutlineLevel("Sheet:1", 1)
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
// Test set and get column outline level with illegal cell reference
|
||||
assert.EqualError(t, f.SetColOutlineLevel("Sheet1", "*", 1), newInvalidColumnNameError("*").Error())
|
||||
_, err = f.GetColOutlineLevel("Sheet1", "*")
|
||||
assert.EqualError(t, err, newInvalidColumnNameError("*").Error())
|
||||
|
||||
// Test set column outline level on not exists worksheet.
|
||||
// Test set column outline level on not exists worksheet
|
||||
assert.EqualError(t, f.SetColOutlineLevel("SheetN", "E", 2), "sheet SheetN does not exist")
|
||||
|
||||
assert.EqualError(t, f.SetRowOutlineLevel("Sheet1", 0, 1), newInvalidRowNumberError(0).Error())
|
||||
|
@ -300,22 +320,24 @@ func TestSetColStyle(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellValue("Sheet1", "B2", "Hello"))
|
||||
styleID, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#94d3a2"],"pattern":1}}`)
|
||||
assert.NoError(t, err)
|
||||
// Test set column style on not exists worksheet.
|
||||
// Test set column style on not exists worksheet
|
||||
assert.EqualError(t, f.SetColStyle("SheetN", "E", styleID), "sheet SheetN does not exist")
|
||||
// Test set column style with illegal column name.
|
||||
// Test set column style with illegal column name
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "*", styleID), newInvalidColumnNameError("*").Error())
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "A:*", styleID), newInvalidColumnNameError("*").Error())
|
||||
// Test set column style with invalid style ID.
|
||||
// Test set column style with invalid style ID
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "B", -1), newInvalidStyleID(-1).Error())
|
||||
// Test set column style with not exists style ID.
|
||||
// Test set column style with not exists style ID
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "B", 10), newInvalidStyleID(10).Error())
|
||||
// Test set column style with invalid sheet name
|
||||
assert.EqualError(t, f.SetColStyle("Sheet:1", "A", 0), ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "B", styleID))
|
||||
style, err := f.GetColStyle("Sheet1", "B")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, styleID, style)
|
||||
|
||||
// Test set column style with already exists column with style.
|
||||
// Test set column style with already exists column with style
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "B", styleID))
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "D:C", styleID))
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
|
@ -325,7 +347,7 @@ func TestSetColStyle(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, styleID, cellStyleID)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetColStyle.xlsx")))
|
||||
// Test set column style with unsupported charset style sheet.
|
||||
// Test set column style with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "C:F", styleID), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
@ -342,19 +364,21 @@ func TestColWidth(t *testing.T) {
|
|||
assert.Equal(t, defaultColWidth, width)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test set and get column width with illegal cell reference.
|
||||
// Test set and get column width with illegal cell reference
|
||||
width, err = f.GetColWidth("Sheet1", "*")
|
||||
assert.Equal(t, defaultColWidth, width)
|
||||
assert.EqualError(t, err, newInvalidColumnNameError("*").Error())
|
||||
assert.EqualError(t, f.SetColWidth("Sheet1", "*", "B", 1), newInvalidColumnNameError("*").Error())
|
||||
assert.EqualError(t, f.SetColWidth("Sheet1", "A", "*", 1), newInvalidColumnNameError("*").Error())
|
||||
|
||||
// Test set column width on not exists worksheet.
|
||||
// Test set column width on not exists worksheet
|
||||
assert.EqualError(t, f.SetColWidth("SheetN", "B", "A", 12), "sheet SheetN does not exist")
|
||||
|
||||
// Test get column width on not exists worksheet.
|
||||
// Test get column width on not exists worksheet
|
||||
_, err = f.GetColWidth("SheetN", "A")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get column width invalid sheet name
|
||||
_, err = f.GetColWidth("Sheet:1", "A")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestColWidth.xlsx")))
|
||||
convertRowHeightToPixels(0)
|
||||
|
@ -366,12 +390,15 @@ func TestGetColStyle(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, styleID, 0)
|
||||
|
||||
// Test set column style on not exists worksheet.
|
||||
// Test get column style on not exists worksheet
|
||||
_, err = f.GetColStyle("SheetN", "A")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test set column style with illegal column name.
|
||||
// Test get column style with illegal column name
|
||||
_, err = f.GetColStyle("Sheet1", "*")
|
||||
assert.EqualError(t, err, newInvalidColumnNameError("*").Error())
|
||||
// Test get column style with invalid sheet name
|
||||
_, err = f.GetColStyle("Sheet:1", "A")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestInsertCols(t *testing.T) {
|
||||
|
@ -386,9 +413,10 @@ func TestInsertCols(t *testing.T) {
|
|||
assert.NoError(t, f.AutoFilter(sheet1, "A2", "B2", `{"column":"B","expression":"x != blanks"}`))
|
||||
assert.NoError(t, f.InsertCols(sheet1, "A", 1))
|
||||
|
||||
// Test insert column with illegal cell reference.
|
||||
// Test insert column with illegal cell reference
|
||||
assert.EqualError(t, f.InsertCols(sheet1, "*", 1), newInvalidColumnNameError("*").Error())
|
||||
|
||||
// Test insert column with invalid sheet name
|
||||
assert.EqualError(t, f.InsertCols("Sheet:1", "A", 1), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, f.InsertCols(sheet1, "A", 0), ErrColumnNumber.Error())
|
||||
assert.EqualError(t, f.InsertCols(sheet1, "A", MaxColumns), ErrColumnNumber.Error())
|
||||
assert.EqualError(t, f.InsertCols(sheet1, "A", MaxColumns-10), ErrColumnNumber.Error())
|
||||
|
@ -411,11 +439,12 @@ func TestRemoveCol(t *testing.T) {
|
|||
assert.NoError(t, f.RemoveCol(sheet1, "A"))
|
||||
assert.NoError(t, f.RemoveCol(sheet1, "A"))
|
||||
|
||||
// Test remove column with illegal cell reference.
|
||||
// Test remove column with illegal cell reference
|
||||
assert.EqualError(t, f.RemoveCol("Sheet1", "*"), newInvalidColumnNameError("*").Error())
|
||||
|
||||
// Test remove column on not exists worksheet.
|
||||
// Test remove column on not exists worksheet
|
||||
assert.EqualError(t, f.RemoveCol("SheetN", "B"), "sheet SheetN does not exist")
|
||||
// Test remove column with invalid sheet name
|
||||
assert.EqualError(t, f.RemoveCol("Sheet:1", "A"), ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRemoveCol.xlsx")))
|
||||
}
|
||||
|
|
|
@ -143,6 +143,9 @@ func (f *File) AddComment(sheet string, comment Comment) error {
|
|||
//
|
||||
// err := f.DeleteComment("Sheet1", "A30")
|
||||
func (f *File) DeleteComment(sheet, cell string) error {
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return err
|
||||
}
|
||||
sheetXMLPath, ok := f.getSheetXMLPath(sheet)
|
||||
if !ok {
|
||||
return newNoExistSheetError(sheet)
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAddComments(t *testing.T) {
|
||||
func TestAddComment(t *testing.T) {
|
||||
f, err := prepareTestBook1()
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
|
@ -30,7 +30,7 @@ func TestAddComments(t *testing.T) {
|
|||
assert.NoError(t, f.AddComment("Sheet1", Comment{Cell: "A30", Author: s, Text: s, Runs: []RichTextRun{{Text: s}, {Text: s}}}))
|
||||
assert.NoError(t, f.AddComment("Sheet2", Comment{Cell: "B7", Author: "Excelize", Text: s[:TotalCellChars-1], Runs: []RichTextRun{{Text: "Excelize: ", Font: &Font{Bold: true}}, {Text: "This is a comment."}}}))
|
||||
|
||||
// Test add comment on not exists worksheet.
|
||||
// Test add comment on not exists worksheet
|
||||
assert.EqualError(t, f.AddComment("SheetN", Comment{Cell: "B7", Author: "Excelize", Runs: []RichTextRun{{Text: "Excelize: ", Font: &Font{Bold: true}}, {Text: "This is a comment."}}}), "sheet SheetN does not exist")
|
||||
// Test add comment on with illegal cell reference
|
||||
assert.EqualError(t, f.AddComment("Sheet1", Comment{Cell: "A", Author: "Excelize", Runs: []RichTextRun{{Text: "Excelize: ", Font: &Font{Bold: true}}, {Text: "This is a comment."}}}), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
@ -50,18 +50,21 @@ func TestAddComments(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, len(comments), 0)
|
||||
|
||||
// Test add comments with unsupported charset.
|
||||
// Test add comments with invalid sheet name
|
||||
assert.EqualError(t, f.AddComment("Sheet:1", Comment{Cell: "A1", Author: "Excelize", Text: "This is a comment."}), ErrSheetNameInvalid.Error())
|
||||
|
||||
// Test add comments with unsupported charset
|
||||
f.Comments["xl/comments2.xml"] = nil
|
||||
f.Pkg.Store("xl/comments2.xml", MacintoshCyrillicCharset)
|
||||
_, err = f.GetComments()
|
||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
|
||||
// Test add comments with unsupported charset.
|
||||
// Test add comments with unsupported charset
|
||||
f.Comments["xl/comments2.xml"] = nil
|
||||
f.Pkg.Store("xl/comments2.xml", MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.AddComment("Sheet2", Comment{Cell: "A30", Text: "Comment"}), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
||||
// Test add comments with unsupported charset style sheet.
|
||||
// Test add comments with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.AddComment("Sheet2", Comment{Cell: "A30", Text: "Comment"}), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
@ -90,6 +93,8 @@ func TestDeleteComment(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, len(comments), 0)
|
||||
|
||||
// Test delete comment with invalid sheet name
|
||||
assert.EqualError(t, f.DeleteComment("Sheet:1", "A1"), ErrSheetNameInvalid.Error())
|
||||
// Test delete all comments in a worksheet
|
||||
assert.NoError(t, f.DeleteComment("Sheet2", "A41"))
|
||||
assert.NoError(t, f.DeleteComment("Sheet2", "C41"))
|
||||
|
@ -118,7 +123,7 @@ func TestDecodeVMLDrawingReader(t *testing.T) {
|
|||
|
||||
func TestCommentsReader(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test read comments with unsupported charset.
|
||||
// Test read comments with unsupported charset
|
||||
path := "xl/comments1.xml"
|
||||
f.Pkg.Store(path, MacintoshCyrillicCharset)
|
||||
_, err := f.commentsReader(path)
|
||||
|
|
|
@ -91,6 +91,9 @@ func TestDataValidation(t *testing.T) {
|
|||
// Test get data validation on no exists worksheet
|
||||
_, err = f.GetDataValidations("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get data validation with invalid sheet name
|
||||
_, err = f.GetDataValidations("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SaveAs(resultFile))
|
||||
|
||||
|
@ -130,7 +133,7 @@ func TestDataValidationError(t *testing.T) {
|
|||
|
||||
assert.NoError(t, f.AddDataValidation("Sheet1", dvRange))
|
||||
|
||||
// Test width invalid data validation formula.
|
||||
// Test width invalid data validation formula
|
||||
prevFormula1 := dvRange.Formula1
|
||||
for _, keys := range [][]string{
|
||||
make([]string, 257),
|
||||
|
@ -156,9 +159,13 @@ func TestDataValidationError(t *testing.T) {
|
|||
DataValidationTypeWhole, DataValidationOperatorGreaterThan), ErrDataValidationRange.Error())
|
||||
assert.NoError(t, f.SaveAs(resultFile))
|
||||
|
||||
// Test add data validation on no exists worksheet.
|
||||
// Test add data validation on no exists worksheet
|
||||
f = NewFile()
|
||||
assert.EqualError(t, f.AddDataValidation("SheetN", nil), "sheet SheetN does not exist")
|
||||
|
||||
// Test add data validation with invalid sheet name
|
||||
f = NewFile()
|
||||
assert.EqualError(t, f.AddDataValidation("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestDeleteDataValidation(t *testing.T) {
|
||||
|
@ -200,10 +207,11 @@ func TestDeleteDataValidation(t *testing.T) {
|
|||
ws.(*xlsxWorksheet).DataValidations.DataValidation[0].Sqref = "A1:A"
|
||||
assert.EqualError(t, f.DeleteDataValidation("Sheet1", "A1:B2"), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
// Test delete data validation on no exists worksheet.
|
||||
// Test delete data validation on no exists worksheet
|
||||
assert.EqualError(t, f.DeleteDataValidation("SheetN", "A1:B2"), "sheet SheetN does not exist")
|
||||
|
||||
// Test delete all data validations in the worksheet.
|
||||
// Test delete all data validation with invalid sheet name
|
||||
assert.EqualError(t, f.DeleteDataValidation("Sheet:1"), ErrSheetNameInvalid.Error())
|
||||
// Test delete all data validations in the worksheet
|
||||
assert.NoError(t, f.DeleteDataValidation("Sheet1"))
|
||||
assert.Nil(t, ws.(*xlsxWorksheet).DataValidations)
|
||||
}
|
||||
|
|
17
errors.go
17
errors.go
|
@ -113,9 +113,8 @@ var (
|
|||
// ErrCoordinates defined the error message on invalid coordinates tuples
|
||||
// length.
|
||||
ErrCoordinates = errors.New("coordinates length must be 4")
|
||||
// ErrExistsWorksheet defined the error message on given worksheet already
|
||||
// exists.
|
||||
ErrExistsWorksheet = errors.New("the same name worksheet already exists")
|
||||
// ErrExistsSheet defined the error message on given sheet already exists.
|
||||
ErrExistsSheet = errors.New("the same name sheet already exists")
|
||||
// ErrTotalSheetHyperlinks defined the error message on hyperlinks count
|
||||
// overflow.
|
||||
ErrTotalSheetHyperlinks = errors.New("over maximum limit hyperlinks in a worksheet")
|
||||
|
@ -219,4 +218,16 @@ var (
|
|||
// ErrWorkbookPassword defined the error message on receiving the incorrect
|
||||
// workbook password.
|
||||
ErrWorkbookPassword = errors.New("the supplied open workbook password is not correct")
|
||||
// ErrSheetNameInvalid defined the error message on receive the sheet name
|
||||
// contains invalid characters.
|
||||
ErrSheetNameInvalid = errors.New("the sheet can not contain any of the characters :\\/?*[or]")
|
||||
// ErrSheetNameSingleQuote defined the error message on the first or last
|
||||
// character of the sheet name was a single quote.
|
||||
ErrSheetNameSingleQuote = errors.New("the first or last character of the sheet name can not be a single quote")
|
||||
// ErrSheetNameBlank defined the error message on receive the blank sheet
|
||||
// name.
|
||||
ErrSheetNameBlank = errors.New("the sheet name can not be blank")
|
||||
// ErrSheetNameLength defined the error message on receiving the sheet
|
||||
// name length exceeds the limit.
|
||||
ErrSheetNameLength = fmt.Errorf("the sheet name length exceeds the %d characters limit", MaxSheetNameLength)
|
||||
)
|
||||
|
|
|
@ -233,6 +233,9 @@ func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err error) {
|
|||
name string
|
||||
ok bool
|
||||
)
|
||||
if err = checkSheetName(sheet); err != nil {
|
||||
return
|
||||
}
|
||||
if name, ok = f.getSheetXMLPath(sheet); !ok {
|
||||
err = newNoExistSheetError(sheet)
|
||||
return
|
||||
|
|
176
excelize_test.go
176
excelize_test.go
|
@ -23,14 +23,17 @@ import (
|
|||
)
|
||||
|
||||
func TestOpenFile(t *testing.T) {
|
||||
// Test update the spreadsheet file.
|
||||
// Test update the spreadsheet file
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test get all the rows in a not exists worksheet.
|
||||
// Test get all the rows in a not exists worksheet
|
||||
_, err = f.GetRows("Sheet4")
|
||||
assert.EqualError(t, err, "sheet Sheet4 does not exist")
|
||||
// Test get all the rows in a worksheet.
|
||||
// Test get all the rows with invalid sheet name
|
||||
_, err = f.GetRows("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
// Test get all the rows in a worksheet
|
||||
rows, err := f.GetRows("Sheet2")
|
||||
expected := [][]string{
|
||||
{"Monitor", "", "Brand", "", "inlineStr"},
|
||||
|
@ -52,40 +55,44 @@ func TestOpenFile(t *testing.T) {
|
|||
|
||||
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(100.1588, 'f', -1, 32)))
|
||||
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(-100.1588, 'f', -1, 64)))
|
||||
|
||||
// Test set cell value with illegal row number.
|
||||
// Test set cell value with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellDefault("Sheet:1", "A1", ""), ErrSheetNameInvalid.Error())
|
||||
// Test set cell value with illegal row number
|
||||
assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(-100.1588, 'f', -1, 64)),
|
||||
newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100))
|
||||
|
||||
// Test set cell integer value with illegal row number.
|
||||
// Test set cell integer value with illegal row number
|
||||
assert.EqualError(t, f.SetCellInt("Sheet2", "A", 100), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test set cell integer value with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellInt("Sheet:1", "A1", 100), ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SetCellStr("Sheet2", "C11", "Knowns"))
|
||||
// Test max characters in a cell.
|
||||
// Test max characters in a cell
|
||||
assert.NoError(t, f.SetCellStr("Sheet2", "D11", strings.Repeat("c", TotalCellChars+2)))
|
||||
f.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.")
|
||||
// Test set worksheet name with illegal name.
|
||||
// Test set worksheet name with illegal name
|
||||
f.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
|
||||
assert.EqualError(t, f.SetCellInt("Sheet3", "A23", 10), "sheet Sheet3 does not exist")
|
||||
assert.EqualError(t, f.SetCellStr("Sheet3", "b230", "10"), "sheet Sheet3 does not exist")
|
||||
assert.EqualError(t, f.SetCellStr("Sheet10", "b230", "10"), "sheet Sheet10 does not exist")
|
||||
|
||||
// Test set cell string value with illegal row number.
|
||||
// Test set cell string data type value with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellStr("Sheet:1", "A1", "1"), ErrSheetNameInvalid.Error())
|
||||
// Test set cell string value with illegal row number
|
||||
assert.EqualError(t, f.SetCellStr("Sheet1", "A", "10"), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
f.SetActiveSheet(2)
|
||||
// Test get cell formula with given rows number.
|
||||
// Test get cell formula with given rows number
|
||||
_, err = f.GetCellFormula("Sheet1", "B19")
|
||||
assert.NoError(t, err)
|
||||
// Test get cell formula with illegal worksheet name.
|
||||
// Test get cell formula with illegal worksheet name
|
||||
_, err = f.GetCellFormula("Sheet2", "B20")
|
||||
assert.NoError(t, err)
|
||||
_, err = f.GetCellFormula("Sheet1", "B20")
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test get cell formula with illegal rows number.
|
||||
// Test get cell formula with illegal rows number
|
||||
_, err = f.GetCellFormula("Sheet1", "B")
|
||||
assert.EqualError(t, err, newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
|
||||
// Test get shared cell formula
|
||||
|
@ -110,7 +117,7 @@ func TestOpenFile(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
_, err = f.GetCellValue("Sheet2", "D12")
|
||||
assert.NoError(t, err)
|
||||
// Test SetCellValue function.
|
||||
// Test SetCellValue function
|
||||
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))
|
||||
|
@ -130,7 +137,7 @@ func TestOpenFile(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellValue("Sheet2", "F16", true))
|
||||
assert.NoError(t, f.SetCellValue("Sheet2", "F17", complex64(5+10i)))
|
||||
|
||||
// Test on not exists worksheet.
|
||||
// Test on not exists worksheet
|
||||
assert.EqualError(t, f.SetCellDefault("SheetN", "A1", ""), "sheet SheetN does not exist")
|
||||
assert.EqualError(t, f.SetCellFloat("SheetN", "A1", 42.65418, 2, 32), "sheet SheetN does not exist")
|
||||
assert.EqualError(t, f.SetCellBool("SheetN", "A1", true), "sheet SheetN does not exist")
|
||||
|
@ -163,18 +170,18 @@ func TestOpenFile(t *testing.T) {
|
|||
assert.EqualError(t, f.SetCellValue("SheetN", "A1", time.Now()), "sheet SheetN does not exist")
|
||||
// 02:46:40
|
||||
assert.NoError(t, f.SetCellValue("Sheet2", "G5", time.Duration(1e13)))
|
||||
// Test completion column.
|
||||
// Test completion column
|
||||
assert.NoError(t, f.SetCellValue("Sheet2", "M2", nil))
|
||||
// Test read cell value with given cell reference large than exists row.
|
||||
// Test read cell value with given cell reference large than exists row
|
||||
_, err = f.GetCellValue("Sheet2", "E231")
|
||||
assert.NoError(t, err)
|
||||
// Test get active worksheet of spreadsheet and get worksheet name of spreadsheet by given worksheet index.
|
||||
// Test get active worksheet of spreadsheet and get worksheet name of spreadsheet by given worksheet index
|
||||
f.GetSheetName(f.GetActiveSheetIndex())
|
||||
// Test get worksheet index of spreadsheet by given worksheet name.
|
||||
// Test get worksheet index of spreadsheet by given worksheet name
|
||||
f.GetSheetIndex("Sheet1")
|
||||
// Test get worksheet name of spreadsheet by given invalid worksheet index.
|
||||
// Test get worksheet name of spreadsheet by given invalid worksheet index
|
||||
f.GetSheetName(4)
|
||||
// Test get worksheet map of workbook.
|
||||
// Test get worksheet map of workbook
|
||||
f.GetSheetMap()
|
||||
for i := 1; i <= 300; i++ {
|
||||
assert.NoError(t, f.SetCellStr("Sheet2", "c"+strconv.Itoa(i), strconv.Itoa(i)))
|
||||
|
@ -202,7 +209,7 @@ func TestSaveFile(t *testing.T) {
|
|||
func TestSaveAsWrongPath(t *testing.T) {
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
// Test write file to not exist directory.
|
||||
// Test write file to not exist directory
|
||||
assert.Error(t, f.SaveAs(filepath.Join("x", "Book1.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
}
|
||||
|
@ -218,7 +225,7 @@ func TestOpenReader(t *testing.T) {
|
|||
_, err = OpenReader(bytes.NewReader(oleIdentifier), Options{Password: "password", UnzipXMLSizeLimit: UnzipSizeLimit + 1})
|
||||
assert.EqualError(t, err, ErrWorkbookFileFormat.Error())
|
||||
|
||||
// Test open workbook with unsupported charset internal calculation chain.
|
||||
// Test open workbook with unsupported charset internal calculation chain
|
||||
preset := func(filePath string) *bytes.Buffer {
|
||||
source, err := zip.OpenReader(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
|
@ -245,11 +252,11 @@ func TestOpenReader(t *testing.T) {
|
|||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
}
|
||||
|
||||
// Test open spreadsheet with unzip size limit.
|
||||
// Test open spreadsheet with unzip size limit
|
||||
_, err = OpenFile(filepath.Join("test", "Book1.xlsx"), Options{UnzipSizeLimit: 100})
|
||||
assert.EqualError(t, err, newUnzipSizeLimitError(100).Error())
|
||||
|
||||
// Test open password protected spreadsheet created by Microsoft Office Excel 2010.
|
||||
// Test open password protected spreadsheet created by Microsoft Office Excel 2010
|
||||
f, err := OpenFile(filepath.Join("test", "encryptSHA1.xlsx"), Options{Password: "password"})
|
||||
assert.NoError(t, err)
|
||||
val, err := f.GetCellValue("Sheet1", "A1")
|
||||
|
@ -257,7 +264,7 @@ func TestOpenReader(t *testing.T) {
|
|||
assert.Equal(t, "SECRET", val)
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test open password protected spreadsheet created by LibreOffice 7.0.0.3.
|
||||
// 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")
|
||||
|
@ -265,11 +272,11 @@ func TestOpenReader(t *testing.T) {
|
|||
assert.Equal(t, "SECRET", val)
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test open spreadsheet with invalid options.
|
||||
// Test open spreadsheet with invalid options
|
||||
_, err = OpenReader(bytes.NewReader(oleIdentifier), Options{UnzipSizeLimit: 1, UnzipXMLSizeLimit: 2})
|
||||
assert.EqualError(t, err, ErrOptionsUnzipSizeLimit.Error())
|
||||
|
||||
// Test unexpected EOF.
|
||||
// Test unexpected EOF
|
||||
var b bytes.Buffer
|
||||
w := gzip.NewWriter(&b)
|
||||
defer w.Close()
|
||||
|
@ -299,7 +306,7 @@ func TestOpenReader(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBrokenFile(t *testing.T) {
|
||||
// Test write file with broken file struct.
|
||||
// Test write file with broken file struct
|
||||
f := File{}
|
||||
|
||||
t.Run("SaveWithoutName", func(t *testing.T) {
|
||||
|
@ -307,12 +314,12 @@ func TestBrokenFile(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("SaveAsEmptyStruct", func(t *testing.T) {
|
||||
// Test write file with broken file struct with given path.
|
||||
// Test write file with broken file struct with given path
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "BadWorkbook.SaveAsEmptyStruct.xlsx")))
|
||||
})
|
||||
|
||||
t.Run("OpenBadWorkbook", func(t *testing.T) {
|
||||
// Test set active sheet without BookViews and Sheets maps in xl/workbook.xml.
|
||||
// Test set active sheet without BookViews and Sheets maps in xl/workbook.xml
|
||||
f3, err := OpenFile(filepath.Join("test", "BadWorkbook.xlsx"))
|
||||
f3.GetActiveSheetIndex()
|
||||
f3.SetActiveSheet(1)
|
||||
|
@ -321,7 +328,7 @@ func TestBrokenFile(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("OpenNotExistsFile", func(t *testing.T) {
|
||||
// Test open a spreadsheet file with given illegal path.
|
||||
// Test open a spreadsheet file with given illegal path
|
||||
_, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
|
||||
if assert.Error(t, err) {
|
||||
assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
|
||||
|
@ -330,7 +337,7 @@ func TestBrokenFile(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewFile(t *testing.T) {
|
||||
// Test create a spreadsheet file.
|
||||
// Test create a spreadsheet file
|
||||
f := NewFile()
|
||||
f.NewSheet("Sheet1")
|
||||
f.NewSheet("XLSXSheet2")
|
||||
|
@ -339,20 +346,20 @@ func TestNewFile(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellStr("Sheet1", "B20", "42"))
|
||||
f.SetActiveSheet(0)
|
||||
|
||||
// Test add picture to sheet with scaling and positioning.
|
||||
// Test add picture to sheet with scaling and positioning
|
||||
err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
|
||||
`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Test add picture to worksheet without options.
|
||||
// Test add picture to worksheet without options
|
||||
err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Test add picture to worksheet with invalid options.
|
||||
// Test add picture to worksheet with invalid options
|
||||
err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), `{`)
|
||||
if !assert.Error(t, err) {
|
||||
t.FailNow()
|
||||
|
@ -363,7 +370,7 @@ func TestNewFile(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAddDrawingVML(t *testing.T) {
|
||||
// Test addDrawingVML with illegal cell reference.
|
||||
// Test addDrawingVML with illegal cell reference
|
||||
f := NewFile()
|
||||
assert.EqualError(t, f.addDrawingVML(0, "", "*", 0, 0), newCellNameToCoordinatesError("*", newInvalidCellNameError("*")).Error())
|
||||
|
||||
|
@ -374,23 +381,22 @@ func TestAddDrawingVML(t *testing.T) {
|
|||
func TestSetCellHyperLink(t *testing.T) {
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
// Test set cell hyperlink in a work sheet already have hyperlinks.
|
||||
// Test set cell hyperlink in a work sheet already have hyperlinks
|
||||
assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/xuri/excelize", "External"))
|
||||
// Test add first hyperlink in a work sheet.
|
||||
// Test add first hyperlink in a work sheet
|
||||
assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/xuri/excelize", "External"))
|
||||
// Test add Location hyperlink in a work sheet.
|
||||
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
|
||||
// Test add Location hyperlink with display & tooltip in a work sheet.
|
||||
// Test add Location hyperlink with display & tooltip in a work sheet
|
||||
display, tooltip := "Display value", "Hover text"
|
||||
assert.NoError(t, f.SetCellHyperLink("Sheet2", "D7", "Sheet1!D9", "Location", HyperlinkOpts{
|
||||
Display: &display,
|
||||
Tooltip: &tooltip,
|
||||
}))
|
||||
|
||||
// Test set cell hyperlink with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellHyperLink("Sheet:1", "A1", "Sheet1!D60", "Location"), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, f.SetCellHyperLink("Sheet2", "C3", "Sheet1!D8", ""), `invalid link type ""`)
|
||||
|
||||
assert.EqualError(t, f.SetCellHyperLink("Sheet2", "", "Sheet1!D60", "Location"), `invalid cell name ""`)
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
|
@ -467,6 +473,10 @@ func TestGetCellHyperLink(t *testing.T) {
|
|||
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
assert.Equal(t, link, false)
|
||||
assert.Equal(t, target, "")
|
||||
|
||||
// Test get cell hyperlink with invalid sheet name
|
||||
_, _, err = f.GetCellHyperLink("Sheet:1", "A1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestSetSheetBackground(t *testing.T) {
|
||||
|
@ -489,12 +499,14 @@ func TestSetSheetBackgroundErrors(t *testing.T) {
|
|||
|
||||
err = f.SetSheetBackground("Sheet2", filepath.Join("test", "Book1.xlsx"))
|
||||
assert.EqualError(t, err, ErrImgExt.Error())
|
||||
// Test set sheet background on not exist worksheet.
|
||||
// Test set sheet background on not exist worksheet
|
||||
err = f.SetSheetBackground("SheetN", filepath.Join("test", "images", "background.jpg"))
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test set sheet background with invalid sheet name
|
||||
assert.EqualError(t, f.SetSheetBackground("Sheet:1", filepath.Join("test", "images", "background.jpg")), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test set sheet background with unsupported charset content types.
|
||||
// Test set sheet background with unsupported charset content types
|
||||
f = NewFile()
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
|
@ -510,7 +522,6 @@ func TestWriteArrayFormula(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -621,15 +632,20 @@ func TestSetCellStyleAlignment(t *testing.T) {
|
|||
|
||||
assert.NoError(t, f.SetCellStyle("Sheet1", "A22", "A22", style))
|
||||
|
||||
// Test set cell style with given illegal rows number.
|
||||
// Test set cell style with given illegal rows number
|
||||
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())
|
||||
|
||||
// Test get cell style with given illegal rows number.
|
||||
// Test set cell style with invalid sheet name
|
||||
assert.EqualError(t, f.SetCellStyle("Sheet:1", "A1", "A2", style), ErrSheetNameInvalid.Error())
|
||||
// Test get cell style with given illegal rows number
|
||||
index, err := f.GetCellStyle("Sheet1", "A")
|
||||
assert.Equal(t, 0, index)
|
||||
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
// Test get cell style with invalid sheet name
|
||||
_, err = f.GetCellStyle("Sheet:1", "A1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleAlignment.xlsx")))
|
||||
}
|
||||
|
||||
|
@ -987,18 +1003,18 @@ func TestSheetVisibility(t *testing.T) {
|
|||
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"))
|
||||
|
||||
visible, err := f.GetSheetVisible("Sheet1")
|
||||
assert.Equal(t, true, visible)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSheetVisibility.xlsx")))
|
||||
}
|
||||
|
||||
func TestCopySheet(t *testing.T) {
|
||||
f, err := prepareTestBook1()
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
idx := f.NewSheet("CopySheet")
|
||||
idx, err := f.NewSheet("CopySheet")
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.CopySheet(0, idx))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("CopySheet", "F1", "Hello"))
|
||||
|
@ -1011,15 +1027,9 @@ func TestCopySheet(t *testing.T) {
|
|||
|
||||
func TestCopySheetError(t *testing.T) {
|
||||
f, err := prepareTestBook1()
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.EqualError(t, f.copySheet(-1, -2), "sheet does not exist")
|
||||
if !assert.EqualError(t, f.CopySheet(-1, -2), "invalid worksheet index") {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.EqualError(t, f.copySheet(-1, -2), ErrSheetNameBlank.Error())
|
||||
assert.EqualError(t, f.CopySheet(-1, -2), ErrSheetIdx.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx")))
|
||||
}
|
||||
|
||||
|
@ -1072,9 +1082,9 @@ func TestConditionalFormat(t *testing.T) {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// Color scales: 2 color.
|
||||
// Color scales: 2 color
|
||||
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"}]`))
|
||||
// Color scales: 3 color.
|
||||
// Color scales: 3 color
|
||||
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"}]`))
|
||||
// Highlight cells rules: between...
|
||||
assert.NoError(t, f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1)))
|
||||
|
@ -1092,29 +1102,31 @@ func TestConditionalFormat(t *testing.T) {
|
|||
assert.NoError(t, f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3)))
|
||||
// Top/Bottom rules: Below Average...
|
||||
assert.NoError(t, f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1)))
|
||||
// Data Bars: Gradient Fill.
|
||||
// Data Bars: Gradient Fill
|
||||
assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
|
||||
// Use a formula to determine which cells to format.
|
||||
// Use a formula to determine which cells to format
|
||||
assert.NoError(t, f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1)))
|
||||
// Alignment/Border cells rules.
|
||||
// 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.
|
||||
// Test set invalid format set in conditional format
|
||||
assert.EqualError(t, f.SetConditionalFormat(sheet1, "L1:L10", ""), "unexpected end of JSON input")
|
||||
// Set conditional format on not exists worksheet.
|
||||
// Test set conditional format on not exists worksheet
|
||||
assert.EqualError(t, f.SetConditionalFormat("SheetN", "L1:L10", "[]"), "sheet SheetN does not exist")
|
||||
// Test set conditional format with invalid sheet name
|
||||
assert.EqualError(t, f.SetConditionalFormat("Sheet:1", "L1:L10", "[]"), ErrSheetNameInvalid.Error())
|
||||
|
||||
err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx"))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Set conditional format with illegal valid type.
|
||||
// Set conditional format with illegal valid type
|
||||
assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
|
||||
// Set conditional format with illegal criteria type.
|
||||
// Set conditional format with illegal criteria type
|
||||
assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
|
||||
|
||||
// Set conditional format with file without dxfs element should not return error.
|
||||
// Set conditional format with file without dxfs element should not return error
|
||||
f, err = OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
|
@ -1168,7 +1180,8 @@ func TestSetSheetCol(t *testing.T) {
|
|||
|
||||
assert.EqualError(t, f.SetSheetCol("Sheet1", "", &[]interface{}{"cell", nil, 2}),
|
||||
newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
|
||||
|
||||
// Test set worksheet column values with invalid sheet name
|
||||
assert.EqualError(t, f.SetSheetCol("Sheet:1", "A1", &[]interface{}{nil}), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, f.SetSheetCol("Sheet1", "B27", []interface{}{}), ErrParameterInvalid.Error())
|
||||
assert.EqualError(t, f.SetSheetCol("Sheet1", "B27", &f), ErrParameterInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetCol.xlsx")))
|
||||
|
@ -1185,7 +1198,8 @@ func TestSetSheetRow(t *testing.T) {
|
|||
|
||||
assert.EqualError(t, f.SetSheetRow("Sheet1", "", &[]interface{}{"cell", nil, 2}),
|
||||
newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
|
||||
|
||||
// Test set worksheet row with invalid sheet name
|
||||
assert.EqualError(t, f.SetSheetRow("Sheet:1", "A1", &[]interface{}{1}), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", []interface{}{}), ErrParameterInvalid.Error())
|
||||
assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", &f), ErrParameterInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetRow.xlsx")))
|
||||
|
@ -1261,6 +1275,8 @@ func TestProtectSheet(t *testing.T) {
|
|||
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 invalid sheet name
|
||||
assert.EqualError(t, f.UnprotectSheet("Sheet:1", "wrongPassword"), ErrSheetNameInvalid.Error())
|
||||
// Test remove sheet protection with password verification
|
||||
assert.NoError(t, f.UnprotectSheet(sheetName, "password"))
|
||||
// Test protect worksheet with empty password
|
||||
|
@ -1276,8 +1292,10 @@ func TestProtectSheet(t *testing.T) {
|
|||
AlgorithmName: "RIPEMD-160",
|
||||
Password: "password",
|
||||
}), ErrUnsupportedHashAlgorithm.Error())
|
||||
// Test protect not exists worksheet.
|
||||
// Test protect not exists worksheet
|
||||
assert.EqualError(t, f.ProtectSheet("SheetN", nil), "sheet SheetN does not exist")
|
||||
// Test protect sheet with invalid sheet name
|
||||
assert.EqualError(t, f.ProtectSheet("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestUnprotectSheet(t *testing.T) {
|
||||
|
@ -1326,10 +1344,10 @@ func TestAddVBAProject(t *testing.T) {
|
|||
assert.EqualError(t, f.AddVBAProject("macros.bin"), "stat macros.bin: no such file or directory")
|
||||
assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "Book1.xlsx")), ErrAddVBAProject.Error())
|
||||
assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
|
||||
// Test add VBA project twice.
|
||||
// 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")))
|
||||
// Test add VBs with unsupported charset workbook relationships.
|
||||
// Test add VBA with unsupported charset workbook relationships
|
||||
f.Relationships.Delete(defaultXMLPathWorkbookRels)
|
||||
f.Pkg.Store(defaultXMLPathWorkbookRels, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
|
|
@ -29,7 +29,8 @@ func TestMergeCell(t *testing.T) {
|
|||
value, err := f.GetCellValue("Sheet1", "H11")
|
||||
assert.Equal(t, "100", value)
|
||||
assert.NoError(t, err)
|
||||
value, err = f.GetCellValue("Sheet2", "A6") // Merged cell ref is single coordinate.
|
||||
// Merged cell ref is single coordinate
|
||||
value, err = f.GetCellValue("Sheet2", "A6")
|
||||
assert.Equal(t, "", value)
|
||||
assert.NoError(t, err)
|
||||
value, err = f.GetCellFormula("Sheet1", "G12")
|
||||
|
@ -64,9 +65,10 @@ func TestMergeCell(t *testing.T) {
|
|||
assert.NoError(t, f.MergeCell("Sheet3", "M8", "Q13"))
|
||||
assert.NoError(t, f.MergeCell("Sheet3", "N10", "O11"))
|
||||
|
||||
// Test get merged cells on not exists worksheet.
|
||||
// Test merge cells on not exists worksheet
|
||||
assert.EqualError(t, f.MergeCell("SheetN", "N10", "O11"), "sheet SheetN does not exist")
|
||||
|
||||
// Test merged cells with invalid sheet name
|
||||
assert.EqualError(t, f.MergeCell("Sheet:1", "N10", "O11"), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestMergeCell.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
|
@ -137,8 +139,10 @@ func TestGetMergeCells(t *testing.T) {
|
|||
assert.Equal(t, wants[i].start, m.GetStartAxis())
|
||||
assert.Equal(t, wants[i].end, m.GetEndAxis())
|
||||
}
|
||||
|
||||
// Test get merged cells on not exists worksheet.
|
||||
// Test get merged cells with invalid sheet name
|
||||
_, err = f.GetMergeCells("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
// Test get merged cells on not exists worksheet
|
||||
_, err = f.GetMergeCells("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
assert.NoError(t, f.Close())
|
||||
|
@ -158,7 +162,7 @@ func TestUnmergeCell(t *testing.T) {
|
|||
|
||||
assert.EqualError(t, f.UnmergeCell("Sheet1", "A", "A"), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
// unmerge the mergecell that contains A1
|
||||
// Test unmerge the merged cells that contains A1
|
||||
assert.NoError(t, f.UnmergeCell(sheet1, "A1", "A1"))
|
||||
if len(sheet.MergeCells.Cells) != mergeCellNum-1 {
|
||||
t.FailNow()
|
||||
|
@ -169,9 +173,12 @@ func TestUnmergeCell(t *testing.T) {
|
|||
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.MergeCell("Sheet1", "A2", "B3"))
|
||||
// Test unmerged range reference on not exists worksheet.
|
||||
// Test unmerged range reference on not exists worksheet
|
||||
assert.EqualError(t, f.UnmergeCell("SheetN", "A1", "A1"), "sheet SheetN does not exist")
|
||||
|
||||
// Test unmerge the merged cells with invalid sheet name
|
||||
assert.EqualError(t, f.UnmergeCell("Sheet:1", "A1", "A1"), ErrSheetNameInvalid.Error())
|
||||
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).MergeCells = nil
|
||||
|
|
|
@ -35,17 +35,17 @@ func TestAddPicture(t *testing.T) {
|
|||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test add picture to worksheet with offset and location hyperlink.
|
||||
// Test add picture to worksheet with offset and location hyperlink
|
||||
assert.NoError(t, f.AddPicture("Sheet2", "I9", filepath.Join("test", "images", "excel.jpg"),
|
||||
`{"x_offset": 140, "y_offset": 120, "hyperlink": "#Sheet2!D8", "hyperlink_type": "Location"}`))
|
||||
// Test add picture to worksheet with offset, external hyperlink and positioning.
|
||||
// Test add picture to worksheet with offset, external hyperlink and positioning
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.jpg"),
|
||||
`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/xuri/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`))
|
||||
|
||||
file, err := os.ReadFile(filepath.Join("test", "images", "excel.png"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test add picture to worksheet with autofit.
|
||||
// Test add picture to worksheet with autofit
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "A30", filepath.Join("test", "images", "excel.jpg"), `{"autofit": true}`))
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "B30", filepath.Join("test", "images", "excel.jpg"), `{"x_offset": 10, "y_offset": 10, "autofit": true}`))
|
||||
f.NewSheet("AddPicture")
|
||||
|
@ -55,41 +55,44 @@ func TestAddPicture(t *testing.T) {
|
|||
assert.NoError(t, f.AddPicture("AddPicture", "C6", filepath.Join("test", "images", "excel.jpg"), `{"autofit": true}`))
|
||||
assert.NoError(t, f.AddPicture("AddPicture", "A1", filepath.Join("test", "images", "excel.jpg"), `{"autofit": true}`))
|
||||
|
||||
// Test add picture to worksheet from bytes.
|
||||
// Test add picture to worksheet from bytes
|
||||
assert.NoError(t, f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".png", file))
|
||||
// Test add picture to worksheet from bytes with illegal cell reference.
|
||||
// Test add picture to worksheet from bytes with illegal cell reference
|
||||
assert.EqualError(t, f.AddPictureFromBytes("Sheet1", "A", "", "Excel Logo", ".png", file), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "Q8", filepath.Join("test", "images", "excel.gif"), ""))
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "Q15", filepath.Join("test", "images", "excel.jpg"), ""))
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "Q22", filepath.Join("test", "images", "excel.tif"), ""))
|
||||
|
||||
// Test write file to given path.
|
||||
// Test write file to given path
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddPicture1.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test add picture with unsupported charset content types.
|
||||
// Test add picture with unsupported charset content types
|
||||
f = NewFile()
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".png", file), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
||||
// Test add picture with invalid sheet name
|
||||
assert.EqualError(t, f.AddPicture("Sheet:1", "A1", filepath.Join("test", "images", "excel.jpg"), ""), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestAddPictureErrors(t *testing.T) {
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test add picture to worksheet with invalid file path.
|
||||
// Test add picture to worksheet with invalid file path
|
||||
assert.Error(t, f.AddPicture("Sheet1", "G21", filepath.Join("test", "not_exists_dir", "not_exists.icon"), ""))
|
||||
|
||||
// Test add picture to worksheet with unsupported file type.
|
||||
// Test add picture to worksheet with unsupported file type
|
||||
assert.EqualError(t, f.AddPicture("Sheet1", "G21", filepath.Join("test", "Book1.xlsx"), ""), ErrImgExt.Error())
|
||||
assert.EqualError(t, f.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", "jpg", make([]byte, 1)), ErrImgExt.Error())
|
||||
|
||||
// Test add picture to worksheet with invalid file data.
|
||||
// Test add picture to worksheet with invalid file data
|
||||
assert.EqualError(t, f.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", ".jpg", make([]byte, 1)), image.ErrFormat.Error())
|
||||
|
||||
// Test add picture with custom image decoder and encoder.
|
||||
// Test add picture with custom image decoder and encoder
|
||||
decode := func(r io.Reader) (image.Image, error) { return nil, nil }
|
||||
decodeConfig := func(r io.Reader) (image.Config, error) { return image.Config{Height: 100, Width: 90}, nil }
|
||||
image.RegisterFormat("emf", "", decode, decodeConfig)
|
||||
|
@ -126,22 +129,26 @@ func TestGetPicture(t *testing.T) {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// Try to get picture from a worksheet with illegal cell reference.
|
||||
// Try to get picture from a worksheet with illegal cell reference
|
||||
_, _, err = f.GetPicture("Sheet1", "A")
|
||||
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
// Try to get picture from a worksheet that doesn't contain any images.
|
||||
// Try to get picture from a worksheet that doesn't contain any images
|
||||
file, raw, err = f.GetPicture("Sheet3", "I9")
|
||||
assert.EqualError(t, err, "sheet Sheet3 does not exist")
|
||||
assert.Empty(t, file)
|
||||
assert.Empty(t, raw)
|
||||
|
||||
// Try to get picture from a cell that doesn't contain an image.
|
||||
// Try to get picture from a cell that doesn't contain an image
|
||||
file, raw, err = f.GetPicture("Sheet2", "A2")
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, file)
|
||||
assert.Empty(t, raw)
|
||||
|
||||
// Test get picture with invalid sheet name
|
||||
_, _, err = f.GetPicture("Sheet:1", "A2")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
f.getDrawingRelationships("xl/worksheets/_rels/sheet1.xml.rels", "rId8")
|
||||
f.getDrawingRelationships("", "")
|
||||
f.getSheetRelationshipsTargetByID("", "")
|
||||
|
@ -160,14 +167,14 @@ func TestGetPicture(t *testing.T) {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
// Try to get picture from a local storage file that doesn't contain an image.
|
||||
// Try to get picture from a local storage file that doesn't contain an image
|
||||
file, raw, err = f.GetPicture("Sheet1", "F22")
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, file)
|
||||
assert.Empty(t, raw)
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test get picture from none drawing worksheet.
|
||||
// Test get picture from none drawing worksheet
|
||||
f = NewFile()
|
||||
file, raw, err = f.GetPicture("Sheet1", "F22")
|
||||
assert.NoError(t, err)
|
||||
|
@ -176,7 +183,7 @@ func TestGetPicture(t *testing.T) {
|
|||
f, err = prepareTestBook1()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test get pictures with unsupported charset.
|
||||
// Test get pictures with unsupported charset
|
||||
path := "xl/drawings/drawing1.xml"
|
||||
f.Pkg.Store(path, MacintoshCyrillicCharset)
|
||||
_, _, err = f.getPicture(20, 5, path, "xl/drawings/_rels/drawing2.xml.rels")
|
||||
|
@ -187,7 +194,7 @@ func TestGetPicture(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAddDrawingPicture(t *testing.T) {
|
||||
// Test addDrawingPicture with illegal cell reference.
|
||||
// Test addDrawingPicture with illegal cell reference
|
||||
f := NewFile()
|
||||
assert.EqualError(t, f.addDrawingPicture("sheet1", "", "A", "", "", 0, 0, image.Config{}, nil), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
|
||||
|
@ -211,6 +218,8 @@ func TestAddPictureFromBytes(t *testing.T) {
|
|||
})
|
||||
assert.Equal(t, 1, imageCount, "Duplicate image should only be stored once.")
|
||||
assert.EqualError(t, f.AddPictureFromBytes("SheetN", fmt.Sprint("A", 1), "", "logo", ".png", imgFile), "sheet SheetN does not exist")
|
||||
// Test add picture from bytes with invalid sheet name
|
||||
assert.EqualError(t, f.AddPictureFromBytes("Sheet:1", fmt.Sprint("A", 1), "", "logo", ".png", imgFile), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestDeletePicture(t *testing.T) {
|
||||
|
@ -220,21 +229,23 @@ func TestDeletePicture(t *testing.T) {
|
|||
assert.NoError(t, f.AddPicture("Sheet1", "P1", filepath.Join("test", "images", "excel.jpg"), ""))
|
||||
assert.NoError(t, f.DeletePicture("Sheet1", "P1"))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDeletePicture.xlsx")))
|
||||
// Test delete picture on not exists worksheet.
|
||||
// Test delete picture on not exists worksheet
|
||||
assert.EqualError(t, f.DeletePicture("SheetN", "A1"), "sheet SheetN does not exist")
|
||||
// Test delete picture with invalid coordinates.
|
||||
// Test delete picture with invalid sheet name
|
||||
assert.EqualError(t, f.DeletePicture("Sheet:1", "A1"), ErrSheetNameInvalid.Error())
|
||||
// Test delete picture with invalid coordinates
|
||||
assert.EqualError(t, f.DeletePicture("Sheet1", ""), newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
|
||||
assert.NoError(t, f.Close())
|
||||
// Test delete picture on no chart worksheet.
|
||||
// Test delete picture on no chart worksheet
|
||||
assert.NoError(t, NewFile().DeletePicture("Sheet1", "A1"))
|
||||
}
|
||||
|
||||
func TestDrawingResize(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test calculate drawing resize on not exists worksheet.
|
||||
// Test calculate drawing resize on not exists worksheet
|
||||
_, _, _, _, err := f.drawingResize("SheetN", "A1", 1, 1, nil)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test calculate drawing resize with invalid coordinates.
|
||||
// Test calculate drawing resize with invalid coordinates
|
||||
_, _, _, _, err = f.drawingResize("Sheet1", "", 1, 1, nil)
|
||||
assert.EqualError(t, err, newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
|
@ -245,7 +256,7 @@ func TestDrawingResize(t *testing.T) {
|
|||
|
||||
func TestSetContentTypePartImageExtensions(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test set content type part image extensions with unsupported charset content types.
|
||||
// Test set content type part image extensions with unsupported charset content types
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.setContentTypePartImageExtensions(), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
@ -253,7 +264,7 @@ func TestSetContentTypePartImageExtensions(t *testing.T) {
|
|||
|
||||
func TestSetContentTypePartVMLExtensions(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test set content type part VML extensions with unsupported charset content types.
|
||||
// Test set content type part VML extensions with unsupported charset content types
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.setContentTypePartVMLExtensions(), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
@ -261,7 +272,7 @@ func TestSetContentTypePartVMLExtensions(t *testing.T) {
|
|||
|
||||
func TestAddContentTypePart(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test add content type part with unsupported charset content types.
|
||||
// Test add content type part with unsupported charset content types
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.addContentTypePart(0, "unknown"), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
|
|
@ -225,6 +225,12 @@ func TestAddPivotTable(t *testing.T) {
|
|||
Data: []PivotTableField{{Data: "Sales", Subtotal: "-", Name: strings.Repeat("s", MaxFieldLength+1)}},
|
||||
}))
|
||||
|
||||
// Test add pivot table with invalid sheet name
|
||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
||||
DataRange: "Sheet:1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet:1!$G$2:$M$34",
|
||||
Rows: []PivotTableField{{Data: "Year"}},
|
||||
}), ErrSheetNameInvalid.Error())
|
||||
// Test adjust range with invalid range
|
||||
_, _, err := f.adjustRange("")
|
||||
assert.EqualError(t, err, ErrParameterRequired.Error())
|
||||
|
|
5
rows.go
5
rows.go
|
@ -260,6 +260,9 @@ func (rows *Rows) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.Sta
|
|||
// fmt.Println(err)
|
||||
// }
|
||||
func (f *File) Rows(sheet string) (*Rows, error) {
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name, ok := f.getSheetXMLPath(sheet)
|
||||
if !ok {
|
||||
return nil, ErrSheetNotExist{sheet}
|
||||
|
@ -268,7 +271,7 @@ func (f *File) Rows(sheet string) (*Rows, error) {
|
|||
worksheet := ws.(*xlsxWorksheet)
|
||||
worksheet.Lock()
|
||||
defer worksheet.Unlock()
|
||||
// flush data
|
||||
// Flush data
|
||||
output, _ := xml.Marshal(worksheet)
|
||||
f.saveFileList(name, f.replaceNameSpaceBytes(name, output))
|
||||
}
|
||||
|
|
75
rows_test.go
75
rows_test.go
|
@ -13,17 +13,15 @@ import (
|
|||
|
||||
func TestRows(t *testing.T) {
|
||||
const sheet2 = "Sheet2"
|
||||
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test get rows with invalid sheet name
|
||||
_, err = f.Rows("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
rows, err := f.Rows(sheet2)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
var collectedRows [][]string
|
||||
for rows.Next() {
|
||||
columns, err := rows.Columns()
|
||||
|
@ -49,13 +47,13 @@ func TestRows(t *testing.T) {
|
|||
_, err = f.Rows("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test reload the file to memory from system temporary directory.
|
||||
// Test reload the file to memory from system temporary directory
|
||||
f, err = OpenFile(filepath.Join("test", "Book1.xlsx"), Options{UnzipXMLSizeLimit: 128})
|
||||
assert.NoError(t, err)
|
||||
value, err := f.GetCellValue("Sheet1", "A19")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Total:", value)
|
||||
// Test load shared string table to memory.
|
||||
// Test load shared string table to memory
|
||||
err = f.SetCellValue("Sheet1", "A19", "A19")
|
||||
assert.NoError(t, err)
|
||||
value, err = f.GetCellValue("Sheet1", "A19")
|
||||
|
@ -64,7 +62,7 @@ func TestRows(t *testing.T) {
|
|||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRow.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
// Test rows iterator with unsupported charset shared strings table.
|
||||
// Test rows iterator with unsupported charset shared strings table
|
||||
f.SharedStrings = nil
|
||||
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
|
||||
rows, err = f.Rows(sheet2)
|
||||
|
@ -154,25 +152,32 @@ func TestRowHeight(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, 111.0, height)
|
||||
|
||||
// Test set row height overflow max row height limit.
|
||||
// Test set row height overflow max row height limit
|
||||
assert.EqualError(t, f.SetRowHeight(sheet1, 4, MaxRowHeight+1), ErrMaxRowHeight.Error())
|
||||
|
||||
// Test get row height that rows index over exists rows.
|
||||
// Test get row height that rows index over exists rows
|
||||
height, err = f.GetRowHeight(sheet1, 5)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, defaultRowHeight, height)
|
||||
|
||||
// Test get row height that rows heights haven't changed.
|
||||
// Test get row height that rows heights haven't changed
|
||||
height, err = f.GetRowHeight(sheet1, 3)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, defaultRowHeight, height)
|
||||
|
||||
// Test set and get row height on not exists worksheet.
|
||||
// Test set and get row height on not exists worksheet
|
||||
assert.EqualError(t, f.SetRowHeight("SheetN", 1, 111.0), "sheet SheetN does not exist")
|
||||
_, err = f.GetRowHeight("SheetN", 3)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
|
||||
// Test get row height with custom default row height.
|
||||
// Test set row height with invalid sheet name
|
||||
assert.EqualError(t, f.SetRowHeight("Sheet:1", 1, 10.0), ErrSheetNameInvalid.Error())
|
||||
|
||||
// Test get row height with invalid sheet name
|
||||
_, err = f.GetRowHeight("Sheet:1", 3)
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
|
||||
// Test get row height with custom default row height
|
||||
assert.NoError(t, f.SetSheetProps(sheet1, &SheetPropsOptions{
|
||||
DefaultRowHeight: float64Ptr(30.0),
|
||||
CustomHeight: boolPtr(true),
|
||||
|
@ -181,7 +186,7 @@ func TestRowHeight(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, 30.0, height)
|
||||
|
||||
// Test set row height with custom default row height with prepare XML.
|
||||
// Test set row height with custom default row height with prepare XML
|
||||
assert.NoError(t, f.SetCellValue(sheet1, "A10", "A10"))
|
||||
|
||||
f.NewSheet("Sheet2")
|
||||
|
@ -233,17 +238,17 @@ func TestColumns(t *testing.T) {
|
|||
|
||||
func TestSharedStringsReader(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test read shared string with unsupported charset.
|
||||
// Test read shared string with unsupported charset
|
||||
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
|
||||
_, err := f.sharedStringsReader()
|
||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test read shared strings with unsupported charset content types.
|
||||
// Test read shared strings with unsupported charset content types
|
||||
f = NewFile()
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
_, err = f.sharedStringsReader()
|
||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test read shared strings with unsupported charset workbook relationships.
|
||||
// Test read shared strings with unsupported charset workbook relationships
|
||||
f = NewFile()
|
||||
f.Relationships.Delete(defaultXMLPathWorkbookRels)
|
||||
f.Pkg.Store(defaultXMLPathWorkbookRels, MacintoshCyrillicCharset)
|
||||
|
@ -267,13 +272,17 @@ func TestRowVisibility(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.EqualError(t, f.SetRowVisible("Sheet3", 0, true), newInvalidRowNumberError(0).Error())
|
||||
assert.EqualError(t, f.SetRowVisible("SheetN", 2, false), "sheet SheetN does not exist")
|
||||
// Test set row visibility with invalid sheet name
|
||||
assert.EqualError(t, f.SetRowVisible("Sheet:1", 1, false), ErrSheetNameInvalid.Error())
|
||||
|
||||
visible, err = f.GetRowVisible("Sheet3", 0)
|
||||
assert.Equal(t, false, visible)
|
||||
assert.EqualError(t, err, newInvalidRowNumberError(0).Error())
|
||||
_, err = f.GetRowVisible("SheetN", 1)
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
|
||||
// Test get row visibility with invalid sheet name
|
||||
_, err = f.GetRowVisible("Sheet:1", 1)
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRowVisibility.xlsx")))
|
||||
}
|
||||
|
||||
|
@ -335,7 +344,9 @@ func TestRemoveRow(t *testing.T) {
|
|||
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 does not exist`)
|
||||
assert.EqualError(t, f.RemoveRow("SheetN", 1), "sheet SheetN does not exist")
|
||||
// Test remove row with invalid sheet name
|
||||
assert.EqualError(t, f.RemoveRow("Sheet:1", 1), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestInsertRows(t *testing.T) {
|
||||
|
@ -365,6 +376,8 @@ func TestInsertRows(t *testing.T) {
|
|||
if !assert.Len(t, r.SheetData.Row, rowCount+4) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Test insert rows with invalid sheet name
|
||||
assert.EqualError(t, f.InsertRows("Sheet:1", 1, 1), ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.EqualError(t, f.InsertRows(sheet1, -1, 1), newInvalidRowNumberError(-1).Error())
|
||||
assert.EqualError(t, f.InsertRows(sheet1, 0, 1), newInvalidRowNumberError(0).Error())
|
||||
|
@ -892,6 +905,12 @@ func TestDuplicateRowInvalidRowNum(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDuplicateRow(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test duplicate row with invalid sheet name
|
||||
assert.EqualError(t, f.DuplicateRowTo("Sheet:1", 1, 2), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestDuplicateRowTo(t *testing.T) {
|
||||
f, sheetName := NewFile(), "Sheet1"
|
||||
// Test duplicate row with invalid target row number
|
||||
|
@ -907,6 +926,8 @@ func TestDuplicateRowTo(t *testing.T) {
|
|||
assert.EqualError(t, f.DuplicateRowTo(sheetName, 1, 2), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
// Test duplicate row on not exists worksheet
|
||||
assert.EqualError(t, f.DuplicateRowTo("SheetN", 1, 2), "sheet SheetN does not exist")
|
||||
// Test duplicate row with invalid sheet name
|
||||
assert.EqualError(t, f.DuplicateRowTo("Sheet:1", 1, 2), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestDuplicateMergeCells(t *testing.T) {
|
||||
|
@ -976,22 +997,24 @@ func TestSetRowStyle(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellStyle("Sheet1", "B2", "B2", style1))
|
||||
assert.EqualError(t, f.SetRowStyle("Sheet1", 5, -1, style2), newInvalidRowNumberError(-1).Error())
|
||||
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, TotalRows+1, style2), ErrMaxRows.Error())
|
||||
// Test set row style with invalid style ID.
|
||||
// Test set row style with invalid style ID
|
||||
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, 1, -1), newInvalidStyleID(-1).Error())
|
||||
// Test set row style with not exists style ID.
|
||||
// Test set row style with not exists style ID
|
||||
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, 1, 10), newInvalidStyleID(10).Error())
|
||||
assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, style2), "sheet SheetN does not exist")
|
||||
// Test set row style with invalid sheet name
|
||||
assert.EqualError(t, f.SetRowStyle("Sheet:1", 1, 1, 0), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.SetRowStyle("Sheet1", 5, 1, style2))
|
||||
cellStyleID, err := f.GetCellStyle("Sheet1", "B2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, style2, cellStyleID)
|
||||
// Test cell inheritance rows style.
|
||||
// Test cell inheritance rows style
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "C1", nil))
|
||||
cellStyleID, err = f.GetCellStyle("Sheet1", "C1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, style2, cellStyleID)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRowStyle.xlsx")))
|
||||
// Test set row style with unsupported charset style sheet.
|
||||
// Test set row style with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, 1, cellStyleID), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
|
|
@ -59,7 +59,7 @@ func TestAddShape(t *testing.T) {
|
|||
}`), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape1.xlsx")))
|
||||
|
||||
// Test add first shape for given sheet.
|
||||
// Test add first shape for given sheet
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.AddShape("Sheet1", "A1", `{
|
||||
"type": "ellipseRibbon",
|
||||
|
@ -87,11 +87,13 @@ func TestAddShape(t *testing.T) {
|
|||
}
|
||||
}`))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape2.xlsx")))
|
||||
// Test add shape with unsupported charset style sheet.
|
||||
// Test add shape with invalid sheet name
|
||||
assert.EqualError(t, f.AddShape("Sheet:1", "A30", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`), ErrSheetNameInvalid.Error())
|
||||
// Test add shape with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.AddShape("Sheet1", "B30", `{"type":"rect","paragraph":[{"text":"Rectangle"},{}]}`), "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test add shape with unsupported charset content types.
|
||||
// Test add shape with unsupported charset content types
|
||||
f = NewFile()
|
||||
f.ContentTypes = nil
|
||||
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||
|
|
170
sheet.go
170
sheet.go
|
@ -35,14 +35,15 @@ import (
|
|||
// name and returns the index of the sheets in the workbook after it appended.
|
||||
// Note that when creating a new workbook, the default worksheet named
|
||||
// `Sheet1` will be created.
|
||||
func (f *File) NewSheet(sheet string) int {
|
||||
if trimSheetName(sheet) == "" {
|
||||
return -1
|
||||
func (f *File) NewSheet(sheet string) (int, error) {
|
||||
var err error
|
||||
if err = checkSheetName(sheet); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
// Check if the worksheet already exists
|
||||
index := f.GetSheetIndex(sheet)
|
||||
index, err := f.GetSheetIndex(sheet)
|
||||
if index != -1 {
|
||||
return index
|
||||
return index, err
|
||||
}
|
||||
f.DeleteSheet(sheet)
|
||||
f.SheetCount++
|
||||
|
@ -235,7 +236,7 @@ func (f *File) setSheet(index int, name string) {
|
|||
},
|
||||
}
|
||||
sheetXMLPath := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
|
||||
f.sheetMap[trimSheetName(name)] = sheetXMLPath
|
||||
f.sheetMap[name] = sheetXMLPath
|
||||
f.Sheet.Store(sheetXMLPath, &ws)
|
||||
f.xmlAttr[sheetXMLPath] = []xml.Attr{NameSpaceSpreadSheet}
|
||||
}
|
||||
|
@ -352,11 +353,16 @@ func (f *File) getActiveSheetID() int {
|
|||
// this function only changes the name of the sheet and will not update the
|
||||
// sheet name in the formula or reference associated with the cell. So there
|
||||
// may be problem formula error or reference missing.
|
||||
func (f *File) SetSheetName(source, target string) {
|
||||
source = trimSheetName(source)
|
||||
target = trimSheetName(target)
|
||||
func (f *File) SetSheetName(source, target string) error {
|
||||
var err error
|
||||
if err = checkSheetName(source); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = checkSheetName(target); err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.EqualFold(target, source) {
|
||||
return
|
||||
return err
|
||||
}
|
||||
wb, _ := f.workbookReader()
|
||||
for k, v := range wb.Sheets.Sheet {
|
||||
|
@ -366,6 +372,7 @@ func (f *File) SetSheetName(source, target string) {
|
|||
delete(f.sheetMap, source)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSheetName provides a function to get the sheet name of the workbook by
|
||||
|
@ -385,9 +392,8 @@ func (f *File) GetSheetName(index int) (name string) {
|
|||
// given sheet name. If given worksheet name is invalid, will return an
|
||||
// integer type value -1.
|
||||
func (f *File) getSheetID(sheet string) int {
|
||||
sheetName := trimSheetName(sheet)
|
||||
for sheetID, name := range f.GetSheetMap() {
|
||||
if strings.EqualFold(name, sheetName) {
|
||||
if strings.EqualFold(name, sheet) {
|
||||
return sheetID
|
||||
}
|
||||
}
|
||||
|
@ -397,14 +403,16 @@ func (f *File) getSheetID(sheet string) int {
|
|||
// GetSheetIndex provides a function to get a sheet index of the workbook by
|
||||
// the given sheet name. If the given sheet name is invalid or sheet doesn't
|
||||
// exist, it will return an integer type value -1.
|
||||
func (f *File) GetSheetIndex(sheet string) int {
|
||||
sheetName := trimSheetName(sheet)
|
||||
func (f *File) GetSheetIndex(sheet string) (int, error) {
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
for index, name := range f.GetSheetList() {
|
||||
if strings.EqualFold(name, sheetName) {
|
||||
return index
|
||||
if strings.EqualFold(name, sheet) {
|
||||
return index, nil
|
||||
}
|
||||
}
|
||||
return -1
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// GetSheetMap provides a function to get worksheets, chart sheets, dialog
|
||||
|
@ -474,7 +482,6 @@ func (f *File) getSheetXMLPath(sheet string) (string, bool) {
|
|||
name string
|
||||
ok bool
|
||||
)
|
||||
sheet = trimSheetName(sheet)
|
||||
for sheetName, filePath := range f.sheetMap {
|
||||
if strings.EqualFold(sheetName, sheet) {
|
||||
name, ok = filePath, true
|
||||
|
@ -530,19 +537,22 @@ func (f *File) setSheetBackground(sheet, extension string, file []byte) error {
|
|||
// references such as formulas, charts, and so on. If there is any referenced
|
||||
// value of the deleted worksheet, it will cause a file error when you open
|
||||
// it. This function will be invalid when only one worksheet is left.
|
||||
func (f *File) DeleteSheet(sheet string) {
|
||||
if f.SheetCount == 1 || f.GetSheetIndex(sheet) == -1 {
|
||||
return
|
||||
func (f *File) DeleteSheet(sheet string) error {
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return err
|
||||
}
|
||||
sheetName := trimSheetName(sheet)
|
||||
if idx, _ := f.GetSheetIndex(sheet); f.SheetCount == 1 || idx == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
wb, _ := f.workbookReader()
|
||||
wbRels, _ := f.relsReader(f.getWorkbookRelsPath())
|
||||
activeSheetName := f.GetSheetName(f.GetActiveSheetIndex())
|
||||
deleteLocalSheetID := f.GetSheetIndex(sheet)
|
||||
deleteLocalSheetID, _ := f.GetSheetIndex(sheet)
|
||||
deleteAndAdjustDefinedNames(wb, deleteLocalSheetID)
|
||||
|
||||
for idx, v := range wb.Sheets.Sheet {
|
||||
if !strings.EqualFold(v.Name, sheetName) {
|
||||
if !strings.EqualFold(v.Name, sheet) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -568,7 +578,9 @@ func (f *File) DeleteSheet(sheet string) {
|
|||
delete(f.xmlAttr, sheetXML)
|
||||
f.SheetCount--
|
||||
}
|
||||
f.SetActiveSheet(f.GetSheetIndex(activeSheetName))
|
||||
index, err := f.GetSheetIndex(activeSheetName)
|
||||
f.SetActiveSheet(index)
|
||||
return err
|
||||
}
|
||||
|
||||
// deleteAndAdjustDefinedNames delete and adjust defined name in the workbook
|
||||
|
@ -683,7 +695,9 @@ func (f *File) copySheet(from, to int) error {
|
|||
//
|
||||
// err := f.SetSheetVisible("Sheet1", false)
|
||||
func (f *File) SetSheetVisible(sheet string, visible bool) error {
|
||||
sheet = trimSheetName(sheet)
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return err
|
||||
}
|
||||
wb, err := f.workbookReader()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -857,17 +871,20 @@ func (f *File) SetPanes(sheet, panes string) error {
|
|||
// name. For example, get visible state of Sheet1:
|
||||
//
|
||||
// f.GetSheetVisible("Sheet1")
|
||||
func (f *File) GetSheetVisible(sheet string) bool {
|
||||
name, visible := trimSheetName(sheet), false
|
||||
func (f *File) GetSheetVisible(sheet string) (bool, error) {
|
||||
var visible bool
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return visible, err
|
||||
}
|
||||
wb, _ := f.workbookReader()
|
||||
for k, v := range wb.Sheets.Sheet {
|
||||
if strings.EqualFold(v.Name, name) {
|
||||
if strings.EqualFold(v.Name, sheet) {
|
||||
if wb.Sheets.Sheet[k].State == "" || wb.Sheets.Sheet[k].State == "visible" {
|
||||
visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return visible
|
||||
return visible, nil
|
||||
}
|
||||
|
||||
// SearchSheet provides a function to get cell reference by given worksheet name,
|
||||
|
@ -889,6 +906,9 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
|
|||
regSearch bool
|
||||
result []string
|
||||
)
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return result, err
|
||||
}
|
||||
for _, r := range reg {
|
||||
regSearch = r
|
||||
}
|
||||
|
@ -897,7 +917,7 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
|
|||
return result, ErrSheetNotExist{sheet}
|
||||
}
|
||||
if ws, ok := f.Sheet.Load(name); ok && ws != nil {
|
||||
// flush data
|
||||
// Flush data
|
||||
output, _ := xml.Marshal(ws.(*xlsxWorksheet))
|
||||
f.saveFileList(name, f.replaceNameSpaceBytes(name, output))
|
||||
}
|
||||
|
@ -1051,7 +1071,7 @@ func attrValToBool(name string, attrs []xml.Attr) (val bool, err error) {
|
|||
// |
|
||||
// &F | Current workbook's file name
|
||||
// |
|
||||
// &G | Drawing object as background
|
||||
// &G | Drawing object as background (Not support currently)
|
||||
// |
|
||||
// &H | Shadow text format
|
||||
// |
|
||||
|
@ -1167,47 +1187,47 @@ func (f *File) SetHeaderFooter(sheet string, settings *HeaderFooterOptions) erro
|
|||
// Password: "password",
|
||||
// EditScenarios: false,
|
||||
// })
|
||||
func (f *File) ProtectSheet(sheet string, settings *SheetProtectionOptions) error {
|
||||
func (f *File) ProtectSheet(sheet string, opts *SheetProtectionOptions) error {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if settings == nil {
|
||||
settings = &SheetProtectionOptions{
|
||||
if opts == nil {
|
||||
opts = &SheetProtectionOptions{
|
||||
EditObjects: true,
|
||||
EditScenarios: true,
|
||||
SelectLockedCells: true,
|
||||
}
|
||||
}
|
||||
ws.SheetProtection = &xlsxSheetProtection{
|
||||
AutoFilter: settings.AutoFilter,
|
||||
DeleteColumns: settings.DeleteColumns,
|
||||
DeleteRows: settings.DeleteRows,
|
||||
FormatCells: settings.FormatCells,
|
||||
FormatColumns: settings.FormatColumns,
|
||||
FormatRows: settings.FormatRows,
|
||||
InsertColumns: settings.InsertColumns,
|
||||
InsertHyperlinks: settings.InsertHyperlinks,
|
||||
InsertRows: settings.InsertRows,
|
||||
Objects: settings.EditObjects,
|
||||
PivotTables: settings.PivotTables,
|
||||
Scenarios: settings.EditScenarios,
|
||||
SelectLockedCells: settings.SelectLockedCells,
|
||||
SelectUnlockedCells: settings.SelectUnlockedCells,
|
||||
AutoFilter: opts.AutoFilter,
|
||||
DeleteColumns: opts.DeleteColumns,
|
||||
DeleteRows: opts.DeleteRows,
|
||||
FormatCells: opts.FormatCells,
|
||||
FormatColumns: opts.FormatColumns,
|
||||
FormatRows: opts.FormatRows,
|
||||
InsertColumns: opts.InsertColumns,
|
||||
InsertHyperlinks: opts.InsertHyperlinks,
|
||||
InsertRows: opts.InsertRows,
|
||||
Objects: opts.EditObjects,
|
||||
PivotTables: opts.PivotTables,
|
||||
Scenarios: opts.EditScenarios,
|
||||
SelectLockedCells: opts.SelectLockedCells,
|
||||
SelectUnlockedCells: opts.SelectUnlockedCells,
|
||||
Sheet: true,
|
||||
Sort: settings.Sort,
|
||||
Sort: opts.Sort,
|
||||
}
|
||||
if settings.Password != "" {
|
||||
if settings.AlgorithmName == "" {
|
||||
ws.SheetProtection.Password = genSheetPasswd(settings.Password)
|
||||
if opts.Password != "" {
|
||||
if opts.AlgorithmName == "" {
|
||||
ws.SheetProtection.Password = genSheetPasswd(opts.Password)
|
||||
return err
|
||||
}
|
||||
hashValue, saltValue, err := genISOPasswdHash(settings.Password, settings.AlgorithmName, "", int(sheetProtectionSpinCount))
|
||||
hashValue, saltValue, err := genISOPasswdHash(opts.Password, opts.AlgorithmName, "", int(sheetProtectionSpinCount))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.SheetProtection.Password = ""
|
||||
ws.SheetProtection.AlgorithmName = settings.AlgorithmName
|
||||
ws.SheetProtection.AlgorithmName = opts.AlgorithmName
|
||||
ws.SheetProtection.SaltValue = saltValue
|
||||
ws.SheetProtection.HashValue = hashValue
|
||||
ws.SheetProtection.SpinCount = int(sheetProtectionSpinCount)
|
||||
|
@ -1246,25 +1266,25 @@ func (f *File) UnprotectSheet(sheet string, password ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// trimSheetName provides a function to trim invalid characters by given worksheet
|
||||
// name.
|
||||
func trimSheetName(name string) string {
|
||||
if strings.ContainsAny(name, ":\\/?*[]") || utf8.RuneCountInString(name) > 31 {
|
||||
r := make([]rune, 0, 31)
|
||||
for _, v := range name {
|
||||
switch v {
|
||||
case 58, 92, 47, 63, 42, 91, 93: // replace :\/?*[]
|
||||
continue
|
||||
default:
|
||||
r = append(r, v)
|
||||
}
|
||||
if len(r) == 31 {
|
||||
break
|
||||
}
|
||||
}
|
||||
name = string(r)
|
||||
// checkSheetName check whether there are illegal characters in the sheet name.
|
||||
// 1. Confirm that the sheet name is not empty
|
||||
// 2. Make sure to enter a name with no more than 31 characters
|
||||
// 3. Make sure the first or last character of the name cannot be a single quote
|
||||
// 4. Verify that the following characters are not included in the name :\/?*[]
|
||||
func checkSheetName(name string) error {
|
||||
if name == "" {
|
||||
return ErrSheetNameBlank
|
||||
}
|
||||
return name
|
||||
if utf8.RuneCountInString(name) > MaxSheetNameLength {
|
||||
return ErrSheetNameLength
|
||||
}
|
||||
if strings.HasPrefix(name, "'") || strings.HasSuffix(name, "'") {
|
||||
return ErrSheetNameSingleQuote
|
||||
}
|
||||
if strings.ContainsAny(name, ":\\/?*[]") {
|
||||
return ErrSheetNameInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPageLayout provides a function to sets worksheet page layout.
|
||||
|
@ -1499,7 +1519,7 @@ func (f *File) SetDefinedName(definedName *DefinedName) error {
|
|||
Data: definedName.RefersTo,
|
||||
}
|
||||
if definedName.Scope != "" {
|
||||
if sheetIndex := f.GetSheetIndex(definedName.Scope); sheetIndex >= 0 {
|
||||
if sheetIndex, _ := f.GetSheetIndex(definedName.Scope); sheetIndex >= 0 {
|
||||
d.LocalSheetID = &sheetIndex
|
||||
}
|
||||
}
|
||||
|
@ -1579,7 +1599,7 @@ func (f *File) GetDefinedName() []DefinedName {
|
|||
// GroupSheets provides a function to group worksheets by given worksheets
|
||||
// name. Group worksheets must contain an active worksheet.
|
||||
func (f *File) GroupSheets(sheets []string) error {
|
||||
// check an active worksheet in group worksheets
|
||||
// Check an active worksheet in group worksheets
|
||||
var inActiveSheet bool
|
||||
activeSheet := f.GetActiveSheetIndex()
|
||||
sheetMap := f.GetSheetList()
|
||||
|
|
124
sheet_test.go
124
sheet_test.go
|
@ -16,18 +16,27 @@ import (
|
|||
func TestNewSheet(t *testing.T) {
|
||||
f := NewFile()
|
||||
f.NewSheet("Sheet2")
|
||||
sheetID := f.NewSheet("sheet2")
|
||||
sheetID, err := f.NewSheet("sheet2")
|
||||
assert.NoError(t, err)
|
||||
f.SetActiveSheet(sheetID)
|
||||
// delete original sheet
|
||||
f.DeleteSheet(f.GetSheetName(f.GetSheetIndex("Sheet1")))
|
||||
// Test delete original sheet
|
||||
idx, err := f.GetSheetIndex("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
f.DeleteSheet(f.GetSheetName(idx))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewSheet.xlsx")))
|
||||
// create new worksheet with already exists name
|
||||
assert.Equal(t, f.GetSheetIndex("Sheet2"), f.NewSheet("Sheet2"))
|
||||
// create new worksheet with empty sheet name
|
||||
assert.Equal(t, -1, f.NewSheet(":\\/?*[]"))
|
||||
// Test create new worksheet with already exists name
|
||||
sheetID, err = f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
idx, err = f.GetSheetIndex("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, idx, sheetID)
|
||||
// Test create new worksheet with empty sheet name
|
||||
sheetID, err = f.NewSheet(":\\/?*[]")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
assert.Equal(t, -1, sheetID)
|
||||
}
|
||||
|
||||
func TestSetPane(t *testing.T) {
|
||||
func TestSetPanes(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetPanes("Sheet1", `{"freeze":false,"split":false}`))
|
||||
f.NewSheet("Panes 2")
|
||||
|
@ -38,6 +47,8 @@ func TestSetPane(t *testing.T) {
|
|||
assert.NoError(t, f.SetPanes("Panes 4", `{"freeze":true,"split":false,"x_split":0,"y_split":9,"top_left_cell":"A34","active_pane":"bottomLeft","panes":[{"sqref":"A11:XFD11","active_cell":"A11","pane":"bottomLeft"}]}`))
|
||||
assert.EqualError(t, f.SetPanes("Panes 4", ""), "unexpected end of JSON input")
|
||||
assert.EqualError(t, f.SetPanes("SheetN", ""), "sheet SheetN does not exist")
|
||||
// Test set panes with invalid sheet name
|
||||
assert.EqualError(t, f.SetPanes("Sheet:1", `{"freeze":false,"split":false}`), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetPane.xlsx")))
|
||||
// Test add pane on empty sheet views worksheet
|
||||
f = NewFile()
|
||||
|
@ -52,11 +63,14 @@ func TestSearchSheet(t *testing.T) {
|
|||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Test search in a not exists worksheet.
|
||||
// Test search in a not exists worksheet
|
||||
_, err = f.SearchSheet("Sheet4", "")
|
||||
assert.EqualError(t, err, "sheet Sheet4 does not exist")
|
||||
// Test search sheet with invalid sheet name
|
||||
_, err = f.SearchSheet("Sheet:1", "")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
var expected []string
|
||||
// Test search a not exists value.
|
||||
// Test search a not exists value
|
||||
result, err := f.SearchSheet("Sheet1", "X")
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, expected, result)
|
||||
|
@ -120,23 +134,30 @@ func TestSetPageLayout(t *testing.T) {
|
|||
opts, err := f.GetPageLayout("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, opts)
|
||||
// Test set page layout on not exists worksheet.
|
||||
// Test set page layout on not exists worksheet
|
||||
assert.EqualError(t, f.SetPageLayout("SheetN", nil), "sheet SheetN does not exist")
|
||||
// Test set page layout with invalid sheet name
|
||||
assert.EqualError(t, f.SetPageLayout("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestGetPageLayout(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get page layout on not exists worksheet.
|
||||
// Test get page layout on not exists worksheet
|
||||
_, err := f.GetPageLayout("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get page layout with invalid sheet name
|
||||
_, err = f.GetPageLayout("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestSetHeaderFooter(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetCellStr("Sheet1", "A1", "Test SetHeaderFooter"))
|
||||
// Test set header and footer on not exists worksheet.
|
||||
// Test set header and footer on not exists worksheet
|
||||
assert.EqualError(t, f.SetHeaderFooter("SheetN", nil), "sheet SheetN does not exist")
|
||||
// Test set header and footer with illegal setting.
|
||||
// Test Sheet:1 with invalid sheet name
|
||||
assert.EqualError(t, f.SetHeaderFooter("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
||||
// Test set header and footer with illegal setting
|
||||
assert.EqualError(t, f.SetHeaderFooter("Sheet1", &HeaderFooterOptions{
|
||||
OddHeader: strings.Repeat("c", MaxFieldLength+1),
|
||||
}), newFieldLengthError("OddHeader").Error())
|
||||
|
@ -190,13 +211,13 @@ func TestDefinedName(t *testing.T) {
|
|||
assert.Exactly(t, "Sheet1!$A$2:$D$5", f.GetDefinedName()[0].RefersTo)
|
||||
assert.Exactly(t, 1, len(f.GetDefinedName()))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDefinedName.xlsx")))
|
||||
// Test set defined name with unsupported charset workbook.
|
||||
// Test set defined name with unsupported charset workbook
|
||||
f.WorkBook = nil
|
||||
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetDefinedName(&DefinedName{
|
||||
Name: "Amount", RefersTo: "Sheet1!$A$2:$D$5",
|
||||
}), "XML syntax error on line 1: invalid UTF-8")
|
||||
// Test delete defined name with unsupported charset workbook.
|
||||
// Test delete defined name with unsupported charset workbook
|
||||
f.WorkBook = nil
|
||||
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.DeleteDefinedName(&DefinedName{Name: "Amount"}),
|
||||
|
@ -211,6 +232,8 @@ func TestGroupSheets(t *testing.T) {
|
|||
}
|
||||
assert.EqualError(t, f.GroupSheets([]string{"Sheet1", "SheetN"}), "sheet SheetN does not exist")
|
||||
assert.EqualError(t, f.GroupSheets([]string{"Sheet2", "Sheet3"}), "group worksheet must contain an active worksheet")
|
||||
// Test group sheets with invalid sheet name
|
||||
assert.EqualError(t, f.GroupSheets([]string{"Sheet:1", "Sheet1"}), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.GroupSheets([]string{"Sheet1", "Sheet2"}))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestGroupSheets.xlsx")))
|
||||
}
|
||||
|
@ -232,6 +255,8 @@ func TestInsertPageBreak(t *testing.T) {
|
|||
assert.NoError(t, f.InsertPageBreak("Sheet1", "C3"))
|
||||
assert.EqualError(t, f.InsertPageBreak("Sheet1", "A"), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
assert.EqualError(t, f.InsertPageBreak("SheetN", "C3"), "sheet SheetN does not exist")
|
||||
// Test insert page break with invalid sheet name
|
||||
assert.EqualError(t, f.InsertPageBreak("Sheet:1", "C3"), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertPageBreak.xlsx")))
|
||||
}
|
||||
|
||||
|
@ -258,6 +283,8 @@ func TestRemovePageBreak(t *testing.T) {
|
|||
|
||||
assert.EqualError(t, f.RemovePageBreak("Sheet1", "A"), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
assert.EqualError(t, f.RemovePageBreak("SheetN", "C3"), "sheet SheetN does not exist")
|
||||
// Test remove page break with invalid sheet name
|
||||
assert.EqualError(t, f.RemovePageBreak("Sheet:1", "A3"), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRemovePageBreak.xlsx")))
|
||||
}
|
||||
|
||||
|
@ -305,7 +332,8 @@ func TestSetActiveSheet(t *testing.T) {
|
|||
|
||||
f = NewFile()
|
||||
f.WorkBook.BookViews = nil
|
||||
idx := f.NewSheet("Sheet2")
|
||||
idx, err := f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
ws, ok = f.Sheet.Load("xl/worksheets/sheet2.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).SheetViews = &xlsxSheetViews{SheetView: []xlsxSheetView{}}
|
||||
|
@ -314,9 +342,11 @@ func TestSetActiveSheet(t *testing.T) {
|
|||
|
||||
func TestSetSheetName(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test set worksheet with the same name.
|
||||
f.SetSheetName("Sheet1", "Sheet1")
|
||||
// Test set worksheet with the same name
|
||||
assert.NoError(t, f.SetSheetName("Sheet1", "Sheet1"))
|
||||
assert.Equal(t, "Sheet1", f.GetSheetName(0))
|
||||
// Test set sheet name with invalid sheet name
|
||||
assert.EqualError(t, f.SetSheetName("Sheet:1", "Sheet1"), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestWorksheetWriter(t *testing.T) {
|
||||
|
@ -348,7 +378,9 @@ func TestGetWorkbookRelsPath(t *testing.T) {
|
|||
|
||||
func TestDeleteSheet(t *testing.T) {
|
||||
f := NewFile()
|
||||
f.SetActiveSheet(f.NewSheet("Sheet2"))
|
||||
idx, err := f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
f.SetActiveSheet(idx)
|
||||
f.NewSheet("Sheet3")
|
||||
f.DeleteSheet("Sheet1")
|
||||
assert.Equal(t, "Sheet2", f.GetSheetName(f.GetActiveSheetIndex()))
|
||||
|
@ -363,8 +395,10 @@ func TestDeleteSheet(t *testing.T) {
|
|||
assert.NoError(t, f.AutoFilter("Sheet1", "A1", "A1", ""))
|
||||
assert.NoError(t, f.AutoFilter("Sheet2", "A1", "A1", ""))
|
||||
assert.NoError(t, f.AutoFilter("Sheet3", "A1", "A1", ""))
|
||||
f.DeleteSheet("Sheet2")
|
||||
f.DeleteSheet("Sheet1")
|
||||
assert.NoError(t, f.DeleteSheet("Sheet2"))
|
||||
assert.NoError(t, f.DeleteSheet("Sheet1"))
|
||||
// Test delete sheet with invalid sheet name
|
||||
assert.EqualError(t, f.DeleteSheet("Sheet:1"), ErrSheetNameInvalid.Error())
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDeleteSheet2.xlsx")))
|
||||
}
|
||||
|
||||
|
@ -382,14 +416,32 @@ func TestGetSheetID(t *testing.T) {
|
|||
|
||||
func TestSetSheetVisible(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test set sheet visible with invalid sheet name
|
||||
assert.EqualError(t, f.SetSheetVisible("Sheet:1", false), ErrSheetNameInvalid.Error())
|
||||
f.WorkBook.Sheets.Sheet[0].Name = "SheetN"
|
||||
assert.EqualError(t, f.SetSheetVisible("Sheet1", false), "sheet SheetN does not exist")
|
||||
// Test set sheet visible with unsupported charset workbook.
|
||||
// Test set sheet visible with unsupported charset workbook
|
||||
f.WorkBook = nil
|
||||
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetSheetVisible("Sheet1", false), "XML syntax error on line 1: invalid UTF-8")
|
||||
}
|
||||
|
||||
func TestGetSheetVisible(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get sheet visible with invalid sheet name
|
||||
visible, err := f.GetSheetVisible("Sheet:1")
|
||||
assert.Equal(t, false, visible)
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestGetSheetIndex(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get sheet index with invalid sheet name
|
||||
idx, err := f.GetSheetIndex("Sheet:1")
|
||||
assert.Equal(t, -1, idx)
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestSetContentTypes(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test set content type with unsupported charset content types.
|
||||
|
@ -482,8 +534,34 @@ func TestSetSheetBackgroundFromBytes(t *testing.T) {
|
|||
assert.NoError(t, img.Close())
|
||||
assert.NoError(t, f.SetSheetBackgroundFromBytes(imageTypes, imageTypes, content))
|
||||
}
|
||||
// Test set worksheet background with invalid sheet name
|
||||
img, err := os.Open(filepath.Join("test", "images", "excel.png"))
|
||||
assert.NoError(t, err)
|
||||
content, err := io.ReadAll(img)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualError(t, f.SetSheetBackgroundFromBytes("Sheet:1", ".png", content), ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetBackgroundFromBytes.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
assert.EqualError(t, f.SetSheetBackgroundFromBytes("Sheet1", ".svg", nil), ErrParameterInvalid.Error())
|
||||
}
|
||||
|
||||
func TestCheckSheetName(t *testing.T) {
|
||||
// Test valid sheet name
|
||||
assert.NoError(t, checkSheetName("Sheet1"))
|
||||
assert.NoError(t, checkSheetName("She'et1"))
|
||||
// Test invalid sheet name, empty name
|
||||
assert.EqualError(t, checkSheetName(""), ErrSheetNameBlank.Error())
|
||||
// Test invalid sheet name, include :\/?*[]
|
||||
assert.EqualError(t, checkSheetName("Sheet:"), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, checkSheetName(`Sheet\`), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, checkSheetName("Sheet/"), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, checkSheetName("Sheet?"), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, checkSheetName("Sheet*"), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, checkSheetName("Sheet["), ErrSheetNameInvalid.Error())
|
||||
assert.EqualError(t, checkSheetName("Sheet]"), ErrSheetNameInvalid.Error())
|
||||
// Test invalid sheet name, single quotes at the front or at the end
|
||||
assert.EqualError(t, checkSheetName("'Sheet"), ErrSheetNameSingleQuote.Error())
|
||||
assert.EqualError(t, checkSheetName("Sheet'"), ErrSheetNameSingleQuote.Error())
|
||||
}
|
||||
|
|
|
@ -27,15 +27,20 @@ func TestSetPageMargins(t *testing.T) {
|
|||
opts, err := f.GetPageMargins("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, opts)
|
||||
// Test set page margins on not exists worksheet.
|
||||
// Test set page margins on not exists worksheet
|
||||
assert.EqualError(t, f.SetPageMargins("SheetN", nil), "sheet SheetN does not exist")
|
||||
// Test set page margins with invalid sheet name
|
||||
assert.EqualError(t, f.SetPageMargins("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestGetPageMargins(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get page margins on not exists worksheet.
|
||||
// Test get page margins on not exists worksheet
|
||||
_, err := f.GetPageMargins("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get page margins with invalid sheet name
|
||||
_, err = f.GetPageMargins("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestSetSheetProps(t *testing.T) {
|
||||
|
@ -80,13 +85,18 @@ func TestSetSheetProps(t *testing.T) {
|
|||
ws.(*xlsxWorksheet).SheetPr = nil
|
||||
assert.NoError(t, f.SetSheetProps("Sheet1", &SheetPropsOptions{TabColorTint: float64Ptr(1)}))
|
||||
|
||||
// Test SetSheetProps on not exists worksheet.
|
||||
// Test set worksheet properties on not exists worksheet
|
||||
assert.EqualError(t, f.SetSheetProps("SheetN", nil), "sheet SheetN does not exist")
|
||||
// Test set worksheet properties with invalid sheet name
|
||||
assert.EqualError(t, f.SetSheetProps("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestGetSheetProps(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test GetSheetProps on not exists worksheet.
|
||||
// Test get worksheet properties on not exists worksheet
|
||||
_, err := f.GetSheetProps("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get worksheet properties with invalid sheet name
|
||||
_, err = f.GetSheetProps("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
Negative: true,
|
||||
}))
|
||||
|
||||
// Save spreadsheet by the given path.
|
||||
// Save spreadsheet by the given path
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddSparkline.xlsx")))
|
||||
|
||||
// Test error exceptions
|
||||
|
@ -225,6 +225,14 @@ func TestAddSparkline(t *testing.T) {
|
|||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", nil), ErrParameterRequired.Error())
|
||||
|
||||
// Test add sparkline with invalid sheet name
|
||||
assert.EqualError(t, f.AddSparkline("Sheet:1", &SparklineOptions{
|
||||
Location: []string{"F3"},
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
Type: "win_loss",
|
||||
Negative: true,
|
||||
}), ErrSheetNameInvalid.Error())
|
||||
|
||||
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
|
||||
Range: []string{"Sheet2!A3:E3"},
|
||||
}), ErrSparklineLocation.Error())
|
||||
|
|
|
@ -102,6 +102,9 @@ type StreamWriter struct {
|
|||
// excelize.Cell{Value: 1}},
|
||||
// excelize.RowOpts{StyleID: styleID, Height: 20, Hidden: false});
|
||||
func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
|
||||
if err := checkSheetName(sheet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sheetID := f.getSheetID(sheet)
|
||||
if sheetID == -1 {
|
||||
return nil, newNoExistSheetError(sheet)
|
||||
|
@ -219,8 +222,8 @@ func (sw *StreamWriter) AddTable(hCell, vCell, opts string) error {
|
|||
sheetRelationshipsTableXML := "../tables/table" + strconv.Itoa(tableID) + ".xml"
|
||||
tableXML := strings.ReplaceAll(sheetRelationshipsTableXML, "..", "xl")
|
||||
|
||||
// Add first table for given sheet.
|
||||
sheetPath := sw.file.sheetMap[trimSheetName(sw.Sheet)]
|
||||
// Add first table for given sheet
|
||||
sheetPath := sw.file.sheetMap[sw.Sheet]
|
||||
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
|
||||
rID := sw.file.addRels(sheetRels, SourceRelationshipTable, sheetRelationshipsTableXML, "")
|
||||
|
||||
|
@ -661,7 +664,7 @@ func (sw *StreamWriter) Flush() error {
|
|||
return err
|
||||
}
|
||||
|
||||
sheetPath := sw.file.sheetMap[trimSheetName(sw.Sheet)]
|
||||
sheetPath := sw.file.sheetMap[sw.Sheet]
|
||||
sw.file.Sheet.Delete(sheetPath)
|
||||
delete(sw.file.checked, sheetPath)
|
||||
sw.file.Pkg.Delete(sheetPath)
|
||||
|
|
|
@ -257,6 +257,9 @@ func TestNewStreamWriter(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
_, err = file.NewStreamWriter("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test new stream write with invalid sheet name
|
||||
_, err = file.NewStreamWriter("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestStreamMarshalAttrs(t *testing.T) {
|
||||
|
|
40
styles.go
40
styles.go
|
@ -1101,11 +1101,25 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
|
|||
return &fs, err
|
||||
}
|
||||
|
||||
// NewStyle provides a function to create the style for cells by given
|
||||
// structure pointer or JSON. This function is concurrency safe. Note that the
|
||||
// color field uses RGB color code.
|
||||
// NewStyle provides a function to create the style for cells by given structure
|
||||
// pointer or JSON. This function is concurrency safe. Note that
|
||||
// the 'Font.Color' field uses an RGB color represented in 'RRGGBB' hexadecimal
|
||||
// notation.
|
||||
//
|
||||
// The following shows the border styles sorted by excelize index number:
|
||||
// The following table shows the border types used in 'Border.Type' supported by
|
||||
// excelize:
|
||||
//
|
||||
// Type | Description
|
||||
// --------------+------------------
|
||||
// left | Left border
|
||||
// top | Top border
|
||||
// right | Right border
|
||||
// bottom | Bottom border
|
||||
// diagonalDown | Diagonal down border
|
||||
// diagonalUp | Diagonal up border
|
||||
//
|
||||
// The following table shows the border styles used in 'Border.Style' supported
|
||||
// by excelize index number:
|
||||
//
|
||||
// Index | Name | Weight | Style
|
||||
// -------+---------------+--------+-------------
|
||||
|
@ -1124,7 +1138,8 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
|
|||
// 12 | Dash Dot Dot | 2 | - . . - . .
|
||||
// 13 | SlantDash Dot | 2 | / - . / - .
|
||||
//
|
||||
// The following shows the borders in the order shown in the Excel dialog:
|
||||
// The following table shows the border styles used in 'Border.Style' in the
|
||||
// order shown in the Excel dialog:
|
||||
//
|
||||
// Index | Style | Index | Style
|
||||
// -------+-------------+-------+-------------
|
||||
|
@ -1136,7 +1151,8 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
|
|||
// 3 | - - - - - - | 5 | -----------
|
||||
// 1 | ----------- | 6 | ===========
|
||||
//
|
||||
// The following shows the shading styles sorted by excelize index number:
|
||||
// The following table shows the shading styles used in 'Fill.Shading' supported
|
||||
// by excelize index number:
|
||||
//
|
||||
// Index | Style | Index | Style
|
||||
// -------+-----------------+-------+-----------------
|
||||
|
@ -1144,7 +1160,8 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
|
|||
// 1 | Vertical | 4 | From corner
|
||||
// 2 | Diagonal Up | 5 | From center
|
||||
//
|
||||
// The following shows the patterns styles sorted by excelize index number:
|
||||
// The following table shows the pattern styles used in 'Fill.Pattern' supported
|
||||
// by excelize index number:
|
||||
//
|
||||
// Index | Style | Index | Style
|
||||
// -------+-----------------+-------+-----------------
|
||||
|
@ -1159,7 +1176,8 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
|
|||
// 8 | darkUp | 18 | gray0625
|
||||
// 9 | darkGrid | |
|
||||
//
|
||||
// The following the type of horizontal alignment in cells:
|
||||
// The following table shows the type of cells' horizontal alignment used
|
||||
// in 'Alignment.Horizontal':
|
||||
//
|
||||
// Style
|
||||
// ------------------
|
||||
|
@ -1171,7 +1189,8 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
|
|||
// centerContinuous
|
||||
// distributed
|
||||
//
|
||||
// The following the type of vertical alignment in cells:
|
||||
// The following table shows the type of cells' vertical alignment used in
|
||||
// 'Alignment.Vertical':
|
||||
//
|
||||
// Style
|
||||
// ------------------
|
||||
|
@ -1180,7 +1199,8 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
|
|||
// justify
|
||||
// distributed
|
||||
//
|
||||
// The following the type of font underline style:
|
||||
// The following table shows the type of font underline style used in
|
||||
// 'Font.Underline':
|
||||
//
|
||||
// Style
|
||||
// ------------------
|
||||
|
|
|
@ -201,6 +201,9 @@ func TestGetConditionalFormats(t *testing.T) {
|
|||
f := NewFile()
|
||||
_, err := f.GetConditionalFormats("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||
// Test get conditional formats with invalid sheet name
|
||||
_, err = f.GetConditionalFormats("Sheet:1")
|
||||
assert.EqualError(t, err, ErrSheetNameInvalid.Error())
|
||||
}
|
||||
|
||||
func TestUnsetConditionalFormat(t *testing.T) {
|
||||
|
@ -211,9 +214,11 @@ func TestUnsetConditionalFormat(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetConditionalFormat("Sheet1", "A1:A10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format)))
|
||||
assert.NoError(t, f.UnsetConditionalFormat("Sheet1", "A1:A10"))
|
||||
// Test unset conditional format on not exists worksheet.
|
||||
// Test unset conditional format on not exists worksheet
|
||||
assert.EqualError(t, f.UnsetConditionalFormat("SheetN", "A1:A10"), "sheet SheetN does not exist")
|
||||
// Save spreadsheet by the given path.
|
||||
// Test unset conditional format with invalid sheet name
|
||||
assert.EqualError(t, f.UnsetConditionalFormat("Sheet:1", "A1:A10"), ErrSheetNameInvalid.Error())
|
||||
// Save spreadsheet by the given path
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnsetConditionalFormat.xlsx")))
|
||||
}
|
||||
|
||||
|
@ -240,7 +245,7 @@ func TestNewStyle(t *testing.T) {
|
|||
_, err = f.NewStyle(&Style{Font: &Font{Size: MaxFontSize + 1}})
|
||||
assert.EqualError(t, err, ErrFontSize.Error())
|
||||
|
||||
// Test create numeric custom style.
|
||||
// Test create numeric custom style
|
||||
numFmt := "####;####"
|
||||
f.Styles.NumFmts = nil
|
||||
styleID, err = f.NewStyle(&Style{
|
||||
|
@ -256,7 +261,7 @@ func TestNewStyle(t *testing.T) {
|
|||
nf := f.Styles.CellXfs.Xf[styleID]
|
||||
assert.Equal(t, 164, *nf.NumFmtID)
|
||||
|
||||
// Test create currency custom style.
|
||||
// Test create currency custom style
|
||||
f.Styles.NumFmts = nil
|
||||
styleID, err = f.NewStyle(&Style{
|
||||
Lang: "ko-kr",
|
||||
|
@ -273,7 +278,7 @@ func TestNewStyle(t *testing.T) {
|
|||
nf = f.Styles.CellXfs.Xf[styleID]
|
||||
assert.Equal(t, 32, *nf.NumFmtID)
|
||||
|
||||
// Test set build-in scientific number format.
|
||||
// Test set build-in scientific number format
|
||||
styleID, err = f.NewStyle(&Style{NumFmt: 11})
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "B1", styleID))
|
||||
|
@ -283,7 +288,7 @@ func TestNewStyle(t *testing.T) {
|
|||
assert.Equal(t, [][]string{{"1.23E+00", "1.23E+00"}}, rows)
|
||||
|
||||
f = NewFile()
|
||||
// Test currency number format.
|
||||
// Test currency number format
|
||||
customNumFmt := "[$$-409]#,##0.00"
|
||||
style1, err := f.NewStyle(&Style{CustomNumFmt: &customNumFmt})
|
||||
assert.NoError(t, err)
|
||||
|
@ -309,7 +314,7 @@ func TestNewStyle(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, style5)
|
||||
|
||||
// Test create style with unsupported charset style sheet.
|
||||
// Test create style with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
_, err = f.NewStyle(&Style{NumFmt: 165})
|
||||
|
@ -318,7 +323,7 @@ func TestNewStyle(t *testing.T) {
|
|||
|
||||
func TestNewConditionalStyle(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test create conditional style with unsupported charset style sheet.
|
||||
// Test create conditional style with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
_, err := f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
|
||||
|
@ -330,7 +335,7 @@ func TestGetDefaultFont(t *testing.T) {
|
|||
s, err := f.GetDefaultFont()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, s, "Calibri", "Default font should be Calibri")
|
||||
// Test get default font with unsupported charset style sheet.
|
||||
// Test get default font with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
_, err = f.GetDefaultFont()
|
||||
|
@ -346,7 +351,7 @@ func TestSetDefaultFont(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, s, "Arial", "Default font should change to Arial")
|
||||
assert.Equal(t, *styles.CellStyles.CellStyle[0].CustomBuiltIn, true)
|
||||
// Test set default font with unsupported charset style sheet.
|
||||
// Test set default font with unsupported charset style sheet
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.SetDefaultFont("Arial"), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
@ -354,7 +359,7 @@ func TestSetDefaultFont(t *testing.T) {
|
|||
|
||||
func TestStylesReader(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test read styles with unsupported charset.
|
||||
// Test read styles with unsupported charset
|
||||
f.Styles = nil
|
||||
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||
styles, err := f.stylesReader()
|
||||
|
@ -364,7 +369,7 @@ func TestStylesReader(t *testing.T) {
|
|||
|
||||
func TestThemeReader(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test read theme with unsupported charset.
|
||||
// Test read theme with unsupported charset
|
||||
f.Pkg.Store(defaultXMLPathTheme, MacintoshCyrillicCharset)
|
||||
theme, err := f.themeReader()
|
||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||
|
|
5
table.go
5
table.go
|
@ -304,7 +304,10 @@ func (f *File) AutoFilter(sheet, hCell, vCell, opts string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sheetID := f.GetSheetIndex(sheet)
|
||||
sheetID, err := f.GetSheetIndex(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filterRange := fmt.Sprintf("'%s'!%s", sheet, ref)
|
||||
d := xlsxDefinedName{
|
||||
Name: filterDB,
|
||||
|
|
|
@ -10,36 +10,24 @@ import (
|
|||
|
||||
func TestAddTable(t *testing.T) {
|
||||
f, err := prepareTestBook1()
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.AddTable("Sheet1", "B26", "A21", `{}`))
|
||||
assert.NoError(t, f.AddTable("Sheet2", "A2", "B5", `{"table_name":"table","table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`))
|
||||
assert.NoError(t, f.AddTable("Sheet2", "F1", "F1", `{"table_style":"TableStyleMedium8"}`))
|
||||
|
||||
err = f.AddTable("Sheet1", "B26", "A21", `{}`)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
err = f.AddTable("Sheet2", "A2", "B5", `{"table_name":"table","table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
err = f.AddTable("Sheet2", "F1", "F1", `{"table_style":"TableStyleMedium8"}`)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// Test add table in not exist worksheet.
|
||||
// Test add table in not exist worksheet
|
||||
assert.EqualError(t, f.AddTable("SheetN", "B26", "A21", `{}`), "sheet SheetN does not exist")
|
||||
// Test add table with illegal options.
|
||||
// Test add table with illegal options
|
||||
assert.EqualError(t, f.AddTable("Sheet1", "B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
|
||||
// Test add table with illegal cell reference.
|
||||
// Test add table with illegal cell reference
|
||||
assert.EqualError(t, f.AddTable("Sheet1", "A", "B1", `{}`), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
assert.EqualError(t, f.AddTable("Sheet1", "A1", "B", `{}`), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddTable.xlsx")))
|
||||
|
||||
// Test addTable with illegal cell reference.
|
||||
// Test add table with invalid sheet name
|
||||
assert.EqualError(t, f.AddTable("Sheet:1", "B26", "A21", `{}`), ErrSheetNameInvalid.Error())
|
||||
// Test addTable with illegal cell reference
|
||||
f = NewFile()
|
||||
assert.EqualError(t, f.addTable("sheet1", "", 0, 0, 0, 0, 0, nil), "invalid cell reference [0, 0]")
|
||||
assert.EqualError(t, f.addTable("sheet1", "", 1, 1, 0, 0, 0, nil), "invalid cell reference [0, 0]")
|
||||
|
@ -53,12 +41,8 @@ func TestSetTableHeader(t *testing.T) {
|
|||
|
||||
func TestAutoFilter(t *testing.T) {
|
||||
outFile := filepath.Join("test", "TestAutoFilter%d.xlsx")
|
||||
|
||||
f, err := prepareTestBook1()
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
formats := []string{
|
||||
``,
|
||||
`{"column":"B","expression":"x != blanks"}`,
|
||||
|
@ -69,7 +53,6 @@ func TestAutoFilter(t *testing.T) {
|
|||
`{"column":"B","expression":"x == 1 or x == 2"}`,
|
||||
`{"column":"B","expression":"x == 1 or x == 2*"}`,
|
||||
}
|
||||
|
||||
for i, format := range formats {
|
||||
t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
|
||||
err = f.AutoFilter("Sheet1", "D4", "B1", format)
|
||||
|
@ -78,10 +61,12 @@ func TestAutoFilter(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
// Test add auto filter with illegal cell reference.
|
||||
// Test add auto filter with invalid sheet name
|
||||
assert.EqualError(t, f.AutoFilter("Sheet:1", "A1", "B1", ""), ErrSheetNameInvalid.Error())
|
||||
// Test add auto filter with illegal cell reference
|
||||
assert.EqualError(t, f.AutoFilter("Sheet1", "A", "B1", ""), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||
assert.EqualError(t, f.AutoFilter("Sheet1", "A1", "B", ""), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
|
||||
// Test add auto filter with unsupported charset workbook.
|
||||
// Test add auto filter with unsupported charset workbook
|
||||
f.WorkBook = nil
|
||||
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.AutoFilter("Sheet1", "D4", "B1", formats[0]), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
@ -132,10 +117,10 @@ func TestAutoFilterError(t *testing.T) {
|
|||
|
||||
func TestParseFilterTokens(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test with unknown operator.
|
||||
// Test with unknown operator
|
||||
_, _, err := f.parseFilterTokens("", []string{"", "!"})
|
||||
assert.EqualError(t, err, "unknown operator: !")
|
||||
// Test invalid operator in context.
|
||||
// Test invalid operator in context
|
||||
_, _, err = f.parseFilterTokens("", []string{"", "<", "x != blanks"})
|
||||
assert.EqualError(t, err, "the operator '<' in expression '' is not valid in relation to Blanks/NonBlanks'")
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ func (f *File) GetWorkbookProps() (WorkbookPropsOptions, error) {
|
|||
func (f *File) setWorkbook(name string, sheetID, rid int) {
|
||||
wb, _ := f.workbookReader()
|
||||
wb.Sheets.Sheet = append(wb.Sheets.Sheet, xlsxSheet{
|
||||
Name: trimSheetName(name),
|
||||
Name: name,
|
||||
SheetID: sheetID,
|
||||
ID: "rId" + strconv.Itoa(rid),
|
||||
})
|
||||
|
|
|
@ -77,6 +77,6 @@ type Comment struct {
|
|||
Author string `json:"author"`
|
||||
AuthorID int `json:"author_id"`
|
||||
Cell string `json:"cell"`
|
||||
Text string `json:"string"`
|
||||
Text string `json:"text"`
|
||||
Runs []RichTextRun `json:"runs"`
|
||||
}
|
||||
|
|
119
xmlDrawing.go
119
xmlDrawing.go
|
@ -19,58 +19,30 @@ import (
|
|||
// Source relationship and namespace list, associated prefixes and schema in which it was
|
||||
// introduced.
|
||||
var (
|
||||
SourceRelationship = xml.Attr{Name: xml.Name{Local: "r", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}
|
||||
SourceRelationshipCompatibility = xml.Attr{Name: xml.Name{Local: "mc", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/markup-compatibility/2006"}
|
||||
SourceRelationshipChart20070802 = xml.Attr{Name: xml.Name{Local: "c14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2007/8/2/chart"}
|
||||
SourceRelationshipChart2014 = xml.Attr{Name: xml.Name{Local: "c16", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2014/chart"}
|
||||
SourceRelationshipChart201506 = xml.Attr{Name: xml.Name{Local: "c16r2", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2015/06/chart"}
|
||||
NameSpaceSpreadSheet = xml.Attr{Name: xml.Name{Local: "xmlns"}, Value: "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
|
||||
NameSpaceSpreadSheetX14 = xml.Attr{Name: xml.Name{Local: "x14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}
|
||||
NameSpaceDocumentPropertiesVariantTypes = xml.Attr{Name: xml.Name{Local: "vt", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"}
|
||||
NameSpaceDrawing2016SVG = xml.Attr{Name: xml.Name{Local: "asvg", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2016/SVG/main"}
|
||||
NameSpaceDrawingML = xml.Attr{Name: xml.Name{Local: "a", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/main"}
|
||||
NameSpaceDrawingMLChart = xml.Attr{Name: xml.Name{Local: "c", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/chart"}
|
||||
NameSpaceDrawingMLSpreadSheet = xml.Attr{Name: xml.Name{Local: "xdr", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"}
|
||||
NameSpaceDrawing2016SVG = xml.Attr{Name: xml.Name{Local: "asvg", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2016/SVG/main"}
|
||||
NameSpaceSpreadSheetX15 = xml.Attr{Name: xml.Name{Local: "x15", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"}
|
||||
NameSpaceSpreadSheetExcel2006Main = xml.Attr{Name: xml.Name{Local: "xne", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/excel/2006/main"}
|
||||
NameSpaceMacExcel2008Main = xml.Attr{Name: xml.Name{Local: "mx", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/mac/excel/2008/main"}
|
||||
NameSpaceDocumentPropertiesVariantTypes = xml.Attr{Name: xml.Name{Local: "vt", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"}
|
||||
NameSpaceSpreadSheet = xml.Attr{Name: xml.Name{Local: "xmlns"}, Value: "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
|
||||
NameSpaceSpreadSheetExcel2006Main = xml.Attr{Name: xml.Name{Local: "xne", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/excel/2006/main"}
|
||||
NameSpaceSpreadSheetX14 = xml.Attr{Name: xml.Name{Local: "x14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}
|
||||
NameSpaceSpreadSheetX15 = xml.Attr{Name: xml.Name{Local: "x15", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"}
|
||||
SourceRelationship = xml.Attr{Name: xml.Name{Local: "r", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}
|
||||
SourceRelationshipChart20070802 = xml.Attr{Name: xml.Name{Local: "c14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2007/8/2/chart"}
|
||||
SourceRelationshipChart2014 = xml.Attr{Name: xml.Name{Local: "c16", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2014/chart"}
|
||||
SourceRelationshipChart201506 = xml.Attr{Name: xml.Name{Local: "c16r2", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2015/06/chart"}
|
||||
SourceRelationshipCompatibility = xml.Attr{Name: xml.Name{Local: "mc", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/markup-compatibility/2006"}
|
||||
)
|
||||
|
||||
// Source relationship and namespace.
|
||||
const (
|
||||
SourceRelationshipOfficeDocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
|
||||
SourceRelationshipChart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"
|
||||
SourceRelationshipComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
|
||||
SourceRelationshipImage = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
|
||||
SourceRelationshipTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"
|
||||
SourceRelationshipDrawingML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
|
||||
SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
|
||||
SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
||||
SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
|
||||
SourceRelationshipChartsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"
|
||||
SourceRelationshipDialogsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet"
|
||||
SourceRelationshipPivotTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable"
|
||||
SourceRelationshipPivotCache = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition"
|
||||
SourceRelationshipSharedStrings = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"
|
||||
SourceRelationshipVBAProject = "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
|
||||
NameSpaceXML = "http://www.w3.org/XML/1998/namespace"
|
||||
NameSpaceXMLSchemaInstance = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
StrictSourceRelationship = "http://purl.oclc.org/ooxml/officeDocument/relationships"
|
||||
StrictSourceRelationshipOfficeDocument = "http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument"
|
||||
StrictSourceRelationshipChart = "http://purl.oclc.org/ooxml/officeDocument/relationships/chart"
|
||||
StrictSourceRelationshipComments = "http://purl.oclc.org/ooxml/officeDocument/relationships/comments"
|
||||
StrictSourceRelationshipImage = "http://purl.oclc.org/ooxml/officeDocument/relationships/image"
|
||||
StrictNameSpaceSpreadSheet = "http://purl.oclc.org/ooxml/spreadsheetml/main"
|
||||
NameSpaceDublinCore = "http://purl.org/dc/elements/1.1/"
|
||||
NameSpaceDublinCoreTerms = "http://purl.org/dc/terms/"
|
||||
NameSpaceDublinCoreMetadataInitiative = "http://purl.org/dc/dcmitype/"
|
||||
ContentTypeAddinMacro = "application/vnd.ms-excel.addin.macroEnabled.main+xml"
|
||||
ContentTypeDrawing = "application/vnd.openxmlformats-officedocument.drawing+xml"
|
||||
ContentTypeDrawingML = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
|
||||
ContentTypeSheetML = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
|
||||
ContentTypeTemplate = "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
|
||||
ContentTypeAddinMacro = "application/vnd.ms-excel.addin.macroEnabled.main+xml"
|
||||
ContentTypeMacro = "application/vnd.ms-excel.sheet.macroEnabled.main+xml"
|
||||
ContentTypeTemplateMacro = "application/vnd.ms-excel.template.macroEnabled.main+xml"
|
||||
ContentTypeSheetML = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
|
||||
ContentTypeSpreadSheetMLChartsheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml"
|
||||
ContentTypeSpreadSheetMLComments = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"
|
||||
ContentTypeSpreadSheetMLPivotCacheDefinition = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"
|
||||
|
@ -78,44 +50,73 @@ const (
|
|||
ContentTypeSpreadSheetMLSharedStrings = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"
|
||||
ContentTypeSpreadSheetMLTable = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"
|
||||
ContentTypeSpreadSheetMLWorksheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
|
||||
ContentTypeTemplate = "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
|
||||
ContentTypeTemplateMacro = "application/vnd.ms-excel.template.macroEnabled.main+xml"
|
||||
ContentTypeVBA = "application/vnd.ms-office.vbaProject"
|
||||
ContentTypeVML = "application/vnd.openxmlformats-officedocument.vmlDrawing"
|
||||
NameSpaceDublinCore = "http://purl.org/dc/elements/1.1/"
|
||||
NameSpaceDublinCoreMetadataInitiative = "http://purl.org/dc/dcmitype/"
|
||||
NameSpaceDublinCoreTerms = "http://purl.org/dc/terms/"
|
||||
NameSpaceXML = "http://www.w3.org/XML/1998/namespace"
|
||||
NameSpaceXMLSchemaInstance = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
SourceRelationshipChart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"
|
||||
SourceRelationshipChartsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"
|
||||
SourceRelationshipComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
|
||||
SourceRelationshipDialogsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet"
|
||||
SourceRelationshipDrawingML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
|
||||
SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
|
||||
SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
||||
SourceRelationshipImage = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
|
||||
SourceRelationshipOfficeDocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
|
||||
SourceRelationshipPivotCache = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition"
|
||||
SourceRelationshipPivotTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable"
|
||||
SourceRelationshipSharedStrings = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"
|
||||
SourceRelationshipTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"
|
||||
SourceRelationshipVBAProject = "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
|
||||
SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
|
||||
StrictNameSpaceSpreadSheet = "http://purl.oclc.org/ooxml/spreadsheetml/main"
|
||||
StrictSourceRelationship = "http://purl.oclc.org/ooxml/officeDocument/relationships"
|
||||
StrictSourceRelationshipChart = "http://purl.oclc.org/ooxml/officeDocument/relationships/chart"
|
||||
StrictSourceRelationshipComments = "http://purl.oclc.org/ooxml/officeDocument/relationships/comments"
|
||||
StrictSourceRelationshipImage = "http://purl.oclc.org/ooxml/officeDocument/relationships/image"
|
||||
StrictSourceRelationshipOfficeDocument = "http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument"
|
||||
// ExtURIConditionalFormattings is the extLst child element
|
||||
// ([ISO/IEC29500-1:2016] section 18.2.10) of the worksheet element
|
||||
// ([ISO/IEC29500-1:2016] section 18.3.1.99) is extended by the addition of
|
||||
// new child ext elements ([ISO/IEC29500-1:2016] section 18.2.7)
|
||||
ExtURIConditionalFormattings = "{78C0D931-6437-407D-A8EE-F0AAD7539E65}"
|
||||
ExtURIDataValidations = "{CCE6A557-97BC-4B89-ADB6-D9C93CAAB3DF}"
|
||||
ExtURISparklineGroups = "{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"
|
||||
ExtURISlicerListX14 = "{A8765BA9-456A-4DAB-B4F3-ACF838C121DE}"
|
||||
ExtURISlicerCachesListX14 = "{BBE1A952-AA13-448e-AADC-164F8A28A991}"
|
||||
ExtURISlicerListX15 = "{3A4CF648-6AED-40f4-86FF-DC5316D8AED3}"
|
||||
ExtURIProtectedRanges = "{FC87AEE6-9EDD-4A0A-B7FB-166176984837}"
|
||||
ExtURIIgnoredErrors = "{01252117-D84E-4E92-8308-4BE1C098FCBB}"
|
||||
ExtURIWebExtensions = "{F7C9EE02-42E1-4005-9D12-6889AFFD525C}"
|
||||
ExtURITimelineRefs = "{7E03D99C-DC04-49d9-9315-930204A7B6E9}"
|
||||
ExtURIDrawingBlip = "{28A0092B-C50C-407E-A947-70E740481C1C}"
|
||||
ExtURIIgnoredErrors = "{01252117-D84E-4E92-8308-4BE1C098FCBB}"
|
||||
ExtURIMacExcelMX = "{64002731-A6B0-56B0-2670-7721B7C09600}"
|
||||
ExtURIProtectedRanges = "{FC87AEE6-9EDD-4A0A-B7FB-166176984837}"
|
||||
ExtURISlicerCachesListX14 = "{BBE1A952-AA13-448e-AADC-164F8A28A991}"
|
||||
ExtURISlicerListX14 = "{A8765BA9-456A-4DAB-B4F3-ACF838C121DE}"
|
||||
ExtURISlicerListX15 = "{3A4CF648-6AED-40f4-86FF-DC5316D8AED3}"
|
||||
ExtURISparklineGroups = "{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"
|
||||
ExtURISVG = "{96DAC541-7B7A-43D3-8B79-37D633B846F1}"
|
||||
ExtURITimelineRefs = "{7E03D99C-DC04-49d9-9315-930204A7B6E9}"
|
||||
ExtURIWebExtensions = "{F7C9EE02-42E1-4005-9D12-6889AFFD525C}"
|
||||
)
|
||||
|
||||
// Excel specifications and limits
|
||||
const (
|
||||
UnzipSizeLimit = 1000 << 24
|
||||
StreamChunkSize = 1 << 24
|
||||
MaxCellStyles = 64000
|
||||
MaxColumns = 16384
|
||||
MaxColumnWidth = 255
|
||||
MaxFieldLength = 255
|
||||
MaxFilePathLength = 207
|
||||
MaxFontFamilyLength = 31
|
||||
MaxFontSize = 409
|
||||
MaxFilePathLength = 207
|
||||
MaxFieldLength = 255
|
||||
MaxColumnWidth = 255
|
||||
MaxRowHeight = 409
|
||||
MaxCellStyles = 64000
|
||||
MinFontSize = 1
|
||||
TotalRows = 1048576
|
||||
MaxSheetNameLength = 31
|
||||
MinColumns = 1
|
||||
MaxColumns = 16384
|
||||
TotalSheetHyperlinks = 65529
|
||||
MinFontSize = 1
|
||||
StreamChunkSize = 1 << 24
|
||||
TotalCellChars = 32767
|
||||
TotalRows = 1048576
|
||||
TotalSheetHyperlinks = 65529
|
||||
UnzipSizeLimit = 1000 << 24
|
||||
// pivotTableVersion should be greater than 3. One or more of the
|
||||
// PivotTables chosen are created in a version of Excel earlier than
|
||||
// Excel 2007 or in compatibility mode. Slicer can only be used with
|
||||
|
|
Loading…
Reference in New Issue