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

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

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

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

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

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

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

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

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

53
	f.SetCellStr("Sheet2", "C11", "Knowns")
54
	// Test max characters in a cell.
55 56
	f.SetCellStr("Sheet2", "D11", strings.Repeat("c", 32769))
	f.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.")
57
	// Test set worksheet name with illegal name.
58 59 60 61
	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")
62

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

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

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

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

xurime's avatar
xurime 已提交
90
	// Test read cell value with given lowercase column number.
91 92 93 94
	f.GetCellValue("Sheet2", "a5")
	f.GetCellValue("Sheet2", "C11")
	f.GetCellValue("Sheet2", "D11")
	f.GetCellValue("Sheet2", "D12")
xurime's avatar
xurime 已提交
95
	// Test SetCellValue function.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
	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 已提交
114 115

	// Test on not exists worksheet.
116 117 118 119 120
	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")
121

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

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

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

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

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

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

186 187 188
func TestOpenReader(t *testing.T) {
	_, err := OpenReader(strings.NewReader(""))
	assert.EqualError(t, err, "zip: not a valid zip file")
189 190 191 192 193 194 195 196
	_, err = OpenReader(bytes.NewReader([]byte{
		0x3c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00,
		0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00,
		0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x44, 0x00, 0x61, 0x00,
		0x74, 0x00, 0x61, 0x00, 0x53, 0x00, 0x70, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00,
		0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
	}))
	assert.EqualError(t, err, "not support encrypted file currently")
197 198
}

199
func TestBrokenFile(t *testing.T) {
xurime's avatar
xurime 已提交
200
	// Test write file with broken file struct.
201
	f := File{}
xurime's avatar
xurime 已提交
202

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

V
Veniamin Albaev 已提交
207 208
	t.Run("SaveAsEmptyStruct", func(t *testing.T) {
		// Test write file with broken file struct with given path.
209
		assert.NoError(t, f.SaveAs(filepath.Join("test", "BrokenFile.SaveAsEmptyStruct.xlsx")))
V
Veniamin Albaev 已提交
210 211 212 213
	})

	t.Run("OpenBadWorkbook", func(t *testing.T) {
		// Test set active sheet without BookViews and Sheets maps in xl/workbook.xml.
214
		f3, err := OpenFile(filepath.Join("test", "BadWorkbook.xlsx"))
V
Veniamin Albaev 已提交
215 216 217 218 219 220 221
		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.
222
		_, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
V
Veniamin Albaev 已提交
223 224 225 226
		if assert.Error(t, err) {
			assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
		}
	})
227 228
}

229
func TestNewFile(t *testing.T) {
230
	// Test create a XLSX file.
231 232 233 234 235 236 237
	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 已提交
238

239
	// Test add picture to sheet with scaling and positioning.
240
	err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
241
		`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
V
Veniamin Albaev 已提交
242 243
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
244
	}
V
Veniamin Albaev 已提交
245

246
	// Test add picture to worksheet without formatset.
247
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
V
Veniamin Albaev 已提交
248 249
	if !assert.NoError(t, err) {
		t.FailNow()
250
	}
V
Veniamin Albaev 已提交
251

252
	// Test add picture to worksheet with invalid formatset.
253
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), `{`)
V
Veniamin Albaev 已提交
254 255
	if !assert.Error(t, err) {
		t.FailNow()
256
	}
V
Veniamin Albaev 已提交
257

258
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewFile.xlsx")))
xurime's avatar
xurime 已提交
259
}
260

261 262 263 264 265 266
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 "*"`)
}

267
func TestSetCellHyperLink(t *testing.T) {
268
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
269 270 271 272
	if err != nil {
		t.Log(err)
	}
	// Test set cell hyperlink in a work sheet already have hyperlinks.
273
	assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
274
	// Test add first hyperlink in a work sheet.
275
	assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
276
	// Test add Location hyperlink in a work sheet.
277
	assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
278

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

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

283 284 285 286 287 288 289 290 291
	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")
292 293
}

294
func TestGetCellHyperLink(t *testing.T) {
295
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
296 297
	if !assert.NoError(t, err) {
		t.FailNow()
298
	}
V
Veniamin Albaev 已提交
299

300
	_, _, err = f.GetCellHyperLink("Sheet1", "")
301
	assert.EqualError(t, err, `invalid cell name ""`)
302

303
	link, target, err := f.GetCellHyperLink("Sheet1", "A22")
304
	assert.NoError(t, err)
305
	t.Log(link, target)
306
	link, target, err = f.GetCellHyperLink("Sheet2", "D6")
307
	assert.NoError(t, err)
308
	t.Log(link, target)
309
	link, target, err = f.GetCellHyperLink("Sheet3", "H3")
xurime's avatar
xurime 已提交
310
	assert.EqualError(t, err, "sheet Sheet3 is not exist")
311 312 313
	t.Log(link, target)
}

