excelize_test.go 40.2 KB
Newer Older
xurime's avatar
xurime 已提交
1 2 3
package excelize

import (
4
	"fmt"
xurime's avatar
xurime 已提交
5
	"image/color"
6 7 8
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
9
	"io/ioutil"
V
Veniamin Albaev 已提交
10
	"os"
11
	"path/filepath"
xurime's avatar
xurime 已提交
12
	"strconv"
xurime's avatar
xurime 已提交
13
	"strings"
xurime's avatar
xurime 已提交
14
	"testing"
15
	"time"
V
Veniamin Albaev 已提交
16 17

	"github.com/stretchr/testify/assert"
xurime's avatar
xurime 已提交
18 19
)

20
func TestOpenFile(t *testing.T) {
xurime's avatar
xurime 已提交
21
	// Test update a XLSX file.
22
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
23 24
	if !assert.NoError(t, err) {
		t.FailNow()
25
	}
V
Veniamin Albaev 已提交
26

27
	// Test get all the rows in a not exists worksheet.
28
	f.GetRows("Sheet4")
29
	// Test get all the rows in a worksheet.
30
	rows, err := f.GetRows("Sheet2")
31
	assert.NoError(t, err)
32 33 34 35 36 37
	for _, row := range rows {
		for _, cell := range row {
			t.Log(cell, "\t")
		}
		t.Log("\r\n")
	}
38
	f.UpdateLinkedValue()
39

40 41
	f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))
	f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
42

43
	// Test set cell value with illegal row number.
44
	assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)),
45
		`cannot convert cell "A" to coordinates: invalid cell name "A"`)
46

47
	f.SetCellInt("Sheet2", "A1", 100)
48

49
	// Test set cell integer value with illegal row number.
