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

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

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

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

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

43 44
	assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32)))
	assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)))
45

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

50
	assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100))
51

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

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

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

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

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

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

xurime's avatar
xurime 已提交
94
	// Test read cell value with given lowercase column number.
95 96 97 98 99 100 101 102
	_, err = f.GetCellValue("Sheet2", "a5")
	assert.NoError(t, err)
	_, err = f.GetCellValue("Sheet2", "C11")
	assert.NoError(t, err)
	_, err = f.GetCellValue("Sheet2", "D11")
	assert.NoError(t, err)
	_, err = f.GetCellValue("Sheet2", "D12")
	assert.NoError(t, err)
xurime's avatar
xurime 已提交
103
	// Test SetCellValue function.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
	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 已提交
122 123

	// Test on not exists worksheet.
124 125 126 127 128
	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")
129

130 131 132 133 134 135 136 137 138
	// Test boolean write
	booltest := []struct {
		value    bool
		expected string
	}{
		{false, "0"},
		{true, "1"},
	}
	for _, test := range booltest {
139
		assert.NoError(t, f.SetCellValue("Sheet2", "F16", test.value))
140
		val, err := f.GetCellValue("Sheet2", "F16")
141 142
		assert.NoError(t, err)
		assert.Equal(t, test.expected, val)
143
	}
144

145
	assert.NoError(t, f.SetCellValue("Sheet2", "G2", nil))
146

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

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

xurime's avatar
xurime 已提交
171
func TestSaveFile(t *testing.T) {
172
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
xurime's avatar
xurime 已提交
173 174 175
	if !assert.NoError(t, err) {
		t.FailNow()
	}
176 177
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSaveFile.xlsx")))
	f, err = OpenFile(filepath.Join("test", "TestSaveFile.xlsx"))
xurime's avatar
xurime 已提交
178 179 180
	if !assert.NoError(t, err) {
		t.FailNow()
	}
181
	assert.NoError(t, f.Save())
xurime's avatar
xurime 已提交
182 183
}

V
Veniamin Albaev 已提交
184
func TestSaveAsWrongPath(t *testing.T) {
185
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
186 187
	if assert.NoError(t, err) {
		// Test write file to not exist directory.
188
		err = f.SaveAs("")
V
Veniamin Albaev 已提交
189 190 191
		if assert.Error(t, err) {
			assert.True(t, os.IsNotExist(err), "Error: %v: Expected os.IsNotExists(err) == true", err)
		}
xurime's avatar
xurime 已提交
192
	}
193 194
}

xurime's avatar
xurime 已提交
195 196 197 198 199
func TestCharsetTranscoder(t *testing.T) {
	f := NewFile()
	f.CharsetTranscoder(*new(charsetTranscoderFn))
}

200 201 202
func TestOpenReader(t *testing.T) {
	_, err := OpenReader(strings.NewReader(""))
	assert.EqualError(t, err, "zip: not a valid zip file")
203 204 205 206 207 208 209 210
	_, 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")
xurime's avatar
xurime 已提交
211 212 213 214 215 216 217 218 219 220 221 222

	// Test unexpected EOF.
	var b bytes.Buffer
	w := gzip.NewWriter(&b)
	defer w.Close()
	w.Flush()

	r, _ := gzip.NewReader(&b)
	defer r.Close()

	_, err = OpenReader(r)
	assert.EqualError(t, err, "unexpected EOF")
223 224
}

225
func TestBrokenFile(t *testing.T) {
xurime's avatar
xurime 已提交
226
	// Test write file with broken file struct.
227
	f := File{}
xurime's avatar
xurime 已提交
228

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

V
Veniamin Albaev 已提交
233 234
	t.Run("SaveAsEmptyStruct", func(t *testing.T) {
		// Test write file with broken file struct with given path.
235
		assert.NoError(t, f.SaveAs(filepath.Join("test", "BrokenFile.SaveAsEmptyStruct.xlsx")))
V
Veniamin Albaev 已提交
236 237 238 239
	})

	t.Run("OpenBadWorkbook", func(t *testing.T) {
		// Test set active sheet without BookViews and Sheets maps in xl/workbook.xml.
240
		f3, err := OpenFile(filepath.Join("test", "BadWorkbook.xlsx"))
V
Veniamin Albaev 已提交
241 242 243 244 245 246 247
		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.
248
		_, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
V
Veniamin Albaev 已提交
249 250 251 252
		if assert.Error(t, err) {
			assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
		}
	})
253 254
}

255
func TestNewFile(t *testing.T) {
256
	// Test create a XLSX file.
257 258 259 260
	f := NewFile()
	f.NewSheet("Sheet1")
	f.NewSheet("XLSXSheet2")
	f.NewSheet("XLSXSheet3")
261 262
	assert.NoError(t, f.SetCellInt("XLSXSheet2", "A23", 56))
	assert.NoError(t, f.SetCellStr("Sheet1", "B20", "42"))
263
	f.SetActiveSheet(0)
V
Veniamin Albaev 已提交
264

265
	// Test add picture to sheet with scaling and positioning.
266
	err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
267
		`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
V
Veniamin Albaev 已提交
268 269
	if !assert.NoError(t, err) {
		t.FailNow()
xurime's avatar
xurime 已提交
270
	}
V
Veniamin Albaev 已提交
271

272
	// Test add picture to worksheet without formatset.
273
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
V
Veniamin Albaev 已提交
274 275
	if !assert.NoError(t, err) {
		t.FailNow()
276
	}
V
Veniamin Albaev 已提交
277

278
	// Test add picture to worksheet with invalid formatset.
279
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), `{`)
V
Veniamin Albaev 已提交
280 281
	if !assert.Error(t, err) {
		t.FailNow()
282
	}
V
Veniamin Albaev 已提交
283

284
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewFile.xlsx")))
xurime's avatar
xurime 已提交
285
}
286

287 288 289 290 291 292
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 "*"`)
}