314
func TestSetCellFormula(t *testing.T) {
315
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
316 317
	if !assert.NoError(t, err) {
		t.FailNow()
318
	}
V
Veniamin Albaev 已提交
319

320 321
	f.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)")
	f.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
322

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

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

328
	f, err = OpenFile(filepath.Join("test", "CalcChain.xlsx"))
329 330 331 332
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	// Test remove cell formula.
333 334
	f.SetCellFormula("Sheet1", "A1", "")
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula2.xlsx")))
335
	// Test remove all cell formula.
336 337
	f.SetCellFormula("Sheet1", "B1", "")
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula3.xlsx")))
338
}
339 340

func TestSetSheetBackground(t *testing.T) {
341
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
342 343
	if !assert.NoError(t, err) {
		t.FailNow()
344
	}
V
Veniamin Albaev 已提交
345

346
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
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", "images", "background.jpg"))
V
Veniamin Albaev 已提交
352 353
	if !assert.NoError(t, err) {
		t.FailNow()
354
	}
V
Veniamin Albaev 已提交
355

356
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetBackground.xlsx")))
V
Veniamin Albaev 已提交
357 358 359
}

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

365
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "not_exists", "not_exists.png"))
V
Veniamin Albaev 已提交
366 367 368 369
	if assert.Error(t, err) {
		assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
	}

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

374
func TestMergeCell(t *testing.T) {
375
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
376 377
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
378
	}
V
Veniamin Albaev 已提交
379

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
	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 已提交
396

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

400
func TestSetCellStyleAlignment(t *testing.T) {
401
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
402 403
	if !assert.NoError(t, err) {
		t.FailNow()
404
	}
V
Veniamin Albaev 已提交
405

406
	var style int
407
	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 已提交
408 409
	if !assert.NoError(t, err) {
		t.FailNow()
410
	}
V
Veniamin Albaev 已提交
411

412
	assert.NoError(t, f.SetCellStyle("Sheet1", "A22", "A22", style))
413

414
	// Test set cell style with given illegal rows number.
415 416
	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"`)
417

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

423
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleAlignment.xlsx")))
424 425 426
}

func TestSetCellStyleBorder(t *testing.T) {
427
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
428 429
	if !assert.NoError(t, err) {
		t.FailNow()
430
	}
431

V
Veniamin Albaev 已提交
432
	var style int
433

434
	// Test set border on overlapping area with vertical variants shading styles gradient fill.
435
	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 已提交
436 437
	if !assert.NoError(t, err) {
		t.FailNow()
438
	}
439
	assert.NoError(t, f.SetCellStyle("Sheet1", "J21", "L25", style))
440

441
	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 已提交
442 443
	if !assert.NoError(t, err) {
		t.FailNow()
444
	}
445
	assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
446

447
	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 已提交
448 449
	if !assert.NoError(t, err) {
		t.FailNow()
450
	}
451
	assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
452

453
	// Test set border and solid style pattern fill for a single cell.
454
	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 已提交
455 456
	if !assert.NoError(t, err) {
		t.FailNow()
457
	}
458

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

461
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleBorder.xlsx")))
V
Veniamin Albaev 已提交
462 463 464
}

func TestSetCellStyleBorderErrors(t *testing.T) {
465
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
466 467 468 469 470
	if !assert.NoError(t, err) {
		t.FailNow()
	}

	// Set border with invalid style parameter.
471
	_, err = f.NewStyle("")
V
Veniamin Albaev 已提交
472 473 474 475 476
	if !assert.EqualError(t, err, "unexpected end of JSON input") {
		t.FailNow()
	}

	// Set border with invalid style index number.
477
	_, 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 已提交
478 479
	if !assert.NoError(t, err) {
		t.FailNow()
480 481 482
	}
}