50
	assert.EqualError(t, f.SetCellInt("Sheet2", "A", 100), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
51

52
	f.SetCellStr("Sheet2", "C11", "Knowns")
53
	// Test max characters in a cell.
54 55
	f.SetCellStr("Sheet2", "D11", strings.Repeat("c", 32769))
	f.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.")
56
	// Test set worksheet name with illegal name.
57 58 59 60
	f.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
	f.SetCellInt("Sheet3", "A23", 10)
	f.SetCellStr("Sheet3", "b230", "10")
	assert.EqualError(t, f.SetCellStr("Sheet10", "b230", "10"), "sheet Sheet10 is not exist")
61

62
	// Test set cell string value with illegal row number.
63
	assert.EqualError(t, f.SetCellStr("Sheet1", "A", "10"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
64

65
	f.SetActiveSheet(2)
66
	// Test get cell formula with given rows number.
67
	_, err = f.GetCellFormula("Sheet1", "B19")
68
	assert.NoError(t, err)
69
	// Test get cell formula with illegal worksheet name.
70
	_, err = f.GetCellFormula("Sheet2", "B20")
71
	assert.NoError(t, err)
72
	_, err = f.GetCellFormula("Sheet1", "B20")
73
	assert.NoError(t, err)
74 75

	// Test get cell formula with illegal rows number.
76
	_, err = f.GetCellFormula("Sheet1", "B")
77
	assert.EqualError(t, err, `cannot convert cell "B" to coordinates: invalid cell name "B"`)
78
	// Test get shared cell formula
79 80
	f.GetCellFormula("Sheet2", "H11")
	f.GetCellFormula("Sheet2", "I11")
81
	getSharedForumula(&xlsxWorksheet{}, "")
82

xurime's avatar
xurime 已提交
83
	// Test read cell value with given illegal rows number.
84
	_, err = f.GetCellValue("Sheet2", "a-1")
85
	assert.EqualError(t, err, `cannot convert cell "A-1" to coordinates: invalid cell name "A-1"`)
86
	_, err = f.GetCellValue("Sheet2", "A")
87
	assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
88

xurime's avatar
xurime 已提交
89
	// Test read cell value with given lowercase column number.
90 91 92 93
	f.GetCellValue("Sheet2", "a5")
	f.GetCellValue("Sheet2", "C11")
	f.GetCellValue("Sheet2", "D11")
	f.GetCellValue("Sheet2", "D12")
xurime's avatar
xurime 已提交
94
	// Test SetCellValue function.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	assert.NoError(t, f.SetCellValue("Sheet2", "F1", " Hello"))
	assert.NoError(t, f.SetCellValue("Sheet2", "G1", []byte("World")))
	assert.NoError(t, f.SetCellValue("Sheet2", "F2", 42))
	assert.NoError(t, f.SetCellValue("Sheet2", "F3", int8(1<<8/2-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F4", int16(1<<16/2-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F5", int32(1<<32/2-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F6", int64(1<<32/2-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F7", float32(42.65418)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F8", float64(-42.65418)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F9", float32(42)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F10", float64(42)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F11", uint(1<<32-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F12", uint8(1<<8-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F13", uint16(1<<16-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F14", uint32(1<<32-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F15", uint64(1<<32-1)))
	assert.NoError(t, f.SetCellValue("Sheet2", "F16", true))
	assert.NoError(t, f.SetCellValue("Sheet2", "F17", complex64(5+10i)))
xurime's avatar
xurime 已提交
113 114

	// Test on not exists worksheet.
115 116 117 118 119
	assert.EqualError(t, f.SetCellDefault("SheetN", "A1", ""), "sheet SheetN is not exist")
	assert.EqualError(t, f.SetCellFloat("SheetN", "A1", 42.65418, 2, 32), "sheet SheetN is not exist")
	assert.EqualError(t, f.SetCellBool("SheetN", "A1", true), "sheet SheetN is not exist")
	assert.EqualError(t, f.SetCellFormula("SheetN", "A1", ""), "sheet SheetN is not exist")
	assert.EqualError(t, f.SetCellHyperLink("SheetN", "A1", "Sheet1!A40", "Location"), "sheet SheetN is not exist")
120

121 122 123 124 125 126 127 128 129
	// Test boolean write
	booltest := []struct {
		value    bool
		expected string
	}{
		{false, "0"},
		{true, "1"},
	}
	for _, test := range booltest {
130 131
		f.SetCellValue("Sheet2", "F16", test.value)
		val, err := f.GetCellValue("Sheet2", "F16")
132 133
		assert.NoError(t, err)
		assert.Equal(t, test.expected, val)
134
	}
135

136
	f.SetCellValue("Sheet2", "G2", nil)
137

138
	assert.EqualError(t, f.SetCellValue("Sheet2", "G4", time.Now()), "only UTC time expected")
139

140
	f.SetCellValue("Sheet2", "G4", time.Now().UTC())
141
	// 02:46:40
142
	f.SetCellValue("Sheet2", "G5", time.Duration(1e13))
xurime's avatar
xurime 已提交
143
	// Test completion column.
144
	f.SetCellValue("Sheet2", "M2", nil)
xurime's avatar
xurime 已提交
145
	// Test read cell value with given axis large than exists row.
146
	f.GetCellValue("Sheet2", "E231")
147
	// Test get active worksheet of XLSX and get worksheet name of XLSX by given worksheet index.
148
	f.GetSheetName(f.GetActiveSheetIndex())
149
	// Test get worksheet index of XLSX by given worksheet name.
150
	f.GetSheetIndex("Sheet1")
151
	// Test get worksheet name of XLSX by given invalid worksheet index.
152 153 154
	f.GetSheetName(4)
	// Test get worksheet map of f.
	f.GetSheetMap()
155
	for i := 1; i <= 300; i++ {
156
		f.SetCellStr("Sheet3", "c"+strconv.Itoa(i), strconv.Itoa(i))
157
	}
158
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestOpenFile.xlsx")))
V
Veniamin Albaev 已提交
159 160
}

xurime's avatar
xurime 已提交
161
func TestSaveFile(t *testing.T) {
162
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
xurime's avatar
xurime 已提交
163 164 165
	if !assert.NoError(t, err) {
		t.FailNow()
	}
166 167
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSaveFile.xlsx")))
	f, err = OpenFile(filepath.Join("test", "TestSaveFile.xlsx"))
xurime's avatar
xurime 已提交
168 169 170
	if !assert.NoError(t, err) {
		t.FailNow()
	}
171
	assert.NoError(t, f.Save())
xurime's avatar
xurime 已提交
172 173
}

V
Veniamin Albaev 已提交
174
func TestSaveAsWrongPath(t *testing.T) {
175
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
176 177
	if assert.NoError(t, err) {
		// Test write file to not exist directory.
178
		err = f.SaveAs("")
V
Veniamin Albaev 已提交
179 180 181
		if assert.Error(t, err) {
			assert.True(t, os.IsNotExist(err), "Error: %v: Expected os.IsNotExists(err) == true", err)
		}
xurime's avatar
xurime 已提交
182
	}
183 184
}

185
func TestBrokenFile(t *testing.T) {
xurime's avatar
xurime 已提交
186
	// Test write file with broken file struct.
187
	f := File{}
xurime's avatar
xurime 已提交
188

V
Veniamin Albaev 已提交
189
	t.Run("SaveWithoutName", func(t *testing.T) {
190
		assert.EqualError(t, f.Save(), "no path defined for file, consider File.WriteTo or File.Write")
V
Veniamin Albaev 已提交
191
	})
192

V
Veniamin Albaev 已提交
193 194
	t.Run("SaveAsEmptyStruct", func(t *testing.T) {
		// Test write file with broken file struct with given path.
195
		assert.NoError(t, f.SaveAs(filepath.Join("test", "BrokenFile.SaveAsEmptyStruct.xlsx")))
V
Veniamin Albaev 已提交
196 197 198 199
	})

	t.Run("OpenBadWorkbook", func(t *testing.T) {
		// Test set active sheet without BookViews and Sheets maps in xl/workbook.xml.
200
		f3, err := OpenFile(filepath.Join("test", "BadWorkbook.xlsx"))
V
Veniamin Albaev 已提交
201 202 203 204 205 206 207
		f3.GetActiveSheetIndex()
		f3.SetActiveSheet(2)
		assert.NoError(t, err)
	})

	t.Run("OpenNotExistsFile", func(t *testing.T) {
		// Test open a XLSX file with given illegal path.
208
		_, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
V
Veniamin Albaev 已提交
209 210 211 212
		if assert.Error(t, err) {
			assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
		}
	})
213 214
}

215
func TestNewFile(t *testing.T) {
216
	// Test create a XLSX file.
217 218 219 220 221 222 223
	f := NewFile()
	f.NewSheet("Sheet1")
	f.NewSheet("XLSXSheet2")
	f.NewSheet("XLSXSheet3")
	f.SetCellInt("XLSXSheet2", "A23", 56)
	f.SetCellStr("Sheet1", "B20", "42")
	f.SetActiveSheet(0)
V
Veniamin Albaev 已提交
224

225
	// Test add picture to sheet with scaling and positioning.
226
	err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
227
		`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
V
Veniamin Albaev 已提交
228 229
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
230
	}
V
Veniamin Albaev 已提交
231

232
	// Test add picture to worksheet without formatset.
233
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
V
Veniamin Albaev 已提交
234 235
	if !assert.NoError(t, err) {
		t.FailNow()
236
	}
V
Veniamin Albaev 已提交
237

238
	// Test add picture to worksheet with invalid formatset.
239
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), `{`)
V
Veniamin Albaev 已提交
240 241
	if !assert.Error(t, err) {
		t.FailNow()
242
	}
V
Veniamin Albaev 已提交
243

244
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewFile.xlsx")))
xurime's avatar
xurime 已提交
245
}
246

247 248 249 250 251 252
func TestAddDrawingVML(t *testing.T) {
	// Test addDrawingVML with illegal cell coordinates.
	f := NewFile()
	assert.EqualError(t, f.addDrawingVML(0, "", "*", 0, 0), `cannot convert cell "*" to coordinates: invalid cell name "*"`)
}

253
func TestSetCellHyperLink(t *testing.T) {
254
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
255 256 257 258
	if err != nil {
		t.Log(err)
	}
	// Test set cell hyperlink in a work sheet already have hyperlinks.
259
	assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
260
	// Test add first hyperlink in a work sheet.
261
	assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
262
	// Test add Location hyperlink in a work sheet.
263
	assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
264

265
	assert.EqualError(t, f.SetCellHyperLink("Sheet2", "C3", "Sheet1!D8", ""), `invalid link type ""`)
266

267
	assert.EqualError(t, f.SetCellHyperLink("Sheet2", "", "Sheet1!D60", "Location"), `invalid cell name ""`)
268

269 270 271 272 273 274 275 276 277
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx")))

	file := NewFile()
	for row := 1; row <= 65530; row++ {
		cell, err := CoordinatesToCellName(1, row)
		assert.NoError(t, err)
		assert.NoError(t, file.SetCellHyperLink("Sheet1", cell, "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
	}
	assert.EqualError(t, file.SetCellHyperLink("Sheet1", "A65531", "https://github.com/360EntSecGroup-Skylar/excelize", "External"), "over maximum limit hyperlinks in a worksheet")
278 279
}

280
func TestGetCellHyperLink(t *testing.T) {
281
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
282 283
	if !assert.NoError(t, err) {
		t.FailNow()
284
	}
V
Veniamin Albaev 已提交
285

286
	_, _, err = f.GetCellHyperLink("Sheet1", "")
287
	assert.EqualError(t, err, `invalid cell name ""`)
288

289
	link, target, err := f.GetCellHyperLink("Sheet1", "A22")
290
	assert.NoError(t, err)
291
	t.Log(link, target)
292
	link, target, err = f.GetCellHyperLink("Sheet2", "D6")
293
	assert.NoError(t, err)
294
	t.Log(link, target)
295
	link, target, err = f.GetCellHyperLink("Sheet3", "H3")
xurime's avatar
xurime 已提交
296
	assert.EqualError(t, err, "sheet Sheet3 is not exist")
297 298 299
	t.Log(link, target)
}

300
func TestSetCellFormula(t *testing.T) {
301
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
302 303
	if !assert.NoError(t, err) {
		t.FailNow()
304
	}
V
Veniamin Albaev 已提交
305

306 307
	f.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)")
	f.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
308

309
	// Test set cell formula with illegal rows number.
310
	assert.EqualError(t, f.SetCellFormula("Sheet1", "C", "SUM(Sheet2!D2,Sheet2!D9)"), `cannot convert cell "C" to coordinates: invalid cell name "C"`)
311

312
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula1.xlsx")))
V
Veniamin Albaev 已提交
313

314
	f, err = OpenFile(filepath.Join("test", "CalcChain.xlsx"))
315 316 317 318
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	// Test remove cell formula.
319 320
	f.SetCellFormula("Sheet1", "A1", "")
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula2.xlsx")))
321
	// Test remove all cell formula.
322 323
	f.SetCellFormula("Sheet1", "B1", "")
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula3.xlsx")))
324
}
325 326

func TestSetSheetBackground(t *testing.T) {
327
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
328 329
	if !assert.NoError(t, err) {
		t.FailNow()
330
	}
V
Veniamin Albaev 已提交
331

332
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
V
Veniamin Albaev 已提交
333 334
	if !assert.NoError(t, err) {
		t.FailNow()
335
	}
V
Veniamin Albaev 已提交
336

337
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
V
Veniamin Albaev 已提交
338 339
	if !assert.NoError(t, err) {
		t.FailNow()
340
	}
V
Veniamin Albaev 已提交
341

342
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetBackground.xlsx")))
V
Veniamin Albaev 已提交
343 344 345
}

func TestSetSheetBackgroundErrors(t *testing.T) {
346
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
347 348
	if !assert.NoError(t, err) {
		t.FailNow()
349
	}
V
Veniamin Albaev 已提交
350

351
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "not_exists", "not_exists.png"))
V
Veniamin Albaev 已提交
352 353 354 355
	if assert.Error(t, err) {
		assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
	}

356
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
357
	assert.EqualError(t, err, "unsupported image extension")
358
}
xurime's avatar
xurime 已提交
359

360
func TestMergeCell(t *testing.T) {
361
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
362 363
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
364
	}
V
Veniamin Albaev 已提交
365

366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
	f.MergeCell("Sheet1", "D9", "D9")
	f.MergeCell("Sheet1", "D9", "E9")
	f.MergeCell("Sheet1", "H14", "G13")
	f.MergeCell("Sheet1", "C9", "D8")
	f.MergeCell("Sheet1", "F11", "G13")
	f.MergeCell("Sheet1", "H7", "B15")
	f.MergeCell("Sheet1", "D11", "F13")
	f.MergeCell("Sheet1", "G10", "K12")
	f.SetCellValue("Sheet1", "G11", "set value in merged cell")
	f.SetCellInt("Sheet1", "H11", 100)
	f.SetCellValue("Sheet1", "I11", float64(0.5))
	f.SetCellHyperLink("Sheet1", "J11", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
	f.SetCellFormula("Sheet1", "G12", "SUM(Sheet1!B19,Sheet1!C19)")
	f.GetCellValue("Sheet1", "H11")
	f.GetCellValue("Sheet2", "A6") // Merged cell ref is single coordinate.
	f.GetCellFormula("Sheet1", "G12")
V
Veniamin Albaev 已提交
382

383
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestMergeCell.xlsx")))
xurime's avatar
xurime 已提交
384
}
N
Nikolas Silva 已提交
385

386
func TestSetCellStyleAlignment(t *testing.T) {
387
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
388 389
	if !assert.NoError(t, err) {
		t.FailNow()
390
	}
V
Veniamin Albaev 已提交
391

392
	var style int
393
	style, err = f.NewStyle(`{"alignment":{"horizontal":"center","ident":1,"justify_last_line":true,"reading_order":0,"relative_indent":1,"shrink_to_fit":true,"text_rotation":45,"vertical":"top","wrap_text":true}}`)
V
Veniamin Albaev 已提交
394 395
	if !assert.NoError(t, err) {
		t.FailNow()
396
	}
V
Veniamin Albaev 已提交
397

398
	assert.NoError(t, f.SetCellStyle("Sheet1", "A22", "A22", style))
399

400
	// Test set cell style with given illegal rows number.
401 402
	assert.EqualError(t, f.SetCellStyle("Sheet1", "A", "A22", style), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
	assert.EqualError(t, f.SetCellStyle("Sheet1", "A22", "A", style), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
403

404
	// Test get cell style with given illegal rows number.
405
	index, err := f.GetCellStyle("Sheet1", "A")
406 407
	assert.Equal(t, 0, index)
	assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
V
Veniamin Albaev 已提交
408

409
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleAlignment.xlsx")))
410 411 412
}

func TestSetCellStyleBorder(t *testing.T) {
413
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
414 415
	if !assert.NoError(t, err) {
		t.FailNow()
416
	}
417

V
Veniamin Albaev 已提交
418
	var style int
419

420
	// Test set border on overlapping area with vertical variants shading styles gradient fill.
421
	style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":12},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":9},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
V
Veniamin Albaev 已提交
422 423
	if !assert.NoError(t, err) {
		t.FailNow()
424
	}
425
	assert.NoError(t, f.SetCellStyle("Sheet1", "J21", "L25", style))
426

427
	style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
V
Veniamin Albaev 已提交
428 429
	if !assert.NoError(t, err) {
		t.FailNow()
430
	}
431
	assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
432

433
	style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":4}}`)
V
Veniamin Albaev 已提交
434 435
	if !assert.NoError(t, err) {
		t.FailNow()
436
	}
437
	assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
438

439
	// Test set border and solid style pattern fill for a single cell.
440
	style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":8},{"type":"top","color":"00FF00","style":9},{"type":"bottom","color":"FFFF00","style":10},{"type":"right","color":"FF0000","style":11},{"type":"diagonalDown","color":"A020F0","style":12},{"type":"diagonalUp","color":"A020F0","style":13}],"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
V
Veniamin Albaev 已提交
441 442
	if !assert.NoError(t, err) {
		t.FailNow()
443
	}
444

445
	assert.NoError(t, f.SetCellStyle("Sheet1", "O22", "O22", style))
V
Veniamin Albaev 已提交
446

447
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleBorder.xlsx")))
V
Veniamin Albaev 已提交
448 449 450
}

func TestSetCellStyleBorderErrors(t *testing.T) {
451
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
452 453 454 455 456
	if !assert.NoError(t, err) {
		t.FailNow()
	}

	// Set border with invalid style parameter.
457
	_, err = f.NewStyle("")
V
Veniamin Albaev 已提交
458 459 460 461 462
	if !assert.EqualError(t, err, "unexpected end of JSON input") {
		t.FailNow()
	}

	// Set border with invalid style index number.
463
	_, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":-1},{"type":"top","color":"00FF00","style":14},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":9},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
V
Veniamin Albaev 已提交
464 465
	if !assert.NoError(t, err) {
		t.FailNow()
466 467 468
	}
}

469
func TestSetCellStyleNumberFormat(t *testing.T) {
470
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
471 472
	if !assert.NoError(t, err) {
		t.FailNow()
473
	}
V
Veniamin Albaev 已提交
474

xurime's avatar
xurime 已提交
475
	// Test only set fill and number format for a cell.
476 477 478 479 480 481 482 483 484
	col := []string{"L", "M", "N", "O", "P"}
	data := []int{0, 1, 2, 3, 4, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
	value := []string{"37947.7500001", "-37947.7500001", "0.007", "2.1", "String"}
	for i, v := range value {
		for k, d := range data {
			c := col[i] + strconv.Itoa(k+1)
			var val float64
			val, err = strconv.ParseFloat(v, 64)
			if err != nil {
485
				f.SetCellValue("Sheet2", c, v)
486
			} else {
487
				f.SetCellValue("Sheet2", c, val)
488
			}
489
			style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format": ` + strconv.Itoa(d) + `}`)
V
Veniamin Albaev 已提交
490 491
			if !assert.NoError(t, err) {
				t.FailNow()
492
			}
493 494
			assert.NoError(t, f.SetCellStyle("Sheet2", c, c, style))
			t.Log(f.GetCellValue("Sheet2", c))
495 496
		}
	}
497
	var style int
498
	style, err = f.NewStyle(`{"number_format":-1}`)
V
Veniamin Albaev 已提交
499 500
	if !assert.NoError(t, err) {
		t.FailNow()
501
	}
502
	assert.NoError(t, f.SetCellStyle("Sheet2", "L33", "L33", style))
V
Veniamin Albaev 已提交
503

504
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleNumberFormat.xlsx")))
505 506
}

507
func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
V
Veniamin Albaev 已提交
508
	t.Run("TestBook3", func(t *testing.T) {
509
		f, err := prepareTestBook3()
V
Veniamin Albaev 已提交
510 511 512
		if !assert.NoError(t, err) {
			t.FailNow()
		}
513

514 515
		f.SetCellValue("Sheet1", "A1", 56)
		f.SetCellValue("Sheet1", "A2", -32.3)
V
Veniamin Albaev 已提交
516
		var style int
517
		style, err = f.NewStyle(`{"number_format": 188, "decimal_places": -1}`)
V
Veniamin Albaev 已提交
518 519 520
		if !assert.NoError(t, err) {
			t.FailNow()
		}
521

522 523
		assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
		style, err = f.NewStyle(`{"number_format": 188, "decimal_places": 31, "negred": true}`)
V
Veniamin Albaev 已提交
524 525 526
		if !assert.NoError(t, err) {
			t.FailNow()
		}
527

528
		assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
529

530
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook3.xlsx")))
V
Veniamin Albaev 已提交
531
	})
532

V
Veniamin Albaev 已提交
533
	t.Run("TestBook4", func(t *testing.T) {
534
		f, err := prepareTestBook4()
V
Veniamin Albaev 已提交
535 536 537
		if !assert.NoError(t, err) {
			t.FailNow()
		}
538 539
		f.SetCellValue("Sheet1", "A1", 42920.5)
		f.SetCellValue("Sheet1", "A2", 42920.5)
V
Veniamin Albaev 已提交
540

541
		_, err = f.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`)
V
Veniamin Albaev 已提交
542 543 544 545
		if !assert.NoError(t, err) {
			t.FailNow()
		}

546
		style, err := f.NewStyle(`{"number_format": 27}`)
V
Veniamin Albaev 已提交
547 548 549 550
		if !assert.NoError(t, err) {
			t.FailNow()
		}

551 552
		assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
		style, err = f.NewStyle(`{"number_format": 31, "lang": "ko-kr"}`)
V
Veniamin Albaev 已提交
553 554 555 556
		if !assert.NoError(t, err) {
			t.FailNow()
		}

557
		assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
V
Veniamin Albaev 已提交
558

559
		style, err = f.NewStyle(`{"number_format": 71, "lang": "th-th"}`)
V
Veniamin Albaev 已提交
560 561 562
		if !assert.NoError(t, err) {
			t.FailNow()
		}
563
		assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
V
Veniamin Albaev 已提交
564

565
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook4.xlsx")))
V
Veniamin Albaev 已提交
566
	})
567 568
}

569
func TestSetCellStyleCustomNumberFormat(t *testing.T) {
570 571 572 573
	f := NewFile()
	f.SetCellValue("Sheet1", "A1", 42920.5)
	f.SetCellValue("Sheet1", "A2", 42920.5)
	style, err := f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
574 575 576
	if err != nil {
		t.Log(err)
	}
577 578
	assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
	style, err = f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
579 580 581
	if err != nil {
		t.Log(err)
	}
582
	assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
V
Veniamin Albaev 已提交
583

584
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCustomNumberFormat.xlsx")))
585 586
}

587
func TestSetCellStyleFill(t *testing.T) {
588
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
589 590
	if !assert.NoError(t, err) {
		t.FailNow()
591
	}
V
Veniamin Albaev 已提交
592

593
	var style int
594
	// Test set fill for cell with invalid parameter.
595
	style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":6}}`)
V
Veniamin Albaev 已提交
596 597
	if !assert.NoError(t, err) {
		t.FailNow()
598
	}
599
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
600

601
	style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF"],"shading":1}}`)
V
Veniamin Albaev 已提交
602 603
	if !assert.NoError(t, err) {
		t.FailNow()
604
	}
605
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
606

607
	style, err = f.NewStyle(`{"fill":{"type":"pattern","color":[],"pattern":1}}`)
V
Veniamin Albaev 已提交
608 609
	if !assert.NoError(t, err) {
		t.FailNow()
610
	}
611
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
xurime's avatar
xurime 已提交
612

613
	style, err = f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":19}}`)
V
Veniamin Albaev 已提交
614 615
	if !assert.NoError(t, err) {
		t.FailNow()
616
	}
617
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
618

619
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFill.xlsx")))
620 621 622
}

func TestSetCellStyleFont(t *testing.T) {
623
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
624 625
	if !assert.NoError(t, err) {
		t.FailNow()
626
	}
V
Veniamin Albaev 已提交
627

628
	var style int
629
	style, err = f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777","underline":"single"}}`)
V
Veniamin Albaev 已提交
630 631
	if !assert.NoError(t, err) {
		t.FailNow()
632
	}
V
Veniamin Albaev 已提交
633

634
	assert.NoError(t, f.SetCellStyle("Sheet2", "A1", "A1", style))
635

636
	style, err = f.NewStyle(`{"font":{"italic":true,"underline":"double"}}`)
V
Veniamin Albaev 已提交
637 638
	if !assert.NoError(t, err) {
		t.FailNow()
639
	}
V
Veniamin Albaev 已提交
640

641
	assert.NoError(t, f.SetCellStyle("Sheet2", "A2", "A2", style))
642

643
	style, err = f.NewStyle(`{"font":{"bold":true}}`)
V
Veniamin Albaev 已提交
644 645
	if !assert.NoError(t, err) {
		t.FailNow()
646
	}
V
Veniamin Albaev 已提交
647

648
	assert.NoError(t, f.SetCellStyle("Sheet2", "A3", "A3", style))
649

650
	style, err = f.NewStyle(`{"font":{"bold":true,"family":"","size":0,"color":"","underline":""}}`)
V
Veniamin Albaev 已提交
651 652
	if !assert.NoError(t, err) {
		t.FailNow()
653
	}
V
Veniamin Albaev 已提交
654

655
	assert.NoError(t, f.SetCellStyle("Sheet2", "A4", "A4", style))
656

657
	style, err = f.NewStyle(`{"font":{"color":"#777777"}}`)
V
Veniamin Albaev 已提交
658 659
	if !assert.NoError(t, err) {
		t.FailNow()
660
	}
V
Veniamin Albaev 已提交
661

662
	assert.NoError(t, f.SetCellStyle("Sheet2", "A5", "A5", style))
V
Veniamin Albaev 已提交
663

664
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFont.xlsx")))
665
}
666

667
func TestSetCellStyleProtection(t *testing.T) {
668
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
669 670
	if !assert.NoError(t, err) {
		t.FailNow()
671
	}
V
Veniamin Albaev 已提交
672

673
	var style int
674
	style, err = f.NewStyle(`{"protection":{"hidden":true, "locked":true}}`)
V
Veniamin Albaev 已提交
675 676
	if !assert.NoError(t, err) {
		t.FailNow()
677
	}
V
Veniamin Albaev 已提交
678

679 680
	assert.NoError(t, f.SetCellStyle("Sheet2", "A6", "A6", style))
	err = f.SaveAs(filepath.Join("test", "TestSetCellStyleProtection.xlsx"))
V
Veniamin Albaev 已提交
681 682
	if !assert.NoError(t, err) {
		t.FailNow()
683 684 685
	}
}

V
Veniamin Albaev 已提交
686 687
func TestSetDeleteSheet(t *testing.T) {
	t.Run("TestBook3", func(t *testing.T) {
688
		f, err := prepareTestBook3()
V
Veniamin Albaev 已提交
689 690 691 692
		if !assert.NoError(t, err) {
			t.FailNow()
		}

693 694
		f.DeleteSheet("XLSXSheet3")
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook3.xlsx")))
V
Veniamin Albaev 已提交
695 696 697
	})

	t.Run("TestBook4", func(t *testing.T) {
698
		f, err := prepareTestBook4()
V
Veniamin Albaev 已提交
699 700 701
		if !assert.NoError(t, err) {
			t.FailNow()
		}
702 703 704 705
		f.DeleteSheet("Sheet1")
		f.AddComment("Sheet1", "A1", "")
		f.AddComment("Sheet1", "A1", `{"author":"Excelize: ","text":"This is a comment."}`)
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook4.xlsx")))
V
Veniamin Albaev 已提交
706
	})
707
}
708

709
func TestSheetVisibility(t *testing.T) {
710
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
711 712
	if !assert.NoError(t, err) {
		t.FailNow()
713
	}
V
Veniamin Albaev 已提交
714

715 716 717 718
	f.SetSheetVisible("Sheet2", false)
	f.SetSheetVisible("Sheet1", false)
	f.SetSheetVisible("Sheet1", true)
	f.GetSheetVisible("Sheet1")
V
Veniamin Albaev 已提交
719

720
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSheetVisibility.xlsx")))
721 722
}

723
func TestCopySheet(t *testing.T) {
724
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
725 726
	if !assert.NoError(t, err) {
		t.FailNow()
727
	}
V
Veniamin Albaev 已提交
728

729
	idx := f.NewSheet("CopySheet")
730
	assert.NoError(t, f.CopySheet(1, idx))
V
Veniamin Albaev 已提交
731

732
	f.SetCellValue("CopySheet", "F1", "Hello")
733
	val, err := f.GetCellValue("Sheet1", "F1")
734 735
	assert.NoError(t, err)
	assert.NotEqual(t, "Hello", val)
V
Veniamin Albaev 已提交
736

737
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheet.xlsx")))
V
Veniamin Albaev 已提交
738 739 740
}

func TestCopySheetError(t *testing.T) {
741
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
742 743
	if !assert.NoError(t, err) {
		t.FailNow()
744
	}
V
Veniamin Albaev 已提交
745

746 747
	assert.EqualError(t, f.copySheet(0, -1), "sheet  is not exist")
	if !assert.EqualError(t, f.CopySheet(0, -1), "invalid worksheet index") {
V
Veniamin Albaev 已提交
748
		t.FailNow()
749
	}
V
Veniamin Albaev 已提交
750

751
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx")))
752
}
753

xurime's avatar
xurime 已提交
754
func TestAddTable(t *testing.T) {
755
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
756 757
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
758
	}
V
Veniamin Albaev 已提交
759

760
	err = f.AddTable("Sheet1", "B26", "A21", `{}`)
V
Veniamin Albaev 已提交
761 762
	if !assert.NoError(t, err) {
		t.FailNow()
763
	}
V
Veniamin Albaev 已提交
764

765
	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}`)
V
Veniamin Albaev 已提交
766 767
	if !assert.NoError(t, err) {
		t.FailNow()
768
	}
V
Veniamin Albaev 已提交
769

770
	err = f.AddTable("Sheet2", "F1", "F1", `{"table_style":"TableStyleMedium8"}`)
V
Veniamin Albaev 已提交
771 772
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
773
	}
V
Veniamin Albaev 已提交
774

775
	// Test add table with illegal formatset.
776
	assert.EqualError(t, f.AddTable("Sheet1", "B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
777
	// Test add table with illegal cell coordinates.
778 779
	assert.EqualError(t, f.AddTable("Sheet1", "A", "B1", `{}`), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
	assert.EqualError(t, f.AddTable("Sheet1", "A1", "B", `{}`), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
780

781
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddTable.xlsx")))
782 783

	// Test addTable with illegal cell coordinates.
784
	f = NewFile()
785 786
	assert.EqualError(t, f.addTable("sheet1", "", 0, 0, 0, 0, 0, nil), "invalid cell coordinates [0, 0]")
	assert.EqualError(t, f.addTable("sheet1", "", 1, 1, 0, 0, 0, nil), "invalid cell coordinates [0, 0]")
xurime's avatar
xurime 已提交
787 788
}

789
func TestAddShape(t *testing.T) {
790
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
791 792
	if !assert.NoError(t, err) {
		t.FailNow()
793
	}
V
Veniamin Albaev 已提交
794

795 796 797 798 799
	f.AddShape("Sheet1", "A30", `{"type":"rect","paragraph":[{"text":"Rectangle","font":{"color":"CD5C5C"}},{"text":"Shape","font":{"bold":true,"color":"2980B9"}}]}`)
	f.AddShape("Sheet1", "B30", `{"type":"rect","paragraph":[{"text":"Rectangle"},{}]}`)
	f.AddShape("Sheet1", "C30", `{"type":"rect","paragraph":[]}`)
	f.AddShape("Sheet3", "H1", `{"type":"ellipseRibbon", "color":{"line":"#4286f4","fill":"#8eb9ff"}, "paragraph":[{"font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777","underline":"single"}}], "height": 90}`)
	f.AddShape("Sheet3", "H1", "")
V
Veniamin Albaev 已提交
800

801
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape.xlsx")))
802 803
}

804
func TestAddComments(t *testing.T) {
805
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
806 807
	if !assert.NoError(t, err) {
		t.FailNow()
808
	}
V
Veniamin Albaev 已提交
809

xurime's avatar
xurime 已提交
810
	s := strings.Repeat("c", 32768)
811 812 813 814 815
	assert.NoError(t, f.AddComment("Sheet1", "A30", `{"author":"`+s+`","text":"`+s+`"}`))
	assert.NoError(t, f.AddComment("Sheet2", "B7", `{"author":"Excelize: ","text":"This is a comment."}`))

	// Test add comment on not exists worksheet.
	assert.EqualError(t, f.AddComment("SheetN", "B7", `{"author":"Excelize: ","text":"This is a comment."}`), "sheet SheetN is not exist")
R
Rad Cirskis 已提交
816

817 818
	if assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddComments.xlsx"))) {
		assert.Len(t, f.GetComments(), 2)
V
Veniamin Albaev 已提交
819
	}
820 821
}

822 823 824 825 826
func TestGetSheetComments(t *testing.T) {
	f := NewFile()
	assert.Equal(t, "", f.getSheetComments(0))
}

827
func TestAutoFilter(t *testing.T) {
828 829
	outFile := filepath.Join("test", "TestAutoFilter%d.xlsx")

830
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
831 832
	if !assert.NoError(t, err) {
		t.FailNow()
833
	}
V
Veniamin Albaev 已提交
834 835 836

	formats := []string{
		``,
837 838 839 840 841 842 843
		`{"column":"B","expression":"x != blanks"}`,
		`{"column":"B","expression":"x == blanks"}`,
		`{"column":"B","expression":"x != nonblanks"}`,
		`{"column":"B","expression":"x == nonblanks"}`,
		`{"column":"B","expression":"x <= 1 and x >= 2"}`,
		`{"column":"B","expression":"x == 1 or x == 2"}`,
		`{"column":"B","expression":"x == 1 or x == 2*"}`,
V
Veniamin Albaev 已提交
844 845 846 847
	}

	for i, format := range formats {
		t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
848
			err = f.AutoFilter("Sheet1", "D4", "B1", format)
xurime's avatar
xurime 已提交
849
			assert.NoError(t, err)
850
			assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
V
Veniamin Albaev 已提交
851 852 853
		})
	}

854
	// testing AutoFilter with illegal cell coordinates.
855 856
	assert.EqualError(t, f.AutoFilter("Sheet1", "A", "B1", ""), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
	assert.EqualError(t, f.AutoFilter("Sheet1", "A1", "B", ""), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
V
Veniamin Albaev 已提交
857 858 859
}

func TestAutoFilterError(t *testing.T) {
860 861
	outFile := filepath.Join("test", "TestAutoFilterError%d.xlsx")

862
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
863 864 865 866 867
	if !assert.NoError(t, err) {
		t.FailNow()
	}

	formats := []string{
868 869 870 871 872 873 874
		`{"column":"B","expression":"x <= 1 and x >= blanks"}`,
		`{"column":"B","expression":"x -- y or x == *2*"}`,
		`{"column":"B","expression":"x != y or x ? *2"}`,
		`{"column":"B","expression":"x -- y o r x == *2"}`,
		`{"column":"B","expression":"x -- y"}`,
		`{"column":"A","expression":"x -- y"}`,
	}
V
Veniamin Albaev 已提交
875 876
	for i, format := range formats {
		t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
877
			err = f.AutoFilter("Sheet3", "D4", "B1", format)
V
Veniamin Albaev 已提交
878
			if assert.Error(t, err) {
879
				assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
V
Veniamin Albaev 已提交
880 881
			}
		})
882 883 884
	}
}

xurime's avatar
xurime 已提交
885
func TestSetPane(t *testing.T) {
886 887 888 889 890 891 892 893 894 895 896
	f := NewFile()
	f.SetPanes("Sheet1", `{"freeze":false,"split":false}`)
	f.NewSheet("Panes 2")
	f.SetPanes("Panes 2", `{"freeze":true,"split":false,"x_split":1,"y_split":0,"top_left_cell":"B1","active_pane":"topRight","panes":[{"sqref":"K16","active_cell":"K16","pane":"topRight"}]}`)
	f.NewSheet("Panes 3")
	f.SetPanes("Panes 3", `{"freeze":false,"split":true,"x_split":3270,"y_split":1800,"top_left_cell":"N57","active_pane":"bottomLeft","panes":[{"sqref":"I36","active_cell":"I36"},{"sqref":"G33","active_cell":"G33","pane":"topRight"},{"sqref":"J60","active_cell":"J60","pane":"bottomLeft"},{"sqref":"O60","active_cell":"O60","pane":"bottomRight"}]}`)
	f.NewSheet("Panes 4")
	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"}]}`)
	f.SetPanes("Panes 4", "")

	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetPane.xlsx")))
xurime's avatar
xurime 已提交
897 898
}

899
func TestConditionalFormat(t *testing.T) {
900 901
	f := NewFile()
	sheet1 := f.GetSheetName(1)
902

903
	fillCells(f, sheet1, 10, 15)
904

905 906 907
	var format1, format2, format3 int
	var err error
	// Rose format for bad conditional.
908
	format1, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
909 910 911 912
	if !assert.NoError(t, err) {
		t.FailNow()
	}

913
	// Light yellow format for neutral conditional.
914
	format2, err = f.NewConditionalStyle(`{"fill":{"type":"pattern","color":["#FEEAA0"],"pattern":1}}`)
V
Veniamin Albaev 已提交
915 916 917 918
	if !assert.NoError(t, err) {
		t.FailNow()
	}

919
	// Light green format for good conditional.
920
	format3, err = f.NewConditionalStyle(`{"font":{"color":"#09600B"},"fill":{"type":"pattern","color":["#C7EECF"],"pattern":1}}`)
V
Veniamin Albaev 已提交
921 922 923 924
	if !assert.NoError(t, err) {
		t.FailNow()
	}

925
	// Color scales: 2 color.
926
	f.SetConditionalFormat(sheet1, "A1:A10", `[{"type":"2_color_scale","criteria":"=","min_type":"min","max_type":"max","min_color":"#F8696B","max_color":"#63BE7B"}]`)
927
	// Color scales: 3 color.
928
	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"}]`)
929
	// Hightlight cells rules: between...
930
	f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1))
931
	// Hightlight cells rules: Greater Than...
932
	f.SetConditionalFormat(sheet1, "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format3))
933
	// Hightlight cells rules: Equal To...
934
	f.SetConditionalFormat(sheet1, "E1:E10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d}]`, format3))
935
	// Hightlight cells rules: Not Equal To...
936
	f.SetConditionalFormat(sheet1, "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format2))
937
	// Hightlight cells rules: Duplicate Values...
938
	f.SetConditionalFormat(sheet1, "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format2))
939
	// Top/Bottom rules: Top 10%.
940
	f.SetConditionalFormat(sheet1, "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1))
941
	// Top/Bottom rules: Above Average...
942
	f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3))
943
	// Top/Bottom rules: Below Average...
944
	f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1))
945
	// Data Bars: Gradient Fill.
946
	f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)
947
	// Use a formula to determine which cells to format.
948
	f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1))
