rows_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  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.NoError(t, xlsx.SetRowVisible("Sheet3", 2, false))
  80. assert.NoError(t, xlsx.SetRowVisible("Sheet3", 2, true))
  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 := xlsx.workSheetReader(sheet1)
  93. const (
  94. colCount = 10
  95. rowCount = 10
  96. )
  97. fillCells(xlsx, sheet1, colCount, rowCount)
  98. xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
  99. assert.EqualError(t, xlsx.RemoveRow(sheet1, -1), "invalid row number -1")
  100. assert.EqualError(t, xlsx.RemoveRow(sheet1, 0), "invalid row number 0")
  101. assert.NoError(t, xlsx.RemoveRow(sheet1, 4))
  102. if !assert.Len(t, r.SheetData.Row, rowCount-1) {
  103. t.FailNow()
  104. }
  105. xlsx.MergeCell(sheet1, "B3", "B5")
  106. assert.NoError(t, xlsx.RemoveRow(sheet1, 2))
  107. if !assert.Len(t, r.SheetData.Row, rowCount-2) {
  108. t.FailNow()
  109. }
  110. assert.NoError(t, xlsx.RemoveRow(sheet1, 4))
  111. if !assert.Len(t, r.SheetData.Row, rowCount-3) {
  112. t.FailNow()
  113. }
  114. err := xlsx.AutoFilter(sheet1, "A2", "A2", `{"column":"A","expression":"x != blanks"}`)
  115. if !assert.NoError(t, err) {
  116. t.FailNow()
  117. }
  118. assert.NoError(t, xlsx.RemoveRow(sheet1, 1))
  119. if !assert.Len(t, r.SheetData.Row, rowCount-4) {
  120. t.FailNow()
  121. }
  122. assert.NoError(t, xlsx.RemoveRow(sheet1, 2))
  123. if !assert.Len(t, r.SheetData.Row, rowCount-5) {
  124. t.FailNow()
  125. }
  126. assert.NoError(t, xlsx.RemoveRow(sheet1, 1))
  127. if !assert.Len(t, r.SheetData.Row, rowCount-6) {
  128. t.FailNow()
  129. }
  130. assert.NoError(t, xlsx.RemoveRow(sheet1, 10))
  131. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestRemoveRow.xlsx")))
  132. }
  133. func TestInsertRow(t *testing.T) {
  134. xlsx := NewFile()
  135. sheet1 := xlsx.GetSheetName(1)
  136. r := xlsx.workSheetReader(sheet1)
  137. const (
  138. colCount = 10
  139. rowCount = 10
  140. )
  141. fillCells(xlsx, sheet1, colCount, rowCount)
  142. xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
  143. assert.EqualError(t, xlsx.InsertRow(sheet1, -1), "invalid row number -1")
  144. assert.EqualError(t, xlsx.InsertRow(sheet1, 0), "invalid row number 0")
  145. assert.NoError(t, xlsx.InsertRow(sheet1, 1))
  146. if !assert.Len(t, r.SheetData.Row, rowCount+1) {
  147. t.FailNow()
  148. }
  149. assert.NoError(t, xlsx.InsertRow(sheet1, 4))
  150. if !assert.Len(t, r.SheetData.Row, rowCount+2) {
  151. t.FailNow()
  152. }
  153. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRow.xlsx")))
  154. }
  155. // Testing internal sructure state after insert operations.
  156. // It is important for insert workflow to be constant to avoid side effect with functions related to internal structure.
  157. func TestInsertRowInEmptyFile(t *testing.T) {
  158. xlsx := NewFile()
  159. sheet1 := xlsx.GetSheetName(1)
  160. r := xlsx.workSheetReader(sheet1)
  161. assert.NoError(t, xlsx.InsertRow(sheet1, 1))
  162. assert.Len(t, r.SheetData.Row, 0)
  163. assert.NoError(t, xlsx.InsertRow(sheet1, 2))
  164. assert.Len(t, r.SheetData.Row, 0)
  165. assert.NoError(t, xlsx.InsertRow(sheet1, 99))
  166. assert.Len(t, r.SheetData.Row, 0)
  167. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
  168. }
  169. func TestDuplicateRow(t *testing.T) {
  170. const sheet = "Sheet1"
  171. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  172. cells := map[string]string{
  173. "A1": "A1 Value",
  174. "A2": "A2 Value",
  175. "A3": "A3 Value",
  176. "B1": "B1 Value",
  177. "B2": "B2 Value",
  178. "B3": "B3 Value",
  179. }
  180. newFileWithDefaults := func() *File {
  181. f := NewFile()
  182. for cell, val := range cells {
  183. f.SetCellStr(sheet, cell, val)
  184. }
  185. return f
  186. }
  187. t.Run("FromSingleRow", func(t *testing.T) {
  188. xlsx := NewFile()
  189. xlsx.SetCellStr(sheet, "A1", cells["A1"])
  190. xlsx.SetCellStr(sheet, "B1", cells["B1"])
  191. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  192. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_1"))) {
  193. t.FailNow()
  194. }
  195. expect := map[string]string{
  196. "A1": cells["A1"], "B1": cells["B1"],
  197. "A2": cells["A1"], "B2": cells["B1"],
  198. }
  199. for cell, val := range expect {
  200. v, err := xlsx.GetCellValue(sheet, cell)
  201. assert.NoError(t, err)
  202. if !assert.Equal(t, val, v, cell) {
  203. t.FailNow()
  204. }
  205. }
  206. assert.NoError(t, xlsx.DuplicateRow(sheet, 2))
  207. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_2"))) {
  208. t.FailNow()
  209. }
  210. expect = map[string]string{
  211. "A1": cells["A1"], "B1": cells["B1"],
  212. "A2": cells["A1"], "B2": cells["B1"],
  213. "A3": cells["A1"], "B3": cells["B1"],
  214. }
  215. for cell, val := range expect {
  216. v, err := xlsx.GetCellValue(sheet, cell)
  217. assert.NoError(t, err)
  218. if !assert.Equal(t, val, v, cell) {
  219. t.FailNow()
  220. }
  221. }
  222. })
  223. t.Run("UpdateDuplicatedRows", func(t *testing.T) {
  224. xlsx := NewFile()
  225. xlsx.SetCellStr(sheet, "A1", cells["A1"])
  226. xlsx.SetCellStr(sheet, "B1", cells["B1"])
  227. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  228. xlsx.SetCellStr(sheet, "A2", cells["A2"])
  229. xlsx.SetCellStr(sheet, "B2", cells["B2"])
  230. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.UpdateDuplicatedRows"))) {
  231. t.FailNow()
  232. }
  233. expect := map[string]string{
  234. "A1": cells["A1"], "B1": cells["B1"],
  235. "A2": cells["A2"], "B2": cells["B2"],
  236. }
  237. for cell, val := range expect {
  238. v, err := xlsx.GetCellValue(sheet, cell)
  239. assert.NoError(t, err)
  240. if !assert.Equal(t, val, v, cell) {
  241. t.FailNow()
  242. }
  243. }
  244. })
  245. t.Run("FirstOfMultipleRows", func(t *testing.T) {
  246. xlsx := newFileWithDefaults()
  247. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  248. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FirstOfMultipleRows"))) {
  249. t.FailNow()
  250. }
  251. expect := map[string]string{
  252. "A1": cells["A1"], "B1": cells["B1"],
  253. "A2": cells["A1"], "B2": cells["B1"],
  254. "A3": cells["A2"], "B3": cells["B2"],
  255. "A4": cells["A3"], "B4": cells["B3"],
  256. }
  257. for cell, val := range expect {
  258. v, err := xlsx.GetCellValue(sheet, cell)
  259. assert.NoError(t, err)
  260. if !assert.Equal(t, val, v, cell) {
  261. t.FailNow()
  262. }
  263. }
  264. })
  265. t.Run("ZeroWithNoRows", func(t *testing.T) {
  266. xlsx := NewFile()
  267. assert.EqualError(t, xlsx.DuplicateRow(sheet, 0), "invalid row number 0")
  268. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.ZeroWithNoRows"))) {
  269. t.FailNow()
  270. }
  271. val, err := xlsx.GetCellValue(sheet, "A1")
  272. assert.NoError(t, err)
  273. assert.Equal(t, "", val)
  274. val, err = xlsx.GetCellValue(sheet, "B1")
  275. assert.NoError(t, err)
  276. assert.Equal(t, "", val)
  277. val, err = xlsx.GetCellValue(sheet, "A2")
  278. assert.NoError(t, err)
  279. assert.Equal(t, "", val)
  280. val, err = xlsx.GetCellValue(sheet, "B2")
  281. assert.NoError(t, err)
  282. assert.Equal(t, "", val)
  283. assert.NoError(t, err)
  284. expect := map[string]string{
  285. "A1": "", "B1": "",
  286. "A2": "", "B2": "",
  287. }
  288. for cell, val := range expect {
  289. v, err := xlsx.GetCellValue(sheet, cell)
  290. assert.NoError(t, err)
  291. if !assert.Equal(t, val, v, cell) {
  292. t.FailNow()
  293. }
  294. }
  295. })
  296. t.Run("MiddleRowOfEmptyFile", func(t *testing.T) {
  297. xlsx := NewFile()
  298. assert.NoError(t, xlsx.DuplicateRow(sheet, 99))
  299. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.MiddleRowOfEmptyFile"))) {
  300. t.FailNow()
  301. }
  302. expect := map[string]string{
  303. "A98": "",
  304. "A99": "",
  305. "A100": "",
  306. }
  307. for cell, val := range expect {
  308. v, err := xlsx.GetCellValue(sheet, cell)
  309. assert.NoError(t, err)
  310. if !assert.Equal(t, val, v, cell) {
  311. t.FailNow()
  312. }
  313. }
  314. })
  315. t.Run("WithLargeOffsetToMiddleOfData", func(t *testing.T) {
  316. xlsx := newFileWithDefaults()
  317. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 3))
  318. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToMiddleOfData"))) {
  319. t.FailNow()
  320. }
  321. expect := map[string]string{
  322. "A1": cells["A1"], "B1": cells["B1"],
  323. "A2": cells["A2"], "B2": cells["B2"],
  324. "A3": cells["A1"], "B3": cells["B1"],
  325. "A4": cells["A3"], "B4": cells["B3"],
  326. }
  327. for cell, val := range expect {
  328. v, err := xlsx.GetCellValue(sheet, cell)
  329. assert.NoError(t, err)
  330. if !assert.Equal(t, val, v, cell) {
  331. t.FailNow()
  332. }
  333. }
  334. })
  335. t.Run("WithLargeOffsetToEmptyRows", func(t *testing.T) {
  336. xlsx := newFileWithDefaults()
  337. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 7))
  338. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToEmptyRows"))) {
  339. t.FailNow()
  340. }
  341. expect := map[string]string{
  342. "A1": cells["A1"], "B1": cells["B1"],
  343. "A2": cells["A2"], "B2": cells["B2"],
  344. "A3": cells["A3"], "B3": cells["B3"],
  345. "A7": cells["A1"], "B7": cells["B1"],
  346. }
  347. for cell, val := range expect {
  348. v, err := xlsx.GetCellValue(sheet, cell)
  349. assert.NoError(t, err)
  350. if !assert.Equal(t, val, v, cell) {
  351. t.FailNow()
  352. }
  353. }
  354. })
  355. t.Run("InsertBefore", func(t *testing.T) {
  356. xlsx := newFileWithDefaults()
  357. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 2, 1))
  358. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBefore"))) {
  359. t.FailNow()
  360. }
  361. expect := map[string]string{
  362. "A1": cells["A2"], "B1": cells["B2"],
  363. "A2": cells["A1"], "B2": cells["B1"],
  364. "A3": cells["A2"], "B3": cells["B2"],
  365. "A4": cells["A3"], "B4": cells["B3"],
  366. }
  367. for cell, val := range expect {
  368. v, err := xlsx.GetCellValue(sheet, cell)
  369. assert.NoError(t, err)
  370. if !assert.Equal(t, val, v, cell) {
  371. t.FailNow()
  372. }
  373. }
  374. })
  375. t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
  376. xlsx := newFileWithDefaults()
  377. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 3, 1))
  378. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithLargeOffset"))) {
  379. t.FailNow()
  380. }
  381. expect := map[string]string{
  382. "A1": cells["A3"], "B1": cells["B3"],
  383. "A2": cells["A1"], "B2": cells["B1"],
  384. "A3": cells["A2"], "B3": cells["B2"],
  385. "A4": cells["A3"], "B4": cells["B3"],
  386. }
  387. for cell, val := range expect {
  388. v, err := xlsx.GetCellValue(sheet, cell)
  389. assert.NoError(t, err)
  390. if !assert.Equal(t, val, v) {
  391. t.FailNow()
  392. }
  393. }
  394. })
  395. }
  396. func TestDuplicateRowInvalidRownum(t *testing.T) {
  397. const sheet = "Sheet1"
  398. outFile := filepath.Join("test", "TestDuplicateRowInvalidRownum.%s.xlsx")
  399. cells := map[string]string{
  400. "A1": "A1 Value",
  401. "A2": "A2 Value",
  402. "A3": "A3 Value",
  403. "B1": "B1 Value",
  404. "B2": "B2 Value",
  405. "B3": "B3 Value",
  406. }
  407. invalidIndexes := []int{-100, -2, -1, 0}
  408. for _, row := range invalidIndexes {
  409. name := fmt.Sprintf("%d", row)
  410. t.Run(name, func(t *testing.T) {
  411. xlsx := NewFile()
  412. for col, val := range cells {
  413. xlsx.SetCellStr(sheet, col, val)
  414. }
  415. assert.EqualError(t, xlsx.DuplicateRow(sheet, row), fmt.Sprintf("invalid row number %d", row))
  416. for col, val := range cells {
  417. v, err := xlsx.GetCellValue(sheet, col)
  418. assert.NoError(t, err)
  419. if !assert.Equal(t, val, v) {
  420. t.FailNow()
  421. }
  422. }
  423. assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
  424. })
  425. }
  426. for _, row1 := range invalidIndexes {
  427. for _, row2 := range invalidIndexes {
  428. name := fmt.Sprintf("[%d,%d]", row1, row2)
  429. t.Run(name, func(t *testing.T) {
  430. xlsx := NewFile()
  431. for col, val := range cells {
  432. xlsx.SetCellStr(sheet, col, val)
  433. }
  434. assert.EqualError(t, xlsx.DuplicateRowTo(sheet, row1, row2), fmt.Sprintf("invalid row number %d", row1))
  435. for col, val := range cells {
  436. v, err := xlsx.GetCellValue(sheet, col)
  437. assert.NoError(t, err)
  438. if !assert.Equal(t, val, v) {
  439. t.FailNow()
  440. }
  441. }
  442. assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
  443. })
  444. }
  445. }
  446. }
  447. func trimSliceSpace(s []string) []string {
  448. for {
  449. if len(s) > 0 && s[len(s)-1] == "" {
  450. s = s[:len(s)-1]
  451. } else {
  452. break
  453. }
  454. }
  455. return s
  456. }