483
func TestSetCellStyleNumberFormat(t *testing.T) {
484
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
485 486
	if !assert.NoError(t, err) {
		t.FailNow()
487
	}
V
Veniamin Albaev 已提交
488

xurime's avatar
xurime 已提交
489
	// Test only set fill and number format for a cell.
490 491 492 493 494 495 496 497 498
	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 {
499
				f.SetCellValue("Sheet2", c, v)
500
			} else {
501
				f.SetCellValue("Sheet2", c, val)
502
			}
503
			style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format": ` + strconv.Itoa(d) + `}`)
V
Veniamin Albaev 已提交
504 505
			if !assert.NoError(t, err) {
				t.FailNow()
506
			}
507 508
			assert.NoError(t, f.SetCellStyle("Sheet2", c, c, style))
			t.Log(f.GetCellValue("Sheet2", c))
509 510
		}
	}
511
	var style int
512
	style, err = f.NewStyle(`{"number_format":-1}`)
V
Veniamin Albaev 已提交
513 514
	if !assert.NoError(t, err) {
		t.FailNow()
515
	}
516
	assert.NoError(t, f.SetCellStyle("Sheet2", "L33", "L33", style))
V
Veniamin Albaev 已提交
517

518
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleNumberFormat.xlsx")))
519 520
}

521
func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
V
Veniamin Albaev 已提交
522
	t.Run("TestBook3", func(t *testing.T) {
523
		f, err := prepareTestBook3()
V
Veniamin Albaev 已提交
524 525 526
		if !assert.NoError(t, err) {
			t.FailNow()
		}
527

528 529
		f.SetCellValue("Sheet1", "A1", 56)
		f.SetCellValue("Sheet1", "A2", -32.3)
V
Veniamin Albaev 已提交
530
		var style int
531
		style, err = f.NewStyle(`{"number_format": 188, "decimal_places": -1}`)
V
Veniamin Albaev 已提交
532 533 534
		if !assert.NoError(t, err) {
			t.FailNow()
		}
535

536 537
		assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
		style, err = f.NewStyle(`{"number_format": 188, "decimal_places": 31, "negred": true}`)
V
Veniamin Albaev 已提交
538 539 540
		if !assert.NoError(t, err) {
			t.FailNow()
		}
541

542
		assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
543

544
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook3.xlsx")))
V
Veniamin Albaev 已提交
545
	})
546

V
Veniamin Albaev 已提交
547
	t.Run("TestBook4", func(t *testing.T) {
548
		f, err := prepareTestBook4()
V
Veniamin Albaev 已提交
549 550 551
		if !assert.NoError(t, err) {
			t.FailNow()
		}
552 553
		f.SetCellValue("Sheet1", "A1", 42920.5)
		f.SetCellValue("Sheet1", "A2", 42920.5)
V
Veniamin Albaev 已提交
554

555
		_, err = f.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`)
V
Veniamin Albaev 已提交
556 557 558 559
		if !assert.NoError(t, err) {
			t.FailNow()
		}

560
		style, err := f.NewStyle(`{"number_format": 27}`)
V
Veniamin Albaev 已提交
561 562 563 564
		if !assert.NoError(t, err) {
			t.FailNow()
		}

565 566
		assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
		style, err = f.NewStyle(`{"number_format": 31, "lang": "ko-kr"}`)
V
Veniamin Albaev 已提交
567 568 569 570
		if !assert.NoError(t, err) {
			t.FailNow()
		}

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

573
		style, err = f.NewStyle(`{"number_format": 71, "lang": "th-th"}`)
V
Veniamin Albaev 已提交
574 575 576
		if !assert.NoError(t, err) {
			t.FailNow()
		}
577
		assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
V
Veniamin Albaev 已提交
578

579
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook4.xlsx")))
V
Veniamin Albaev 已提交
580
	})
581 582
}

583
func TestSetCellStyleCustomNumberFormat(t *testing.T) {
584 585 586 587
	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;@"}`)
588 589 590
	if err != nil {
		t.Log(err)
	}
591 592
	assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
	style, err = f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
593 594 595
	if err != nil {
		t.Log(err)
	}
596
	assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
V
Veniamin Albaev 已提交
597

598
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCustomNumberFormat.xlsx")))
599 600
}