949
	// Test set invalid format set in conditional format
950
	f.SetConditionalFormat(sheet1, "L1:L10", "")
V
Veniamin Albaev 已提交
951

952
	err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx"))
V
Veniamin Albaev 已提交
953 954
	if !assert.NoError(t, err) {
		t.FailNow()
955 956 957
	}

	// Set conditional format with illegal valid type.
958
	f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)
959
	// Set conditional format with illegal criteria type.
960
	f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)
V
Veniamin Albaev 已提交
961 962

	// Set conditional format with file without dxfs element shold not return error.
963
	f, err = OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
964 965 966 967
	if !assert.NoError(t, err) {
		t.FailNow()
	}

968
	_, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
969 970 971
	if !assert.NoError(t, err) {
		t.FailNow()
	}
972
}
xurime's avatar
xurime 已提交
973

V
Veniamin Albaev 已提交
974
func TestConditionalFormatError(t *testing.T) {
975 976
	f := NewFile()
	sheet1 := f.GetSheetName(1)
977

978
	fillCells(f, sheet1, 10, 15)
V
Veniamin Albaev 已提交
979 980

	// Set conditional format with illegal JSON string should return error
981
	_, err := f.NewConditionalStyle("")
V
Veniamin Albaev 已提交
982 983
	if !assert.EqualError(t, err, "unexpected end of JSON input") {
		t.FailNow()
xurime's avatar
xurime 已提交
984 985
	}
}
986 987