293
func TestSetCellHyperLink(t *testing.T) {
294
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
295 296 297 298
	if err != nil {
		t.Log(err)
	}
	// Test set cell hyperlink in a work sheet already have hyperlinks.
299
	assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
300
	// Test add first hyperlink in a work sheet.
301
	assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
302
	// Test add Location hyperlink in a work sheet.
303
	assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
304

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

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

309 310
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx")))

311
	f = NewFile()
312 313
	_, err = f.workSheetReader("Sheet1")
	assert.NoError(t, err)
314 315
	f.Sheet["xl/worksheets/sheet1.xml"].Hyperlinks = &xlsxHyperlinks{Hyperlink: make([]xlsxHyperlink, 65530)}
	assert.EqualError(t, f.SetCellHyperLink("Sheet1", "A65531", "https://github.com/360EntSecGroup-Skylar/excelize", "External"), "over maximum limit hyperlinks in a worksheet")
316 317

	f = NewFile()
318 319
	_, err = f.workSheetReader("Sheet1")
	assert.NoError(t, err)
320 321 322
	f.Sheet["xl/worksheets/sheet1.xml"].MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
	err = f.SetCellHyperLink("Sheet1", "A1", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
	assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
323 324
}

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

331
	_, _, err = f.GetCellHyperLink("Sheet1", "")
332
	assert.EqualError(t, err, `invalid cell name ""`)
333

334
	link, target, err := f.GetCellHyperLink("Sheet1", "A22")
335
	assert.NoError(t, err)
336
	t.Log(link, target)
337
	link, target, err = f.GetCellHyperLink("Sheet2", "D6")
338
	assert.NoError(t, err)
339
	t.Log(link, target)
340
	link, target, err = f.GetCellHyperLink("Sheet3", "H3")
xurime's avatar
xurime 已提交
341
	assert.EqualError(t, err, "sheet Sheet3 is not exist")
342
	t.Log(link, target)
343 344

	f = NewFile()
345 346
	_, err = f.workSheetReader("Sheet1")
	assert.NoError(t, err)
347 348 349 350 351 352 353 354 355 356 357 358 359 360
	f.Sheet["xl/worksheets/sheet1.xml"].Hyperlinks = &xlsxHyperlinks{
		Hyperlink: []xlsxHyperlink{{Ref: "A1"}},
	}
	link, target, err = f.GetCellHyperLink("Sheet1", "A1")
	assert.NoError(t, err)
	assert.Equal(t, link, true)
	assert.Equal(t, target, "")

	f.Sheet["xl/worksheets/sheet1.xml"].MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
	link, target, err = f.GetCellHyperLink("Sheet1", "A1")
	assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
	assert.Equal(t, link, false)
	assert.Equal(t, target, "")

361 362
}

363
func TestSetCellFormula(t *testing.T) {
364
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
365 366
	if !assert.NoError(t, err) {
		t.FailNow()
367
	}
V
Veniamin Albaev 已提交
368

369 370
	assert.NoError(t, f.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)"))
	assert.NoError(t, f.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)"))
371

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

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

377
	f, err = OpenFile(filepath.Join("test", "CalcChain.xlsx"))
378 379 380 381
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	// Test remove cell formula.
382
	assert.NoError(t, f.SetCellFormula("Sheet1", "A1", ""))
383
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula2.xlsx")))
384
	// Test remove all cell formula.
385
	assert.NoError(t, f.SetCellFormula("Sheet1", "B1", ""))
386
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula3.xlsx")))
387
}
388 389

func TestSetSheetBackground(t *testing.T) {
390
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
391 392
	if !assert.NoError(t, err) {
		t.FailNow()
393
	}
V
Veniamin Albaev 已提交
394

395
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
V
Veniamin Albaev 已提交
396 397
	if !assert.NoError(t, err) {
		t.FailNow()
398
	}
V
Veniamin Albaev 已提交
399

400
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
V
Veniamin Albaev 已提交
401 402
	if !assert.NoError(t, err) {
		t.FailNow()
403
	}
V
Veniamin Albaev 已提交
404

405
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetBackground.xlsx")))
V
Veniamin Albaev 已提交
406 407 408
}

