rows_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. package excelize
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "testing"
  6. "github.com/stretchr/testify/assert"
  7. )
  8. func TestRows(t *testing.T) {
  9. const sheet2 = "Sheet2"
  10. xlsx, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  11. if !assert.NoError(t, err) {
  12. t.FailNow()
  13. }
  14. rows, err := xlsx.Rows(sheet2)
  15. if !assert.NoError(t, err) {
  16. t.FailNow()
  17. }
  18. collectedRows := make([][]string, 0)
  19. for rows.Next() {
  20. columns, err := rows.Columns()
  21. assert.NoError(t, err)
  22. collectedRows = append(collectedRows, trimSliceSpace(columns))
  23. }
  24. if !assert.NoError(t, rows.Error()) {
  25. t.FailNow()
  26. }
  27. returnedRows, err := xlsx.GetRows(sheet2)
  28. assert.NoError(t, err)
  29. for i := range returnedRows {
  30. returnedRows[i] = trimSliceSpace(returnedRows[i])
  31. }
  32. if !assert.Equal(t, collectedRows, returnedRows) {
  33. t.FailNow()
  34. }
  35. r := Rows{}
  36. r.Columns()
  37. }
  38. func TestRowsError(t *testing.T) {
  39. xlsx, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  40. if !assert.NoError(t, err) {
  41. t.FailNow()
  42. }
  43. _, err = xlsx.Rows("SheetN")
  44. assert.EqualError(t, err, "Sheet SheetN is not exist")
  45. }
  46. func TestRowHeight(t *testing.T) {
  47. xlsx := NewFile()
  48. sheet1 := xlsx.GetSheetName(1)
  49. assert.EqualError(t, xlsx.SetRowHeight(sheet1, 0, defaultRowHeightPixels+1.0), "invalid row number 0")
  50. height, err := xlsx.GetRowHeight("Sheet1", 0)
  51. assert.EqualError(t, err, "invalid row number 0")
  52. assert.NoError(t, xlsx.SetRowHeight(sheet1, 1, 111.0))
  53. height, err = xlsx.GetRowHeight(sheet1, 1)
  54. assert.NoError(t, err)
  55. assert.Equal(t, 111.0, height)
  56. assert.NoError(t, xlsx.SetRowHeight(sheet1, 4, 444.0))
  57. height, err = xlsx.GetRowHeight(sheet1, 4)
  58. assert.NoError(t, err)
  59. assert.Equal(t, 444.0, height)
  60. // Test get row height that rows index over exists rows.
  61. height, err = xlsx.GetRowHeight(sheet1, 5)
  62. assert.NoError(t, err)
  63. assert.Equal(t, defaultRowHeightPixels, height)
  64. // Test get row height that rows heights haven't changed.
  65. height, err = xlsx.GetRowHeight(sheet1, 3)
  66. assert.NoError(t, err)
  67. assert.Equal(t, defaultRowHeightPixels, height)
  68. err = xlsx.SaveAs(filepath.Join("test", "TestRowHeight.xlsx"))
  69. if !assert.NoError(t, err) {
  70. t.FailNow()
  71. }
  72. convertColWidthToPixels(0)
  73. }
  74. func TestRowVisibility(t *testing.T) {
  75. xlsx, err := prepareTestBook1()
  76. if !assert.NoError(t, err) {
  77. t.FailNow()
  78. }
  79. assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 2, false), "Sheet Sheet3 is not exist")
  80. assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 2, true), "Sheet Sheet3 is not exist")
  81. xlsx.GetRowVisible("Sheet3", 2)
  82. xlsx.GetRowVisible("Sheet3", 25)
  83. assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 0, true), "invalid row number 0")
  84. visible, err := xlsx.GetRowVisible("Sheet3", 0)
  85. assert.Equal(t, false, visible)
  86. assert.EqualError(t, err, "invalid row number 0")
  87. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestRowVisibility.xlsx")))
  88. }
  89. func TestRemoveRow(t *testing.T) {
  90. xlsx := NewFile()
  91. sheet1 := xlsx.GetSheetName(1)
  92. r, err := xlsx.workSheetReader(sheet1)
  93. assert.NoError(t, err)
  94. const (
  95. colCount = 10
  96. rowCount = 10
  97. )
  98. fillCells(xlsx, sheet1, colCount, rowCount)
  99. xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
  100. assert.EqualError(t, xlsx.RemoveRow(sheet1, -1), "invalid row number -1")
  101. assert.EqualError(t, xlsx.RemoveRow(sheet1, 0), "invalid row number 0")
  102. assert.NoError(t, xlsx.RemoveRow(sheet1, 4))
  103. if !assert.Len(t, r.SheetData.Row, rowCount-1) {
  104. t.FailNow()
  105. }
  106. xlsx.MergeCell(sheet1, "B3", "B5")
  107. assert.NoError(t, xlsx.RemoveRow(sheet1, 2))
  108. if !assert.Len(t, r.SheetData.Row, rowCount-2) {
  109. t.FailNow()
  110. }
  111. assert.NoError(t, xlsx.RemoveRow(sheet1, 4))
  112. if !assert.Len(t, r.SheetData.Row, rowCount-3) {
  113. t.FailNow()
  114. }
  115. err = xlsx.AutoFilter(sheet1, "A2", "A2", `{"column":"A","expression":"x != blanks"}`)
  116. if !assert.NoError(t, err) {
  117. t.FailNow()
  118. }
  119. assert.NoError(t, xlsx.RemoveRow(sheet1, 1))
  120. if !assert.Len(t, r.SheetData.Row, rowCount-4) {
  121. t.FailNow()
  122. }
  123. assert.NoError(t, xlsx.RemoveRow(sheet1, 2))
  124. if !assert.Len(t, r.SheetData.Row, rowCount-5) {
  125. t.FailNow()
  126. }
  127. assert.NoError(t, xlsx.RemoveRow(sheet1, 1))
  128. if !assert.Len(t, r.SheetData.Row, rowCount-6) {
  129. t.FailNow()
  130. }
  131. assert.NoError(t, xlsx.RemoveRow(sheet1, 10))
  132. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestRemoveRow.xlsx")))
  133. }
  134. func TestInsertRow(t *testing.T) {
  135. xlsx := NewFile()
  136. sheet1 := xlsx.GetSheetName(1)
  137. r, err := xlsx.workSheetReader(sheet1)
  138. assert.NoError(t, err)
  139. const (
  140. colCount = 10
  141. rowCount = 10
  142. )
  143. fillCells(xlsx, sheet1, colCount, rowCount)
  144. xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
  145. assert.EqualError(t, xlsx.InsertRow(sheet1, -1), "invalid row number -1")
  146. assert.EqualError(t, xlsx.InsertRow(sheet1, 0), "invalid row number 0")
  147. assert.NoError(t, xlsx.InsertRow(sheet1, 1))
  148. if !assert.Len(t, r.SheetData.Row, rowCount+1) {
  149. t.FailNow()
  150. }
  151. assert.NoError(t, xlsx.InsertRow(sheet1, 4))
  152. if !assert.Len(t, r.SheetData.Row, rowCount+2) {
  153. t.FailNow()
  154. }
  155. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRow.xlsx")))
  156. }
  157. // Testing internal sructure state after insert operations.
  158. // It is important for insert workflow to be constant to avoid side effect with functions related to internal structure.
  159. func TestInsertRowInEmptyFile(t *testing.T) {
  160. xlsx := NewFile()
  161. sheet1 := xlsx.GetSheetName(1)
  162. r, err := xlsx.workSheetReader(sheet1)
  163. assert.NoError(t, err)
  164. assert.NoError(t, xlsx.InsertRow(sheet1, 1))
  165. assert.Len(t, r.SheetData.Row, 0)
  166. assert.NoError(t, xlsx.InsertRow(sheet1, 2))
  167. assert.Len(t, r.SheetData.Row, 0)
  168. assert.NoError(t, xlsx.InsertRow(sheet1, 99))
  169. assert.Len(t, r.SheetData.Row, 0)
  170. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
  171. }
  172. func TestDuplicateRow(t *testing.T) {
  173. const sheet = "Sheet1"
  174. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  175. cells := map[string]string{
  176. "A1": "A1 Value",
  177. "A2": "A2 Value",
  178. "A3": "A3 Value",
  179. "B1": "B1 Value",
  180. "B2": "B2 Value",
  181. "B3": "B3 Value",
  182. }
  183. newFileWithDefaults := func() *File {
  184. f := NewFile()
  185. for cell, val := range cells {
  186. f.SetCellStr(sheet, cell, val)
  187. }
  188. return f
  189. }
  190. t.Run("FromSingleRow", func(t *testing.T) {
  191. xlsx := NewFile()
  192. xlsx.SetCellStr(sheet, "A1", cells["A1"])
  193. xlsx.SetCellStr(sheet, "B1", cells["B1"])
  194. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  195. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_1"))) {
  196. t.FailNow()
  197. }
  198. expect := map[string]string{
  199. "A1": cells["A1"], "B1": cells["B1"],
  200. "A2": cells["A1"], "B2": cells["B1"],
  201. }
  202. for cell, val := range expect {
  203. v, err := xlsx.GetCellValue(sheet, cell)
  204. assert.NoError(t, err)
  205. if !assert.Equal(t, val, v, cell) {
  206. t.FailNow()
  207. }
  208. }
  209. assert.NoError(t, xlsx.DuplicateRow(sheet, 2))
  210. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_2"))) {
  211. t.FailNow()
  212. }
  213. expect = map[string]string{
  214. "A1": cells["A1"], "B1": cells["B1"],
  215. "A2": cells["A1"], "B2": cells["B1"],
  216. "A3": cells["A1"], "B3": cells["B1"],
  217. }
  218. for cell, val := range expect {
  219. v, err := xlsx.GetCellValue(sheet, cell)
  220. assert.NoError(t, err)
  221. if !assert.Equal(t, val, v, cell) {
  222. t.FailNow()
  223. }
  224. }
  225. })
  226. t.Run("UpdateDuplicatedRows", func(t *testing.T) {
  227. xlsx := NewFile()
  228. xlsx.SetCellStr(sheet, "A1", cells["A1"])
  229. xlsx.SetCellStr(sheet, "B1", cells["B1"])
  230. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  231. xlsx.SetCellStr(sheet, "A2", cells["A2"])
  232. xlsx.SetCellStr(sheet, "B2", cells["B2"])
  233. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.UpdateDuplicatedRows"))) {
  234. t.FailNow()
  235. }
  236. expect := map[string]string{
  237. "A1": cells["A1"], "B1": cells["B1"],
  238. "A2": cells["A2"], "B2": cells["B2"],
  239. }
  240. for cell, val := range expect {
  241. v, err := xlsx.GetCellValue(sheet, cell)
  242. assert.NoError(t, err)
  243. if !assert.Equal(t, val, v, cell) {
  244. t.FailNow()
  245. }
  246. }
  247. })
  248. t.Run("FirstOfMultipleRows", func(t *testing.T) {
  249. xlsx := newFileWithDefaults()
  250. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  251. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FirstOfMultipleRows"))) {
  252. t.FailNow()
  253. }
  254. expect := map[string]string{
  255. "A1": cells["A1"], "B1": cells["B1"],
  256. "A2": cells["A1"], "B2": cells["B1"],
  257. "A3": cells["A2"], "B3": cells["B2"],
  258. "A4": cells["A3"], "B4": cells["B3"],
  259. }
  260. for cell, val := range expect {
  261. v, err := xlsx.GetCellValue(sheet, cell)
  262. assert.NoError(t, err)
  263. if !assert.Equal(t, val, v, cell) {
  264. t.FailNow()
  265. }
  266. }
  267. })
  268. t.Run("ZeroWithNoRows", func(t *testing.T) {
  269. xlsx := NewFile()
  270. assert.EqualError(t, xlsx.DuplicateRow(sheet, 0), "invalid row number 0")
  271. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.ZeroWithNoRows"))) {
  272. t.FailNow()
  273. }
  274. val, err := xlsx.GetCellValue(sheet, "A1")
  275. assert.NoError(t, err)
  276. assert.Equal(t, "", val)
  277. val, err = xlsx.GetCellValue(sheet, "B1")
  278. assert.NoError(t, err)
  279. assert.Equal(t, "", val)
  280. val, err = xlsx.GetCellValue(sheet, "A2")
  281. assert.NoError(t, err)
  282. assert.Equal(t, "", val)
  283. val, err = xlsx.GetCellValue(sheet, "B2")
  284. assert.NoError(t, err)
  285. assert.Equal(t, "", val)
  286. assert.NoError(t, err)
  287. expect := map[string]string{
  288. "A1": "", "B1": "",
  289. "A2": "", "B2": "",
  290. }
  291. for cell, val := range expect {
  292. v, err := xlsx.GetCellValue(sheet, cell)
  293. assert.NoError(t, err)
  294. if !assert.Equal(t, val, v, cell) {
  295. t.FailNow()
  296. }
  297. }
  298. })
  299. t.Run("MiddleRowOfEmptyFile", func(t *testing.T) {
  300. xlsx := NewFile()
  301. assert.NoError(t, xlsx.DuplicateRow(sheet, 99))
  302. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.MiddleRowOfEmptyFile"))) {
  303. t.FailNow()
  304. }
  305. expect := map[string]string{
  306. "A98": "",
  307. "A99": "",
  308. "A100": "",
  309. }
  310. for cell, val := range expect {
  311. v, err := xlsx.GetCellValue(sheet, cell)
  312. assert.NoError(t, err)
  313. if !assert.Equal(t, val, v, cell) {
  314. t.FailNow()
  315. }
  316. }
  317. })
  318. t.Run("WithLargeOffsetToMiddleOfData", func(t *testing.T) {
  319. xlsx := newFileWithDefaults()
  320. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 3))
  321. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToMiddleOfData"))) {
  322. t.FailNow()
  323. }
  324. expect := map[string]string{
  325. "A1": cells["A1"], "B1": cells["B1"],
  326. "A2": cells["A2"], "B2": cells["B2"],
  327. "A3": cells["A1"], "B3": cells["B1"],
  328. "A4": cells["A3"], "B4": cells["B3"],
  329. }
  330. for cell, val := range expect {
  331. v, err := xlsx.GetCellValue(sheet, cell)
  332. assert.NoError(t, err)
  333. if !assert.Equal(t, val, v, cell) {
  334. t.FailNow()
  335. }
  336. }
  337. })
  338. t.Run("WithLargeOffsetToEmptyRows", func(t *testing.T) {
  339. xlsx := newFileWithDefaults()
  340. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 7))
  341. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToEmptyRows"))) {
  342. t.FailNow()
  343. }
  344. expect := map[string]string{
  345. "A1": cells["A1"], "B1": cells["B1"],
  346. "A2": cells["A2"], "B2": cells["B2"],
  347. "A3": cells["A3"], "B3": cells["B3"],
  348. "A7": cells["A1"], "B7": cells["B1"],
  349. }
  350. for cell, val := range expect {
  351. v, err := xlsx.GetCellValue(sheet, cell)
  352. assert.NoError(t, err)
  353. if !assert.Equal(t, val, v, cell) {
  354. t.FailNow()
  355. }
  356. }
  357. })
  358. t.Run("InsertBefore", func(t *testing.T) {
  359. xlsx := newFileWithDefaults()
  360. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 2, 1))
  361. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBefore"))) {
  362. t.FailNow()
  363. }
  364. expect := map[string]string{
  365. "A1": cells["A2"], "B1": cells["B2"],
  366. "A2": cells["A1"], "B2": cells["B1"],
  367. "A3": cells["A2"], "B3": cells["B2"],
  368. "A4": cells["A3"], "B4": cells["B3"],
  369. }
  370. for cell, val := range expect {
  371. v, err := xlsx.GetCellValue(sheet, cell)
  372. assert.NoError(t, err)
  373. if !assert.Equal(t, val, v, cell) {
  374. t.FailNow()
  375. }
  376. }
  377. })
  378. t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
  379. xlsx := newFileWithDefaults()
  380. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 3, 1))
  381. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithLargeOffset"))) {
  382. t.FailNow()
  383. }
  384. expect := map[string]string{
  385. "A1": cells["A3"], "B1": cells["B3"],
  386. "A2": cells["A1"], "B2": cells["B1"],
  387. "A3": cells["A2"], "B3": cells["B2"],
  388. "A4": cells["A3"], "B4": cells["B3"],
  389. }
  390. for cell, val := range expect {
  391. v, err := xlsx.GetCellValue(sheet, cell)
  392. assert.NoError(t, err)
  393. if !assert.Equal(t, val, v) {
  394. t.FailNow()
  395. }
  396. }
  397. })
  398. }
  399. func TestDuplicateRowInvalidRownum(t *testing.T) {
  400. const sheet = "Sheet1"
  401. outFile := filepath.Join("test", "TestDuplicateRowInvalidRownum.%s.xlsx")
  402. cells := map[string]string{
  403. "A1": "A1 Value",
  404. "A2": "A2 Value",
  405. "A3": "A3 Value",
  406. "B1": "B1 Value",
  407. "B2": "B2 Value",
  408. "B3": "B3 Value",
  409. }
  410. invalidIndexes := []int{-100, -2, -1, 0}
  411. for _, row := range invalidIndexes {
  412. name := fmt.Sprintf("%d", row)
  413. t.Run(name, func(t *testing.T) {
  414. xlsx := NewFile()
  415. for col, val := range cells {
  416. xlsx.SetCellStr(sheet, col, val)
  417. }
  418. assert.EqualError(t, xlsx.DuplicateRow(sheet, row), fmt.Sprintf("invalid row number %d", row))
  419. for col, val := range cells {
  420. v, err := xlsx.GetCellValue(sheet, col)
  421. assert.NoError(t, err)
  422. if !assert.Equal(t, val, v) {
  423. t.FailNow()
  424. }
  425. }
  426. assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
  427. })
  428. }
  429. for _, row1 := range invalidIndexes {
  430. for _, row2 := range invalidIndexes {
  431. name := fmt.Sprintf("[%d,%d]", row1, row2)
  432. t.Run(name, func(t *testing.T) {
  433. xlsx := NewFile()
  434. for col, val := range cells {
  435. xlsx.SetCellStr(sheet, col, val)
  436. }
  437. assert.EqualError(t, xlsx.DuplicateRowTo(sheet, row1, row2), fmt.Sprintf("invalid row number %d", row1))
  438. for col, val := range cells {
  439. v, err := xlsx.GetCellValue(sheet, col)
  440. assert.NoError(t, err)
  441. if !assert.Equal(t, val, v) {
  442. t.FailNow()
  443. }
  444. }
  445. assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
  446. })
  447. }
  448. }
  449. }
  450. func trimSliceSpace(s []string) []string {
  451. for {
  452. if len(s) > 0 && s[len(s)-1] == "" {
  453. s = s[:len(s)-1]
  454. } else {
  455. break
  456. }
  457. }
  458. return s
  459. }