func TestSharedStrings(t *testing.T) {
988
	f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
V
Veniamin Albaev 已提交
989 990
	if !assert.NoError(t, err) {
		t.FailNow()
991
	}
992
	f.GetRows("Sheet1")
993
}
994 995

func TestSetSheetRow(t *testing.T) {
996
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
997 998
	if !assert.NoError(t, err) {
		t.FailNow()
999
	}
V
Veniamin Albaev 已提交
1000

1001
	f.SetSheetRow("Sheet1", "B27", &[]interface{}{"cell", nil, int32(42), float64(42), time.Now().UTC()})
1002

1003
	assert.EqualError(t, f.SetSheetRow("Sheet1", "", &[]interface{}{"cell", nil, 2}),
1004
		`cannot convert cell "" to coordinates: invalid cell name ""`)
V
Veniamin Albaev 已提交
1005

1006 1007 1008
	assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", []interface{}{}), `pointer to slice expected`)
	assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", &f), `pointer to slice expected`)
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetRow.xlsx")))
1009
}
1010

xurime's avatar
xurime 已提交
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
func TestThemeColor(t *testing.T) {
	t.Log(ThemeColor("000000", -0.1))
	t.Log(ThemeColor("000000", 0))
	t.Log(ThemeColor("000000", 1))
}