601
func TestSetCellStyleFill(t *testing.T) {
602
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
603 604
	if !assert.NoError(t, err) {
		t.FailNow()
605
	}
V
Veniamin Albaev 已提交
606

607
	var style int
608
	// Test set fill for cell with invalid parameter.
609
	style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":6}}`)
V
Veniamin Albaev 已提交
610 611
	if !assert.NoError(t, err) {
		t.FailNow()
612
	}
613
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
614

615
	style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF"],"shading":1}}`)
V
Veniamin Albaev 已提交
616 617
	if !assert.NoError(t, err) {
		t.FailNow()
618
	}
619
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
620

621
	style, err = f.NewStyle(`{"fill":{"type":"pattern","color":[],"pattern":1}}`)
V
Veniamin Albaev 已提交
622 623
	if !assert.NoError(t, err) {
		t.FailNow()
624
	}
625
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
xurime's avatar
xurime 已提交
626

627
	style, err = f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":19}}`)
V
Veniamin Albaev 已提交
628 629
	if !assert.NoError(t, err) {
		t.FailNow()
630
	}
631
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
632

633
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFill.xlsx")))
634 635 636
}

func TestSetCellStyleFont(t *testing.T) {
637
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
638 639
	if !assert.NoError(t, err) {
		t.FailNow()
640
	}
V
Veniamin Albaev 已提交
641

642
	var style int
643
	style, err = f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777","underline":"single"}}`)
V
Veniamin Albaev 已提交
644 645
	if !assert.NoError(t, err) {
		t.FailNow()
646
	}
V
Veniamin Albaev 已提交
647

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

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

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

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

662
	assert.NoError(t, f.SetCellStyle("Sheet2", "A3", "A3", style))
663

664
	style, err = f.NewStyle(`{"font":{"bold":true,"family":"","size":0,"color":"","underline":""}}`)
V
Veniamin Albaev 已提交
665 666
	if !assert.NoError(t, err) {
		t.FailNow()
667
	}
V
Veniamin Albaev 已提交
668

669
	assert.NoError(t, f.SetCellStyle("Sheet2", "A4", "A4", style))
670

671
	style, err = f.NewStyle(`{"font":{"color":"#777777"}}`)
V
Veniamin Albaev 已提交
672 673
	if !assert.NoError(t, err) {
		t.FailNow()
674
	}
V
Veniamin Albaev 已提交
675

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

678
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFont.xlsx")))
679
}
680

681
func TestSetCellStyleProtection(t *testing.T) {
682
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
683 684
	if !assert.NoError(t, err) {
		t.FailNow()
685
	}
V
Veniamin Albaev 已提交
686

687
	var style int
688
	style, err = f.NewStyle(`{"protection":{"hidden":true, "locked":true}}`)
V
Veniamin Albaev 已提交
689 690
	if !assert.NoError(t, err) {
		t.FailNow()
691
	}
V
Veniamin Albaev 已提交
692

693 694
	assert.NoError(t, f.SetCellStyle("Sheet2", "A6", "A6", style))
	err = f.SaveAs(filepath.Join("test", "TestSetCellStyleProtection.xlsx"))
V
Veniamin Albaev 已提交
695 696
	if !assert.NoError(t, err) {
		t.FailNow()
697 698 699
	}
}

V
Veniamin Albaev 已提交
700 701
func TestSetDeleteSheet(t *testing.T) {
	t.Run("TestBook3", func(t *testing.T) {
702
		f, err := prepareTestBook3()
V
Veniamin Albaev 已提交
703 704 705 706
		if !assert.NoError(t, err) {
			t.FailNow()
		}

707 708
		f.DeleteSheet("XLSXSheet3")
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook3.xlsx")))
V
Veniamin Albaev 已提交
709 710 711
	})

	t.Run("TestBook4", func(t *testing.T) {
712
		f, err := prepareTestBook4()
V
Veniamin Albaev 已提交
713 714 715
		if !assert.NoError(t, err) {
			t.FailNow()
		}
716 717 718 719
		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 已提交
720
	})
721
}
722

723
func TestSheetVisibility(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 730 731 732
	f.SetSheetVisible("Sheet2", false)
	f.SetSheetVisible("Sheet1", false)
	f.SetSheetVisible("Sheet1", true)
	f.GetSheetVisible("Sheet1")
V
Veniamin Albaev 已提交
733

734
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSheetVisibility.xlsx")))
735 736
}

737
func TestCopySheet(t *testing.T) {
738
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
739 740
	if !assert.NoError(t, err) {
		t.FailNow()
741
	}
V
Veniamin Albaev 已提交
742

743
	idx := f.NewSheet("CopySheet")
744
	assert.NoError(t, f.CopySheet(1, idx))
V
Veniamin Albaev 已提交
745

746
	f.SetCellValue("CopySheet", "F1", "Hello")
747
	val, err := f.GetCellValue("Sheet1", "F1")
748 749
	assert.NoError(t, err)
	assert.NotEqual(t, "Hello", val)
V
Veniamin Albaev 已提交
750

751
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheet.xlsx")))
V
Veniamin Albaev 已提交
752 753 754
}

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