func TestSetSheetBackgroundErrors(t *testing.T) {
409
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
410 411
	if !assert.NoError(t, err) {
		t.FailNow()
412
	}
V
Veniamin Albaev 已提交
413

414
	err = f.SetSheetBackground("Sheet2", filepath.Join("test", "not_exists", "not_exists.png"))
V
Veniamin Albaev 已提交
415 416 417 418
	if assert.Error(t, err) {
		assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
	}

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

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
// TestWriteArrayFormula tests the extended options of SetCellFormula by writing an array function
// to a workbook. In the resulting file, the lines 2 and 3 as well as 4 and 5 should have matching
// contents.
func TestWriteArrayFormula(t *testing.T) {
	cell := func(col, row int) string {
		c, err := CoordinatesToCellName(col, row)
		if err != nil {
			t.Fatal(err)
		}

		return c
	}

	f := NewFile()

	sample := []string{"Sample 1", "Sample 2", "Sample 3"}
	values := []int{1855, 1709, 1462, 1115, 1524, 625, 773, 126, 1027, 1696, 1078, 1917, 1109, 1753, 1884, 659, 994, 1911, 1925, 899, 196, 244, 1488, 1056, 1986, 66, 784, 725, 767, 1722, 1541, 1026, 1455, 264, 1538, 877, 1581, 1098, 383, 762, 237, 493, 29, 1923, 474, 430, 585, 688, 308, 200, 1259, 622, 798, 1048, 996, 601, 582, 332, 377, 805, 250, 1860, 1360, 840, 911, 1346, 1651, 1651, 665, 584, 1057, 1145, 925, 1752, 202, 149, 1917, 1398, 1894, 818, 714, 624, 1085, 1566, 635, 78, 313, 1686, 1820, 494, 614, 1913, 271, 1016, 338, 1301, 489, 1733, 1483, 1141}
	assoc := []int{2, 0, 0, 0, 0, 1, 1, 0, 0, 1, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 2, 0, 2, 1, 2, 2, 2, 1, 0, 1, 0, 1, 1, 2, 0, 2, 1, 0, 2, 1, 0, 1, 0, 0, 2, 0, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 1, 0, 1, 0, 2, 0, 0, 1, 2, 1, 0, 1, 0, 0, 2, 1, 1, 2, 0, 2, 1, 0, 2, 2, 2, 1, 0, 0, 1, 1, 1, 2, 0, 2, 0, 1, 1}
	if len(values) != len(assoc) {
		t.Fatal("values and assoc must be of same length")
	}

	// Average calculates the average of the n-th sample (0 <= n < len(sample)).
	average := func(n int) int {
		sum := 0
		count := 0
		for i := 0; i != len(values); i++ {
			if assoc[i] == n {
				sum += values[i]
				count++
			}
		}

		return int(math.Round(float64(sum) / float64(count)))
	}

	// Stdev calculates the standard deviation of the n-th sample (0 <= n < len(sample)).
	stdev := func(n int) int {
		avg := average(n)

		sum := 0
		count := 0
		for i := 0; i != len(values); i++ {
			if assoc[i] == n {
				sum += (values[i] - avg) * (values[i] - avg)
				count++
			}
		}

		return int(math.Round(math.Sqrt(float64(sum) / float64(count))))
	}

	// Line 2 contains the results of AVERAGEIF
476
	assert.NoError(t, f.SetCellStr("Sheet1", "A2", "Average"))
477 478

	// Line 3 contains the average that was calculated in Go
479
	assert.NoError(t, f.SetCellStr("Sheet1", "A3", "Average (calculated)"))
480 481

	// Line 4 contains the results of the array function that calculates the standard deviation
482
	assert.NoError(t, f.SetCellStr("Sheet1", "A4", "Std. deviation"))
483 484

	// Line 5 contains the standard deviations calculated in Go
485
	assert.NoError(t, f.SetCellStr("Sheet1", "A5", "Std. deviation (calculated)"))
486

487 488 489
	assert.NoError(t, f.SetCellStr("Sheet1", "B1", sample[0]))
	assert.NoError(t, f.SetCellStr("Sheet1", "C1", sample[1]))
	assert.NoError(t, f.SetCellStr("Sheet1", "D1", sample[2]))
490 491

	firstResLine := 8
492 493
	assert.NoError(t, f.SetCellStr("Sheet1", cell(1, firstResLine-1), "Result Values"))
	assert.NoError(t, f.SetCellStr("Sheet1", cell(2, firstResLine-1), "Sample"))
494 495 496 497 498

	for i := 0; i != len(values); i++ {
		valCell := cell(1, i+firstResLine)
		assocCell := cell(2, i+firstResLine)

499 500
		assert.NoError(t, f.SetCellInt("Sheet1", valCell, values[i]))
		assert.NoError(t, f.SetCellStr("Sheet1", assocCell, sample[assoc[i]]))
501 502 503 504 505 506 507 508 509 510 511 512
	}

	valRange := fmt.Sprintf("$A$%d:$A$%d", firstResLine, len(values)+firstResLine-1)
	assocRange := fmt.Sprintf("$B$%d:$B$%d", firstResLine, len(values)+firstResLine-1)

	for i := 0; i != len(sample); i++ {
		nameCell := cell(i+2, 1)
		avgCell := cell(i+2, 2)
		calcAvgCell := cell(i+2, 3)
		stdevCell := cell(i+2, 4)
		calcStdevCell := cell(i+2, 5)

513 514
		assert.NoError(t, f.SetCellInt("Sheet1", calcAvgCell, average(i)))
		assert.NoError(t, f.SetCellInt("Sheet1", calcStdevCell, stdev(i)))
515 516

		// Average can be done with AVERAGEIF
517
		assert.NoError(t, f.SetCellFormula("Sheet1", avgCell, fmt.Sprintf("ROUND(AVERAGEIF(%s,%s,%s),0)", assocRange, nameCell, valRange)))
518 519 520 521 522 523 524 525 526 527 528

		ref := stdevCell + ":" + stdevCell
		t := STCellFormulaTypeArray
		// Use an array formula for standard deviation
		f.SetCellFormula("Sheet1", stdevCell, fmt.Sprintf("ROUND(STDEVP(IF(%s=%s,%s)),0)", assocRange, nameCell, valRange),
			FormulaOpts{}, FormulaOpts{Type: &t}, FormulaOpts{Ref: &ref})
	}

	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestWriteArrayFormula.xlsx")))
}

529
func TestSetCellStyleAlignment(t *testing.T) {
530
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
531 532
	if !assert.NoError(t, err) {
		t.FailNow()
533
	}
V
Veniamin Albaev 已提交
534

535
	var style int
536
	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 已提交
537 538
	if !assert.NoError(t, err) {
		t.FailNow()
539
	}
V
Veniamin Albaev 已提交
540

541
	assert.NoError(t, f.SetCellStyle("Sheet1", "A22", "A22", style))
542

543
	// Test set cell style with given illegal rows number.
544 545
	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"`)
546

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

552
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleAlignment.xlsx")))
553 554 555
}

func TestSetCellStyleBorder(t *testing.T) {
556
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
557 558
	if !assert.NoError(t, err) {
		t.FailNow()
559
	}
560

V
Veniamin Albaev 已提交
561
	var style int
562

563
	// Test set border on overlapping area with vertical variants shading styles gradient fill.
564
	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 已提交
565 566
	if !assert.NoError(t, err) {
		t.FailNow()
567
	}
568
	assert.NoError(t, f.SetCellStyle("Sheet1", "J21", "L25", style))
569

570
	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 已提交
571 572
	if !assert.NoError(t, err) {
		t.FailNow()
573
	}
574
	assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
575

576
	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 已提交
577 578
	if !assert.NoError(t, err) {
		t.FailNow()
579
	}
580
	assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
581

582
	// Test set border and solid style pattern fill for a single cell.
583
	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 已提交
584 585
	if !assert.NoError(t, err) {
		t.FailNow()
586
	}
587

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

590
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleBorder.xlsx")))
V
Veniamin Albaev 已提交
591 592 593
}

func TestSetCellStyleBorderErrors(t *testing.T) {
594
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
595 596 597 598 599
	if !assert.NoError(t, err) {
		t.FailNow()
	}

	// Set border with invalid style parameter.
600
	_, err = f.NewStyle("")
V
Veniamin Albaev 已提交
601 602 603 604 605
	if !assert.EqualError(t, err, "unexpected end of JSON input") {
		t.FailNow()
	}

	// Set border with invalid style index number.
606
	_, 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 已提交
607 608
	if !assert.NoError(t, err) {
		t.FailNow()
609 610 611
	}
}

612
func TestSetCellStyleNumberFormat(t *testing.T) {
613
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
614 615
	if !assert.NoError(t, err) {
		t.FailNow()
616
	}
V
Veniamin Albaev 已提交
617

xurime's avatar
xurime 已提交
618
	// Test only set fill and number format for a cell.
619 620 621 622 623 624 625 626 627
	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 {
628
				assert.NoError(t, f.SetCellValue("Sheet2", c, v))
629
			} else {
630
				assert.NoError(t, f.SetCellValue("Sheet2", c, val))
631
			}
632
			style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format": ` + strconv.Itoa(d) + `}`)
V
Veniamin Albaev 已提交
633 634
			if !assert.NoError(t, err) {
				t.FailNow()
635
			}
636 637
			assert.NoError(t, f.SetCellStyle("Sheet2", c, c, style))
			t.Log(f.GetCellValue("Sheet2", c))
638 639
		}
	}