func TestHSL(t *testing.T) {
	var hsl HSL
	t.Log(hsl.RGBA())
	t.Log(hslModel(hsl))
	t.Log(hslModel(color.Gray16{Y: uint16(1)}))
	t.Log(HSLToRGB(0, 1, 0.4))
	t.Log(HSLToRGB(0, 1, 0.6))
	t.Log(hueToRGB(0, 0, -1))
	t.Log(hueToRGB(0, 0, 2))
	t.Log(hueToRGB(0, 0, 1.0/7))
	t.Log(hueToRGB(0, 0, 0.4))
	t.Log(hueToRGB(0, 0, 2.0/4))
	t.Log(RGBToHSL(255, 255, 0))
	t.Log(RGBToHSL(0, 255, 255))
	t.Log(RGBToHSL(250, 100, 50))
	t.Log(RGBToHSL(50, 100, 250))
	t.Log(RGBToHSL(250, 50, 100))
}

1036
func TestSearchSheet(t *testing.T) {
1037
	f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
V
Veniamin Albaev 已提交
1038 1039
	if !assert.NoError(t, err) {
		t.FailNow()
1040
	}
V
Veniamin Albaev 已提交
1041

1042
	// Test search in a not exists worksheet.
1043
	t.Log(f.SearchSheet("Sheet4", ""))
1044
	// Test search a not exists value.
1045 1046
	t.Log(f.SearchSheet("Sheet1", "X"))
	t.Log(f.SearchSheet("Sheet1", "A"))
1047 1048
	// Test search the coordinates where the numerical value in the range of
	// "0-9" of Sheet1 is described by regular expression:
1049
	t.Log(f.SearchSheet("Sheet1", "[0-9]", true))
R
r-uchino 已提交
1050 1051
}

