excelize_test.go 58.8 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", "TestBrokenFile.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
	}
}

885
func TestAddChart(t *testing.T) {
886
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
887 888
	if !assert.NoError(t, err) {
		t.FailNow()
889
	}
V
Veniamin Albaev 已提交
890

xurime's avatar
xurime 已提交
891 892 893
	categories := map[string]string{"A30": "Small", "A31": "Normal", "A32": "Large", "B29": "Apple", "C29": "Orange", "D29": "Pear"}
	values := map[string]int{"B30": 2, "C30": 3, "D30": 3, "B31": 5, "C31": 2, "D31": 4, "B32": 6, "C32": 7, "D32": 8}
	for k, v := range categories {
894
		assert.NoError(t, f.SetCellValue("Sheet1", k, v))
xurime's avatar
xurime 已提交
895 896
	}
	for k, v := range values {
897
		assert.NoError(t, f.SetCellValue("Sheet1", k, v))
xurime's avatar
xurime 已提交
898
	}
899
	assert.EqualError(t, f.AddChart("Sheet1", "P1", ""), "unexpected end of JSON input")
xurime's avatar
xurime 已提交
900 901

	// Test add chart on not exists worksheet.
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
	assert.EqualError(t, f.AddChart("SheetN", "P1", "{}"), "sheet SheetN is not exist")

	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"}],"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":"Fruit 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.AddChart("Sheet1", "X1", `{"type":"colStacked","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"}],"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":"Fruit 2D Stacked 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.AddChart("Sheet1", "P16", `{"type":"colPercentStacked","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"}],"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":"Fruit 100% Stacked 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.AddChart("Sheet1", "X16", `{"type":"col3DClustered","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"}],"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":"bottom","show_legend_key":false},"title":{"name":"Fruit 3D Clustered 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.AddChart("Sheet1", "P30", `{"type":"col3DStacked","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"}],"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":"Fruit 3D 100% Stacked Bar 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.AddChart("Sheet1", "X30", `{"type":"col3DPercentStacked","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"}],"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":"Fruit 3D 100% Stacked 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.AddChart("Sheet1", "P45", `{"type":"col3D","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"}],"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":"Fruit 3D 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.AddChart("Sheet2", "P1", `{"type":"radar","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"}],"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":"top_right","show_legend_key":false},"title":{"name":"Fruit Radar 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":"span"}`))
	assert.NoError(t, f.AddChart("Sheet2", "X1", `{"type":"scatter","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"}],"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":"bottom","show_legend_key":false},"title":{"name":"Fruit Scatter 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.AddChart("Sheet2", "P16", `{"type":"doughnut","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"}],"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":"right","show_legend_key":false},"title":{"name":"Fruit Doughnut Chart"},"plotarea":{"show_bubble_size":false,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":false,"show_val":false},"show_blanks_as":"zero"}`))
	assert.NoError(t, f.AddChart("Sheet2", "X16", `{"type":"line","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"}],"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":"top","show_legend_key":false},"title":{"name":"Fruit Line 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.AddChart("Sheet2", "P32", `{"type":"pie3D","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"}],"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":"bottom","show_legend_key":false},"title":{"name":"Fruit 3D Pie Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":false,"show_val":false},"show_blanks_as":"zero"}`))
	assert.NoError(t, f.AddChart("Sheet2", "X32", `{"type":"pie","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"}],"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":"bottom","show_legend_key":false},"title":{"name":"Fruit Pie Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":false,"show_val":false},"show_blanks_as":"gap"}`))
	assert.NoError(t, f.AddChart("Sheet2", "P48", `{"type":"bar","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"}],"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":"Fruit 2D Clustered Bar 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.AddChart("Sheet2", "X48", `{"type":"barStacked","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"}],"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":"Fruit 2D Stacked Bar 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.AddChart("Sheet2", "P64", `{"type":"barPercentStacked","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"}],"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":"Fruit 2D Stacked 100% Bar 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.AddChart("Sheet2", "X64", `{"type":"bar3DClustered","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"}],"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":"Fruit 3D Clustered Bar 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.AddChart("Sheet2", "P80", `{"type":"bar3DStacked","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"}],"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":"Fruit 3D Stacked Bar 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","y_axis":{"maximum":7.5,"minimum":0.5}}`))
	assert.NoError(t, f.AddChart("Sheet2", "X80", `{"type":"bar3DPercentStacked","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"}],"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":"Fruit 3D 100% Stacked Bar 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","x_axis":{"reverse_order":true,"maximum":0,"minimum":0},"y_axis":{"reverse_order":true,"maximum":0,"minimum":0}}`))