640
	var style int
641
	style, err = f.NewStyle(`{"number_format":-1}`)
V
Veniamin Albaev 已提交
642 643
	if !assert.NoError(t, err) {
		t.FailNow()
644
	}
645
	assert.NoError(t, f.SetCellStyle("Sheet2", "L33", "L33", style))
V
Veniamin Albaev 已提交
646

647
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleNumberFormat.xlsx")))
648 649
}

650
func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
V
Veniamin Albaev 已提交
651
	t.Run("TestBook3", func(t *testing.T) {
652
		f, err := prepareTestBook3()
V
Veniamin Albaev 已提交
653 654 655
		if !assert.NoError(t, err) {
			t.FailNow()
		}
656

657 658
		assert.NoError(t, f.SetCellValue("Sheet1", "A1", 56))
		assert.NoError(t, f.SetCellValue("Sheet1", "A2", -32.3))
V
Veniamin Albaev 已提交
659
		var style int
660
		style, err = f.NewStyle(`{"number_format": 188, "decimal_places": -1}`)
V
Veniamin Albaev 已提交
661 662 663
		if !assert.NoError(t, err) {
			t.FailNow()
		}
664

665 666
		assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
		style, err = f.NewStyle(`{"number_format": 188, "decimal_places": 31, "negred": true}`)
V
Veniamin Albaev 已提交
667 668 669
		if !assert.NoError(t, err) {
			t.FailNow()
		}
670

671
		assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
672

673
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook3.xlsx")))
V
Veniamin Albaev 已提交
674
	})
675

V
Veniamin Albaev 已提交
676
	t.Run("TestBook4", func(t *testing.T) {
677
		f, err := prepareTestBook4()
V
Veniamin Albaev 已提交
678 679 680
		if !assert.NoError(t, err) {
			t.FailNow()
		}
681 682
		assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5))
		assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5))
V
Veniamin Albaev 已提交
683

