sheet_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. package excelize
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "strconv"
  6. "strings"
  7. "testing"
  8. "github.com/mohae/deepcopy"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func ExampleFile_SetPageLayout() {
  12. f := NewFile()
  13. if err := f.SetPageLayout(
  14. "Sheet1",
  15. PageLayoutOrientation(OrientationLandscape),
  16. ); err != nil {
  17. fmt.Println(err)
  18. }
  19. if err := f.SetPageLayout(
  20. "Sheet1",
  21. PageLayoutPaperSize(10),
  22. FitToHeight(2),
  23. FitToWidth(2),
  24. PageLayoutScale(50),
  25. ); err != nil {
  26. fmt.Println(err)
  27. }
  28. // Output:
  29. }
  30. func ExampleFile_GetPageLayout() {
  31. f := NewFile()
  32. var (
  33. orientation PageLayoutOrientation
  34. paperSize PageLayoutPaperSize
  35. fitToHeight FitToHeight
  36. fitToWidth FitToWidth
  37. scale PageLayoutScale
  38. )
  39. if err := f.GetPageLayout("Sheet1", &orientation); err != nil {
  40. fmt.Println(err)
  41. }
  42. if err := f.GetPageLayout("Sheet1", &paperSize); err != nil {
  43. fmt.Println(err)
  44. }
  45. if err := f.GetPageLayout("Sheet1", &fitToHeight); err != nil {
  46. fmt.Println(err)
  47. }
  48. if err := f.GetPageLayout("Sheet1", &fitToWidth); err != nil {
  49. fmt.Println(err)
  50. }
  51. if err := f.GetPageLayout("Sheet1", &scale); err != nil {
  52. fmt.Println(err)
  53. }
  54. fmt.Println("Defaults:")
  55. fmt.Printf("- orientation: %q\n", orientation)
  56. fmt.Printf("- paper size: %d\n", paperSize)
  57. fmt.Printf("- fit to height: %d\n", fitToHeight)
  58. fmt.Printf("- fit to width: %d\n", fitToWidth)
  59. fmt.Printf("- scale: %d\n", scale)
  60. // Output:
  61. // Defaults:
  62. // - orientation: "portrait"
  63. // - paper size: 1
  64. // - fit to height: 1
  65. // - fit to width: 1
  66. // - scale: 100
  67. }
  68. func TestNewSheet(t *testing.T) {
  69. f := NewFile()
  70. sheetID := f.NewSheet("Sheet2")
  71. f.SetActiveSheet(sheetID)
  72. // delete original sheet
  73. f.DeleteSheet(f.GetSheetName(f.GetSheetIndex("Sheet1")))
  74. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestNewSheet.xlsx")))
  75. // create new worksheet with already exists name
  76. assert.Equal(t, f.GetSheetIndex("Sheet2"), f.NewSheet("Sheet2"))
  77. }
  78. func TestSetPane(t *testing.T) {
  79. f := NewFile()
  80. assert.NoError(t, f.SetPanes("Sheet1", `{"freeze":false,"split":false}`))
  81. f.NewSheet("Panes 2")
  82. assert.NoError(t, f.SetPanes("Panes 2", `{"freeze":true,"split":false,"x_split":1,"y_split":0,"top_left_cell":"B1","active_pane":"topRight","panes":[{"sqref":"K16","active_cell":"K16","pane":"topRight"}]}`))
  83. f.NewSheet("Panes 3")
  84. assert.NoError(t, f.SetPanes("Panes 3", `{"freeze":false,"split":true,"x_split":3270,"y_split":1800,"top_left_cell":"N57","active_pane":"bottomLeft","panes":[{"sqref":"I36","active_cell":"I36"},{"sqref":"G33","active_cell":"G33","pane":"topRight"},{"sqref":"J60","active_cell":"J60","pane":"bottomLeft"},{"sqref":"O60","active_cell":"O60","pane":"bottomRight"}]}`))
  85. f.NewSheet("Panes 4")
  86. assert.NoError(t, f.SetPanes("Panes 4", `{"freeze":true,"split":false,"x_split":0,"y_split":9,"top_left_cell":"A34","active_pane":"bottomLeft","panes":[{"sqref":"A11:XFD11","active_cell":"A11","pane":"bottomLeft"}]}`))
  87. assert.NoError(t, f.SetPanes("Panes 4", ""))
  88. assert.EqualError(t, f.SetPanes("SheetN", ""), "sheet SheetN is not exist")
  89. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetPane.xlsx")))
  90. }
  91. func TestPageLayoutOption(t *testing.T) {
  92. const sheet = "Sheet1"
  93. testData := []struct {
  94. container PageLayoutOptionPtr
  95. nonDefault PageLayoutOption
  96. }{
  97. {new(PageLayoutOrientation), PageLayoutOrientation(OrientationLandscape)},
  98. {new(PageLayoutPaperSize), PageLayoutPaperSize(10)},
  99. {new(FitToHeight), FitToHeight(2)},
  100. {new(FitToWidth), FitToWidth(2)},
  101. {new(PageLayoutScale), PageLayoutScale(50)},
  102. }
  103. for i, test := range testData {
  104. t.Run(fmt.Sprintf("TestData%d", i), func(t *testing.T) {
  105. opt := test.nonDefault
  106. t.Logf("option %T", opt)
  107. def := deepcopy.Copy(test.container).(PageLayoutOptionPtr)
  108. val1 := deepcopy.Copy(def).(PageLayoutOptionPtr)
  109. val2 := deepcopy.Copy(def).(PageLayoutOptionPtr)
  110. f := NewFile()
  111. // Get the default value
  112. assert.NoError(t, f.GetPageLayout(sheet, def), opt)
  113. // Get again and check
  114. assert.NoError(t, f.GetPageLayout(sheet, val1), opt)
  115. if !assert.Equal(t, val1, def, opt) {
  116. t.FailNow()
  117. }
  118. // Set the same value
  119. assert.NoError(t, f.SetPageLayout(sheet, val1), opt)
  120. // Get again and check
  121. assert.NoError(t, f.GetPageLayout(sheet, val1), opt)
  122. if !assert.Equal(t, val1, def, "%T: value should not have changed", opt) {
  123. t.FailNow()
  124. }
  125. // Set a different value
  126. assert.NoError(t, f.SetPageLayout(sheet, test.nonDefault), opt)
  127. assert.NoError(t, f.GetPageLayout(sheet, val1), opt)
  128. // Get again and compare
  129. assert.NoError(t, f.GetPageLayout(sheet, val2), opt)
  130. if !assert.Equal(t, val1, val2, "%T: value should not have changed", opt) {
  131. t.FailNow()
  132. }
  133. // Value should not be the same as the default
  134. if !assert.NotEqual(t, def, val1, "%T: value should have changed from default", opt) {
  135. t.FailNow()
  136. }
  137. // Restore the default value
  138. assert.NoError(t, f.SetPageLayout(sheet, def), opt)
  139. assert.NoError(t, f.GetPageLayout(sheet, val1), opt)
  140. if !assert.Equal(t, def, val1) {
  141. t.FailNow()
  142. }
  143. })
  144. }
  145. }
  146. func TestSearchSheet(t *testing.T) {
  147. f, err := OpenFile(filepath.Join("test", "SharedStrings.xlsx"))
  148. if !assert.NoError(t, err) {
  149. t.FailNow()
  150. }
  151. // Test search in a not exists worksheet.
  152. _, err = f.SearchSheet("Sheet4", "")
  153. assert.EqualError(t, err, "sheet Sheet4 is not exist")
  154. var expected []string
  155. // Test search a not exists value.
  156. result, err := f.SearchSheet("Sheet1", "X")
  157. assert.NoError(t, err)
  158. assert.EqualValues(t, expected, result)
  159. result, err = f.SearchSheet("Sheet1", "A")
  160. assert.NoError(t, err)
  161. assert.EqualValues(t, []string{"A1"}, result)
  162. // Test search the coordinates where the numerical value in the range of
  163. // "0-9" of Sheet1 is described by regular expression:
  164. result, err = f.SearchSheet("Sheet1", "[0-9]", true)
  165. assert.NoError(t, err)
  166. assert.EqualValues(t, expected, result)
  167. // Test search worksheet data after set cell value
  168. f = NewFile()
  169. assert.NoError(t, f.SetCellValue("Sheet1", "A1", true))
  170. _, err = f.SearchSheet("Sheet1", "")
  171. assert.NoError(t, err)
  172. }
  173. func TestSetPageLayout(t *testing.T) {
  174. f := NewFile()
  175. // Test set page layout on not exists worksheet.
  176. assert.EqualError(t, f.SetPageLayout("SheetN"), "sheet SheetN is not exist")
  177. }
  178. func TestGetPageLayout(t *testing.T) {
  179. f := NewFile()
  180. // Test get page layout on not exists worksheet.
  181. assert.EqualError(t, f.GetPageLayout("SheetN"), "sheet SheetN is not exist")
  182. }
  183. func TestSetHeaderFooter(t *testing.T) {
  184. f := NewFile()
  185. assert.NoError(t, f.SetCellStr("Sheet1", "A1", "Test SetHeaderFooter"))
  186. // Test set header and footer on not exists worksheet.
  187. assert.EqualError(t, f.SetHeaderFooter("SheetN", nil), "sheet SheetN is not exist")
  188. // Test set header and footer with illegal setting.
  189. assert.EqualError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
  190. OddHeader: strings.Repeat("c", 256),
  191. }), "field OddHeader must be less than 255 characters")
  192. assert.NoError(t, f.SetHeaderFooter("Sheet1", nil))
  193. assert.NoError(t, f.SetHeaderFooter("Sheet1", &FormatHeaderFooter{
  194. DifferentFirst: true,
  195. DifferentOddEven: true,
  196. OddHeader: "&R&P",
  197. OddFooter: "&C&F",
  198. EvenHeader: "&L&P",
  199. EvenFooter: "&L&D&R&T",
  200. FirstHeader: `&CCenter &"-,Bold"Bold&"-,Regular"HeaderU+000A&D`,
  201. }))
  202. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetHeaderFooter.xlsx")))
  203. }
  204. func TestDefinedName(t *testing.T) {
  205. f := NewFile()
  206. assert.NoError(t, f.SetDefinedName(&DefinedName{
  207. Name: "Amount",
  208. RefersTo: "Sheet1!$A$2:$D$5",
  209. Comment: "defined name comment",
  210. Scope: "Sheet1",
  211. }))
  212. assert.NoError(t, f.SetDefinedName(&DefinedName{
  213. Name: "Amount",
  214. RefersTo: "Sheet1!$A$2:$D$5",
  215. Comment: "defined name comment",
  216. }))
  217. assert.EqualError(t, f.SetDefinedName(&DefinedName{
  218. Name: "Amount",
  219. RefersTo: "Sheet1!$A$2:$D$5",
  220. Comment: "defined name comment",
  221. }), "the same name already exists on the scope")
  222. assert.EqualError(t, f.DeleteDefinedName(&DefinedName{
  223. Name: "No Exist Defined Name",
  224. }), "no defined name on the scope")
  225. assert.Exactly(t, "Sheet1!$A$2:$D$5", f.GetDefinedName()[1].RefersTo)
  226. assert.NoError(t, f.DeleteDefinedName(&DefinedName{
  227. Name: "Amount",
  228. }))
  229. assert.Exactly(t, "Sheet1!$A$2:$D$5", f.GetDefinedName()[0].RefersTo)
  230. assert.Exactly(t, 1, len(f.GetDefinedName()))
  231. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDefinedName.xlsx")))
  232. }
  233. func TestGroupSheets(t *testing.T) {
  234. f := NewFile()
  235. sheets := []string{"Sheet2", "Sheet3"}
  236. for _, sheet := range sheets {
  237. f.NewSheet(sheet)
  238. }
  239. assert.EqualError(t, f.GroupSheets([]string{"Sheet1", "SheetN"}), "sheet SheetN is not exist")
  240. assert.EqualError(t, f.GroupSheets([]string{"Sheet2", "Sheet3"}), "group worksheet must contain an active worksheet")
  241. assert.NoError(t, f.GroupSheets([]string{"Sheet1", "Sheet2"}))
  242. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestGroupSheets.xlsx")))
  243. }
  244. func TestUngroupSheets(t *testing.T) {
  245. f := NewFile()
  246. sheets := []string{"Sheet2", "Sheet3", "Sheet4", "Sheet5"}
  247. for _, sheet := range sheets {
  248. f.NewSheet(sheet)
  249. }
  250. assert.NoError(t, f.UngroupSheets())
  251. }
  252. func TestInsertPageBreak(t *testing.T) {
  253. f := NewFile()
  254. assert.NoError(t, f.InsertPageBreak("Sheet1", "A1"))
  255. assert.NoError(t, f.InsertPageBreak("Sheet1", "B2"))
  256. assert.NoError(t, f.InsertPageBreak("Sheet1", "C3"))
  257. assert.NoError(t, f.InsertPageBreak("Sheet1", "C3"))
  258. assert.EqualError(t, f.InsertPageBreak("Sheet1", "A"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  259. assert.EqualError(t, f.InsertPageBreak("SheetN", "C3"), "sheet SheetN is not exist")
  260. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertPageBreak.xlsx")))
  261. }
  262. func TestRemovePageBreak(t *testing.T) {
  263. f := NewFile()
  264. assert.NoError(t, f.RemovePageBreak("Sheet1", "A2"))
  265. assert.NoError(t, f.InsertPageBreak("Sheet1", "A2"))
  266. assert.NoError(t, f.InsertPageBreak("Sheet1", "B2"))
  267. assert.NoError(t, f.RemovePageBreak("Sheet1", "A1"))
  268. assert.NoError(t, f.RemovePageBreak("Sheet1", "B2"))
  269. assert.NoError(t, f.InsertPageBreak("Sheet1", "C3"))
  270. assert.NoError(t, f.RemovePageBreak("Sheet1", "C3"))
  271. assert.NoError(t, f.InsertPageBreak("Sheet1", "A3"))
  272. assert.NoError(t, f.RemovePageBreak("Sheet1", "B3"))
  273. assert.NoError(t, f.RemovePageBreak("Sheet1", "A3"))
  274. f.NewSheet("Sheet2")
  275. assert.NoError(t, f.InsertPageBreak("Sheet2", "B2"))
  276. assert.NoError(t, f.InsertPageBreak("Sheet2", "C2"))
  277. assert.NoError(t, f.RemovePageBreak("Sheet2", "B2"))
  278. assert.EqualError(t, f.RemovePageBreak("Sheet1", "A"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  279. assert.EqualError(t, f.RemovePageBreak("SheetN", "C3"), "sheet SheetN is not exist")
  280. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRemovePageBreak.xlsx")))
  281. }
  282. func TestGetSheetName(t *testing.T) {
  283. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  284. assert.NoError(t, err)
  285. assert.Equal(t, "Sheet1", f.GetSheetName(0))
  286. assert.Equal(t, "Sheet2", f.GetSheetName(1))
  287. assert.Equal(t, "", f.GetSheetName(-1))
  288. assert.Equal(t, "", f.GetSheetName(2))
  289. }
  290. func TestGetSheetMap(t *testing.T) {
  291. expectedMap := map[int]string{
  292. 1: "Sheet1",
  293. 2: "Sheet2",
  294. }
  295. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  296. assert.NoError(t, err)
  297. sheetMap := f.GetSheetMap()
  298. for idx, name := range sheetMap {
  299. assert.Equal(t, expectedMap[idx], name)
  300. }
  301. assert.Equal(t, len(sheetMap), 2)
  302. }
  303. func TestSetActiveSheet(t *testing.T) {
  304. f := NewFile()
  305. f.WorkBook.BookViews = nil
  306. f.SetActiveSheet(1)
  307. f.WorkBook.BookViews = &xlsxBookViews{WorkBookView: []xlsxWorkBookView{}}
  308. f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = &xlsxSheetViews{SheetView: []xlsxSheetView{}}
  309. f.SetActiveSheet(1)
  310. f.Sheet["xl/worksheets/sheet1.xml"].SheetViews = nil
  311. f.SetActiveSheet(1)
  312. f = NewFile()
  313. f.SetActiveSheet(-1)
  314. assert.Equal(t, f.GetActiveSheetIndex(), 0)
  315. }
  316. func TestSetSheetName(t *testing.T) {
  317. f := NewFile()
  318. // Test set workksheet with the same name.
  319. f.SetSheetName("Sheet1", "Sheet1")
  320. assert.Equal(t, "Sheet1", f.GetSheetName(0))
  321. }
  322. func TestGetWorkbookPath(t *testing.T) {
  323. f := NewFile()
  324. delete(f.XLSX, "_rels/.rels")
  325. assert.Equal(t, "", f.getWorkbookPath())
  326. }
  327. func TestGetWorkbookRelsPath(t *testing.T) {
  328. f := NewFile()
  329. delete(f.XLSX, "xl/_rels/.rels")
  330. f.XLSX["_rels/.rels"] = []byte(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument" Target="/workbook.xml"/></Relationships>`)
  331. assert.Equal(t, "_rels/workbook.xml.rels", f.getWorkbookRelsPath())
  332. }
  333. func TestDeleteSheet(t *testing.T) {
  334. f := NewFile()
  335. f.SetActiveSheet(f.NewSheet("Sheet2"))
  336. f.NewSheet("Sheet3")
  337. f.DeleteSheet("Sheet1")
  338. assert.Equal(t, "Sheet2", f.GetSheetName(f.GetActiveSheetIndex()))
  339. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDeleteSheet.xlsx")))
  340. }
  341. func BenchmarkNewSheet(b *testing.B) {
  342. b.RunParallel(func(pb *testing.PB) {
  343. for pb.Next() {
  344. newSheetWithSet()
  345. }
  346. })
  347. }
  348. func newSheetWithSet() {
  349. file := NewFile()
  350. file.NewSheet("sheet1")
  351. for i := 0; i < 1000; i++ {
  352. file.SetCellInt("sheet1", "A"+strconv.Itoa(i+1), i)
  353. }
  354. file = nil
  355. }
  356. func BenchmarkFile_SaveAs(b *testing.B) {
  357. b.RunParallel(func(pb *testing.PB) {
  358. for pb.Next() {
  359. newSheetWithSave()
  360. }
  361. })
  362. }
  363. func newSheetWithSave() {
  364. file := NewFile()
  365. file.NewSheet("sheet1")
  366. for i := 0; i < 1000; i++ {
  367. file.SetCellInt("sheet1", "A"+strconv.Itoa(i+1), i)
  368. }
  369. file.Save()
  370. }