923
	// area series charts
924 925 926 927 928 929 930 931
	assert.NoError(t, f.AddChart("Sheet2", "AF1", `{"type":"area","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"}],"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":"Fruit 2D Area 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.AddChart("Sheet2", "AN1", `{"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"}],"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":"Fruit 2D Stacked Area 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.AddChart("Sheet2", "AF16", `{"type":"areaPercentStacked","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"}],"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":"Fruit 2D 100% Stacked Area 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.AddChart("Sheet2", "AN16", `{"type":"area3D","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"}],"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":"Fruit 3D Area 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.AddChart("Sheet2", "AF32", `{"type":"area3DStacked","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"}],"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":"Fruit 3D Stacked Area 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.AddChart("Sheet2", "AN32", `{"type":"area3DPercentStacked","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"}],"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":"Fruit 3D 100% Stacked Area 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.SaveAs(filepath.Join("test", "TestAddChart.xlsx")))
932 933
}

xurime's avatar
xurime 已提交
934
func TestSetPane(t *testing.T) {
935 936 937 938 939 940 941 942 943 944 945
	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 已提交
946 947
}

948
func TestConditionalFormat(t *testing.T) {
949 950
	f := NewFile()
	sheet1 := f.GetSheetName(1)
951

952
	fillCells(f, sheet1, 10, 15)
953

954 955 956
	var format1, format2, format3 int
	var err error
	// Rose format for bad conditional.
957
	format1, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
958 959 960 961
	if !assert.NoError(t, err) {
		t.FailNow()
	}

962
	// Light yellow format for neutral conditional.
963
	format2, err = f.NewConditionalStyle(`{"fill":{"type":"pattern","color":["#FEEAA0"],"pattern":1}}`)
V
Veniamin Albaev 已提交
964 965 966 967
	if !assert.NoError(t, err) {
		t.FailNow()
	}

968
	// Light green format for good conditional.
969
	format3, err = f.NewConditionalStyle(`{"font":{"color":"#09600B"},"fill":{"type":"pattern","color":["#C7EECF"],"pattern":1}}`)
V
Veniamin Albaev 已提交
970 971 972 973
	if !assert.NoError(t, err) {
		t.FailNow()
	}

974
	// Color scales: 2 color.
975
	f.SetConditionalFormat(sheet1, "A1:A10", `[{"type":"2_color_scale","criteria":"=","min_type":"min","max_type":"max","min_color":"#F8696B","max_color":"#63BE7B"}]`)
976
	// Color scales: 3 color.
977
	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"}]`)
978
	// Hightlight cells rules: between...
979
	f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1))
980
	// Hightlight cells rules: Greater Than...
981
	f.SetConditionalFormat(sheet1, "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format3))
982
	// Hightlight cells rules: Equal To...
983
	f.SetConditionalFormat(sheet1, "E1:E10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d}]`, format3))
984
	// Hightlight cells rules: Not Equal To...
985
	f.SetConditionalFormat(sheet1, "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format2))
986
	// Hightlight cells rules: Duplicate Values...
987
	f.SetConditionalFormat(sheet1, "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format2))
988
	// Top/Bottom rules: Top 10%.
989
	f.SetConditionalFormat(sheet1, "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1))
990
	// Top/Bottom rules: Above Average...
991
	f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3))
992
	// Top/Bottom rules: Below Average...
993
	f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1))
994
	// Data Bars: Gradient Fill.
995
	f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)
996
	// Use a formula to determine which cells to format.
997
	f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1))
998
	// Test set invalid format set in conditional format
999
	f.SetConditionalFormat(sheet1, "L1:L10", "")
V
Veniamin Albaev 已提交
1000

1001
	err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx"))
V
Veniamin Albaev 已提交
1002 1003
	if !assert.NoError(t, err) {
		t.FailNow()
1004 1005 1006
	}

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

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

1017
	_, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
1018 1019 1020
	if !assert.NoError(t, err) {
		t.FailNow()
	}
1021
}
xurime's avatar
xurime 已提交
1022

V
Veniamin Albaev 已提交
1023
func TestConditionalFormatError(t *testing.T) {
1024 1025
	f := NewFile()
	sheet1 := f.GetSheetName(1)
1026

1027
	fillCells(f, sheet1, 10, 15)
V
Veniamin Albaev 已提交
1028 1029

	// Set conditional format with illegal JSON string should return error
1030
	_, err := f.NewConditionalStyle("")
V
Veniamin Albaev 已提交
1031 1032
	if !assert.EqualError(t, err, "unexpected end of JSON input") {
		t.FailNow()
xurime's avatar
xurime 已提交
1033 1034
	}
}
1035 1036