684
		_, err = f.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`)
V
Veniamin Albaev 已提交
685 686 687 688
		if !assert.NoError(t, err) {
			t.FailNow()
		}

689
		style, err := f.NewStyle(`{"number_format": 27}`)
V
Veniamin Albaev 已提交
690 691 692 693
		if !assert.NoError(t, err) {
			t.FailNow()
		}

694 695
		assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
		style, err = f.NewStyle(`{"number_format": 31, "lang": "ko-kr"}`)
V
Veniamin Albaev 已提交
696 697 698 699
		if !assert.NoError(t, err) {
			t.FailNow()
		}

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

702
		style, err = f.NewStyle(`{"number_format": 71, "lang": "th-th"}`)
V
Veniamin Albaev 已提交
703 704 705
		if !assert.NoError(t, err) {
			t.FailNow()
		}
706
		assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
V
Veniamin Albaev 已提交
707

708
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook4.xlsx")))
V
Veniamin Albaev 已提交
709
	})
710 711
}

712
func TestSetCellStyleCustomNumberFormat(t *testing.T) {
713
	f := NewFile()
714 715
	assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5))
	assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5))
716
	style, err := f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
717 718 719
	if err != nil {
		t.Log(err)
	}
720 721
	assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
	style, err = f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
722 723 724
	if err != nil {
		t.Log(err)
	}
725
	assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
V
Veniamin Albaev 已提交
726

727
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCustomNumberFormat.xlsx")))
728 729
}

730
func TestSetCellStyleFill(t *testing.T) {
731
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
732 733
	if !assert.NoError(t, err) {
		t.FailNow()
734
	}
V
Veniamin Albaev 已提交
735

736
	var style int
737
	// Test set fill for cell with invalid parameter.
738
	style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":6}}`)
V
Veniamin Albaev 已提交
739 740
	if !assert.NoError(t, err) {
		t.FailNow()
741
	}
742
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
743

744
	style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF"],"shading":1}}`)
V
Veniamin Albaev 已提交
745 746
	if !assert.NoError(t, err) {
		t.FailNow()
747
	}
748
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
749

750
	style, err = f.NewStyle(`{"fill":{"type":"pattern","color":[],"pattern":1}}`)
V
Veniamin Albaev 已提交
751 752
	if !assert.NoError(t, err) {
		t.FailNow()
753
	}
754
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
xurime's avatar
xurime 已提交
755

756
	style, err = f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":19}}`)
V
Veniamin Albaev 已提交
757 758
	if !assert.NoError(t, err) {
		t.FailNow()
759
	}
760
	assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
761

762
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFill.xlsx")))
763 764 765
}