1052
func TestProtectSheet(t *testing.T) {
1053 1054 1055
	f := NewFile()
	f.ProtectSheet("Sheet1", nil)
	f.ProtectSheet("Sheet1", &FormatSheetProtection{
1056 1057 1058
		Password:      "password",
		EditScenarios: false,
	})
V
Veniamin Albaev 已提交
1059

1060
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx")))
xurime's avatar
xurime 已提交
1061
	// Test protect not exists worksheet.
1062
	assert.EqualError(t, f.ProtectSheet("SheetN", nil), "sheet SheetN is not exist")
1063 1064
}

1065
func TestUnprotectSheet(t *testing.T) {
1066
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1067 1068
	if !assert.NoError(t, err) {
		t.FailNow()
1069
	}
xurime's avatar
xurime 已提交
1070
	// Test unprotect not exists worksheet.
1071
	assert.EqualError(t, f.UnprotectSheet("SheetN"), "sheet SheetN is not exist")
V
Veniamin Albaev 已提交
1072

1073 1074
	f.UnprotectSheet("Sheet1")
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnprotectSheet.xlsx")))
1075
}
xurime's avatar
xurime 已提交
1076 1077 1078 1079 1080 1081

func TestSetDefaultTimeStyle(t *testing.T) {
	f := NewFile()
	// Test set default time style on not exists worksheet.
	assert.EqualError(t, f.setDefaultTimeStyle("SheetN", "", 0), "sheet SheetN is not exist")
}
1082

