lib_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. package xlsx
  2. import (
  3. "bytes"
  4. "encoding/xml"
  5. "strconv"
  6. "strings"
  7. "testing"
  8. )
  9. // Test we can correctly open a XSLX file and return a xlsx.File
  10. // struct.
  11. func TestOpenFile(t *testing.T) {
  12. var xlsxFile *File
  13. var error error
  14. xlsxFile, error = OpenFile("testfile.xlsx")
  15. if error != nil {
  16. t.Error(error.Error())
  17. return
  18. }
  19. if xlsxFile == nil {
  20. t.Error("OpenFile returned nil FileInterface without generating an os.Error")
  21. return
  22. }
  23. }
  24. // Test that when we open a real XLSX file we create xlsx.Sheet
  25. // objects for the sheets inside the file and that these sheets are
  26. // themselves correct.
  27. func TestCreateSheet(t *testing.T) {
  28. var xlsxFile *File
  29. var error error
  30. var sheet *Sheet
  31. var row *Row
  32. xlsxFile, error = OpenFile("testfile.xlsx")
  33. if error != nil {
  34. t.Error(error.Error())
  35. return
  36. }
  37. if xlsxFile == nil {
  38. t.Error("OpenFile returned a nil File pointer but did not generate an error.")
  39. return
  40. }
  41. sheetLen := len(xlsxFile.Sheets)
  42. if sheetLen == 0 {
  43. t.Error("Expected len(xlsxFile.Sheets) > 0, but got ", sheetLen)
  44. return
  45. }
  46. sheet = xlsxFile.Sheets[0]
  47. rowLen := len(sheet.Rows)
  48. if rowLen != 2 {
  49. t.Error("Expected len(sheet.Rows) == 2, but got ", rowLen)
  50. return
  51. }
  52. row = sheet.Rows[0]
  53. if len(row.Cells) != 2 {
  54. t.Error("Expected len(row.Cells) == 2")
  55. return
  56. }
  57. cell := row.Cells[0]
  58. cellstring := cell.String()
  59. if cellstring != "Foo" {
  60. t.Error("Expected cell.String() == 'Foo', got ", cellstring)
  61. }
  62. }
  63. // Test that GetStyle correctly converts the xlsxStyle.Fonts.
  64. func TestGetStyleWithFonts(t *testing.T) {
  65. var cell *Cell
  66. var style *Style
  67. var xStyles *xlsxStyles
  68. var fonts []xlsxFont
  69. var cellXfs []xlsxXf
  70. fonts = make([]xlsxFont, 1)
  71. fonts[0] = xlsxFont{
  72. Sz: xlsxVal{Val: "10"},
  73. Name: xlsxVal{Val: "Calibra"}}
  74. cellXfs = make([]xlsxXf, 1)
  75. cellXfs[0] = xlsxXf{ApplyFont: true, FontId: 0}
  76. xStyles = &xlsxStyles{Fonts: fonts, CellXfs: cellXfs}
  77. cell = &Cell{Value: "123", styleIndex: 1, styles: xStyles}
  78. style = cell.GetStyle()
  79. if style == nil {
  80. t.Error("No style returned by cell.GetStyle()")
  81. }
  82. if style.Font.Size != 10 {
  83. t.Error("Expected style.Font.Size == 10, but got ", style.Font.Size)
  84. }
  85. if style.Font.Name != "Calibra" {
  86. t.Error("Expected style.Font.Name == 'Calibra', but got ", style.Font.Name)
  87. }
  88. }
  89. // Test that GetStyle correctly converts the xlsxStyle.Fills.
  90. func TestGetStyleWithFills(t *testing.T) {
  91. var cell *Cell
  92. var style *Style
  93. var xStyles *xlsxStyles
  94. var fills []xlsxFill
  95. var cellXfs []xlsxXf
  96. fills = make([]xlsxFill, 1)
  97. fills[0] = xlsxFill{
  98. PatternFill: xlsxPatternFill{
  99. PatternType: "solid",
  100. FgColor: xlsxColor{RGB: "FF000000"},
  101. BgColor: xlsxColor{RGB: "00FF0000"}}}
  102. cellXfs = make([]xlsxXf, 1)
  103. cellXfs[0] = xlsxXf{ApplyFill: true, FillId: 0}
  104. xStyles = &xlsxStyles{Fills: fills, CellXfs: cellXfs}
  105. cell = &Cell{Value: "123", styleIndex: 1, styles: xStyles}
  106. style = cell.GetStyle()
  107. fill := style.Fill
  108. if fill.PatternType != "solid" {
  109. t.Error("Expected fill.PatternType == 'solid', but got ",
  110. fill.PatternType)
  111. }
  112. if fill.BgColor != "00FF0000" {
  113. t.Error("Expected fill.BgColor == '00FF0000', but got ",
  114. fill.BgColor)
  115. }
  116. if fill.FgColor != "FF000000" {
  117. t.Error("Expected fill.FgColor == 'FF000000', but got ",
  118. fill.FgColor)
  119. }
  120. }
  121. // Test that GetStyle correctly converts the xlsxStyle.Borders.
  122. func TestGetStyleWithBorders(t *testing.T) {
  123. var cell *Cell
  124. var style *Style
  125. var xStyles *xlsxStyles
  126. var borders []xlsxBorder
  127. var cellXfs []xlsxXf
  128. borders = make([]xlsxBorder, 1)
  129. borders[0] = xlsxBorder{
  130. Left: xlsxLine{Style: "thin"},
  131. Right: xlsxLine{Style: "thin"},
  132. Top: xlsxLine{Style: "thin"},
  133. Bottom: xlsxLine{Style: "thin"}}
  134. cellXfs = make([]xlsxXf, 1)
  135. cellXfs[0] = xlsxXf{ApplyBorder: true, BorderId: 0}
  136. xStyles = &xlsxStyles{Borders: borders, CellXfs: cellXfs}
  137. cell = &Cell{Value: "123", styleIndex: 1, styles: xStyles}
  138. style = cell.GetStyle()
  139. border := style.Border
  140. if border.Left != "thin" {
  141. t.Error("Expected border.Left == 'thin', but got ",
  142. border.Left)
  143. }
  144. if border.Right != "thin" {
  145. t.Error("Expected border.Right == 'thin', but got ",
  146. border.Right)
  147. }
  148. if border.Top != "thin" {
  149. t.Error("Expected border.Top == 'thin', but got ",
  150. border.Top)
  151. }
  152. if border.Bottom != "thin" {
  153. t.Error("Expected border.Bottom == 'thin', but got ",
  154. border.Bottom)
  155. }
  156. }
  157. // Test that we can correctly extract a reference table from the
  158. // sharedStrings.xml file embedded in the XLSX file and return a
  159. // reference table of string values from it.
  160. func TestReadSharedStringsFromZipFile(t *testing.T) {
  161. var xlsxFile *File
  162. var error error
  163. xlsxFile, error = OpenFile("testfile.xlsx")
  164. if error != nil {
  165. t.Error(error.Error())
  166. return
  167. }
  168. if xlsxFile.referenceTable == nil {
  169. t.Error("expected non nil xlsxFile.referenceTable")
  170. return
  171. }
  172. }
  173. func testXf(t *testing.T, result, expected *xlsxXf) {
  174. if result.ApplyAlignment != expected.ApplyAlignment {
  175. t.Error("Expected result.ApplyAlignment == ", expected.ApplyAlignment,
  176. ", got", result.ApplyAlignment)
  177. return
  178. }
  179. if result.ApplyBorder != expected.ApplyBorder {
  180. t.Error("Expected result.ApplyBorder == ", expected.ApplyBorder,
  181. ", got ", result.ApplyBorder)
  182. return
  183. }
  184. if result.ApplyFont != expected.ApplyFont {
  185. t.Error("Expect result.ApplyFont == ", expected.ApplyFont,
  186. ", got ", result.ApplyFont)
  187. return
  188. }
  189. if result.ApplyFill != expected.ApplyFill {
  190. t.Error("Expected result.ApplyFill == ", expected.ApplyFill,
  191. ", got ", result.ApplyFill)
  192. return
  193. }
  194. if result.ApplyProtection != expected.ApplyProtection {
  195. t.Error("Expexcted result.ApplyProtection == ", expected.ApplyProtection,
  196. ", got ", result.ApplyProtection)
  197. return
  198. }
  199. if result.BorderId != expected.BorderId {
  200. t.Error("Expected BorderId == ", expected.BorderId,
  201. ". got ", result.BorderId)
  202. return
  203. }
  204. if result.FillId != expected.FillId {
  205. t.Error("Expected result.FillId == ", expected.FillId,
  206. ", got ", result.FillId)
  207. return
  208. }
  209. if result.FontId != expected.FontId {
  210. t.Error("Expected result.FontId == ", expected.FontId,
  211. ", got ", result.FontId)
  212. return
  213. }
  214. if result.NumFmtId != expected.NumFmtId {
  215. t.Error("Expected result.NumFmtId == ", expected.NumFmtId,
  216. ", got ", result.NumFmtId)
  217. return
  218. }
  219. }
  220. // We can correctly extract a style table from the style.xml file
  221. // embedded in the XLSX file and return a styles struct from it.
  222. func TestReadStylesFromZipFile(t *testing.T) {
  223. var xlsxFile *File
  224. var error error
  225. var fontCount, fillCount, borderCount, cellStyleXfCount, cellXfCount int
  226. var font xlsxFont
  227. var fill xlsxFill
  228. var border xlsxBorder
  229. var xf xlsxXf
  230. xlsxFile, error = OpenFile("testfile.xlsx")
  231. if error != nil {
  232. t.Error(error.Error())
  233. return
  234. }
  235. if xlsxFile.styles == nil {
  236. t.Error("expected non nil xlsxFile.styles")
  237. return
  238. }
  239. fontCount = len(xlsxFile.styles.Fonts)
  240. if fontCount != 4 {
  241. t.Error("expected exactly 4 xslxFonts, got ", fontCount)
  242. return
  243. }
  244. font = xlsxFile.styles.Fonts[0]
  245. if font.Sz.Val != "11" {
  246. t.Error("expected font.Sz.Val == 11, got ", font.Sz.Val)
  247. return
  248. }
  249. if font.Name.Val != "Calibri" {
  250. t.Error("expected font.Name.Val == 'Calibri', got ", font.Name.Val)
  251. return
  252. }
  253. fillCount = len(xlsxFile.styles.Fills)
  254. if fillCount != 3 {
  255. t.Error("Expected exactly 3 xlsxFills, got ", fillCount)
  256. return
  257. }
  258. fill = xlsxFile.styles.Fills[2]
  259. if fill.PatternFill.PatternType != "solid" {
  260. t.Error("Expected PatternFill.PatternType == 'solid', but got ",
  261. fill.PatternFill.PatternType)
  262. return
  263. }
  264. borderCount = len(xlsxFile.styles.Borders)
  265. if borderCount != 2 {
  266. t.Error("Expected exactly 2 xlsxBorders, got ", borderCount)
  267. return
  268. }
  269. border = xlsxFile.styles.Borders[1]
  270. if border.Left.Style != "thin" {
  271. t.Error("Expected border.Left.Style == 'thin', got ", border.Left.Style)
  272. return
  273. }
  274. if border.Right.Style != "thin" {
  275. t.Error("Expected border.Right.Style == 'thin', got ", border.Right.Style)
  276. return
  277. }
  278. if border.Top.Style != "thin" {
  279. t.Error("Expected border.Top.Style == 'thin', got ", border.Top.Style)
  280. return
  281. }
  282. if border.Bottom.Style != "thin" {
  283. t.Error("Expected border.Bottom.Style == 'thin', got ", border.Bottom.Style)
  284. return
  285. }
  286. cellStyleXfCount = len(xlsxFile.styles.CellStyleXfs)
  287. if cellStyleXfCount != 20 {
  288. t.Error("Expected excactly 20 cellStyleXfs, got ", cellStyleXfCount)
  289. return
  290. }
  291. xf = xlsxFile.styles.CellStyleXfs[0]
  292. expectedXf := &xlsxXf{
  293. ApplyAlignment: true,
  294. ApplyBorder: true,
  295. ApplyFont: true,
  296. ApplyFill: false,
  297. ApplyProtection: true,
  298. BorderId: 0,
  299. FillId: 0,
  300. FontId: 0,
  301. NumFmtId: 164}
  302. testXf(t, &xf, expectedXf)
  303. cellXfCount = len(xlsxFile.styles.CellXfs)
  304. if cellXfCount != 3 {
  305. t.Error("Expected excactly 3 cellXfs, got ", cellXfCount)
  306. return
  307. }
  308. xf = xlsxFile.styles.CellXfs[0]
  309. expectedXf = &xlsxXf{
  310. ApplyAlignment: false,
  311. ApplyBorder: false,
  312. ApplyFont: false,
  313. ApplyFill: false,
  314. ApplyProtection: false,
  315. BorderId: 0,
  316. FillId: 0,
  317. FontId: 0,
  318. NumFmtId: 164}
  319. testXf(t, &xf, expectedXf)
  320. }
  321. // We can correctly extract a map of relationship Ids to the worksheet files in
  322. // which they are contained from the XLSX file.
  323. func TestReadWorkbookRelationsFromZipFile(t *testing.T) {
  324. var xlsxFile *File
  325. var error error
  326. xlsxFile, error = OpenFile("testfile.xlsx")
  327. if error != nil {
  328. t.Error(error.Error())
  329. return
  330. }
  331. sheetCount := len(xlsxFile.Sheet)
  332. if sheetCount != 3 {
  333. t.Error("Expected 3 items in xlsxFile.Sheet, but found ", strconv.Itoa(sheetCount))
  334. }
  335. }
  336. func TestLettersToNumeric(t *testing.T) {
  337. cases := map[string]int{"A": 0, "G": 6, "z": 25, "AA": 26, "Az": 51,
  338. "BA": 52, "Bz": 77, "ZA": 26*26 + 0, "ZZ": 26*26 + 25,
  339. "AAA": 26*26 + 26 + 0, "AMI": 1022}
  340. for input, ans := range cases {
  341. output := lettersToNumeric(input)
  342. if output != ans {
  343. t.Error("Expected output '"+input+"' == ", ans,
  344. "but got ", strconv.Itoa(output))
  345. }
  346. }
  347. }
  348. func TestLetterOnlyMapFunction(t *testing.T) {
  349. var input string = "ABC123"
  350. var output string = strings.Map(letterOnlyMapF, input)
  351. if output != "ABC" {
  352. t.Error("Expected output == 'ABC' but got ", output)
  353. }
  354. input = "abc123"
  355. output = strings.Map(letterOnlyMapF, input)
  356. if output != "ABC" {
  357. t.Error("Expected output == 'ABC' but got ", output)
  358. }
  359. }
  360. func TestIntOnlyMapFunction(t *testing.T) {
  361. var input string = "ABC123"
  362. var output string = strings.Map(intOnlyMapF, input)
  363. if output != "123" {
  364. t.Error("Expected output == '123' but got ", output)
  365. }
  366. }
  367. func TestGetCoordsFromCellIDString(t *testing.T) {
  368. var cellIDString string = "A3"
  369. var x, y int
  370. var error error
  371. x, y, error = getCoordsFromCellIDString(cellIDString)
  372. if error != nil {
  373. t.Error(error)
  374. }
  375. if x != 0 {
  376. t.Error("Expected x == 0, but got ", strconv.Itoa(x))
  377. }
  378. if y != 2 {
  379. t.Error("Expected y == 2, but got ", strconv.Itoa(y))
  380. }
  381. }
  382. func TestGetMaxMinFromDimensionRef(t *testing.T) {
  383. var dimensionRef string = "A1:B2"
  384. var minx, miny, maxx, maxy int
  385. var err error
  386. minx, miny, maxx, maxy, err = getMaxMinFromDimensionRef(dimensionRef)
  387. if err != nil {
  388. t.Error(err)
  389. }
  390. if minx != 0 {
  391. t.Error("Expected minx == 0, but got ", strconv.Itoa(minx))
  392. }
  393. if miny != 0 {
  394. t.Error("Expected miny == 0, but got ", strconv.Itoa(miny))
  395. }
  396. if maxx != 1 {
  397. t.Error("Expected maxx == 0, but got ", strconv.Itoa(maxx))
  398. }
  399. if maxy != 1 {
  400. t.Error("Expected maxy == 0, but got ", strconv.Itoa(maxy))
  401. }
  402. }
  403. func TestGetRangeFromString(t *testing.T) {
  404. var rangeString string
  405. var lower, upper int
  406. var error error
  407. rangeString = "1:3"
  408. lower, upper, error = getRangeFromString(rangeString)
  409. if error != nil {
  410. t.Error(error)
  411. }
  412. if lower != 1 {
  413. t.Error("Expected lower bound == 1, but got ", strconv.Itoa(lower))
  414. }
  415. if upper != 3 {
  416. t.Error("Expected upper bound == 3, but got ", strconv.Itoa(upper))
  417. }
  418. }
  419. func TestMakeRowFromSpan(t *testing.T) {
  420. var rangeString string
  421. var row *Row
  422. var length int
  423. rangeString = "1:3"
  424. row = makeRowFromSpan(rangeString)
  425. length = len(row.Cells)
  426. if length != 3 {
  427. t.Error("Expected a row with 3 cells, but got ", strconv.Itoa(length))
  428. }
  429. rangeString = "5:7" // Note - we ignore lower bound!
  430. row = makeRowFromSpan(rangeString)
  431. length = len(row.Cells)
  432. if length != 7 {
  433. t.Error("Expected a row with 7 cells, but got ", strconv.Itoa(length))
  434. }
  435. rangeString = "1:1"
  436. row = makeRowFromSpan(rangeString)
  437. length = len(row.Cells)
  438. if length != 1 {
  439. t.Error("Expected a row with 1 cells, but got ", strconv.Itoa(length))
  440. }
  441. }
  442. func TestReadRowsFromSheet(t *testing.T) {
  443. var sharedstringsXML = bytes.NewBufferString(`
  444. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  445. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="4" uniqueCount="4">
  446. <si>
  447. <t>Foo</t>
  448. </si>
  449. <si>
  450. <t>Bar</t>
  451. </si>
  452. <si>
  453. <t xml:space="preserve">Baz </t>
  454. </si>
  455. <si>
  456. <t>Quuk</t>
  457. </si>
  458. </sst>`)
  459. var sheetxml = bytes.NewBufferString(`
  460. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  461. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  462. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  463. <dimension ref="A1:B2"/>
  464. <sheetViews>
  465. <sheetView tabSelected="1" workbookViewId="0">
  466. <selection activeCell="C2" sqref="C2"/>
  467. </sheetView>
  468. </sheetViews>
  469. <sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  470. <sheetData>
  471. <row r="1" spans="1:2">
  472. <c r="A1" t="s">
  473. <v>0</v>
  474. </c>
  475. <c r="B1" t="s">
  476. <v>1</v>
  477. </c>
  478. </row>
  479. <row r="2" spans="1:2">
  480. <c r="A2" t="s">
  481. <v>2</v>
  482. </c>
  483. <c r="B2" t="s">
  484. <v>3</v>
  485. </c>
  486. </row>
  487. </sheetData>
  488. <pageMargins left="0.7" right="0.7"
  489. top="0.78740157499999996"
  490. bottom="0.78740157499999996"
  491. header="0.3"
  492. footer="0.3"/>
  493. </worksheet>`)
  494. worksheet := new(xlsxWorksheet)
  495. error := xml.NewDecoder(sheetxml).Decode(worksheet)
  496. if error != nil {
  497. t.Error(error.Error())
  498. return
  499. }
  500. sst := new(xlsxSST)
  501. error = xml.NewDecoder(sharedstringsXML).Decode(sst)
  502. if error != nil {
  503. t.Error(error.Error())
  504. return
  505. }
  506. file := new(File)
  507. file.referenceTable = MakeSharedStringRefTable(sst)
  508. rows, maxCols, maxRows := readRowsFromSheet(worksheet, file)
  509. if maxRows != 2 {
  510. t.Error("Expected maxRows == 2")
  511. }
  512. if maxCols != 2 {
  513. t.Error("Expected maxCols == 2")
  514. }
  515. row := rows[0]
  516. if len(row.Cells) != 2 {
  517. t.Error("Expected len(row.Cells) == 2, got ", strconv.Itoa(len(row.Cells)))
  518. }
  519. cell1 := row.Cells[0]
  520. if cell1.String() != "Foo" {
  521. t.Error("Expected cell1.String() == 'Foo', got ", cell1.String())
  522. }
  523. cell2 := row.Cells[1]
  524. if cell2.String() != "Bar" {
  525. t.Error("Expected cell2.String() == 'Bar', got ", cell2.String())
  526. }
  527. }
  528. func TestReadRowsFromSheetWithLeadingEmptyRows(t *testing.T) {
  529. var sharedstringsXML = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  530. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="2" uniqueCount="2"><si><t>ABC</t></si><si><t>DEF</t></si></sst>`)
  531. var sheetxml = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  532. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
  533. <dimension ref="A4:A5"/>
  534. <sheetViews>
  535. <sheetView tabSelected="1" workbookViewId="0">
  536. <selection activeCell="A2" sqref="A2"/>
  537. </sheetView>
  538. </sheetViews>
  539. <sheetFormatPr baseColWidth="10" defaultRowHeight="15" x14ac:dyDescent="0"/>
  540. <sheetData>
  541. <row r="4" spans="1:1">
  542. <c r="A4" t="s">
  543. <v>0</v>
  544. </c>
  545. </row>
  546. <row r="5" spans="1:1">
  547. <c r="A5" t="s">
  548. <v>1</v>
  549. </c>
  550. </row>
  551. </sheetData>
  552. <pageMargins left="0.75" right="0.75" top="1" bottom="1" header="0.5" footer="0.5"/>
  553. <pageSetup paperSize="9" orientation="portrait" horizontalDpi="4294967292" verticalDpi="4294967292"/>
  554. <extLst>
  555. <ext uri="{64002731-A6B0-56B0-2670-7721B7C09600}" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main">
  556. <mx:PLV Mode="0" OnePage="0" WScale="0"/>
  557. </ext>
  558. </extLst>
  559. </worksheet>
  560. `)
  561. worksheet := new(xlsxWorksheet)
  562. error := xml.NewDecoder(sheetxml).Decode(worksheet)
  563. if error != nil {
  564. t.Error(error.Error())
  565. return
  566. }
  567. sst := new(xlsxSST)
  568. error = xml.NewDecoder(sharedstringsXML).Decode(sst)
  569. if error != nil {
  570. t.Error(error.Error())
  571. return
  572. }
  573. file := new(File)
  574. file.referenceTable = MakeSharedStringRefTable(sst)
  575. rows, maxCols, maxRows := readRowsFromSheet(worksheet, file)
  576. if maxRows != 2 {
  577. t.Error("Expected maxRows == 2, got ", strconv.Itoa(len(rows)))
  578. }
  579. if maxCols != 1 {
  580. t.Error("Expected maxCols == 1, got ", strconv.Itoa(maxCols))
  581. }
  582. }
  583. func TestReadRowsFromSheetWithEmptyCells(t *testing.T) {
  584. var sharedstringsXML = bytes.NewBufferString(`
  585. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  586. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="8" uniqueCount="5"><si><t>Bob</t></si><si><t>Alice</t></si><si><t>Sue</t></si><si><t>Yes</t></si><si><t>No</t></si></sst>`)
  587. var sheetxml = bytes.NewBufferString(`
  588. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  589. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><dimension ref="A1:C3"/><sheetViews><sheetView tabSelected="1" workbookViewId="0"><selection activeCell="D3" sqref="D3"/></sheetView></sheetViews><sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  590. <sheetData>
  591. <row r="1" spans="1:3">
  592. <c r="A1" t="s">
  593. <v>
  594. 0
  595. </v>
  596. </c>
  597. <c r="B1" t="s">
  598. <v>
  599. 1
  600. </v>
  601. </c>
  602. <c r="C1" t="s">
  603. <v>
  604. 2
  605. </v>
  606. </c>
  607. </row>
  608. <row r="2" spans="1:3">
  609. <c r="A2" t="s">
  610. <v>
  611. 3
  612. </v>
  613. </c>
  614. <c r="B2" t="s">
  615. <v>
  616. 4
  617. </v>
  618. </c>
  619. <c r="C2" t="s">
  620. <v>
  621. 3
  622. </v>
  623. </c>
  624. </row>
  625. <row r="3" spans="1:3">
  626. <c r="A3" t="s">
  627. <v>
  628. 4
  629. </v>
  630. </c>
  631. <c r="C3" t="s">
  632. <v>
  633. 3
  634. </v>
  635. </c>
  636. </row>
  637. </sheetData>
  638. <pageMargins left="0.7" right="0.7" top="0.78740157499999996" bottom="0.78740157499999996" header="0.3" footer="0.3"/>
  639. </worksheet>
  640. `)
  641. worksheet := new(xlsxWorksheet)
  642. error := xml.NewDecoder(sheetxml).Decode(worksheet)
  643. if error != nil {
  644. t.Error(error.Error())
  645. return
  646. }
  647. sst := new(xlsxSST)
  648. error = xml.NewDecoder(sharedstringsXML).Decode(sst)
  649. if error != nil {
  650. t.Error(error.Error())
  651. return
  652. }
  653. file := new(File)
  654. file.referenceTable = MakeSharedStringRefTable(sst)
  655. rows, maxCols, maxRows := readRowsFromSheet(worksheet, file)
  656. if maxRows != 3 {
  657. t.Error("Expected maxRows == 3, got ", strconv.Itoa(len(rows)))
  658. }
  659. if maxCols != 3 {
  660. t.Error("Expected maxCols == 3, got ", strconv.Itoa(maxCols))
  661. }
  662. row := rows[2]
  663. if len(row.Cells) != 3 {
  664. t.Error("Expected len(row.Cells) == 3, got ", strconv.Itoa(len(row.Cells)))
  665. }
  666. cell1 := row.Cells[0]
  667. if cell1.String() != "No" {
  668. t.Error("Expected cell1.String() == 'No', got ", cell1.String())
  669. }
  670. cell2 := row.Cells[1]
  671. if cell2.String() != "" {
  672. t.Error("Expected cell2.String() == '', got ", cell2.String())
  673. }
  674. cell3 := row.Cells[2]
  675. if cell3.String() != "Yes" {
  676. t.Error("Expected cell3.String() == 'Yes', got ", cell3.String())
  677. }
  678. }
  679. func TestReadRowsFromSheetWithTrailingEmptyCells(t *testing.T) {
  680. var row *Row
  681. var cell1, cell2, cell3, cell4 *Cell
  682. var sharedstringsXML = bytes.NewBufferString(`
  683. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  684. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="4" uniqueCount="4"><si><t>A</t></si><si><t>B</t></si><si><t>C</t></si><si><t>D</t></si></sst>`)
  685. var sheetxml = bytes.NewBufferString(`
  686. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  687. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><dimension ref="A1:D8"/><sheetViews><sheetView tabSelected="1" workbookViewId="0"><selection activeCell="A7" sqref="A7"/></sheetView></sheetViews><sheetFormatPr baseColWidth="10" defaultRowHeight="15"/><sheetData><row r="1" spans="1:4"><c r="A1" t="s"><v>0</v></c><c r="B1" t="s"><v>1</v></c><c r="C1" t="s"><v>2</v></c><c r="D1" t="s"><v>3</v></c></row><row r="2" spans="1:4"><c r="A2"><v>1</v></c></row><row r="3" spans="1:4"><c r="B3"><v>1</v></c></row><row r="4" spans="1:4"><c r="C4"><v>1</v></c></row><row r="5" spans="1:4"><c r="D5"><v>1</v></c></row><row r="6" spans="1:4"><c r="C6"><v>1</v></c></row><row r="7" spans="1:4"><c r="B7"><v>1</v></c></row><row r="8" spans="1:4"><c r="A8"><v>1</v></c></row></sheetData><pageMargins left="0.7" right="0.7" top="0.78740157499999996" bottom="0.78740157499999996" header="0.3" footer="0.3"/></worksheet>
  688. `)
  689. worksheet := new(xlsxWorksheet)
  690. error := xml.NewDecoder(sheetxml).Decode(worksheet)
  691. if error != nil {
  692. t.Error(error.Error())
  693. return
  694. }
  695. sst := new(xlsxSST)
  696. error = xml.NewDecoder(sharedstringsXML).Decode(sst)
  697. if error != nil {
  698. t.Error(error.Error())
  699. return
  700. }
  701. file := new(File)
  702. file.referenceTable = MakeSharedStringRefTable(sst)
  703. rows, maxCol, maxRow := readRowsFromSheet(worksheet, file)
  704. if maxCol != 4 {
  705. t.Error("Expected maxCol == 4, got ", strconv.Itoa(maxCol))
  706. }
  707. if maxRow != 8 {
  708. t.Error("Expected maxRow == 8, got ", strconv.Itoa(maxRow))
  709. }
  710. row = rows[0]
  711. if len(row.Cells) != 4 {
  712. t.Error("Expected len(row.Cells) == 4, got ", strconv.Itoa(len(row.Cells)))
  713. }
  714. cell1 = row.Cells[0]
  715. if cell1.String() != "A" {
  716. t.Error("Expected cell1.String() == 'A', got ", cell1.String())
  717. }
  718. cell2 = row.Cells[1]
  719. if cell2.String() != "B" {
  720. t.Error("Expected cell2.String() == 'B', got ", cell2.String())
  721. }
  722. cell3 = row.Cells[2]
  723. if cell3.String() != "C" {
  724. t.Error("Expected cell3.String() == 'C', got ", cell3.String())
  725. }
  726. cell4 = row.Cells[3]
  727. if cell4.String() != "D" {
  728. t.Error("Expected cell4.String() == 'D', got ", cell4.String())
  729. }
  730. row = rows[1]
  731. if len(row.Cells) != 4 {
  732. t.Error("Expected len(row.Cells) == 4, got ", strconv.Itoa(len(row.Cells)))
  733. }
  734. cell1 = row.Cells[0]
  735. if cell1.String() != "1" {
  736. t.Error("Expected cell1.String() == '1', got ", cell1.String())
  737. }
  738. cell2 = row.Cells[1]
  739. if cell2.String() != "" {
  740. t.Error("Expected cell2.String() == '', got ", cell2.String())
  741. }
  742. cell3 = row.Cells[2]
  743. if cell3.String() != "" {
  744. t.Error("Expected cell3.String() == '', got ", cell3.String())
  745. }
  746. cell4 = row.Cells[3]
  747. if cell4.String() != "" {
  748. t.Error("Expected cell4.String() == '', got ", cell4.String())
  749. }
  750. }