excelize_test.go 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332
  1. package excelize
  2. import (
  3. "bytes"
  4. "compress/gzip"
  5. "encoding/xml"
  6. "fmt"
  7. "image/color"
  8. _ "image/gif"
  9. _ "image/jpeg"
  10. _ "image/png"
  11. "io/ioutil"
  12. "math"
  13. "os"
  14. "path/filepath"
  15. "strconv"
  16. "strings"
  17. "testing"
  18. "time"
  19. "github.com/stretchr/testify/assert"
  20. )
  21. func TestOpenFile(t *testing.T) {
  22. // Test update the spreadsheet file.
  23. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  24. assert.NoError(t, err)
  25. // Test get all the rows in a not exists worksheet.
  26. _, err = f.GetRows("Sheet4")
  27. assert.EqualError(t, err, "sheet Sheet4 is not exist")
  28. // Test get all the rows in a worksheet.
  29. rows, err := f.GetRows("Sheet2")
  30. assert.NoError(t, err)
  31. for _, row := range rows {
  32. for _, cell := range row {
  33. t.Log(cell, "\t")
  34. }
  35. t.Log("\r\n")
  36. }
  37. assert.NoError(t, f.UpdateLinkedValue())
  38. assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32)))
  39. assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)))
  40. // Test set cell value with illegal row number.
  41. assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)),
  42. `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  43. assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100))
  44. // Test set cell integer value with illegal row number.
  45. assert.EqualError(t, f.SetCellInt("Sheet2", "A", 100), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  46. assert.NoError(t, f.SetCellStr("Sheet2", "C11", "Knowns"))
  47. // Test max characters in a cell.
  48. assert.NoError(t, f.SetCellStr("Sheet2", "D11", strings.Repeat("c", 32769)))
  49. f.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.")
  50. // Test set worksheet name with illegal name.
  51. f.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
  52. assert.EqualError(t, f.SetCellInt("Sheet3", "A23", 10), "sheet Sheet3 is not exist")
  53. assert.EqualError(t, f.SetCellStr("Sheet3", "b230", "10"), "sheet Sheet3 is not exist")
  54. assert.EqualError(t, f.SetCellStr("Sheet10", "b230", "10"), "sheet Sheet10 is not exist")
  55. // Test set cell string value with illegal row number.
  56. assert.EqualError(t, f.SetCellStr("Sheet1", "A", "10"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  57. f.SetActiveSheet(2)
  58. // Test get cell formula with given rows number.
  59. _, err = f.GetCellFormula("Sheet1", "B19")
  60. assert.NoError(t, err)
  61. // Test get cell formula with illegal worksheet name.
  62. _, err = f.GetCellFormula("Sheet2", "B20")
  63. assert.NoError(t, err)
  64. _, err = f.GetCellFormula("Sheet1", "B20")
  65. assert.NoError(t, err)
  66. // Test get cell formula with illegal rows number.
  67. _, err = f.GetCellFormula("Sheet1", "B")
  68. assert.EqualError(t, err, `cannot convert cell "B" to coordinates: invalid cell name "B"`)
  69. // Test get shared cell formula
  70. _, err = f.GetCellFormula("Sheet2", "H11")
  71. assert.NoError(t, err)
  72. _, err = f.GetCellFormula("Sheet2", "I11")
  73. assert.NoError(t, err)
  74. getSharedForumula(&xlsxWorksheet{}, "")
  75. // Test read cell value with given illegal rows number.
  76. _, err = f.GetCellValue("Sheet2", "a-1")
  77. assert.EqualError(t, err, `cannot convert cell "A-1" to coordinates: invalid cell name "A-1"`)
  78. _, err = f.GetCellValue("Sheet2", "A")
  79. assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  80. // Test read cell value with given lowercase column number.
  81. _, err = f.GetCellValue("Sheet2", "a5")
  82. assert.NoError(t, err)
  83. _, err = f.GetCellValue("Sheet2", "C11")
  84. assert.NoError(t, err)
  85. _, err = f.GetCellValue("Sheet2", "D11")
  86. assert.NoError(t, err)
  87. _, err = f.GetCellValue("Sheet2", "D12")
  88. assert.NoError(t, err)
  89. // Test SetCellValue function.
  90. assert.NoError(t, f.SetCellValue("Sheet2", "F1", " Hello"))
  91. assert.NoError(t, f.SetCellValue("Sheet2", "G1", []byte("World")))
  92. assert.NoError(t, f.SetCellValue("Sheet2", "F2", 42))
  93. assert.NoError(t, f.SetCellValue("Sheet2", "F3", int8(1<<8/2-1)))
  94. assert.NoError(t, f.SetCellValue("Sheet2", "F4", int16(1<<16/2-1)))
  95. assert.NoError(t, f.SetCellValue("Sheet2", "F5", int32(1<<32/2-1)))
  96. assert.NoError(t, f.SetCellValue("Sheet2", "F6", int64(1<<32/2-1)))
  97. assert.NoError(t, f.SetCellValue("Sheet2", "F7", float32(42.65418)))
  98. assert.NoError(t, f.SetCellValue("Sheet2", "F8", float64(-42.65418)))
  99. assert.NoError(t, f.SetCellValue("Sheet2", "F9", float32(42)))
  100. assert.NoError(t, f.SetCellValue("Sheet2", "F10", float64(42)))
  101. assert.NoError(t, f.SetCellValue("Sheet2", "F11", uint(1<<32-1)))
  102. assert.NoError(t, f.SetCellValue("Sheet2", "F12", uint8(1<<8-1)))
  103. assert.NoError(t, f.SetCellValue("Sheet2", "F13", uint16(1<<16-1)))
  104. assert.NoError(t, f.SetCellValue("Sheet2", "F14", uint32(1<<32-1)))
  105. assert.NoError(t, f.SetCellValue("Sheet2", "F15", uint64(1<<32-1)))
  106. assert.NoError(t, f.SetCellValue("Sheet2", "F16", true))
  107. assert.NoError(t, f.SetCellValue("Sheet2", "F17", complex64(5+10i)))
  108. // Test on not exists worksheet.
  109. assert.EqualError(t, f.SetCellDefault("SheetN", "A1", ""), "sheet SheetN is not exist")
  110. assert.EqualError(t, f.SetCellFloat("SheetN", "A1", 42.65418, 2, 32), "sheet SheetN is not exist")
  111. assert.EqualError(t, f.SetCellBool("SheetN", "A1", true), "sheet SheetN is not exist")
  112. assert.EqualError(t, f.SetCellFormula("SheetN", "A1", ""), "sheet SheetN is not exist")
  113. assert.EqualError(t, f.SetCellHyperLink("SheetN", "A1", "Sheet1!A40", "Location"), "sheet SheetN is not exist")
  114. // Test boolean write
  115. booltest := []struct {
  116. value bool
  117. expected string
  118. }{
  119. {false, "0"},
  120. {true, "1"},
  121. }
  122. for _, test := range booltest {
  123. assert.NoError(t, f.SetCellValue("Sheet2", "F16", test.value))
  124. val, err := f.GetCellValue("Sheet2", "F16")
  125. assert.NoError(t, err)
  126. assert.Equal(t, test.expected, val)
  127. }
  128. assert.NoError(t, f.SetCellValue("Sheet2", "G2", nil))
  129. assert.EqualError(t, f.SetCellValue("Sheet2", "G4", time.Now()), "only UTC time expected")
  130. assert.NoError(t, f.SetCellValue("Sheet2", "G4", time.Now().UTC()))
  131. // 02:46:40
  132. assert.NoError(t, f.SetCellValue("Sheet2", "G5", time.Duration(1e13)))
  133. // Test completion column.
  134. assert.NoError(t, f.SetCellValue("Sheet2", "M2", nil))
  135. // Test read cell value with given axis large than exists row.
  136. _, err = f.GetCellValue("Sheet2", "E231")
  137. assert.NoError(t, err)
  138. // Test get active worksheet of spreadsheet and get worksheet name of spreadsheet by given worksheet index.
  139. f.GetSheetName(f.GetActiveSheetIndex())
  140. // Test get worksheet index of spreadsheet by given worksheet name.
  141. f.GetSheetIndex("Sheet1")
  142. // Test get worksheet name of spreadsheet by given invalid worksheet index.
  143. f.GetSheetName(4)
  144. // Test get worksheet map of workbook.
  145. f.GetSheetMap()
  146. for i := 1; i <= 300; i++ {
  147. assert.NoError(t, f.SetCellStr("Sheet2", "c"+strconv.Itoa(i), strconv.Itoa(i)))
  148. }
  149. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestOpenFile.xlsx")))
  150. assert.EqualError(t, f.SaveAs(filepath.Join("test", strings.Repeat("c", 199), ".xlsx")), "file name length exceeds maximum limit")
  151. }
  152. func TestSaveFile(t *testing.T) {
  153. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  154. if !assert.NoError(t, err) {
  155. t.FailNow()
  156. }
  157. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSaveFile.xlsx")))
  158. f, err = OpenFile(filepath.Join("test", "TestSaveFile.xlsx"))
  159. if !assert.NoError(t, err) {
  160. t.FailNow()
  161. }
  162. assert.NoError(t, f.Save())
  163. }
  164. func TestSaveAsWrongPath(t *testing.T) {
  165. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  166. if assert.NoError(t, err) {
  167. // Test write file to not exist directory.
  168. err = f.SaveAs("")
  169. if assert.Error(t, err) {
  170. assert.True(t, os.IsNotExist(err), "Error: %v: Expected os.IsNotExists(err) == true", err)
  171. }
  172. }
  173. }
  174. func TestCharsetTranscoder(t *testing.T) {
  175. f := NewFile()
  176. f.CharsetTranscoder(*new(charsetTranscoderFn))
  177. }
  178. func TestOpenReader(t *testing.T) {
  179. _, err := OpenReader(strings.NewReader(""))
  180. assert.EqualError(t, err, "zip: not a valid zip file")
  181. _, err = OpenReader(bytes.NewReader(cryptoIdentifier))
  182. assert.EqualError(t, err, "decrypted file failed")
  183. f, err := OpenFile(filepath.Join("test", "encryptSHA1.xlsx"), Options{Password: "password"})
  184. assert.NoError(t, err)
  185. val, err := f.GetCellValue("Sheet1", "A1")
  186. assert.NoError(t, err)
  187. assert.Equal(t, "SECRET", val)
  188. // Test unexpected EOF.
  189. var b bytes.Buffer
  190. w := gzip.NewWriter(&b)
  191. defer w.Close()
  192. w.Flush()
  193. r, _ := gzip.NewReader(&b)
  194. defer r.Close()
  195. _, err = OpenReader(r)
  196. assert.EqualError(t, err, "unexpected EOF")
  197. _, err = OpenReader(bytes.NewReader([]byte{
  198. 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x09, 0x00, 0x63, 0x00, 0x47, 0xa3, 0xb6, 0x50, 0x00, 0x00,
  199. 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x70, 0x61,
  200. 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x01, 0x99, 0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00,
  201. 0x00, 0x21, 0x06, 0x59, 0xc0, 0x12, 0xf3, 0x19, 0xc7, 0x51, 0xd1, 0xc9, 0x31, 0xcb, 0xcc, 0x8a,
  202. 0xe1, 0x44, 0xe1, 0x56, 0x20, 0x24, 0x1f, 0xba, 0x09, 0xda, 0x53, 0xd5, 0xef, 0x50, 0x4b, 0x07,
  203. 0x08, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x01,
  204. 0x02, 0x1f, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x63, 0x00, 0x47, 0xa3, 0xb6, 0x50, 0x00, 0x00, 0x00,
  205. 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00,
  206. 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x73, 0x73, 0x77,
  207. 0x6f, 0x72, 0x64, 0x01, 0x99, 0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00, 0x50, 0x4b,
  208. 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00, 0x5d, 0x00,
  209. 0x00, 0x00, 0x00, 0x00,
  210. }))
  211. assert.EqualError(t, err, "zip: unsupported compression algorithm")
  212. }
  213. func TestBrokenFile(t *testing.T) {
  214. // Test write file with broken file struct.
  215. f := File{}
  216. t.Run("SaveWithoutName", func(t *testing.T) {
  217. assert.EqualError(t, f.Save(), "no path defined for file, consider File.WriteTo or File.Write")
  218. })
  219. t.Run("SaveAsEmptyStruct", func(t *testing.T) {
  220. // Test write file with broken file struct with given path.
  221. assert.NoError(t, f.SaveAs(filepath.Join("test", "BrokenFile.SaveAsEmptyStruct.xlsx")))
  222. })
  223. t.Run("OpenBadWorkbook", func(t *testing.T) {
  224. // Test set active sheet without BookViews and Sheets maps in xl/workbook.xml.
  225. f3, err := OpenFile(filepath.Join("test", "BadWorkbook.xlsx"))
  226. f3.GetActiveSheetIndex()
  227. f3.SetActiveSheet(1)
  228. assert.NoError(t, err)
  229. })
  230. t.Run("OpenNotExistsFile", func(t *testing.T) {
  231. // Test open a spreadsheet file with given illegal path.
  232. _, err := OpenFile(filepath.Join("test", "NotExistsFile.xlsx"))
  233. if assert.Error(t, err) {
  234. assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
  235. }
  236. })
  237. }
  238. func TestNewFile(t *testing.T) {
  239. // Test create a spreadsheet file.
  240. f := NewFile()
  241. f.NewSheet("Sheet1")
  242. f.NewSheet("XLSXSheet2")
  243. f.NewSheet("XLSXSheet3")
  244. assert.NoError(t, f.SetCellInt("XLSXSheet2", "A23", 56))
  245. assert.NoError(t, f.SetCellStr("Sheet1", "B20", "42"))
  246. f.SetActiveSheet(0)
  247. // Test add picture to sheet with scaling and positioning.
  248. err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
  249. `{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
  250. if !assert.NoError(t, err) {
  251. t.FailNow()
  252. }
  253. // Test add picture to worksheet without formatset.
  254. err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
  255. if !assert.NoError(t, err) {
  256. t.FailNow()
  257. }
  258. // Test add picture to worksheet with invalid formatset.
  259. err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), `{`)
  260. if !assert.Error(t, err) {
  261. t.FailNow()
  262. }
  263. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewFile.xlsx")))
  264. }
  265. func TestAddDrawingVML(t *testing.T) {
  266. // Test addDrawingVML with illegal cell coordinates.
  267. f := NewFile()
  268. assert.EqualError(t, f.addDrawingVML(0, "", "*", 0, 0), `cannot convert cell "*" to coordinates: invalid cell name "*"`)
  269. }
  270. func TestSetCellHyperLink(t *testing.T) {
  271. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  272. if err != nil {
  273. t.Log(err)
  274. }
  275. // Test set cell hyperlink in a work sheet already have hyperlinks.
  276. assert.NoError(t, f.SetCellHyperLink("Sheet1", "B19", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
  277. // Test add first hyperlink in a work sheet.
  278. assert.NoError(t, f.SetCellHyperLink("Sheet2", "C1", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
  279. // Test add Location hyperlink in a work sheet.
  280. assert.NoError(t, f.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
  281. assert.EqualError(t, f.SetCellHyperLink("Sheet2", "C3", "Sheet1!D8", ""), `invalid link type ""`)
  282. assert.EqualError(t, f.SetCellHyperLink("Sheet2", "", "Sheet1!D60", "Location"), `invalid cell name ""`)
  283. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx")))
  284. f = NewFile()
  285. _, err = f.workSheetReader("Sheet1")
  286. assert.NoError(t, err)
  287. f.Sheet["xl/worksheets/sheet1.xml"].Hyperlinks = &xlsxHyperlinks{Hyperlink: make([]xlsxHyperlink, 65530)}
  288. assert.EqualError(t, f.SetCellHyperLink("Sheet1", "A65531", "https://github.com/360EntSecGroup-Skylar/excelize", "External"), "over maximum limit hyperlinks in a worksheet")
  289. f = NewFile()
  290. _, err = f.workSheetReader("Sheet1")
  291. assert.NoError(t, err)
  292. f.Sheet["xl/worksheets/sheet1.xml"].MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
  293. err = f.SetCellHyperLink("Sheet1", "A1", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
  294. assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  295. }
  296. func TestGetCellHyperLink(t *testing.T) {
  297. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  298. if !assert.NoError(t, err) {
  299. t.FailNow()
  300. }
  301. _, _, err = f.GetCellHyperLink("Sheet1", "")
  302. assert.EqualError(t, err, `invalid cell name ""`)
  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")
  310. assert.EqualError(t, err, "sheet Sheet3 is not exist")
  311. t.Log(link, target)
  312. f = NewFile()
  313. _, err = f.workSheetReader("Sheet1")
  314. assert.NoError(t, err)
  315. f.Sheet["xl/worksheets/sheet1.xml"].Hyperlinks = &xlsxHyperlinks{
  316. Hyperlink: []xlsxHyperlink{{Ref: "A1"}},
  317. }
  318. link, target, err = f.GetCellHyperLink("Sheet1", "A1")
  319. assert.NoError(t, err)
  320. assert.Equal(t, link, true)
  321. assert.Equal(t, target, "")
  322. f.Sheet["xl/worksheets/sheet1.xml"].MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:A"}}}
  323. link, target, err = f.GetCellHyperLink("Sheet1", "A1")
  324. assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  325. assert.Equal(t, link, false)
  326. assert.Equal(t, target, "")
  327. }
  328. func TestSetCellFormula(t *testing.T) {
  329. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  330. if !assert.NoError(t, err) {
  331. t.FailNow()
  332. }
  333. assert.NoError(t, f.SetCellFormula("Sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)"))
  334. assert.NoError(t, f.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)"))
  335. // Test set cell formula with illegal rows number.
  336. assert.EqualError(t, f.SetCellFormula("Sheet1", "C", "SUM(Sheet2!D2,Sheet2!D9)"), `cannot convert cell "C" to coordinates: invalid cell name "C"`)
  337. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula1.xlsx")))
  338. f, err = OpenFile(filepath.Join("test", "CalcChain.xlsx"))
  339. if !assert.NoError(t, err) {
  340. t.FailNow()
  341. }
  342. // Test remove cell formula.
  343. assert.NoError(t, f.SetCellFormula("Sheet1", "A1", ""))
  344. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula2.xlsx")))
  345. // Test remove all cell formula.
  346. assert.NoError(t, f.SetCellFormula("Sheet1", "B1", ""))
  347. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellFormula3.xlsx")))
  348. }
  349. func TestSetSheetBackground(t *testing.T) {
  350. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  351. if !assert.NoError(t, err) {
  352. t.FailNow()
  353. }
  354. err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
  355. if !assert.NoError(t, err) {
  356. t.FailNow()
  357. }
  358. err = f.SetSheetBackground("Sheet2", filepath.Join("test", "images", "background.jpg"))
  359. if !assert.NoError(t, err) {
  360. t.FailNow()
  361. }
  362. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetBackground.xlsx")))
  363. }
  364. func TestSetSheetBackgroundErrors(t *testing.T) {
  365. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  366. if !assert.NoError(t, err) {
  367. t.FailNow()
  368. }
  369. err = f.SetSheetBackground("Sheet2", filepath.Join("test", "not_exists", "not_exists.png"))
  370. if assert.Error(t, err) {
  371. assert.True(t, os.IsNotExist(err), "Expected os.IsNotExists(err) == true")
  372. }
  373. err = f.SetSheetBackground("Sheet2", filepath.Join("test", "Book1.xlsx"))
  374. assert.EqualError(t, err, "unsupported image extension")
  375. }
  376. // TestWriteArrayFormula tests the extended options of SetCellFormula by writing an array function
  377. // to a workbook. In the resulting file, the lines 2 and 3 as well as 4 and 5 should have matching
  378. // contents.
  379. func TestWriteArrayFormula(t *testing.T) {
  380. cell := func(col, row int) string {
  381. c, err := CoordinatesToCellName(col, row)
  382. if err != nil {
  383. t.Fatal(err)
  384. }
  385. return c
  386. }
  387. f := NewFile()
  388. sample := []string{"Sample 1", "Sample 2", "Sample 3"}
  389. 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}
  390. 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}
  391. if len(values) != len(assoc) {
  392. t.Fatal("values and assoc must be of same length")
  393. }
  394. // Average calculates the average of the n-th sample (0 <= n < len(sample)).
  395. average := func(n int) int {
  396. sum := 0
  397. count := 0
  398. for i := 0; i != len(values); i++ {
  399. if assoc[i] == n {
  400. sum += values[i]
  401. count++
  402. }
  403. }
  404. return int(math.Round(float64(sum) / float64(count)))
  405. }
  406. // Stdev calculates the standard deviation of the n-th sample (0 <= n < len(sample)).
  407. stdev := func(n int) int {
  408. avg := average(n)
  409. sum := 0
  410. count := 0
  411. for i := 0; i != len(values); i++ {
  412. if assoc[i] == n {
  413. sum += (values[i] - avg) * (values[i] - avg)
  414. count++
  415. }
  416. }
  417. return int(math.Round(math.Sqrt(float64(sum) / float64(count))))
  418. }
  419. // Line 2 contains the results of AVERAGEIF
  420. assert.NoError(t, f.SetCellStr("Sheet1", "A2", "Average"))
  421. // Line 3 contains the average that was calculated in Go
  422. assert.NoError(t, f.SetCellStr("Sheet1", "A3", "Average (calculated)"))
  423. // Line 4 contains the results of the array function that calculates the standard deviation
  424. assert.NoError(t, f.SetCellStr("Sheet1", "A4", "Std. deviation"))
  425. // Line 5 contains the standard deviations calculated in Go
  426. assert.NoError(t, f.SetCellStr("Sheet1", "A5", "Std. deviation (calculated)"))
  427. assert.NoError(t, f.SetCellStr("Sheet1", "B1", sample[0]))
  428. assert.NoError(t, f.SetCellStr("Sheet1", "C1", sample[1]))
  429. assert.NoError(t, f.SetCellStr("Sheet1", "D1", sample[2]))
  430. firstResLine := 8
  431. assert.NoError(t, f.SetCellStr("Sheet1", cell(1, firstResLine-1), "Result Values"))
  432. assert.NoError(t, f.SetCellStr("Sheet1", cell(2, firstResLine-1), "Sample"))
  433. for i := 0; i != len(values); i++ {
  434. valCell := cell(1, i+firstResLine)
  435. assocCell := cell(2, i+firstResLine)
  436. assert.NoError(t, f.SetCellInt("Sheet1", valCell, values[i]))
  437. assert.NoError(t, f.SetCellStr("Sheet1", assocCell, sample[assoc[i]]))
  438. }
  439. valRange := fmt.Sprintf("$A$%d:$A$%d", firstResLine, len(values)+firstResLine-1)
  440. assocRange := fmt.Sprintf("$B$%d:$B$%d", firstResLine, len(values)+firstResLine-1)
  441. for i := 0; i != len(sample); i++ {
  442. nameCell := cell(i+2, 1)
  443. avgCell := cell(i+2, 2)
  444. calcAvgCell := cell(i+2, 3)
  445. stdevCell := cell(i+2, 4)
  446. calcStdevCell := cell(i+2, 5)
  447. assert.NoError(t, f.SetCellInt("Sheet1", calcAvgCell, average(i)))
  448. assert.NoError(t, f.SetCellInt("Sheet1", calcStdevCell, stdev(i)))
  449. // Average can be done with AVERAGEIF
  450. assert.NoError(t, f.SetCellFormula("Sheet1", avgCell, fmt.Sprintf("ROUND(AVERAGEIF(%s,%s,%s),0)", assocRange, nameCell, valRange)))
  451. ref := stdevCell + ":" + stdevCell
  452. t := STCellFormulaTypeArray
  453. // Use an array formula for standard deviation
  454. f.SetCellFormula("Sheet1", stdevCell, fmt.Sprintf("ROUND(STDEVP(IF(%s=%s,%s)),0)", assocRange, nameCell, valRange),
  455. FormulaOpts{}, FormulaOpts{Type: &t}, FormulaOpts{Ref: &ref})
  456. }
  457. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestWriteArrayFormula.xlsx")))
  458. }
  459. func TestSetCellStyleAlignment(t *testing.T) {
  460. f, err := prepareTestBook1()
  461. if !assert.NoError(t, err) {
  462. t.FailNow()
  463. }
  464. var style int
  465. 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}}`)
  466. if !assert.NoError(t, err) {
  467. t.FailNow()
  468. }
  469. assert.NoError(t, f.SetCellStyle("Sheet1", "A22", "A22", style))
  470. // Test set cell style with given illegal rows number.
  471. assert.EqualError(t, f.SetCellStyle("Sheet1", "A", "A22", style), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  472. assert.EqualError(t, f.SetCellStyle("Sheet1", "A22", "A", style), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  473. // Test get cell style with given illegal rows number.
  474. index, err := f.GetCellStyle("Sheet1", "A")
  475. assert.Equal(t, 0, index)
  476. assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  477. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleAlignment.xlsx")))
  478. }
  479. func TestSetCellStyleBorder(t *testing.T) {
  480. f, err := prepareTestBook1()
  481. if !assert.NoError(t, err) {
  482. t.FailNow()
  483. }
  484. var style int
  485. // Test set border on overlapping area with vertical variants shading styles gradient fill.
  486. 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}]}`)
  487. if !assert.NoError(t, err) {
  488. t.FailNow()
  489. }
  490. assert.NoError(t, f.SetCellStyle("Sheet1", "J21", "L25", style))
  491. 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}}`)
  492. if !assert.NoError(t, err) {
  493. t.FailNow()
  494. }
  495. assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
  496. 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}}`)
  497. if !assert.NoError(t, err) {
  498. t.FailNow()
  499. }
  500. assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
  501. // Test set border and solid style pattern fill for a single cell.
  502. style, err = f.NewStyle(&Style{
  503. Border: []Border{
  504. {
  505. Type: "left",
  506. Color: "0000FF",
  507. Style: 8,
  508. },
  509. {
  510. Type: "top",
  511. Color: "00FF00",
  512. Style: 9,
  513. },
  514. {
  515. Type: "bottom",
  516. Color: "FFFF00",
  517. Style: 10,
  518. },
  519. {
  520. Type: "right",
  521. Color: "FF0000",
  522. Style: 11,
  523. },
  524. {
  525. Type: "diagonalDown",
  526. Color: "A020F0",
  527. Style: 12,
  528. },
  529. {
  530. Type: "diagonalUp",
  531. Color: "A020F0",
  532. Style: 13,
  533. },
  534. },
  535. Fill: Fill{
  536. Type: "pattern",
  537. Color: []string{"#E0EBF5"},
  538. Pattern: 1,
  539. },
  540. })
  541. if !assert.NoError(t, err) {
  542. t.FailNow()
  543. }
  544. assert.NoError(t, f.SetCellStyle("Sheet1", "O22", "O22", style))
  545. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleBorder.xlsx")))
  546. }
  547. func TestSetCellStyleBorderErrors(t *testing.T) {
  548. f, err := prepareTestBook1()
  549. if !assert.NoError(t, err) {
  550. t.FailNow()
  551. }
  552. // Set border with invalid style parameter.
  553. _, err = f.NewStyle("")
  554. if !assert.EqualError(t, err, "unexpected end of JSON input") {
  555. t.FailNow()
  556. }
  557. // Set border with invalid style index number.
  558. _, 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}]}`)
  559. if !assert.NoError(t, err) {
  560. t.FailNow()
  561. }
  562. }
  563. func TestSetCellStyleNumberFormat(t *testing.T) {
  564. f, err := prepareTestBook1()
  565. if !assert.NoError(t, err) {
  566. t.FailNow()
  567. }
  568. // Test only set fill and number format for a cell.
  569. col := []string{"L", "M", "N", "O", "P"}
  570. 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}
  571. value := []string{"37947.7500001", "-37947.7500001", "0.007", "2.1", "String"}
  572. for i, v := range value {
  573. for k, d := range data {
  574. c := col[i] + strconv.Itoa(k+1)
  575. var val float64
  576. val, err = strconv.ParseFloat(v, 64)
  577. if err != nil {
  578. assert.NoError(t, f.SetCellValue("Sheet2", c, v))
  579. } else {
  580. assert.NoError(t, f.SetCellValue("Sheet2", c, val))
  581. }
  582. style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format": ` + strconv.Itoa(d) + `}`)
  583. if !assert.NoError(t, err) {
  584. t.FailNow()
  585. }
  586. assert.NoError(t, f.SetCellStyle("Sheet2", c, c, style))
  587. t.Log(f.GetCellValue("Sheet2", c))
  588. }
  589. }
  590. var style int
  591. style, err = f.NewStyle(`{"number_format":-1}`)
  592. if !assert.NoError(t, err) {
  593. t.FailNow()
  594. }
  595. assert.NoError(t, f.SetCellStyle("Sheet2", "L33", "L33", style))
  596. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleNumberFormat.xlsx")))
  597. }
  598. func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
  599. t.Run("TestBook3", func(t *testing.T) {
  600. f, err := prepareTestBook3()
  601. if !assert.NoError(t, err) {
  602. t.FailNow()
  603. }
  604. assert.NoError(t, f.SetCellValue("Sheet1", "A1", 56))
  605. assert.NoError(t, f.SetCellValue("Sheet1", "A2", -32.3))
  606. var style int
  607. style, err = f.NewStyle(`{"number_format": 188, "decimal_places": -1}`)
  608. if !assert.NoError(t, err) {
  609. t.FailNow()
  610. }
  611. assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
  612. style, err = f.NewStyle(`{"number_format": 188, "decimal_places": 31, "negred": true}`)
  613. if !assert.NoError(t, err) {
  614. t.FailNow()
  615. }
  616. assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
  617. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook3.xlsx")))
  618. })
  619. t.Run("TestBook4", func(t *testing.T) {
  620. f, err := prepareTestBook4()
  621. if !assert.NoError(t, err) {
  622. t.FailNow()
  623. }
  624. assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5))
  625. assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5))
  626. _, err = f.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`)
  627. if !assert.NoError(t, err) {
  628. t.FailNow()
  629. }
  630. style, err := f.NewStyle(`{"number_format": 27}`)
  631. if !assert.NoError(t, err) {
  632. t.FailNow()
  633. }
  634. assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
  635. style, err = f.NewStyle(`{"number_format": 31, "lang": "ko-kr"}`)
  636. if !assert.NoError(t, err) {
  637. t.FailNow()
  638. }
  639. assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
  640. style, err = f.NewStyle(`{"number_format": 71, "lang": "th-th"}`)
  641. if !assert.NoError(t, err) {
  642. t.FailNow()
  643. }
  644. assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
  645. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook4.xlsx")))
  646. })
  647. }
  648. func TestSetCellStyleCustomNumberFormat(t *testing.T) {
  649. f := NewFile()
  650. assert.NoError(t, f.SetCellValue("Sheet1", "A1", 42920.5))
  651. assert.NoError(t, f.SetCellValue("Sheet1", "A2", 42920.5))
  652. style, err := f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
  653. assert.NoError(t, err)
  654. assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
  655. style, err = f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@","font":{"color":"#9A0511"}}`)
  656. assert.NoError(t, err)
  657. assert.NoError(t, f.SetCellStyle("Sheet1", "A2", "A2", style))
  658. _, err = f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yy;@"}`)
  659. assert.NoError(t, err)
  660. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleCustomNumberFormat.xlsx")))
  661. }
  662. func TestSetCellStyleFill(t *testing.T) {
  663. f, err := prepareTestBook1()
  664. if !assert.NoError(t, err) {
  665. t.FailNow()
  666. }
  667. var style int
  668. // Test set fill for cell with invalid parameter.
  669. style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":6}}`)
  670. assert.NoError(t, err)
  671. assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
  672. style, err = f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF"],"shading":1}}`)
  673. assert.NoError(t, err)
  674. assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
  675. style, err = f.NewStyle(`{"fill":{"type":"pattern","color":[],"pattern":1}}`)
  676. assert.NoError(t, err)
  677. assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
  678. style, err = f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":19}}`)
  679. if !assert.NoError(t, err) {
  680. t.FailNow()
  681. }
  682. assert.NoError(t, f.SetCellStyle("Sheet1", "O23", "O23", style))
  683. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFill.xlsx")))
  684. }
  685. func TestSetCellStyleFont(t *testing.T) {
  686. f, err := prepareTestBook1()
  687. if !assert.NoError(t, err) {
  688. t.FailNow()
  689. }
  690. var style int
  691. style, err = f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777","underline":"single"}}`)
  692. if !assert.NoError(t, err) {
  693. t.FailNow()
  694. }
  695. assert.NoError(t, f.SetCellStyle("Sheet2", "A1", "A1", style))
  696. style, err = f.NewStyle(`{"font":{"italic":true,"underline":"double"}}`)
  697. if !assert.NoError(t, err) {
  698. t.FailNow()
  699. }
  700. assert.NoError(t, f.SetCellStyle("Sheet2", "A2", "A2", style))
  701. style, err = f.NewStyle(`{"font":{"bold":true}}`)
  702. if !assert.NoError(t, err) {
  703. t.FailNow()
  704. }
  705. assert.NoError(t, f.SetCellStyle("Sheet2", "A3", "A3", style))
  706. style, err = f.NewStyle(`{"font":{"bold":true,"family":"","size":0,"color":"","underline":""}}`)
  707. if !assert.NoError(t, err) {
  708. t.FailNow()
  709. }
  710. assert.NoError(t, f.SetCellStyle("Sheet2", "A4", "A4", style))
  711. style, err = f.NewStyle(`{"font":{"color":"#777777","strike":true}}`)
  712. if !assert.NoError(t, err) {
  713. t.FailNow()
  714. }
  715. assert.NoError(t, f.SetCellStyle("Sheet2", "A5", "A5", style))
  716. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellStyleFont.xlsx")))
  717. }
  718. func TestSetCellStyleProtection(t *testing.T) {
  719. f, err := prepareTestBook1()
  720. if !assert.NoError(t, err) {
  721. t.FailNow()
  722. }
  723. var style int
  724. style, err = f.NewStyle(`{"protection":{"hidden":true, "locked":true}}`)
  725. if !assert.NoError(t, err) {
  726. t.FailNow()
  727. }
  728. assert.NoError(t, f.SetCellStyle("Sheet2", "A6", "A6", style))
  729. err = f.SaveAs(filepath.Join("test", "TestSetCellStyleProtection.xlsx"))
  730. if !assert.NoError(t, err) {
  731. t.FailNow()
  732. }
  733. }
  734. func TestSetDeleteSheet(t *testing.T) {
  735. t.Run("TestBook3", func(t *testing.T) {
  736. f, err := prepareTestBook3()
  737. if !assert.NoError(t, err) {
  738. t.FailNow()
  739. }
  740. f.DeleteSheet("XLSXSheet3")
  741. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook3.xlsx")))
  742. })
  743. t.Run("TestBook4", func(t *testing.T) {
  744. f, err := prepareTestBook4()
  745. if !assert.NoError(t, err) {
  746. t.FailNow()
  747. }
  748. f.DeleteSheet("Sheet1")
  749. assert.EqualError(t, f.AddComment("Sheet1", "A1", ""), "unexpected end of JSON input")
  750. assert.NoError(t, f.AddComment("Sheet1", "A1", `{"author":"Excelize: ","text":"This is a comment."}`))
  751. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetDeleteSheet.TestBook4.xlsx")))
  752. })
  753. }
  754. func TestSheetVisibility(t *testing.T) {
  755. f, err := prepareTestBook1()
  756. if !assert.NoError(t, err) {
  757. t.FailNow()
  758. }
  759. assert.NoError(t, f.SetSheetVisible("Sheet2", false))
  760. assert.NoError(t, f.SetSheetVisible("Sheet1", false))
  761. assert.NoError(t, f.SetSheetVisible("Sheet1", true))
  762. assert.Equal(t, true, f.GetSheetVisible("Sheet1"))
  763. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSheetVisibility.xlsx")))
  764. }
  765. func TestCopySheet(t *testing.T) {
  766. f, err := prepareTestBook1()
  767. if !assert.NoError(t, err) {
  768. t.FailNow()
  769. }
  770. idx := f.NewSheet("CopySheet")
  771. assert.NoError(t, f.CopySheet(0, idx))
  772. assert.NoError(t, f.SetCellValue("CopySheet", "F1", "Hello"))
  773. val, err := f.GetCellValue("Sheet1", "F1")
  774. assert.NoError(t, err)
  775. assert.NotEqual(t, "Hello", val)
  776. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheet.xlsx")))
  777. }
  778. func TestCopySheetError(t *testing.T) {
  779. f, err := prepareTestBook1()
  780. if !assert.NoError(t, err) {
  781. t.FailNow()
  782. }
  783. assert.EqualError(t, f.copySheet(-1, -2), "sheet is not exist")
  784. if !assert.EqualError(t, f.CopySheet(-1, -2), "invalid worksheet index") {
  785. t.FailNow()
  786. }
  787. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestCopySheetError.xlsx")))
  788. }
  789. func TestGetSheetComments(t *testing.T) {
  790. f := NewFile()
  791. assert.Equal(t, "", f.getSheetComments("sheet0"))
  792. }
  793. func TestSetActiveSheet(t *testing.T) {
  794. f := NewFile()
  795. f.WorkBook.BookViews = nil
  796. f.SetActiveSheet(1)
  797. f.WorkBook.BookViews = &xlsxBookViews{WorkBookView: []xlsxWorkBookView{}}
  798. f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = &xlsxSheetViews{SheetView: []xlsxSheetView{}}
  799. f.SetActiveSheet(1)
  800. f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = nil
  801. f.SetActiveSheet(1)
  802. }
  803. func TestSetSheetVisible(t *testing.T) {
  804. f := NewFile()
  805. f.WorkBook.Sheets.Sheet[0].Name = "SheetN"
  806. assert.EqualError(t, f.SetSheetVisible("Sheet1", false), "sheet SheetN is not exist")
  807. }
  808. func TestGetActiveSheetIndex(t *testing.T) {
  809. f := NewFile()
  810. f.WorkBook.BookViews = nil
  811. assert.Equal(t, 0, f.GetActiveSheetIndex())
  812. }
  813. func TestRelsWriter(t *testing.T) {
  814. f := NewFile()
  815. f.Relationships["xl/worksheets/sheet/rels/sheet1.xml.rel"] = &xlsxRelationships{}
  816. f.relsWriter()
  817. }
  818. func TestGetSheetView(t *testing.T) {
  819. f := NewFile()
  820. _, err := f.getSheetView("SheetN", 0)
  821. assert.EqualError(t, err, "sheet SheetN is not exist")
  822. }
  823. func TestConditionalFormat(t *testing.T) {
  824. f := NewFile()
  825. sheet1 := f.GetSheetName(0)
  826. fillCells(f, sheet1, 10, 15)
  827. var format1, format2, format3, format4 int
  828. var err error
  829. // Rose format for bad conditional.
  830. format1, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
  831. if !assert.NoError(t, err) {
  832. t.FailNow()
  833. }
  834. // Light yellow format for neutral conditional.
  835. format2, err = f.NewConditionalStyle(`{"fill":{"type":"pattern","color":["#FEEAA0"],"pattern":1}}`)
  836. if !assert.NoError(t, err) {
  837. t.FailNow()
  838. }
  839. // Light green format for good conditional.
  840. format3, err = f.NewConditionalStyle(`{"font":{"color":"#09600B"},"fill":{"type":"pattern","color":["#C7EECF"],"pattern":1}}`)
  841. if !assert.NoError(t, err) {
  842. t.FailNow()
  843. }
  844. // conditional style with align and left border.
  845. format4, err = f.NewConditionalStyle(`{"alignment":{"wrap_text":true},"border":[{"type":"left","color":"#000000","style":1}]}`)
  846. if !assert.NoError(t, err) {
  847. t.FailNow()
  848. }
  849. // Color scales: 2 color.
  850. 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"}]`))
  851. // Color scales: 3 color.
  852. 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"}]`))
  853. // Hightlight cells rules: between...
  854. assert.NoError(t, f.SetConditionalFormat(sheet1, "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1)))
  855. // Hightlight cells rules: Greater Than...
  856. assert.NoError(t, f.SetConditionalFormat(sheet1, "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format3)))
  857. // Hightlight cells rules: Equal To...
  858. assert.NoError(t, f.SetConditionalFormat(sheet1, "E1:E10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d}]`, format3)))
  859. // Hightlight cells rules: Not Equal To...
  860. assert.NoError(t, f.SetConditionalFormat(sheet1, "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format2)))
  861. // Hightlight cells rules: Duplicate Values...
  862. assert.NoError(t, f.SetConditionalFormat(sheet1, "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format2)))
  863. // Top/Bottom rules: Top 10%.
  864. assert.NoError(t, f.SetConditionalFormat(sheet1, "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1)))
  865. // Top/Bottom rules: Above Average...
  866. assert.NoError(t, f.SetConditionalFormat(sheet1, "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format3)))
  867. // Top/Bottom rules: Below Average...
  868. assert.NoError(t, f.SetConditionalFormat(sheet1, "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format1)))
  869. // Data Bars: Gradient Fill.
  870. assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
  871. // Use a formula to determine which cells to format.
  872. assert.NoError(t, f.SetConditionalFormat(sheet1, "L1:L10", fmt.Sprintf(`[{"type":"formula", "criteria":"L2<3", "format":%d}]`, format1)))
  873. // Alignment/Border cells rules.
  874. assert.NoError(t, f.SetConditionalFormat(sheet1, "M1:M10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"0"}]`, format4)))
  875. // Test set invalid format set in conditional format.
  876. assert.EqualError(t, f.SetConditionalFormat(sheet1, "L1:L10", ""), "unexpected end of JSON input")
  877. // Set conditional format on not exists worksheet.
  878. assert.EqualError(t, f.SetConditionalFormat("SheetN", "L1:L10", "[]"), "sheet SheetN is not exist")
  879. err = f.SaveAs(filepath.Join("test", "TestConditionalFormat.xlsx"))
  880. if !assert.NoError(t, err) {
  881. t.FailNow()
  882. }
  883. // Set conditional format with illegal valid type.
  884. assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
  885. // Set conditional format with illegal criteria type.
  886. assert.NoError(t, f.SetConditionalFormat(sheet1, "K1:K10", `[{"type":"data_bar", "criteria":"", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`))
  887. // Set conditional format with file without dxfs element shold not return error.
  888. f, err = OpenFile(filepath.Join("test", "Book1.xlsx"))
  889. if !assert.NoError(t, err) {
  890. t.FailNow()
  891. }
  892. _, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
  893. if !assert.NoError(t, err) {
  894. t.FailNow()
  895. }
  896. }
  897. func TestConditionalFormatError(t *testing.T) {
  898. f := NewFile()
  899. sheet1 := f.GetSheetName(0)
  900. fillCells(f, sheet1, 10, 15)
  901. // Set conditional format with illegal JSON string should return error.
  902. _, err := f.NewConditionalStyle("")
  903. if !assert.EqualError(t, err, "unexpected end of JSON input") {
  904. t.FailNow()
  905. }
  906. }
  907. func TestSharedStrings(t *testing.T) {
  908. f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
  909. if !assert.NoError(t, err) {
  910. t.FailNow()
  911. }
  912. rows, err := f.GetRows("Sheet1")
  913. if !assert.NoError(t, err) {
  914. t.FailNow()
  915. }
  916. assert.Equal(t, "A", rows[0][0])
  917. rows, err = f.GetRows("Sheet2")
  918. if !assert.NoError(t, err) {
  919. t.FailNow()
  920. }
  921. assert.Equal(t, "Test Weight (Kgs)", rows[0][0])
  922. }
  923. func TestSetSheetRow(t *testing.T) {
  924. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  925. if !assert.NoError(t, err) {
  926. t.FailNow()
  927. }
  928. assert.NoError(t, f.SetSheetRow("Sheet1", "B27", &[]interface{}{"cell", nil, int32(42), float64(42), time.Now().UTC()}))
  929. assert.EqualError(t, f.SetSheetRow("Sheet1", "", &[]interface{}{"cell", nil, 2}),
  930. `cannot convert cell "" to coordinates: invalid cell name ""`)
  931. assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", []interface{}{}), `pointer to slice expected`)
  932. assert.EqualError(t, f.SetSheetRow("Sheet1", "B27", &f), `pointer to slice expected`)
  933. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetSheetRow.xlsx")))
  934. }
  935. func TestThemeColor(t *testing.T) {
  936. t.Log(ThemeColor("000000", -0.1))
  937. t.Log(ThemeColor("000000", 0))
  938. t.Log(ThemeColor("000000", 1))
  939. }
  940. func TestHSL(t *testing.T) {
  941. var hsl HSL
  942. t.Log(hsl.RGBA())
  943. t.Log(hslModel(hsl))
  944. t.Log(hslModel(color.Gray16{Y: uint16(1)}))
  945. t.Log(HSLToRGB(0, 1, 0.4))
  946. t.Log(HSLToRGB(0, 1, 0.6))
  947. t.Log(hueToRGB(0, 0, -1))
  948. t.Log(hueToRGB(0, 0, 2))
  949. t.Log(hueToRGB(0, 0, 1.0/7))
  950. t.Log(hueToRGB(0, 0, 0.4))
  951. t.Log(hueToRGB(0, 0, 2.0/4))
  952. t.Log(RGBToHSL(255, 255, 0))
  953. t.Log(RGBToHSL(0, 255, 255))
  954. t.Log(RGBToHSL(250, 100, 50))
  955. t.Log(RGBToHSL(50, 100, 250))
  956. t.Log(RGBToHSL(250, 50, 100))
  957. }
  958. func TestProtectSheet(t *testing.T) {
  959. f := NewFile()
  960. assert.NoError(t, f.ProtectSheet("Sheet1", nil))
  961. assert.NoError(t, f.ProtectSheet("Sheet1", &FormatSheetProtection{
  962. Password: "password",
  963. EditScenarios: false,
  964. }))
  965. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestProtectSheet.xlsx")))
  966. // Test protect not exists worksheet.
  967. assert.EqualError(t, f.ProtectSheet("SheetN", nil), "sheet SheetN is not exist")
  968. }
  969. func TestUnprotectSheet(t *testing.T) {
  970. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  971. if !assert.NoError(t, err) {
  972. t.FailNow()
  973. }
  974. // Test unprotect not exists worksheet.
  975. assert.EqualError(t, f.UnprotectSheet("SheetN"), "sheet SheetN is not exist")
  976. assert.NoError(t, f.UnprotectSheet("Sheet1"))
  977. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnprotectSheet.xlsx")))
  978. }
  979. func TestSetDefaultTimeStyle(t *testing.T) {
  980. f := NewFile()
  981. // Test set default time style on not exists worksheet.
  982. assert.EqualError(t, f.setDefaultTimeStyle("SheetN", "", 0), "sheet SheetN is not exist")
  983. }
  984. func TestAddVBAProject(t *testing.T) {
  985. f := NewFile()
  986. assert.NoError(t, f.SetSheetPrOptions("Sheet1", CodeName("Sheet1")))
  987. assert.EqualError(t, f.AddVBAProject("macros.bin"), "stat macros.bin: no such file or directory")
  988. assert.EqualError(t, f.AddVBAProject(filepath.Join("test", "Book1.xlsx")), "unsupported VBA project extension")
  989. assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
  990. // Test add VBA project twice.
  991. assert.NoError(t, f.AddVBAProject(filepath.Join("test", "vbaProject.bin")))
  992. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddVBAProject.xlsm")))
  993. }
  994. func TestContentTypesReader(t *testing.T) {
  995. // Test unsupport charset.
  996. f := NewFile()
  997. f.ContentTypes = nil
  998. f.XLSX["[Content_Types].xml"] = MacintoshCyrillicCharset
  999. f.contentTypesReader()
  1000. }
  1001. func TestWorkbookReader(t *testing.T) {
  1002. // Test unsupport charset.
  1003. f := NewFile()
  1004. f.WorkBook = nil
  1005. f.XLSX["xl/workbook.xml"] = MacintoshCyrillicCharset
  1006. f.workbookReader()
  1007. }
  1008. func TestWorkSheetReader(t *testing.T) {
  1009. // Test unsupport charset.
  1010. f := NewFile()
  1011. delete(f.Sheet, "xl/worksheets/sheet1.xml")
  1012. f.XLSX["xl/worksheets/sheet1.xml"] = MacintoshCyrillicCharset
  1013. _, err := f.workSheetReader("Sheet1")
  1014. assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
  1015. // Test on no checked worksheet.
  1016. f = NewFile()
  1017. delete(f.Sheet, "xl/worksheets/sheet1.xml")
  1018. f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData/></worksheet>`)
  1019. f.checked = nil
  1020. _, err = f.workSheetReader("Sheet1")
  1021. assert.NoError(t, err)
  1022. }
  1023. func TestRelsReader(t *testing.T) {
  1024. // Test unsupport charset.
  1025. f := NewFile()
  1026. rels := "xl/_rels/workbook.xml.rels"
  1027. f.Relationships[rels] = nil
  1028. f.XLSX[rels] = MacintoshCyrillicCharset
  1029. f.relsReader(rels)
  1030. }
  1031. func TestDeleteSheetFromWorkbookRels(t *testing.T) {
  1032. f := NewFile()
  1033. rels := "xl/_rels/workbook.xml.rels"
  1034. f.Relationships[rels] = nil
  1035. assert.Equal(t, f.deleteSheetFromWorkbookRels("rID"), "")
  1036. }
  1037. func TestAttrValToInt(t *testing.T) {
  1038. _, err := attrValToInt("r", []xml.Attr{
  1039. {Name: xml.Name{Local: "r"}, Value: "s"}})
  1040. assert.EqualError(t, err, `strconv.Atoi: parsing "s": invalid syntax`)
  1041. }
  1042. func prepareTestBook1() (*File, error) {
  1043. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  1044. if err != nil {
  1045. return nil, err
  1046. }
  1047. err = f.AddPicture("Sheet2", "I9", filepath.Join("test", "images", "excel.jpg"),
  1048. `{"x_offset": 140, "y_offset": 120, "hyperlink": "#Sheet2!D8", "hyperlink_type": "Location"}`)
  1049. if err != nil {
  1050. return nil, err
  1051. }
  1052. // Test add picture to worksheet with offset, external hyperlink and positioning.
  1053. err = f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.png"),
  1054. `{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`)
  1055. if err != nil {
  1056. return nil, err
  1057. }
  1058. file, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.jpg"))
  1059. if err != nil {
  1060. return nil, err
  1061. }
  1062. err = f.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file)
  1063. if err != nil {
  1064. return nil, err
  1065. }
  1066. return f, nil
  1067. }
  1068. func prepareTestBook3() (*File, error) {
  1069. f := NewFile()
  1070. f.NewSheet("Sheet1")
  1071. f.NewSheet("XLSXSheet2")
  1072. f.NewSheet("XLSXSheet3")
  1073. if err := f.SetCellInt("XLSXSheet2", "A23", 56); err != nil {
  1074. return nil, err
  1075. }
  1076. if err := f.SetCellStr("Sheet1", "B20", "42"); err != nil {
  1077. return nil, err
  1078. }
  1079. f.SetActiveSheet(0)
  1080. err := f.AddPicture("Sheet1", "H2", filepath.Join("test", "images", "excel.gif"),
  1081. `{"x_scale": 0.5, "y_scale": 0.5, "positioning": "absolute"}`)
  1082. if err != nil {
  1083. return nil, err
  1084. }
  1085. err = f.AddPicture("Sheet1", "C2", filepath.Join("test", "images", "excel.png"), "")
  1086. if err != nil {
  1087. return nil, err
  1088. }
  1089. return f, nil
  1090. }
  1091. func prepareTestBook4() (*File, error) {
  1092. f := NewFile()
  1093. if err := f.SetColWidth("Sheet1", "B", "A", 12); err != nil {
  1094. return f, err
  1095. }
  1096. if err := f.SetColWidth("Sheet1", "A", "B", 12); err != nil {
  1097. return f, err
  1098. }
  1099. if _, err := f.GetColWidth("Sheet1", "A"); err != nil {
  1100. return f, err
  1101. }
  1102. if _, err := f.GetColWidth("Sheet1", "C"); err != nil {
  1103. return f, err
  1104. }
  1105. return f, nil
  1106. }
  1107. func fillCells(f *File, sheet string, colCount, rowCount int) {
  1108. for col := 1; col <= colCount; col++ {
  1109. for row := 1; row <= rowCount; row++ {
  1110. cell, _ := CoordinatesToCellName(col, row)
  1111. if err := f.SetCellStr(sheet, cell, cell); err != nil {
  1112. fmt.Println(err)
  1113. }
  1114. }
  1115. }
  1116. }
  1117. func BenchmarkOpenFile(b *testing.B) {
  1118. for i := 0; i < b.N; i++ {
  1119. if _, err := OpenFile(filepath.Join("test", "Book1.xlsx")); err != nil {
  1120. b.Error(err)
  1121. }
  1122. }
  1123. }