lib_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  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 we can correctly extract a reference table from the
  64. // sharedStrings.xml file embedded in the XLSX file and return a
  65. // reference table of string values from it.
  66. func TestReadSharedStringsFromZipFile(t *testing.T) {
  67. var xlsxFile *File
  68. var error error
  69. xlsxFile, error = OpenFile("testfile.xlsx")
  70. if error != nil {
  71. t.Error(error.Error())
  72. return
  73. }
  74. if xlsxFile.referenceTable == nil {
  75. t.Error("expected non nil xlsxFile.referenceTable")
  76. return
  77. }
  78. }
  79. func TestLettersToNumeric(t *testing.T) {
  80. var input string
  81. var output int
  82. input = "A"
  83. output = lettersToNumeric(input)
  84. if output != 0 {
  85. t.Error("Expected output 'A' == 0, but got ", strconv.Itoa(output))
  86. }
  87. input = "z"
  88. output = lettersToNumeric(input)
  89. if output != 25 {
  90. t.Error("Expected output 'z' == 25, but got ", strconv.Itoa(output))
  91. }
  92. input = "AA"
  93. output = lettersToNumeric(input)
  94. if output != 26 {
  95. t.Error("Expected output 'AA' == 26, but got ", strconv.Itoa(output))
  96. }
  97. input = "Az"
  98. output = lettersToNumeric(input)
  99. if output != 51 {
  100. t.Error("Expected output 'Az' == 51, but got ", strconv.Itoa(output))
  101. }
  102. input = "BA"
  103. output = lettersToNumeric(input)
  104. if output != 52 {
  105. t.Error("Expected output 'BA' == 52, but got ", strconv.Itoa(output))
  106. }
  107. input = "Bz"
  108. output = lettersToNumeric(input)
  109. if output != 77 {
  110. t.Error("Expected output 'Bz' == 77, but got ", strconv.Itoa(output))
  111. }
  112. input = "AAA"
  113. output = lettersToNumeric(input)
  114. if output != 676 {
  115. t.Error("Expected output 'AAA' == 676, but got ", strconv.Itoa(output))
  116. }
  117. }
  118. func TestPositionalLetterMultiplier(t *testing.T) {
  119. var output int
  120. output = positionalLetterMultiplier(1, 0)
  121. if output != 1 {
  122. t.Error("Expected positionalLetterMultiplier(1, 0) == 1, got ", output)
  123. }
  124. output = positionalLetterMultiplier(2, 0)
  125. if output != 26 {
  126. t.Error("Expected positionalLetterMultiplier(2, 0) == 26, got ", output)
  127. }
  128. output = positionalLetterMultiplier(2, 1)
  129. if output != 1 {
  130. t.Error("Expected positionalLetterMultiplier(2, 1) == 1, got ", output)
  131. }
  132. output = positionalLetterMultiplier(3, 0)
  133. if output != 676 {
  134. t.Error("Expected positionalLetterMultiplier(3, 0) == 676, got ", output)
  135. }
  136. output = positionalLetterMultiplier(3, 1)
  137. if output != 26 {
  138. t.Error("Expected positionalLetterMultiplier(3, 1) == 26, got ", output)
  139. }
  140. output = positionalLetterMultiplier(3, 2)
  141. if output != 1 {
  142. t.Error("Expected positionalLetterMultiplier(3, 2) == 1, got ", output)
  143. }
  144. }
  145. func TestLetterOnlyMapFunction(t *testing.T) {
  146. var input string = "ABC123"
  147. var output string = strings.Map(letterOnlyMapF, input)
  148. if output != "ABC" {
  149. t.Error("Expected output == 'ABC' but got ", output)
  150. }
  151. input = "abc123"
  152. output = strings.Map(letterOnlyMapF, input)
  153. if output != "ABC" {
  154. t.Error("Expected output == 'ABC' but got ", output)
  155. }
  156. }
  157. func TestIntOnlyMapFunction(t *testing.T) {
  158. var input string = "ABC123"
  159. var output string = strings.Map(intOnlyMapF, input)
  160. if output != "123" {
  161. t.Error("Expected output == '123' but got ", output)
  162. }
  163. }
  164. func TestGetCoordsFromCellIDString(t *testing.T) {
  165. var cellIDString string = "A3"
  166. var x, y int
  167. var error error
  168. x, y, error = getCoordsFromCellIDString(cellIDString)
  169. if error != nil {
  170. t.Error(error)
  171. }
  172. if x != 0 {
  173. t.Error("Expected x == 0, but got ", strconv.Itoa(x))
  174. }
  175. if y != 2 {
  176. t.Error("Expected y == 2, but got ", strconv.Itoa(y))
  177. }
  178. }
  179. func TestGetRangeFromString(t *testing.T) {
  180. var rangeString string
  181. var lower, upper int
  182. var error error
  183. rangeString = "1:3"
  184. lower, upper, error = getRangeFromString(rangeString)
  185. if error != nil {
  186. t.Error(error)
  187. }
  188. if lower != 1 {
  189. t.Error("Expected lower bound == 1, but got ", strconv.Itoa(lower))
  190. }
  191. if upper != 3 {
  192. t.Error("Expected upper bound == 3, but got ", strconv.Itoa(upper))
  193. }
  194. }
  195. func TestMakeRowFromSpan(t *testing.T) {
  196. var rangeString string
  197. var row *Row
  198. var length int
  199. rangeString = "1:3"
  200. row = makeRowFromSpan(rangeString)
  201. length = len(row.Cells)
  202. if length != 3 {
  203. t.Error("Expected a row with 3 cells, but got ", strconv.Itoa(length))
  204. }
  205. rangeString = "5:7" // Note - we ignore lower bound!
  206. row = makeRowFromSpan(rangeString)
  207. length = len(row.Cells)
  208. if length != 7 {
  209. t.Error("Expected a row with 7 cells, but got ", strconv.Itoa(length))
  210. }
  211. rangeString = "1:1"
  212. row = makeRowFromSpan(rangeString)
  213. length = len(row.Cells)
  214. if length != 1 {
  215. t.Error("Expected a row with 1 cells, but got ", strconv.Itoa(length))
  216. }
  217. }
  218. func TestReadRowsFromSheet(t *testing.T) {
  219. var sharedstringsXML = bytes.NewBufferString(`
  220. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  221. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="4" uniqueCount="4">
  222. <si>
  223. <t>Foo</t>
  224. </si>
  225. <si>
  226. <t>Bar</t>
  227. </si>
  228. <si>
  229. <t xml:space="preserve">Baz </t>
  230. </si>
  231. <si>
  232. <t>Quuk</t>
  233. </si>
  234. </sst>`)
  235. var sheetxml = bytes.NewBufferString(`
  236. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  237. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  238. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  239. <dimension ref="A1:B2"/>
  240. <sheetViews>
  241. <sheetView tabSelected="1" workbookViewId="0">
  242. <selection activeCell="C2" sqref="C2"/>
  243. </sheetView>
  244. </sheetViews>
  245. <sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  246. <sheetData>
  247. <row r="1" spans="1:2">
  248. <c r="A1" t="s">
  249. <v>0</v>
  250. </c>
  251. <c r="B1" t="s">
  252. <v>1</v>
  253. </c>
  254. </row>
  255. <row r="2" spans="1:2">
  256. <c r="A2" t="s">
  257. <v>2</v>
  258. </c>
  259. <c r="B2" t="s">
  260. <v>3</v>
  261. </c>
  262. </row>
  263. </sheetData>
  264. <pageMargins left="0.7" right="0.7"
  265. top="0.78740157499999996"
  266. bottom="0.78740157499999996"
  267. header="0.3"
  268. footer="0.3"/>
  269. </worksheet>`)
  270. worksheet := new(xlsxWorksheet)
  271. error := xml.NewDecoder(sheetxml).Decode(worksheet)
  272. if error != nil {
  273. t.Error(error.Error())
  274. return
  275. }
  276. sst := new(xlsxSST)
  277. error = xml.NewDecoder(sharedstringsXML).Decode(sst)
  278. if error != nil {
  279. t.Error(error.Error())
  280. return
  281. }
  282. reftable := MakeSharedStringRefTable(sst)
  283. rows := readRowsFromSheet(worksheet, reftable)
  284. if len(rows) != 2 {
  285. t.Error("Expected len(rows) == 2")
  286. }
  287. row := rows[0]
  288. if len(row.Cells) != 2 {
  289. t.Error("Expected len(row.Cells) == 2, got ", strconv.Itoa(len(row.Cells)))
  290. }
  291. cell1 := row.Cells[0]
  292. if cell1.String() != "Foo" {
  293. t.Error("Expected cell1.String() == 'Foo', got ", cell1.String())
  294. }
  295. cell2 := row.Cells[1]
  296. if cell2.String() != "Bar" {
  297. t.Error("Expected cell2.String() == 'Bar', got ", cell2.String())
  298. }
  299. }
  300. func TestReadRowsFromSheetWithEmptyCells(t *testing.T) {
  301. var sharedstringsXML = bytes.NewBufferString(`
  302. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  303. <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>`)
  304. var sheetxml = bytes.NewBufferString(`
  305. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  306. <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"/>
  307. <sheetData>
  308. <row r="1" spans="1:3">
  309. <c r="A1" t="s">
  310. <v>
  311. 0
  312. </v>
  313. </c>
  314. <c r="B1" t="s">
  315. <v>
  316. 1
  317. </v>
  318. </c>
  319. <c r="C1" t="s">
  320. <v>
  321. 2
  322. </v>
  323. </c>
  324. </row>
  325. <row r="2" spans="1:3">
  326. <c r="A2" t="s">
  327. <v>
  328. 3
  329. </v>
  330. </c>
  331. <c r="B2" t="s">
  332. <v>
  333. 4
  334. </v>
  335. </c>
  336. <c r="C2" t="s">
  337. <v>
  338. 3
  339. </v>
  340. </c>
  341. </row>
  342. <row r="3" spans="1:3">
  343. <c r="A3" t="s">
  344. <v>
  345. 4
  346. </v>
  347. </c>
  348. <c r="C3" t="s">
  349. <v>
  350. 3
  351. </v>
  352. </c>
  353. </row>
  354. </sheetData>
  355. <pageMargins left="0.7" right="0.7" top="0.78740157499999996" bottom="0.78740157499999996" header="0.3" footer="0.3"/>
  356. </worksheet>
  357. `)
  358. worksheet := new(xlsxWorksheet)
  359. error := xml.NewDecoder(sheetxml).Decode(worksheet)
  360. if error != nil {
  361. t.Error(error.Error())
  362. return
  363. }
  364. sst := new(xlsxSST)
  365. error = xml.NewDecoder(sharedstringsXML).Decode(sst)
  366. if error != nil {
  367. t.Error(error.Error())
  368. return
  369. }
  370. reftable := MakeSharedStringRefTable(sst)
  371. rows := readRowsFromSheet(worksheet, reftable)
  372. if len(rows) != 3 {
  373. t.Error("Expected len(rows) == 3, got ", strconv.Itoa(len(rows)))
  374. }
  375. row := rows[2]
  376. if len(row.Cells) != 3 {
  377. t.Error("Expected len(row.Cells) == 3, got ", strconv.Itoa(len(row.Cells)))
  378. }
  379. cell1 := row.Cells[0]
  380. if cell1.String() != "No" {
  381. t.Error("Expected cell1.String() == 'No', got ", cell1.String())
  382. }
  383. cell2 := row.Cells[1]
  384. if cell2.String() != "" {
  385. t.Error("Expected cell2.String() == '', got ", cell2.String())
  386. }
  387. cell3 := row.Cells[2]
  388. if cell3.String() != "Yes" {
  389. t.Error("Expected cell3.String() == 'Yes', got ", cell3.String())
  390. }
  391. }
  392. func TestReadRowsFromSheetWithTrailingEmptyCells(t *testing.T) {
  393. var row *Row
  394. var cell1, cell2, cell3, cell4 *Cell
  395. var sharedstringsXML = bytes.NewBufferString(`
  396. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  397. <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>`)
  398. var sheetxml = bytes.NewBufferString(`
  399. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  400. <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>
  401. `)
  402. worksheet := new(xlsxWorksheet)
  403. error := xml.NewDecoder(sheetxml).Decode(worksheet)
  404. if error != nil {
  405. t.Error(error.Error())
  406. return
  407. }
  408. sst := new(xlsxSST)
  409. error = xml.NewDecoder(sharedstringsXML).Decode(sst)
  410. if error != nil {
  411. t.Error(error.Error())
  412. return
  413. }
  414. reftable := MakeSharedStringRefTable(sst)
  415. rows := readRowsFromSheet(worksheet, reftable)
  416. if len(rows) != 8 {
  417. t.Error("Expected len(rows) == 8, got ", strconv.Itoa(len(rows)))
  418. }
  419. row = rows[0]
  420. if len(row.Cells) != 4 {
  421. t.Error("Expected len(row.Cells) == 4, got ", strconv.Itoa(len(row.Cells)))
  422. }
  423. cell1 = row.Cells[0]
  424. if cell1.String() != "A" {
  425. t.Error("Expected cell1.String() == 'A', got ", cell1.String())
  426. }
  427. cell2 = row.Cells[1]
  428. if cell2.String() != "B" {
  429. t.Error("Expected cell2.String() == 'B', got ", cell2.String())
  430. }
  431. cell3 = row.Cells[2]
  432. if cell3.String() != "C" {
  433. t.Error("Expected cell3.String() == 'C', got ", cell3.String())
  434. }
  435. cell4 = row.Cells[3]
  436. if cell4.String() != "D" {
  437. t.Error("Expected cell4.String() == 'D', got ", cell4.String())
  438. }
  439. row = rows[1]
  440. if len(row.Cells) != 4 {
  441. t.Error("Expected len(row.Cells) == 4, got ", strconv.Itoa(len(row.Cells)))
  442. }
  443. cell1 = row.Cells[0]
  444. if cell1.String() != "1" {
  445. t.Error("Expected cell1.String() == '1', got ", cell1.String())
  446. }
  447. cell2 = row.Cells[1]
  448. if cell2.String() != "" {
  449. t.Error("Expected cell2.String() == '', got ", cell2.String())
  450. }
  451. cell3 = row.Cells[2]
  452. if cell3.String() != "" {
  453. t.Error("Expected cell3.String() == '', got ", cell3.String())
  454. }
  455. cell4 = row.Cells[3]
  456. if cell4.String() != "" {
  457. t.Error("Expected cell4.String() == '', got ", cell4.String())
  458. }
  459. }