rows_test.go 24 KB

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