rows_test.go 12 KB

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