rows_test.go 13 KB

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