760 761
	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 已提交
762
		t.FailNow()
763
	}
V
Veniamin Albaev 已提交
764

765
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx")))
766
}
767

xurime's avatar
xurime 已提交
768
func TestAddTable(t *testing.T) {
769
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
770 771
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
772
	}
V
Veniamin Albaev 已提交
773

774
	err = f.AddTable("Sheet1", "B26", "A21", `{}`)
V
Veniamin Albaev 已提交
775 776
	if !assert.NoError(t, err) {
		t.FailNow()
777
	}
V
Veniamin Albaev 已提交
778

779
	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 已提交
780 781
	if !assert.NoError(t, err) {
		t.FailNow()
782
	}
V
Veniamin Albaev 已提交
783

784
	err = f.AddTable("Sheet2", "F1", "F1", `{"table_style":"TableStyleMedium8"}`)
V
Veniamin Albaev 已提交
785 786
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
787
	}
V
Veniamin Albaev 已提交
788

789
	// Test add table with illegal formatset.
790
	assert.EqualError(t, f.AddTable("Sheet1", "B26", "A21", `{x}`), "invalid character 'x' looking for beginning of object key string")
791
	// Test add table with illegal cell coordinates.
792 793
	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"`)
794

795
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddTable.xlsx")))
796 797

	// Test addTable with illegal cell coordinates.
798
	f = NewFile()
799 800
	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 已提交
801 802
}

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

809 810 811 812 813
	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 已提交
814

815
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape.xlsx")))
816 817
}

818
func TestAddComments(t *testing.T) {
819
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
820 821
	if !assert.NoError(t, err) {
		t.FailNow()
822
	}
V
Veniamin Albaev 已提交
823

xurime's avatar
xurime 已提交
824
	s := strings.Repeat("c", 32768)
825 826 827 828 829
	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 已提交
830

831 832
	if assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddComments.xlsx"))) {
		assert.Len(t, f.GetComments(), 2)
V
Veniamin Albaev 已提交
833
	}
834 835
}

836 837 838 839 840
func TestGetSheetComments(t *testing.T) {
	f := NewFile()
	assert.Equal(t, "", f.getSheetComments(0))
}

841
func TestAutoFilter(t *testing.T) {
842 843
	outFile := filepath.Join("test", "TestAutoFilter%d.xlsx")

844
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
845 846
	if !assert.NoError(t, err) {
		t.FailNow()
847
	}
V
Veniamin Albaev 已提交
848 849 850

	formats := []string{
		``,
851 852 853 854 855 856 857
		`{"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 已提交
858 859 860 861
	}

	for i, format := range formats {
		t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
862
			err = f.AutoFilter("Sheet1", "D4", "B1", format)
xurime's avatar
xurime 已提交
863
			assert.NoError(t, err)
864
			assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
V
Veniamin Albaev 已提交
865 866 867
		})
	}

868
	// testing AutoFilter with illegal cell coordinates.
869 870
	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 已提交
871 872 873
}

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

876
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
877 878 879 880 881
	if !assert.NoError(t, err) {
		t.FailNow()
	}

	formats := []string{
882 883 884 885 886 887 888
		`{"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 已提交
889 890
	for i, format := range formats {
		t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
891
			err = f.AutoFilter("Sheet3", "D4", "B1", format)
V
Veniamin Albaev 已提交
892
			if assert.Error(t, err) {
893
				assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, i+1)))
V
Veniamin Albaev 已提交
894 895
			}
		})
896 897 898
	}
}

xurime's avatar
xurime 已提交
899
func TestSetPane(t *testing.T) {
900 901 902 903 904 905 906 907 908 909 910
	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 已提交
911 912
}

913
func TestConditionalFormat(t *testing.T) {
914 915
	f := NewFile()
	sheet1 := f.GetSheetName(1)
916

917
	fillCells(f, sheet1, 10, 15)
918

919 920 921
	var format1, format2, format3 int
	var err error
	// Rose format for bad conditional.
922
	format1, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
923 924 925 926
	if !assert.NoError(t, err) {
		t.FailNow()
	}

927
	// Light yellow format for neutral conditional.
928
	format2, err = f.NewConditionalStyle(`{"fill":{"type":"pattern","color":["#FEEAA0"],"pattern":1}}`)
V
Veniamin Albaev 已提交
929 930 931 932
	if !assert.NoError(t, err) {
		t.FailNow()
	}

933
	// Light green format for good conditional.
934
	format3, err = f.NewConditionalStyle(`{"font":{"color":"#09600B"},"fill":{"type":"pattern","color":["#C7EECF"],"pattern":1}}`)
V
Veniamin Albaev 已提交
935 936 937 938
	if !assert.NoError(t, err) {
		t.FailNow()
	}

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

966
	err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx"))
V
Veniamin Albaev 已提交
967 968
	if !assert.NoError(t, err) {
		t.FailNow()
969 970 971
	}

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

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

982
	_, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
983 984 985
	if !assert.NoError(t, err) {
		t.FailNow()
	}
986
}
xurime's avatar
xurime 已提交
987

