rows_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. package excelize
  2. import (
  3. "bytes"
  4. "fmt"
  5. "path/filepath"
  6. "testing"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. )
  10. func TestRows(t *testing.T) {
  11. const sheet2 = "Sheet2"
  12. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  13. if !assert.NoError(t, err) {
  14. t.FailNow()
  15. }
  16. rows, err := f.Rows(sheet2)
  17. if !assert.NoError(t, err) {
  18. t.FailNow()
  19. }
  20. var collectedRows [][]string
  21. for rows.Next() {
  22. columns, err := rows.Columns()
  23. assert.NoError(t, err)
  24. collectedRows = append(collectedRows, trimSliceSpace(columns))
  25. }
  26. if !assert.NoError(t, rows.Error()) {
  27. t.FailNow()
  28. }
  29. returnedRows, err := f.GetRows(sheet2)
  30. assert.NoError(t, err)
  31. for i := range returnedRows {
  32. returnedRows[i] = trimSliceSpace(returnedRows[i])
  33. }
  34. if !assert.Equal(t, collectedRows, returnedRows) {
  35. t.FailNow()
  36. }
  37. f = NewFile()
  38. f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<worksheet><sheetData><row r="1"><c r="A1" t="s"><v>1</v></c></row><row r="A"><c r="2" t="str"><v>B</v></c></row></sheetData></worksheet>`)
  39. _, err = f.Rows("Sheet1")
  40. assert.EqualError(t, err, `strconv.Atoi: parsing "A": invalid syntax`)
  41. }
  42. func TestRowsIterator(t *testing.T) {
  43. const (
  44. sheet2 = "Sheet2"
  45. expectedNumRow = 11
  46. )
  47. f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  48. require.NoError(t, err)
  49. rows, err := f.Rows(sheet2)
  50. require.NoError(t, err)
  51. var rowCount int
  52. for rows.Next() {
  53. rowCount++
  54. require.True(t, rowCount <= expectedNumRow, "rowCount is greater than expected")
  55. }
  56. assert.Equal(t, expectedNumRow, rowCount)
  57. // Valued cell sparse distribution test
  58. f = NewFile()
  59. cells := []string{"C1", "E1", "A3", "B3", "C3", "D3", "E3"}
  60. for _, cell := range cells {
  61. assert.NoError(t, f.SetCellValue("Sheet1", cell, 1))
  62. }
  63. rows, err = f.Rows("Sheet1")
  64. require.NoError(t, err)
  65. rowCount = 0
  66. for rows.Next() {
  67. rowCount++
  68. require.True(t, rowCount <= 3, "rowCount is greater than expected")
  69. }
  70. assert.Equal(t, 3, rowCount)
  71. }
  72. func TestRowsError(t *testing.T) {
  73. xlsx, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
  74. if !assert.NoError(t, err) {
  75. t.FailNow()
  76. }
  77. _, err = xlsx.Rows("SheetN")
  78. assert.EqualError(t, err, "sheet SheetN is not exist")
  79. }
  80. func TestRowHeight(t *testing.T) {
  81. xlsx := NewFile()
  82. sheet1 := xlsx.GetSheetName(1)
  83. assert.EqualError(t, xlsx.SetRowHeight(sheet1, 0, defaultRowHeightPixels+1.0), "invalid row number 0")
  84. _, err := xlsx.GetRowHeight("Sheet1", 0)
  85. assert.EqualError(t, err, "invalid row number 0")
  86. assert.NoError(t, xlsx.SetRowHeight(sheet1, 1, 111.0))
  87. height, err := xlsx.GetRowHeight(sheet1, 1)
  88. assert.NoError(t, err)
  89. assert.Equal(t, 111.0, height)
  90. assert.NoError(t, xlsx.SetRowHeight(sheet1, 4, 444.0))
  91. height, err = xlsx.GetRowHeight(sheet1, 4)
  92. assert.NoError(t, err)
  93. assert.Equal(t, 444.0, height)
  94. // Test get row height that rows index over exists rows.
  95. height, err = xlsx.GetRowHeight(sheet1, 5)
  96. assert.NoError(t, err)
  97. assert.Equal(t, defaultRowHeightPixels, height)
  98. // Test get row height that rows heights haven't changed.
  99. height, err = xlsx.GetRowHeight(sheet1, 3)
  100. assert.NoError(t, err)
  101. assert.Equal(t, defaultRowHeightPixels, height)
  102. // Test set and get row height on not exists worksheet.
  103. assert.EqualError(t, xlsx.SetRowHeight("SheetN", 1, 111.0), "sheet SheetN is not exist")
  104. _, err = xlsx.GetRowHeight("SheetN", 3)
  105. assert.EqualError(t, err, "sheet SheetN is not exist")
  106. err = xlsx.SaveAs(filepath.Join("test", "TestRowHeight.xlsx"))
  107. if !assert.NoError(t, err) {
  108. t.FailNow()
  109. }
  110. convertColWidthToPixels(0)
  111. }
  112. func TestColumns(t *testing.T) {
  113. f := NewFile()
  114. rows, err := f.Rows("Sheet1")
  115. assert.NoError(t, err)
  116. rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="2"><c r="A1" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
  117. _, err = rows.Columns()
  118. assert.NoError(t, err)
  119. rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="2"><c r="A1" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
  120. rows.curRow = 1
  121. _, err = rows.Columns()
  122. rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="A"><c r="A1" t="s"><v>1</v></c></row><row r="A"><c r="2" t="str"><v>B</v></c></row></sheetData></worksheet>`)))
  123. rows.stashRow, rows.curRow = 0, 1
  124. _, err = rows.Columns()
  125. assert.EqualError(t, err, `strconv.Atoi: parsing "A": invalid syntax`)
  126. rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="1"><c r="A1" t="s"><v>1</v></c></row><row r="A"><c r="2" t="str"><v>B</v></c></row></sheetData></worksheet>`)))
  127. _, err = rows.Columns()
  128. assert.NoError(t, err)
  129. rows.curRow = 3
  130. rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="1"><c r="A" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
  131. _, err = rows.Columns()
  132. assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
  133. // Test token is nil
  134. rows.decoder = f.xmlNewDecoder(bytes.NewReader(nil))
  135. _, err = rows.Columns()
  136. assert.NoError(t, err)
  137. }
  138. func TestSharedStringsReader(t *testing.T) {
  139. f := NewFile()
  140. f.XLSX["xl/sharedStrings.xml"] = MacintoshCyrillicCharset
  141. f.sharedStringsReader()
  142. }
  143. func TestRowVisibility(t *testing.T) {
  144. f, err := prepareTestBook1()
  145. if !assert.NoError(t, err) {
  146. t.FailNow()
  147. }
  148. f.NewSheet("Sheet3")
  149. assert.NoError(t, f.SetRowVisible("Sheet3", 2, false))
  150. assert.NoError(t, f.SetRowVisible("Sheet3", 2, true))
  151. visiable, err := f.GetRowVisible("Sheet3", 2)
  152. assert.Equal(t, true, visiable)
  153. assert.NoError(t, err)
  154. visiable, err = f.GetRowVisible("Sheet3", 25)
  155. assert.Equal(t, false, visiable)
  156. assert.NoError(t, err)
  157. assert.EqualError(t, f.SetRowVisible("Sheet3", 0, true), "invalid row number 0")
  158. assert.EqualError(t, f.SetRowVisible("SheetN", 2, false), "sheet SheetN is not exist")
  159. visible, err := f.GetRowVisible("Sheet3", 0)
  160. assert.Equal(t, false, visible)
  161. assert.EqualError(t, err, "invalid row number 0")
  162. _, err = f.GetRowVisible("SheetN", 1)
  163. assert.EqualError(t, err, "sheet SheetN is not exist")
  164. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRowVisibility.xlsx")))
  165. }
  166. func TestRemoveRow(t *testing.T) {
  167. f := NewFile()
  168. sheet1 := f.GetSheetName(1)
  169. r, err := f.workSheetReader(sheet1)
  170. assert.NoError(t, err)
  171. const (
  172. colCount = 10
  173. rowCount = 10
  174. )
  175. fillCells(f, sheet1, colCount, rowCount)
  176. assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
  177. assert.EqualError(t, f.RemoveRow(sheet1, -1), "invalid row number -1")
  178. assert.EqualError(t, f.RemoveRow(sheet1, 0), "invalid row number 0")
  179. assert.NoError(t, f.RemoveRow(sheet1, 4))
  180. if !assert.Len(t, r.SheetData.Row, rowCount-1) {
  181. t.FailNow()
  182. }
  183. assert.NoError(t, f.MergeCell(sheet1, "B3", "B5"))
  184. assert.NoError(t, f.RemoveRow(sheet1, 2))
  185. if !assert.Len(t, r.SheetData.Row, rowCount-2) {
  186. t.FailNow()
  187. }
  188. assert.NoError(t, f.RemoveRow(sheet1, 4))
  189. if !assert.Len(t, r.SheetData.Row, rowCount-3) {
  190. t.FailNow()
  191. }
  192. err = f.AutoFilter(sheet1, "A2", "A2", `{"column":"A","expression":"x != blanks"}`)
  193. if !assert.NoError(t, err) {
  194. t.FailNow()
  195. }
  196. assert.NoError(t, f.RemoveRow(sheet1, 1))
  197. if !assert.Len(t, r.SheetData.Row, rowCount-4) {
  198. t.FailNow()
  199. }
  200. assert.NoError(t, f.RemoveRow(sheet1, 2))
  201. if !assert.Len(t, r.SheetData.Row, rowCount-5) {
  202. t.FailNow()
  203. }
  204. assert.NoError(t, f.RemoveRow(sheet1, 1))
  205. if !assert.Len(t, r.SheetData.Row, rowCount-6) {
  206. t.FailNow()
  207. }
  208. assert.NoError(t, f.RemoveRow(sheet1, 10))
  209. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRemoveRow.xlsx")))
  210. // Test remove row on not exist worksheet
  211. assert.EqualError(t, f.RemoveRow("SheetN", 1), `sheet SheetN is not exist`)
  212. }
  213. func TestInsertRow(t *testing.T) {
  214. xlsx := NewFile()
  215. sheet1 := xlsx.GetSheetName(1)
  216. r, err := xlsx.workSheetReader(sheet1)
  217. assert.NoError(t, err)
  218. const (
  219. colCount = 10
  220. rowCount = 10
  221. )
  222. fillCells(xlsx, sheet1, colCount, rowCount)
  223. assert.NoError(t, xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
  224. assert.EqualError(t, xlsx.InsertRow(sheet1, -1), "invalid row number -1")
  225. assert.EqualError(t, xlsx.InsertRow(sheet1, 0), "invalid row number 0")
  226. assert.NoError(t, xlsx.InsertRow(sheet1, 1))
  227. if !assert.Len(t, r.SheetData.Row, rowCount+1) {
  228. t.FailNow()
  229. }
  230. assert.NoError(t, xlsx.InsertRow(sheet1, 4))
  231. if !assert.Len(t, r.SheetData.Row, rowCount+2) {
  232. t.FailNow()
  233. }
  234. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRow.xlsx")))
  235. }
  236. // Testing internal sructure state after insert operations.
  237. // It is important for insert workflow to be constant to avoid side effect with functions related to internal structure.
  238. func TestInsertRowInEmptyFile(t *testing.T) {
  239. xlsx := NewFile()
  240. sheet1 := xlsx.GetSheetName(1)
  241. r, err := xlsx.workSheetReader(sheet1)
  242. assert.NoError(t, err)
  243. assert.NoError(t, xlsx.InsertRow(sheet1, 1))
  244. assert.Len(t, r.SheetData.Row, 0)
  245. assert.NoError(t, xlsx.InsertRow(sheet1, 2))
  246. assert.Len(t, r.SheetData.Row, 0)
  247. assert.NoError(t, xlsx.InsertRow(sheet1, 99))
  248. assert.Len(t, r.SheetData.Row, 0)
  249. assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
  250. }
  251. func TestDuplicateRowFromSingleRow(t *testing.T) {
  252. const sheet = "Sheet1"
  253. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  254. cells := map[string]string{
  255. "A1": "A1 Value",
  256. "A2": "A2 Value",
  257. "A3": "A3 Value",
  258. "B1": "B1 Value",
  259. "B2": "B2 Value",
  260. "B3": "B3 Value",
  261. }
  262. t.Run("FromSingleRow", func(t *testing.T) {
  263. xlsx := NewFile()
  264. assert.NoError(t, xlsx.SetCellStr(sheet, "A1", cells["A1"]))
  265. assert.NoError(t, xlsx.SetCellStr(sheet, "B1", cells["B1"]))
  266. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  267. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_1"))) {
  268. t.FailNow()
  269. }
  270. expect := map[string]string{
  271. "A1": cells["A1"], "B1": cells["B1"],
  272. "A2": cells["A1"], "B2": cells["B1"],
  273. }
  274. for cell, val := range expect {
  275. v, err := xlsx.GetCellValue(sheet, cell)
  276. assert.NoError(t, err)
  277. if !assert.Equal(t, val, v, cell) {
  278. t.FailNow()
  279. }
  280. }
  281. assert.NoError(t, xlsx.DuplicateRow(sheet, 2))
  282. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_2"))) {
  283. t.FailNow()
  284. }
  285. expect = map[string]string{
  286. "A1": cells["A1"], "B1": cells["B1"],
  287. "A2": cells["A1"], "B2": cells["B1"],
  288. "A3": cells["A1"], "B3": cells["B1"],
  289. }
  290. for cell, val := range expect {
  291. v, err := xlsx.GetCellValue(sheet, cell)
  292. assert.NoError(t, err)
  293. if !assert.Equal(t, val, v, cell) {
  294. t.FailNow()
  295. }
  296. }
  297. })
  298. }
  299. func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) {
  300. const sheet = "Sheet1"
  301. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  302. cells := map[string]string{
  303. "A1": "A1 Value",
  304. "A2": "A2 Value",
  305. "A3": "A3 Value",
  306. "B1": "B1 Value",
  307. "B2": "B2 Value",
  308. "B3": "B3 Value",
  309. }
  310. t.Run("UpdateDuplicatedRows", func(t *testing.T) {
  311. xlsx := NewFile()
  312. assert.NoError(t, xlsx.SetCellStr(sheet, "A1", cells["A1"]))
  313. assert.NoError(t, xlsx.SetCellStr(sheet, "B1", cells["B1"]))
  314. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  315. assert.NoError(t, xlsx.SetCellStr(sheet, "A2", cells["A2"]))
  316. assert.NoError(t, xlsx.SetCellStr(sheet, "B2", cells["B2"]))
  317. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.UpdateDuplicatedRows"))) {
  318. t.FailNow()
  319. }
  320. expect := map[string]string{
  321. "A1": cells["A1"], "B1": cells["B1"],
  322. "A2": cells["A2"], "B2": cells["B2"],
  323. }
  324. for cell, val := range expect {
  325. v, err := xlsx.GetCellValue(sheet, cell)
  326. assert.NoError(t, err)
  327. if !assert.Equal(t, val, v, cell) {
  328. t.FailNow()
  329. }
  330. }
  331. })
  332. }
  333. func TestDuplicateRowFirstOfMultipleRows(t *testing.T) {
  334. const sheet = "Sheet1"
  335. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  336. cells := map[string]string{
  337. "A1": "A1 Value",
  338. "A2": "A2 Value",
  339. "A3": "A3 Value",
  340. "B1": "B1 Value",
  341. "B2": "B2 Value",
  342. "B3": "B3 Value",
  343. }
  344. newFileWithDefaults := func() *File {
  345. f := NewFile()
  346. for cell, val := range cells {
  347. assert.NoError(t, f.SetCellStr(sheet, cell, val))
  348. }
  349. return f
  350. }
  351. t.Run("FirstOfMultipleRows", func(t *testing.T) {
  352. xlsx := newFileWithDefaults()
  353. assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
  354. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FirstOfMultipleRows"))) {
  355. t.FailNow()
  356. }
  357. expect := map[string]string{
  358. "A1": cells["A1"], "B1": cells["B1"],
  359. "A2": cells["A1"], "B2": cells["B1"],
  360. "A3": cells["A2"], "B3": cells["B2"],
  361. "A4": cells["A3"], "B4": cells["B3"],
  362. }
  363. for cell, val := range expect {
  364. v, err := xlsx.GetCellValue(sheet, cell)
  365. assert.NoError(t, err)
  366. if !assert.Equal(t, val, v, cell) {
  367. t.FailNow()
  368. }
  369. }
  370. })
  371. }
  372. func TestDuplicateRowZeroWithNoRows(t *testing.T) {
  373. const sheet = "Sheet1"
  374. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  375. t.Run("ZeroWithNoRows", func(t *testing.T) {
  376. xlsx := NewFile()
  377. assert.EqualError(t, xlsx.DuplicateRow(sheet, 0), "invalid row number 0")
  378. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.ZeroWithNoRows"))) {
  379. t.FailNow()
  380. }
  381. val, err := xlsx.GetCellValue(sheet, "A1")
  382. assert.NoError(t, err)
  383. assert.Equal(t, "", val)
  384. val, err = xlsx.GetCellValue(sheet, "B1")
  385. assert.NoError(t, err)
  386. assert.Equal(t, "", val)
  387. val, err = xlsx.GetCellValue(sheet, "A2")
  388. assert.NoError(t, err)
  389. assert.Equal(t, "", val)
  390. val, err = xlsx.GetCellValue(sheet, "B2")
  391. assert.NoError(t, err)
  392. assert.Equal(t, "", val)
  393. assert.NoError(t, err)
  394. expect := map[string]string{
  395. "A1": "", "B1": "",
  396. "A2": "", "B2": "",
  397. }
  398. for cell, val := range expect {
  399. v, err := xlsx.GetCellValue(sheet, cell)
  400. assert.NoError(t, err)
  401. if !assert.Equal(t, val, v, cell) {
  402. t.FailNow()
  403. }
  404. }
  405. })
  406. }
  407. func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) {
  408. const sheet = "Sheet1"
  409. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  410. t.Run("MiddleRowOfEmptyFile", func(t *testing.T) {
  411. xlsx := NewFile()
  412. assert.NoError(t, xlsx.DuplicateRow(sheet, 99))
  413. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.MiddleRowOfEmptyFile"))) {
  414. t.FailNow()
  415. }
  416. expect := map[string]string{
  417. "A98": "",
  418. "A99": "",
  419. "A100": "",
  420. }
  421. for cell, val := range expect {
  422. v, err := xlsx.GetCellValue(sheet, cell)
  423. assert.NoError(t, err)
  424. if !assert.Equal(t, val, v, cell) {
  425. t.FailNow()
  426. }
  427. }
  428. })
  429. }
  430. func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) {
  431. const sheet = "Sheet1"
  432. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  433. cells := map[string]string{
  434. "A1": "A1 Value",
  435. "A2": "A2 Value",
  436. "A3": "A3 Value",
  437. "B1": "B1 Value",
  438. "B2": "B2 Value",
  439. "B3": "B3 Value",
  440. }
  441. newFileWithDefaults := func() *File {
  442. f := NewFile()
  443. for cell, val := range cells {
  444. assert.NoError(t, f.SetCellStr(sheet, cell, val))
  445. }
  446. return f
  447. }
  448. t.Run("WithLargeOffsetToMiddleOfData", func(t *testing.T) {
  449. xlsx := newFileWithDefaults()
  450. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 3))
  451. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToMiddleOfData"))) {
  452. t.FailNow()
  453. }
  454. expect := map[string]string{
  455. "A1": cells["A1"], "B1": cells["B1"],
  456. "A2": cells["A2"], "B2": cells["B2"],
  457. "A3": cells["A1"], "B3": cells["B1"],
  458. "A4": cells["A3"], "B4": cells["B3"],
  459. }
  460. for cell, val := range expect {
  461. v, err := xlsx.GetCellValue(sheet, cell)
  462. assert.NoError(t, err)
  463. if !assert.Equal(t, val, v, cell) {
  464. t.FailNow()
  465. }
  466. }
  467. })
  468. }
  469. func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) {
  470. const sheet = "Sheet1"
  471. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  472. cells := map[string]string{
  473. "A1": "A1 Value",
  474. "A2": "A2 Value",
  475. "A3": "A3 Value",
  476. "B1": "B1 Value",
  477. "B2": "B2 Value",
  478. "B3": "B3 Value",
  479. }
  480. newFileWithDefaults := func() *File {
  481. f := NewFile()
  482. for cell, val := range cells {
  483. assert.NoError(t, f.SetCellStr(sheet, cell, val))
  484. }
  485. return f
  486. }
  487. t.Run("WithLargeOffsetToEmptyRows", func(t *testing.T) {
  488. xlsx := newFileWithDefaults()
  489. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 7))
  490. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToEmptyRows"))) {
  491. t.FailNow()
  492. }
  493. expect := map[string]string{
  494. "A1": cells["A1"], "B1": cells["B1"],
  495. "A2": cells["A2"], "B2": cells["B2"],
  496. "A3": cells["A3"], "B3": cells["B3"],
  497. "A7": cells["A1"], "B7": cells["B1"],
  498. }
  499. for cell, val := range expect {
  500. v, err := xlsx.GetCellValue(sheet, cell)
  501. assert.NoError(t, err)
  502. if !assert.Equal(t, val, v, cell) {
  503. t.FailNow()
  504. }
  505. }
  506. })
  507. }
  508. func TestDuplicateRowInsertBefore(t *testing.T) {
  509. const sheet = "Sheet1"
  510. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  511. cells := map[string]string{
  512. "A1": "A1 Value",
  513. "A2": "A2 Value",
  514. "A3": "A3 Value",
  515. "B1": "B1 Value",
  516. "B2": "B2 Value",
  517. "B3": "B3 Value",
  518. }
  519. newFileWithDefaults := func() *File {
  520. f := NewFile()
  521. for cell, val := range cells {
  522. assert.NoError(t, f.SetCellStr(sheet, cell, val))
  523. }
  524. return f
  525. }
  526. t.Run("InsertBefore", func(t *testing.T) {
  527. xlsx := newFileWithDefaults()
  528. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 2, 1))
  529. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBefore"))) {
  530. t.FailNow()
  531. }
  532. expect := map[string]string{
  533. "A1": cells["A2"], "B1": cells["B2"],
  534. "A2": cells["A1"], "B2": cells["B1"],
  535. "A3": cells["A2"], "B3": cells["B2"],
  536. "A4": cells["A3"], "B4": cells["B3"],
  537. }
  538. for cell, val := range expect {
  539. v, err := xlsx.GetCellValue(sheet, cell)
  540. assert.NoError(t, err)
  541. if !assert.Equal(t, val, v, cell) {
  542. t.FailNow()
  543. }
  544. }
  545. })
  546. }
  547. func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) {
  548. const sheet = "Sheet1"
  549. outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
  550. cells := map[string]string{
  551. "A1": "A1 Value",
  552. "A2": "A2 Value",
  553. "A3": "A3 Value",
  554. "B1": "B1 Value",
  555. "B2": "B2 Value",
  556. "B3": "B3 Value",
  557. }
  558. newFileWithDefaults := func() *File {
  559. f := NewFile()
  560. for cell, val := range cells {
  561. assert.NoError(t, f.SetCellStr(sheet, cell, val))
  562. }
  563. return f
  564. }
  565. t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
  566. xlsx := newFileWithDefaults()
  567. assert.NoError(t, xlsx.DuplicateRowTo(sheet, 3, 1))
  568. if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithLargeOffset"))) {
  569. t.FailNow()
  570. }
  571. expect := map[string]string{
  572. "A1": cells["A3"], "B1": cells["B3"],
  573. "A2": cells["A1"], "B2": cells["B1"],
  574. "A3": cells["A2"], "B3": cells["B2"],
  575. "A4": cells["A3"], "B4": cells["B3"],
  576. }
  577. for cell, val := range expect {
  578. v, err := xlsx.GetCellValue(sheet, cell)
  579. assert.NoError(t, err)
  580. if !assert.Equal(t, val, v) {
  581. t.FailNow()
  582. }
  583. }
  584. })
  585. }
  586. func TestDuplicateRowInvalidRownum(t *testing.T) {
  587. const sheet = "Sheet1"
  588. outFile := filepath.Join("test", "TestDuplicateRowInvalidRownum.%s.xlsx")
  589. cells := map[string]string{
  590. "A1": "A1 Value",
  591. "A2": "A2 Value",
  592. "A3": "A3 Value",
  593. "B1": "B1 Value",
  594. "B2": "B2 Value",
  595. "B3": "B3 Value",
  596. }
  597. invalidIndexes := []int{-100, -2, -1, 0}
  598. for _, row := range invalidIndexes {
  599. name := fmt.Sprintf("%d", row)
  600. t.Run(name, func(t *testing.T) {
  601. xlsx := NewFile()
  602. for col, val := range cells {
  603. assert.NoError(t, xlsx.SetCellStr(sheet, col, val))
  604. }
  605. assert.EqualError(t, xlsx.DuplicateRow(sheet, row), fmt.Sprintf("invalid row number %d", row))
  606. for col, val := range cells {
  607. v, err := xlsx.GetCellValue(sheet, col)
  608. assert.NoError(t, err)
  609. if !assert.Equal(t, val, v) {
  610. t.FailNow()
  611. }
  612. }
  613. assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
  614. })
  615. }
  616. for _, row1 := range invalidIndexes {
  617. for _, row2 := range invalidIndexes {
  618. name := fmt.Sprintf("[%d,%d]", row1, row2)
  619. t.Run(name, func(t *testing.T) {
  620. xlsx := NewFile()
  621. for col, val := range cells {
  622. assert.NoError(t, xlsx.SetCellStr(sheet, col, val))
  623. }
  624. assert.EqualError(t, xlsx.DuplicateRowTo(sheet, row1, row2), fmt.Sprintf("invalid row number %d", row1))
  625. for col, val := range cells {
  626. v, err := xlsx.GetCellValue(sheet, col)
  627. assert.NoError(t, err)
  628. if !assert.Equal(t, val, v) {
  629. t.FailNow()
  630. }
  631. }
  632. assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
  633. })
  634. }
  635. }
  636. }
  637. func TestGetValueFrom(t *testing.T) {
  638. c := &xlsxC{T: "inlineStr"}
  639. f := NewFile()
  640. d := &xlsxSST{}
  641. val, err := c.getValueFrom(f, d)
  642. assert.NoError(t, err)
  643. assert.Equal(t, "", val)
  644. }
  645. func TestErrSheetNotExistError(t *testing.T) {
  646. err := ErrSheetNotExist{SheetName: "Sheet1"}
  647. assert.EqualValues(t, err.Error(), "sheet Sheet1 is not exist")
  648. }
  649. func BenchmarkRows(b *testing.B) {
  650. f, _ := OpenFile(filepath.Join("test", "Book1.xlsx"))
  651. for i := 0; i < b.N; i++ {
  652. rows, _ := f.Rows("Sheet2")
  653. for rows.Next() {
  654. row, _ := rows.Columns()
  655. for i := range row {
  656. if i >= 0 {
  657. continue
  658. }
  659. }
  660. }
  661. }
  662. }
  663. func trimSliceSpace(s []string) []string {
  664. for {
  665. if len(s) > 0 && s[len(s)-1] == "" {
  666. s = s[:len(s)-1]
  667. } else {
  668. break
  669. }
  670. }
  671. return s
  672. }