func TestSetCellStyleFont(t *testing.T) {
766
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
767 768
	if !assert.NoError(t, err) {
		t.FailNow()
769
	}
V
Veniamin Albaev 已提交
770

771
	var style int
xurime's avatar
xurime 已提交
772
	style, err = f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}`)
V
Veniamin Albaev 已提交
773 774
	if !assert.NoError(t, err) {
		t.FailNow()
775
	}
V
Veniamin Albaev 已提交
776

777
	assert.NoError(t, f.SetCellStyle("Sheet2", "A1", "A1", style))
778

779
	style, err = f.NewStyle(`{"font":{"italic":true,"underline":"double"}}`)
V
Veniamin Albaev 已提交
780 781
	if !assert.NoError(t, err) {
		t.FailNow()
782
	}
V
Veniamin Albaev 已提交
783

784
	assert.NoError(t, f.SetCellStyle("Sheet2", "A2", "A2", style))
785

786
	style, err = f.NewStyle(`{"font":{"bold":true}}`)
V
Veniamin Albaev 已提交
787 788
	if !assert.NoError(t, err) {
		t.FailNow()
789
	}
V
Veniamin Albaev 已提交
790

791
	assert.NoError(t, f.SetCellStyle("Sheet2", "A3", "A3", style))
792

793
	style, err = f.NewStyle(`{"font":{"bold":true,"family":"","size":0,"color":"","underline":""}}`)
V
Veniamin Albaev 已提交
794 795
	if !assert.NoError(t, err) {
		t.FailNow()
796
	}
V
Veniamin Albaev 已提交
797

798
	assert.NoError(t, f.SetCellStyle("Sheet2", "A4", "A4", style))
799

xurime's avatar
xurime 已提交
800
	style, err = f.NewStyle(`{"font":{"color":"#777777","strike":true}}`)
V
Veniamin Albaev 已提交
801 802
	if !assert.NoError(t, err) {
		t.FailNow()
803
	}
V
Veniamin Albaev 已提交
804

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

807
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFont.xlsx")))
808
}
809

810
func TestSetCellStyleProtection(t *testing.T) {
811
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
812 813
	if !assert.NoError(t, err) {
		t.FailNow()
814
	}
V
Veniamin Albaev 已提交
815

816
	var style int
817
	style, err = f.NewStyle(`{"protection":{"hidden":true, "locked":true}}`)
V
Veniamin Albaev 已提交
818 819
	if !assert.NoError(t, err) {
		t.FailNow()
820
	}
V
Veniamin Albaev 已提交
821

822 823
	assert.NoError(t, f.SetCellStyle("Sheet2", "A6", "A6", style))
	err = f.SaveAs(filepath.Join("test", "TestSetCellStyleProtection.xlsx"))
V
Veniamin Albaev 已提交
824 825
	if !assert.NoError(t, err) {
		t.FailNow()
826 827 828
	}
}

V
Veniamin Albaev 已提交
829 830
func TestSetDeleteSheet(t *testing.T) {
	t.Run("TestBook3", func(t *testing.T) {
831
		f, err := prepareTestBook3()
V
Veniamin Albaev 已提交
832 833 834 835
		if !assert.NoError(t, err) {
			t.FailNow()
		}

836 837
		f.DeleteSheet("XLSXSheet3")
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook3.xlsx")))
V
Veniamin Albaev 已提交
838 839 840
	})

	t.Run("TestBook4", func(t *testing.T) {
841
		f, err := prepareTestBook4()
V
Veniamin Albaev 已提交
842 843 844
		if !assert.NoError(t, err) {
			t.FailNow()
		}
845
		f.DeleteSheet("Sheet1")
846 847
		assert.EqualError(t, f.AddComment("Sheet1", "A1", ""), "unexpected end of JSON input")
		assert.NoError(t, f.AddComment("Sheet1", "A1", `{"author":"Excelize: ","text":"This is a comment."}`))
848
		assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook4.xlsx")))
V
Veniamin Albaev 已提交
849
	})
850
}
851

852
func TestSheetVisibility(t *testing.T) {
853
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
854 855
	if !assert.NoError(t, err) {
		t.FailNow()
856
	}
V
Veniamin Albaev 已提交
857

858 859 860 861
	assert.NoError(t, f.SetSheetVisible("Sheet2", false))
	assert.NoError(t, f.SetSheetVisible("Sheet1", false))
	assert.NoError(t, f.SetSheetVisible("Sheet1", true))
	assert.Equal(t, true, f.GetSheetVisible("Sheet1"))
V
Veniamin Albaev 已提交
862

863
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSheetVisibility.xlsx")))
864 865
}

866
func TestCopySheet(t *testing.T) {
867
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
868 869
	if !assert.NoError(t, err) {
		t.FailNow()
870
	}
V
Veniamin Albaev 已提交
871

872
	idx := f.NewSheet("CopySheet")
873
	assert.NoError(t, f.CopySheet(1, idx))
V
Veniamin Albaev 已提交
874

875
	assert.NoError(t, f.SetCellValue("CopySheet", "F1", "Hello"))
876
	val, err := f.GetCellValue("Sheet1", "F1")
877 878
	assert.NoError(t, err)
	assert.NotEqual(t, "Hello", val)
V
Veniamin Albaev 已提交
879

880
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheet.xlsx")))
V
Veniamin Albaev 已提交
881 882 883
}

func TestCopySheetError(t *testing.T) {
884
	f, err := prepareTestBook1()
V
Veniamin Albaev 已提交
885 886
	if !assert.NoError(t, err) {
		t.FailNow()
887
	}
V
Veniamin Albaev 已提交
888

889 890
	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 已提交
891
		t.FailNow()
892
	}
V
Veniamin Albaev 已提交
893

894
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx")))
895
}
896

897 898 899 900 901
func TestGetSheetComments(t *testing.T) {
	f := NewFile()
	assert.Equal(t, "", f.getSheetComments(0))
}

xurime's avatar
xurime 已提交
902 903 904 905 906 907 908
func TestSetActiveSheet(t *testing.T) {
	f := NewFile()
	f.WorkBook.BookViews = nil
	f.SetActiveSheet(1)
	f.WorkBook.BookViews = &xlsxBookViews{WorkBookView: []xlsxWorkBookView{}}
	f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = &xlsxSheetViews{SheetView: []xlsxSheetView{}}
	f.SetActiveSheet(1)
909 910
	f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = nil
	f.SetActiveSheet(1)
xurime's avatar
xurime 已提交
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
}

func TestSetSheetVisible(t *testing.T) {
	f := NewFile()
	f.WorkBook.Sheets.Sheet[0].Name = "SheetN"
	assert.EqualError(t, f.SetSheetVisible("Sheet1", false), "sheet SheetN is not exist")
}

func TestGetActiveSheetIndex(t *testing.T) {
	f := NewFile()
	f.WorkBook.BookViews = nil
	assert.Equal(t, 1, f.GetActiveSheetIndex())
}

func TestRelsWriter(t *testing.T) {
	f := NewFile()
	f.Relationships["xl/worksheets/sheet/rels/sheet1.xml.rel"] = &xlsxRelationships{}
	f.relsWriter()
}

func TestGetSheetView(t *testing.T) {
932
	f := NewFile()
xurime's avatar
xurime 已提交
933 934
	_, err := f.getSheetView("SheetN", 0)
	assert.EqualError(t, err, "sheet SheetN is not exist")
xurime's avatar
xurime 已提交
935 936
}

937
func TestConditionalFormat(t *testing.T) {
938 939
	f := NewFile()
	sheet1 := f.GetSheetName(1)
940

941
	fillCells(f, sheet1, 10, 15)
942

943 944 945
	var format1, format2, format3 int
	var err error
	// Rose format for bad conditional.
946
	format1, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
947 948 949 950
	if !assert.NoError(t, err) {
		t.FailNow()
	}

951
	// Light yellow format for neutral conditional.
952
	format2, err = f.NewConditionalStyle(`{"fill":{"type":"pattern","color":["#FEEAA0"],"pattern":1}}`)
V
Veniamin Albaev 已提交
953 954 955 956
	if !assert.NoError(t, err) {
		t.FailNow()
	}

957
	// Light green format for good conditional.
958
	format3, err = f.NewConditionalStyle(`{"font":{"color":"#09600B"},"fill":{"type":"pattern","color":["#C7EECF"],"pattern":1}}`)
V
Veniamin Albaev 已提交
959 960 961 962
	if !assert.NoError(t, err) {
		t.FailNow()
	}

963
	// Color scales: 2 color.
964
	assert.NoError(t, f.SetConditionalFormat(sheet1, "A1:A10", `[{"type":"2_color_scale","criteria":"=","min_type":"min","max_type":"max","min_color":"#F8696B","max_color":"#63BE7B"}]`))
965
	// Color scales: 3 color.
966
	assert.NoError(t, f.SetConditionalFormat(sheet1, "B1:B10", `[{"type":"3_color_scale","criteria":"=","min_type":"min","mid_type":"percentile","max_type":"max","min_color":"#F8696B","mid_color":"#FFEB84","max_color":"#63BE7B"}]`))
967
	// Hightlight cells rules: between...
968
	assert.NoError(t, f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1)))
969
	// Hightlight cells rules: Greater Than...
970
	assert.NoError(t, f.SetConditionalFormat(sheet1, "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format3)))
971
	// Hightlight cells rules: Equal To...
972
	assert.NoError(t, f.SetConditionalFormat(sheet1, "E1:E10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d}]`, format3)))