V
Veniamin Albaev 已提交
1083
func prepareTestBook1() (*File, error) {
1084
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1085 1086 1087 1088
	if err != nil {
		return nil, err
	}

1089
	err = f.AddPicture("Sheet2", "I9", filepath.Join("test", "images", "excel.jpg"),
V
Veniamin Albaev 已提交
1090 1091 1092 1093 1094 1095
		`{"x_offset": 140, "y_offset": 120, "hyperlink": "#Sheet2!D8", "hyperlink_type": "Location"}`)
	if err != nil {
		return nil, err
	}

	// Test add picture to worksheet with offset, external hyperlink and positioning.
1096
	err = f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.png"),
V
Veniamin Albaev 已提交
1097 1098 1099 1100 1101
		`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`)
	if err != nil {
		return nil, err
	}

1102
	file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.jpg"))
V
Veniamin Albaev 已提交
1103 1104 1105 1106
	if err != nil {
		return nil, err
	}

1107
	err = f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file)
V
Veniamin Albaev 已提交
1108 1109 1110 1111
	if err != nil {
		return nil, err
	}

1112
	return f, nil
V
Veniamin Albaev 已提交
1113 1114 1115
}

func prepareTestBook3() (*File, error) {
1116 1117 1118 1119 1120 1121 1122 1123 1124
	f := NewFile()
	f.NewSheet("Sheet1")
	f.NewSheet("XLSXSheet2")
	f.NewSheet("XLSXSheet3")
	f.SetCellInt("XLSXSheet2", "A23", 56)
	f.SetCellStr("Sheet1", "B20", "42")
	f.SetActiveSheet(0)

	err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
1125
		`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
V
Veniamin Albaev 已提交
1126 1127 1128 1129
	if err != nil {
		return nil, err
	}

1130
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
V
Veniamin Albaev 已提交
1131 1132 1133 1134
	if err != nil {
		return nil, err
	}

1135
	return f, nil
V
Veniamin Albaev 已提交
1136 1137 1138
}

func prepareTestBook4() (*File, error) {
1139 1140 1141 1142 1143
	f := NewFile()
	f.SetColWidth("Sheet1", "B", "A", 12)
	f.SetColWidth("Sheet1", "A", "B", 12)
	f.GetColWidth("Sheet1", "A")
	f.GetColWidth("Sheet1", "C")
V
Veniamin Albaev 已提交
1144

1145
	return f, nil
V
Veniamin Albaev 已提交
1146
}
1147

1148
func fillCells(f *File, sheet string, colCount, rowCount int) {
1149 1150
	for col := 1; col <= colCount; col++ {
		for row := 1; row <= rowCount; row++ {
1151
			cell, _ := CoordinatesToCellName(col, row)
1152
			f.SetCellStr(sheet, cell, cell)
1153 1154 1155
		}
	}
}