func TestSharedStrings(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
	}
1041
	f.GetRows("Sheet1")
1042
}
1043 1044

func TestSetSheetRow(t *testing.T) {
1045
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1046 1047
	if !assert.NoError(t, err) {
		t.FailNow()
1048
	}
V
Veniamin Albaev 已提交
1049

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

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

1055 1056 1057
	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")))
1058
}
1059

xurime's avatar
xurime 已提交
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
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))
}

1085
func TestSearchSheet(t *testing.T) {
1086
	f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
V
Veniamin Albaev 已提交
1087 1088
	if !assert.NoError(t, err) {
		t.FailNow()
1089
	}
V
Veniamin Albaev 已提交
1090

1091
	// Test search in a not exists worksheet.
1092
	t.Log(f.SearchSheet("Sheet4", ""))
1093
	// Test search a not exists value.
1094 1095
	t.Log(f.SearchSheet("Sheet1", "X"))
	t.Log(f.SearchSheet("Sheet1", "A"))
1096 1097
	// Test search the coordinates where the numerical value in the range of
	// "0-9" of Sheet1 is described by regular expression:
1098
	t.Log(f.SearchSheet("Sheet1", "[0-9]", true))
R
r-uchino 已提交
1099 1100
}

1101
func TestProtectSheet(t *testing.T) {
1102 1103 1104
	f := NewFile()
	f.ProtectSheet("Sheet1", nil)
	f.ProtectSheet("Sheet1", &FormatSheetProtection{
1105 1106 1107
		Password:      "password",
		EditScenarios: false,
	})
V
Veniamin Albaev 已提交
1108

1109
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx")))
xurime's avatar
xurime 已提交
1110
	// Test protect not exists worksheet.
1111
	assert.EqualError(t, f.ProtectSheet("SheetN", nil), "sheet SheetN is not exist")
1112 1113
}

1114
func TestUnprotectSheet(t *testing.T) {
1115
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1116 1117
	if !assert.NoError(t, err) {
		t.FailNow()
1118
	}
xurime's avatar
xurime 已提交
1119
	// Test unprotect not exists worksheet.
1120
	assert.EqualError(t, f.UnprotectSheet("SheetN"), "sheet SheetN is not exist")
V
Veniamin Albaev 已提交
1121

1122 1123
	f.UnprotectSheet("Sheet1")
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnprotectSheet.xlsx")))
1124
}
xurime's avatar
xurime 已提交
1125 1126 1127 1128 1129 1130

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")
}
1131

V
Veniamin Albaev 已提交
1132
func prepareTestBook1() (*File, error) {
1133
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1134 1135 1136 1137
	if err != nil {
		return nil, err
	}

1138
	err = f.AddPicture("Sheet2", "I9", filepath.Join("test", "images", "excel.jpg"),
V
Veniamin Albaev 已提交
1139 1140 1141 1142 1143 1144
		`{"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.
1145
	err = f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.png"),
V
Veniamin Albaev 已提交
1146 1147 1148 1149 1150
		`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`)
	if err != nil {
		return nil, err
	}

1151
	file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.jpg"))
V
Veniamin Albaev 已提交
1152 1153 1154 1155
	if err != nil {
		return nil, err
	}

1156
	err = f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file)
V
Veniamin Albaev 已提交
1157 1158 1159 1160
	if err != nil {
		return nil, err
	}

1161
	return f, nil
V
Veniamin Albaev 已提交
1162 1163 1164
}

func prepareTestBook3() (*File, error) {
1165 1166 1167 1168 1169 1170 1171 1172 1173
	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"),
1174
		`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
V
Veniamin Albaev 已提交
1175 1176 1177 1178
	if err != nil {
		return nil, err
	}

1179
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
V
Veniamin Albaev 已提交
1180 1181 1182 1183
	if err != nil {
		return nil, err
	}

1184
	return f, nil
V
Veniamin Albaev 已提交
1185 1186 1187
}

func prepareTestBook4() (*File, error) {
1188 1189 1190 1191 1192
	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 已提交
1193

1194
	return f, nil
V
Veniamin Albaev 已提交
1195
}
1196

1197
func fillCells(f *File, sheet string, colCount, rowCount int) {
1198 1199
	for col := 1; col <= colCount; col++ {
		for row := 1; row <= rowCount; row++ {
1200
			cell, _ := CoordinatesToCellName(col, row)
1201
			f.SetCellStr(sheet, cell, cell)
1202 1203 1204
		}
	}
}