973
	// Hightlight cells rules: Not Equal To...
974
	assert.NoError(t, f.SetConditionalFormat(sheet1, "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format2)))
975
	// Hightlight cells rules: Duplicate Values...
976
	assert.NoError(t, f.SetConditionalFormat(sheet1, "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format2)))
977
	// Top/Bottom rules: Top 10%.
978
	assert.NoError(t, f.SetConditionalFormat(sheet1, "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1)))
979
	// Top/Bottom rules: Above Average...
980
	assert.NoError(t, f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3)))
981
	// Top/Bottom rules: Below Average...
982
	assert.NoError(t, f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1)))
983
	// Data Bars: Gradient Fill.
984
	assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
985
	// Use a formula to determine which cells to format.
986
	assert.NoError(t, f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1)))
987
	// Test set invalid format set in conditional format
988
	assert.EqualError(t, f.SetConditionalFormat(sheet1, "L1:L10", ""), "unexpected end of JSON input")
V
Veniamin Albaev 已提交
989

990
	err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx"))
V
Veniamin Albaev 已提交
991 992
	if !assert.NoError(t, err) {
		t.FailNow()
993 994 995
	}

	// Set conditional format with illegal valid type.
996
	assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
997
	// Set conditional format with illegal criteria type.
998
	assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
V
Veniamin Albaev 已提交
999 1000

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

1006
	_, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
V
Veniamin Albaev 已提交
1007 1008 1009
	if !assert.NoError(t, err) {
		t.FailNow()
	}
1010
}
xurime's avatar
xurime 已提交
1011

V
Veniamin Albaev 已提交
1012
func TestConditionalFormatError(t *testing.T) {
1013 1014
	f := NewFile()
	sheet1 := f.GetSheetName(1)
1015

1016
	fillCells(f, sheet1, 10, 15)
V
Veniamin Albaev 已提交
1017 1018

	// Set conditional format with illegal JSON string should return error
1019
	_, err := f.NewConditionalStyle("")
V
Veniamin Albaev 已提交
1020 1021
	if !assert.EqualError(t, err, "unexpected end of JSON input") {
		t.FailNow()
xurime's avatar
xurime 已提交
1022 1023
	}
}
1024 1025

func TestSharedStrings(t *testing.T) {
1026
	f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
V
Veniamin Albaev 已提交
1027 1028
	if !assert.NoError(t, err) {
		t.FailNow()
1029
	}
H
Harris 已提交
1030 1031 1032 1033 1034
	rows, err := f.GetRows("Sheet1")
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	assert.Equal(t, "A", rows[0][0])
H
Harris 已提交
1035 1036 1037 1038 1039
	rows, err = f.GetRows("Sheet2")
	if !assert.NoError(t, err) {
		t.FailNow()
	}
	assert.Equal(t, "Test Weight (Kgs)", rows[0][0])
1040
}
1041 1042

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

1048
	assert.NoError(t, f.SetSheetRow("Sheet1", "B27", &[]interface{}{"cell", nil, int32(42), float64(42), time.Now().UTC()}))
1049

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

1053 1054 1055
	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")))
1056
}
1057

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

1083
func TestProtectSheet(t *testing.T) {
1084
	f := NewFile()
1085 1086
	assert.NoError(t, f.ProtectSheet("Sheet1", nil))
	assert.NoError(t, f.ProtectSheet("Sheet1", &FormatSheetProtection{
1087 1088
		Password:      "password",
		EditScenarios: false,
1089
	}))
V
Veniamin Albaev 已提交
1090

1091
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx")))
xurime's avatar
xurime 已提交
1092
	// Test protect not exists worksheet.
1093
	assert.EqualError(t, f.ProtectSheet("SheetN", nil), "sheet SheetN is not exist")
1094 1095
}

1096
func TestUnprotectSheet(t *testing.T) {
1097
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1098 1099
	if !assert.NoError(t, err) {
		t.FailNow()
1100
	}
xurime's avatar
xurime 已提交
1101
	// Test unprotect not exists worksheet.
1102
	assert.EqualError(t, f.UnprotectSheet("SheetN"), "sheet SheetN is not exist")
V
Veniamin Albaev 已提交
1103

1104
	assert.NoError(t, f.UnprotectSheet("Sheet1"))
1105
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnprotectSheet.xlsx")))
1106
}
xurime's avatar
xurime 已提交
1107 1108 1109 1110 1111 1112

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

