rows_test.go 25 KB

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