V
Veniamin Albaev 已提交
988
func TestConditionalFormatError(t *testing.T) {
989 990
	f := NewFile()
	sheet1 := f.GetSheetName(1)
991

992
	fillCells(f, sheet1, 10, 15)
V
Veniamin Albaev 已提交
993 994

	// Set conditional format with illegal JSON string should return error
995
	_, err := f.NewConditionalStyle("")
V
Veniamin Albaev 已提交
996 997
	if !assert.EqualError(t, err, "unexpected end of JSON input") {
		t.FailNow()
xurime's avatar
xurime 已提交
998 999
	}
}
1000 1001

func TestSharedStrings(t *testing.T) {
1002
	f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
V
Veniamin Albaev 已提交
1003 1004
	if !assert.NoError(t, err) {
		t.FailNow()
1005
	}
H
Harris 已提交
1006 1007 1008 1009 1010
	rows, err := f.GetRows("Sheet1")
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	assert.Equal(t, "A", rows[0][0])
1011
}
1012 1013

func TestSetSheetRow(t *testing.T) {
1014
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1015 1016
	if !assert.NoError(t, err) {
		t.FailNow()
1017
	}
V
Veniamin Albaev 已提交
1018

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

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

1024 1025 1026
	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")))
1027
}
1028

xurime's avatar
xurime 已提交
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
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))
}

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

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

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

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

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

1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
func TestAddVBAProject(t *testing.T) {
	f := NewFile()
	assert.NoError(t, f.SetSheetPrOptions("Sheet1", CodeName("Sheet1")))
	assert.EqualError(t, f.AddVBAProject("macros.bin"), "stat macros.bin: no such file or directory")
	assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "Book1.xlsx")), "unsupported VBA project extension")
	assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
	// Test add VBA project twice.
	assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddVBAProject.xlsm")))
}

V
Veniamin Albaev 已提交
1096
func prepareTestBook1() (*File, error) {
1097
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1098 1099 1100 1101
	if err != nil {
		return nil, err
	}

1102
	err = f.AddPicture("Sheet2", "I9", filepath.Join("test", "images", "excel.jpg"),
V
Veniamin Albaev 已提交
1103 1104 1105 1106 1107 1108
		`{"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.
1109
	err = f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.png"),
V
Veniamin Albaev 已提交
1110 1111 1112 1113 1114
		`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`)
	if err != nil {
		return nil, err
	}

1115
	file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.jpg"))
V
Veniamin Albaev 已提交
1116 1117 1118 1119
	if err != nil {
		return nil, err
	}

1120
	err = f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file)
V
Veniamin Albaev 已提交
1121 1122 1123 1124
	if err != nil {
		return nil, err
	}

1125
	return f, nil
V
Veniamin Albaev 已提交
1126 1127 1128
}

func prepareTestBook3() (*File, error) {
1129 1130 1131 1132 1133 1134 1135 1136 1137
	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"),
1138
		`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
V
Veniamin Albaev 已提交
1139 1140 1141 1142
	if err != nil {
		return nil, err
	}

1143
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
V
Veniamin Albaev 已提交
1144 1145 1146 1147
	if err != nil {
		return nil, err
	}

1148
	return f, nil
V
Veniamin Albaev 已提交
1149 1150 1151
}

func prepareTestBook4() (*File, error) {
1152 1153 1154 1155 1156
	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 已提交
1157

1158
	return f, nil
V
Veniamin Albaev 已提交
1159
}
1160

1161
func fillCells(f *File, sheet string, colCount, rowCount int) {
1162 1163
	for col := 1; col <= colCount; col++ {
		for row := 1; row <= rowCount; row++ {
1164
			cell, _ := CoordinatesToCellName(col, row)
1165
			f.SetCellStr(sheet, cell, cell)
1166 1167 1168
		}
	}
}