1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
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")))
}

xurime's avatar
xurime 已提交
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
func TestContentTypesReader(t *testing.T) {
	// Test unsupport charset.
	f := NewFile()
	f.ContentTypes = nil
	f.XLSX["[Content_Types].xml"] = MacintoshCyrillicCharset
	f.contentTypesReader()
}

func TestWorkbookReader(t *testing.T) {
	// Test unsupport charset.
	f := NewFile()
	f.WorkBook = nil
	f.XLSX["xl/workbook.xml"] = MacintoshCyrillicCharset
	f.workbookReader()
}

func TestWorkSheetReader(t *testing.T) {
	// Test unsupport charset.
	f := NewFile()
	delete(f.Sheet, "xl/worksheets/sheet1.xml")
	f.XLSX["xl/worksheets/sheet1.xml"] = MacintoshCyrillicCharset
	_, err := f.workSheetReader("Sheet1")
	assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")

	// Test on no checked worksheet.
	f = NewFile()
	delete(f.Sheet, "xl/worksheets/sheet1.xml")
	f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData/></worksheet>`)
	f.checked = nil
	_, err = f.workSheetReader("Sheet1")
	assert.NoError(t, err)
}

func TestRelsReader(t *testing.T) {
	// Test unsupport charset.
	f := NewFile()
	rels := "xl/_rels/workbook.xml.rels"
	f.Relationships[rels] = nil
	f.XLSX[rels] = MacintoshCyrillicCharset
	f.relsReader(rels)
}

func TestDeleteSheetFromWorkbookRels(t *testing.T) {
	f := NewFile()
	rels := "xl/_rels/workbook.xml.rels"
	f.Relationships[rels] = nil
	assert.Equal(t, f.deleteSheetFromWorkbookRels("rID"), "")
}

func TestAttrValToInt(t *testing.T) {
	_, err := attrValToInt("r", []xml.Attr{
		{Name: xml.Name{Local: "r"}, Value: "s"}})
	assert.EqualError(t, err, `strconv.Atoi: parsing "s": invalid syntax`)
}

V
Veniamin Albaev 已提交
1180
func prepareTestBook1() (*File, error) {
1181
	f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
V
Veniamin Albaev 已提交
1182 1183 1184 1185
	if err != nil {
		return nil, err
	}

1186
	err = f.AddPicture("Sheet2", "I9", filepath.Join("test", "images", "excel.jpg"),
V
Veniamin Albaev 已提交
1187 1188 1189 1190 1191 1192
		`{"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.
1193
	err = f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.png"),
V
Veniamin Albaev 已提交
1194 1195 1196 1197 1198
		`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`)
	if err != nil {
		return nil, err
	}

1199
	file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.jpg"))
V
Veniamin Albaev 已提交
1200 1201 1202 1203
	if err != nil {
		return nil, err
	}

1204
	err = f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file)
V
Veniamin Albaev 已提交
1205 1206 1207 1208
	if err != nil {
		return nil, err
	}

1209
	return f, nil
V
Veniamin Albaev 已提交
1210 1211 1212
}

func prepareTestBook3() (*File, error) {
1213 1214 1215 1216
	f := NewFile()
	f.NewSheet("Sheet1")
	f.NewSheet("XLSXSheet2")
	f.NewSheet("XLSXSheet3")
1217 1218 1219 1220 1221 1222
	if err := f.SetCellInt("XLSXSheet2", "A23", 56); err != nil {
		return nil, err
	}
	if err := f.SetCellStr("Sheet1", "B20", "42"); err != nil {
		return nil, err
	}
1223 1224 1225
	f.SetActiveSheet(0)

	err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
1226
		`{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
V
Veniamin Albaev 已提交
1227 1228 1229 1230
	if err != nil {
		return nil, err
	}

1231
	err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
V
Veniamin Albaev 已提交
1232 1233 1234 1235
	if err != nil {
		return nil, err
	}

1236
	return f, nil
V
Veniamin Albaev 已提交
1237 1238 1239
}

func prepareTestBook4() (*File, error) {
1240
	f := NewFile()
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252
	if err := f.SetColWidth("Sheet1", "B", "A", 12); err != nil {
		return f, err
	}
	if err := f.SetColWidth("Sheet1", "A", "B", 12); err != nil {
		return f, err
	}
	if _, err := f.GetColWidth("Sheet1", "A"); err != nil {
		return f, err
	}
	if _, err := f.GetColWidth("Sheet1", "C"); err != nil {
		return f, err
	}
V
Veniamin Albaev 已提交
1253

1254
	return f, nil
V
Veniamin Albaev 已提交
1255
}
1256

1257
func fillCells(f *File, sheet string, colCount, rowCount int) {
1258 1259
	for col := 1; col <= colCount; col++ {
		for row := 1; row <= rowCount; row++ {
1260
			cell, _ := CoordinatesToCellName(col, row)
1261
			if err := f.SetCellStr(sheet, cell, cell); err != nil {
xurime's avatar
xurime 已提交
1262
				fmt.Println(err)
1263
			}
1264 1265 1266
		}
	}
}
1267 1268 1269

func BenchmarkOpenFile(b *testing.B) {
	for i := 0; i < b.N; i++ {
1270 1271 1272
		if _, err := OpenFile(filepath.Join("test", "Book1.xlsx")); err != nil {
			b.Error(err)
		}
1273 1274
	}
}