lib_test.go 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252
  1. package xlsx
  2. import (
  3. "bytes"
  4. "encoding/xml"
  5. "os"
  6. "strings"
  7. . "gopkg.in/check.v1"
  8. )
  9. type LibSuite struct{}
  10. var _ = Suite(&LibSuite{})
  11. // Attempting to open a file without workbook.xml.rels returns an error.
  12. func (l *LibSuite) TestReadZipReaderWithFileWithNoWorkbookRels(c *C) {
  13. _, err := OpenFile("./testdocs/badfile_noWorkbookRels.xlsx")
  14. c.Assert(err, NotNil)
  15. c.Assert(err.Error(), Equals, "xl/_rels/workbook.xml.rels not found in input xlsx.")
  16. }
  17. // Attempting to open a file with no worksheets returns an error.
  18. func (l *LibSuite) TestReadZipReaderWithFileWithNoWorksheets(c *C) {
  19. _, err := OpenFile("./testdocs/badfile_noWorksheets.xlsx")
  20. c.Assert(err, NotNil)
  21. c.Assert(err.Error(), Equals, "Input xlsx contains no worksheets.")
  22. }
  23. // which they are contained from the XLSX file, even when the
  24. // worksheet files have arbitrary, non-numeric names.
  25. func (l *LibSuite) TestReadWorkbookRelationsFromZipFileWithFunnyNames(c *C) {
  26. var xlsxFile *File
  27. var err error
  28. xlsxFile, err = OpenFile("./testdocs/testrels.xlsx")
  29. c.Assert(err, IsNil)
  30. bob := xlsxFile.Sheet["Bob"]
  31. row1 := bob.Rows[0]
  32. cell1 := row1.Cells[0]
  33. c.Assert(cell1.String(), Equals, "I am Bob")
  34. }
  35. // We can marshal WorkBookRels to an xml file
  36. func (l *LibSuite) TestWorkBookRelsMarshal(c *C) {
  37. var rels WorkBookRels = make(WorkBookRels)
  38. rels["rId1"] = "worksheets/sheet.xml"
  39. expectedXML := `<?xml version="1.0" encoding="UTF-8"?>
  40. <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Target="worksheets/sheet.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"></Relationship><Relationship Id="rId2" Target="sharedStrings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"></Relationship><Relationship Id="rId3" Target="theme/theme1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"></Relationship><Relationship Id="rId4" Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"></Relationship></Relationships>`
  41. xRels := rels.MakeXLSXWorkbookRels()
  42. output := bytes.NewBufferString(xml.Header)
  43. body, err := xml.Marshal(xRels)
  44. c.Assert(err, IsNil)
  45. c.Assert(body, NotNil)
  46. _, err = output.Write(body)
  47. c.Assert(err, IsNil)
  48. c.Assert(output.String(), Equals, expectedXML)
  49. }
  50. // Excel column codes are a special form of base26 that doesn't allow
  51. // zeros, except in the least significant part of the code. Test we
  52. // can smoosh the numbers in a normal base26 representation (presented
  53. // as a slice of integers) down to this form.
  54. func (l *LibSuite) TestSmooshBase26Slice(c *C) {
  55. input := []int{20, 0, 1}
  56. expected := []int{19, 26, 1}
  57. c.Assert(smooshBase26Slice(input), DeepEquals, expected)
  58. }
  59. // formatColumnName converts slices of base26 integers to alphabetical
  60. // column names. Note that the least signifcant character has a
  61. // different numeric offset (Yuck!)
  62. func (l *LibSuite) TestFormatColumnName(c *C) {
  63. c.Assert(formatColumnName([]int{0}), Equals, "A")
  64. c.Assert(formatColumnName([]int{25}), Equals, "Z")
  65. c.Assert(formatColumnName([]int{1, 25}), Equals, "AZ")
  66. c.Assert(formatColumnName([]int{26, 25}), Equals, "ZZ")
  67. c.Assert(formatColumnName([]int{26, 26, 25}), Equals, "ZZZ")
  68. }
  69. // getLargestDenominator returns the largest power of a provided value
  70. // that can fit within a given value.
  71. func (l *LibSuite) TestGetLargestDenominator(c *C) {
  72. d, p := getLargestDenominator(0, 1, 2, 0)
  73. c.Assert(d, Equals, 1)
  74. c.Assert(p, Equals, 0)
  75. d, p = getLargestDenominator(1, 1, 2, 0)
  76. c.Assert(d, Equals, 1)
  77. c.Assert(p, Equals, 0)
  78. d, p = getLargestDenominator(2, 1, 2, 0)
  79. c.Assert(d, Equals, 2)
  80. c.Assert(p, Equals, 1)
  81. d, p = getLargestDenominator(4, 1, 2, 0)
  82. c.Assert(d, Equals, 4)
  83. c.Assert(p, Equals, 2)
  84. d, p = getLargestDenominator(8, 1, 2, 0)
  85. c.Assert(d, Equals, 8)
  86. c.Assert(p, Equals, 3)
  87. d, p = getLargestDenominator(9, 1, 2, 0)
  88. c.Assert(d, Equals, 8)
  89. c.Assert(p, Equals, 3)
  90. d, p = getLargestDenominator(15, 1, 2, 0)
  91. c.Assert(d, Equals, 8)
  92. c.Assert(p, Equals, 3)
  93. d, p = getLargestDenominator(16, 1, 2, 0)
  94. c.Assert(d, Equals, 16)
  95. c.Assert(p, Equals, 4)
  96. }
  97. func (l *LibSuite) TestLettersToNumeric(c *C) {
  98. cases := map[string]int{"A": 0, "G": 6, "z": 25, "AA": 26, "Az": 51,
  99. "BA": 52, "BZ": 77, "ZA": 26*26 + 0, "ZZ": 26*26 + 25,
  100. "AAA": 26*26 + 26 + 0, "AMI": 1022}
  101. for input, ans := range cases {
  102. output := lettersToNumeric(input)
  103. c.Assert(output, Equals, ans)
  104. }
  105. }
  106. func (l *LibSuite) TestNumericToLetters(c *C) {
  107. cases := map[string]int{
  108. "A": 0,
  109. "G": 6,
  110. "Z": 25,
  111. "AA": 26,
  112. "AZ": 51,
  113. "BA": 52,
  114. "BZ": 77, "ZA": 26 * 26, "ZB": 26*26 + 1,
  115. "ZZ": 26*26 + 25,
  116. "AAA": 26*26 + 26 + 0, "AMI": 1022}
  117. for ans, input := range cases {
  118. output := numericToLetters(input)
  119. c.Assert(output, Equals, ans)
  120. }
  121. }
  122. func (l *LibSuite) TestLetterOnlyMapFunction(c *C) {
  123. var input string = "ABC123"
  124. var output string = strings.Map(letterOnlyMapF, input)
  125. c.Assert(output, Equals, "ABC")
  126. input = "abc123"
  127. output = strings.Map(letterOnlyMapF, input)
  128. c.Assert(output, Equals, "ABC")
  129. }
  130. func (l *LibSuite) TestIntOnlyMapFunction(c *C) {
  131. var input string = "ABC123"
  132. var output string = strings.Map(intOnlyMapF, input)
  133. c.Assert(output, Equals, "123")
  134. }
  135. func (l *LibSuite) TestGetCoordsFromCellIDString(c *C) {
  136. var cellIDString string = "A3"
  137. var x, y int
  138. var err error
  139. x, y, err = getCoordsFromCellIDString(cellIDString)
  140. c.Assert(err, IsNil)
  141. c.Assert(x, Equals, 0)
  142. c.Assert(y, Equals, 2)
  143. }
  144. func (l *LibSuite) TestGetCellIDStringFromCoords(c *C) {
  145. c.Assert(getCellIDStringFromCoords(0, 0), Equals, "A1")
  146. c.Assert(getCellIDStringFromCoords(2, 2), Equals, "C3")
  147. }
  148. func (l *LibSuite) TestGetMaxMinFromDimensionRef(c *C) {
  149. var dimensionRef string = "A1:B2"
  150. var minx, miny, maxx, maxy int
  151. var err error
  152. minx, miny, maxx, maxy, err = getMaxMinFromDimensionRef(dimensionRef)
  153. c.Assert(err, IsNil)
  154. c.Assert(minx, Equals, 0)
  155. c.Assert(miny, Equals, 0)
  156. c.Assert(maxx, Equals, 1)
  157. c.Assert(maxy, Equals, 1)
  158. }
  159. func (l *LibSuite) TestCalculateMaxMinFromWorksheet(c *C) {
  160. var sheetxml = bytes.NewBufferString(`
  161. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  162. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  163. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
  164. xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main"
  165. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  166. xmlns:mv="urn:schemas-microsoft-com:mac:vml"
  167. xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
  168. xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"
  169. xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
  170. <sheetViews>
  171. <sheetView workbookViewId="0"/>
  172. </sheetViews>
  173. <sheetFormatPr customHeight="1" defaultColWidth="14.43" defaultRowHeight="15.75"/>
  174. <sheetData>
  175. <row r="1">
  176. <c t="s" s="1" r="A1">
  177. <v>0</v>
  178. </c>
  179. <c t="s" s="1" r="B1">
  180. <v>1</v>
  181. </c>
  182. </row>
  183. <row r="2">
  184. <c t="s" s="1" r="A2">
  185. <v>2</v>
  186. </c>
  187. <c t="s" s="1" r="B2">
  188. <v>3</v>
  189. </c>
  190. </row>
  191. </sheetData>
  192. <drawing r:id="rId1"/>
  193. </worksheet>`)
  194. worksheet := new(xlsxWorksheet)
  195. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  196. c.Assert(err, IsNil)
  197. minx, miny, maxx, maxy, err := calculateMaxMinFromWorksheet(worksheet)
  198. c.Assert(err, IsNil)
  199. c.Assert(minx, Equals, 0)
  200. c.Assert(miny, Equals, 0)
  201. c.Assert(maxx, Equals, 1)
  202. c.Assert(maxy, Equals, 1)
  203. }
  204. func (l *LibSuite) TestGetRangeFromString(c *C) {
  205. var rangeString string
  206. var lower, upper int
  207. var err error
  208. rangeString = "1:3"
  209. lower, upper, err = getRangeFromString(rangeString)
  210. c.Assert(err, IsNil)
  211. c.Assert(lower, Equals, 1)
  212. c.Assert(upper, Equals, 3)
  213. }
  214. func (l *LibSuite) TestMakeRowFromSpan(c *C) {
  215. var rangeString string
  216. var row *Row
  217. var length int
  218. var sheet *Sheet
  219. sheet = new(Sheet)
  220. rangeString = "1:3"
  221. row = makeRowFromSpan(rangeString, sheet)
  222. length = len(row.Cells)
  223. c.Assert(length, Equals, 3)
  224. c.Assert(row.Sheet, Equals, sheet)
  225. rangeString = "5:7" // Note - we ignore lower bound!
  226. row = makeRowFromSpan(rangeString, sheet)
  227. length = len(row.Cells)
  228. c.Assert(length, Equals, 7)
  229. c.Assert(row.Sheet, Equals, sheet)
  230. rangeString = "1:1"
  231. row = makeRowFromSpan(rangeString, sheet)
  232. length = len(row.Cells)
  233. c.Assert(length, Equals, 1)
  234. c.Assert(row.Sheet, Equals, sheet)
  235. }
  236. func (l *LibSuite) TestReadRowsFromSheet(c *C) {
  237. var sharedstringsXML = bytes.NewBufferString(`
  238. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  239. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="4" uniqueCount="4">
  240. <si>
  241. <t>Foo</t>
  242. </si>
  243. <si>
  244. <t>Bar</t>
  245. </si>
  246. <si>
  247. <t xml:space="preserve">Baz </t>
  248. </si>
  249. <si>
  250. <t>Quuk</t>
  251. </si>
  252. </sst>`)
  253. var sheetxml = bytes.NewBufferString(`
  254. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  255. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  256. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  257. <dimension ref="A1:B2"/>
  258. <sheetViews>
  259. <sheetView tabSelected="1" workbookViewId="0">
  260. <selection activeCell="C2" sqref="C2"/>
  261. <pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/>
  262. </sheetView>
  263. </sheetViews>
  264. <sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  265. <sheetData>
  266. <row r="1" spans="1:2">
  267. <c r="A1" t="s">
  268. <v>0</v>
  269. </c>
  270. <c r="B1" t="s">
  271. <v>1</v>
  272. </c>
  273. </row>
  274. <row r="2" spans="1:2">
  275. <c r="A2" t="s">
  276. <v>2</v>
  277. </c>
  278. <c r="B2" t="s">
  279. <v>3</v>
  280. </c>
  281. </row>
  282. </sheetData>
  283. <pageMargins left="0.7" right="0.7"
  284. top="0.78740157499999996"
  285. bottom="0.78740157499999996"
  286. header="0.3"
  287. footer="0.3"/>
  288. </worksheet>`)
  289. worksheet := new(xlsxWorksheet)
  290. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  291. c.Assert(err, IsNil)
  292. sst := new(xlsxSST)
  293. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  294. c.Assert(err, IsNil)
  295. file := new(File)
  296. file.referenceTable = MakeSharedStringRefTable(sst)
  297. sheet := new(Sheet)
  298. rows, cols, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  299. c.Assert(maxRows, Equals, 2)
  300. c.Assert(maxCols, Equals, 2)
  301. row := rows[0]
  302. c.Assert(row.Sheet, Equals, sheet)
  303. c.Assert(len(row.Cells), Equals, 2)
  304. cell1 := row.Cells[0]
  305. c.Assert(cell1.Value, Equals, "Foo")
  306. cell2 := row.Cells[1]
  307. c.Assert(cell2.Value, Equals, "Bar")
  308. col := cols[0]
  309. c.Assert(col.Min, Equals, 0)
  310. c.Assert(col.Max, Equals, 0)
  311. c.Assert(col.Hidden, Equals, false)
  312. c.Assert(len(worksheet.SheetViews.SheetView), Equals, 1)
  313. sheetView := worksheet.SheetViews.SheetView[0]
  314. c.Assert(sheetView.Pane, NotNil)
  315. pane := sheetView.Pane
  316. c.Assert(pane.XSplit, Equals, 0.0)
  317. c.Assert(pane.YSplit, Equals, 1.0)
  318. }
  319. func (l *LibSuite) TestReadRowsFromSheetWithMergeCells(c *C) {
  320. var sharedstringsXML = bytes.NewBufferString(`
  321. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  322. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="3" uniqueCount="3">
  323. <si>
  324. <t>Value A</t>
  325. </si>
  326. <si>
  327. <t>Value B</t>
  328. </si>
  329. <si>
  330. <t>Value C</t>
  331. </si>
  332. </sst>
  333. `)
  334. var sheetxml = bytes.NewBufferString(`
  335. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  336. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
  337. <sheetViews>
  338. <sheetView workbookViewId="0"/>
  339. </sheetViews>
  340. <sheetFormatPr customHeight="1" defaultColWidth="17.29" defaultRowHeight="15.0"/>
  341. <cols>
  342. <col customWidth="1" min="1" max="6" width="14.43"/>
  343. </cols>
  344. <sheetData>
  345. <row r="1" ht="15.75" customHeight="1">
  346. <c r="A1" s="1" t="s">
  347. <v>0</v>
  348. </c>
  349. </row>
  350. <row r="2" ht="15.75" customHeight="1">
  351. <c r="A2" s="1" t="s">
  352. <v>1</v>
  353. </c>
  354. <c r="B2" s="1" t="s">
  355. <v>2</v>
  356. </c>
  357. </row>
  358. </sheetData>
  359. <mergeCells count="1">
  360. <mergeCell ref="A1:B1"/>
  361. </mergeCells>
  362. <drawing r:id="rId1"/>
  363. </worksheet>`)
  364. worksheet := new(xlsxWorksheet)
  365. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  366. c.Assert(err, IsNil)
  367. sst := new(xlsxSST)
  368. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  369. c.Assert(err, IsNil)
  370. file := new(File)
  371. file.referenceTable = MakeSharedStringRefTable(sst)
  372. sheet := new(Sheet)
  373. rows, _, _, _ := readRowsFromSheet(worksheet, file, sheet)
  374. row := rows[0] //
  375. cell1 := row.Cells[0]
  376. c.Assert(cell1.HMerge, Equals, 1)
  377. c.Assert(cell1.VMerge, Equals, 0)
  378. }
  379. // An invalid value in the "r" attribute in a <row> was causing a panic
  380. // in readRowsFromSheet. This test is a copy of TestReadRowsFromSheet,
  381. // with the important difference of the value 1048576 below in <row r="1048576", which is
  382. // higher than the number of rows in the sheet. That number itself isn't significant;
  383. // it just happens to be the value found to trigger the error in a user's file.
  384. func (l *LibSuite) TestReadRowsFromSheetBadR(c *C) {
  385. var sharedstringsXML = bytes.NewBufferString(`
  386. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  387. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="4" uniqueCount="4">
  388. <si>
  389. <t>Foo</t>
  390. </si>
  391. <si>
  392. <t>Bar</t>
  393. </si>
  394. <si>
  395. <t xml:space="preserve">Baz </t>
  396. </si>
  397. <si>
  398. <t>Quuk</t>
  399. </si>
  400. </sst>`)
  401. var sheetxml = bytes.NewBufferString(`
  402. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  403. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  404. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  405. <dimension ref="A1:B2"/>
  406. <sheetViews>
  407. <sheetView tabSelected="1" workbookViewId="0">
  408. <selection activeCell="C2" sqref="C2"/>
  409. <pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/>
  410. </sheetView>
  411. </sheetViews>
  412. <sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  413. <sheetData>
  414. <row r="1" spans="1:2">
  415. <c r="A1" t="s">
  416. <v>0</v>
  417. </c>
  418. <c r="B1" t="s">
  419. <v>1</v>
  420. </c>
  421. </row>
  422. <row r="1048576" spans="1:2">
  423. <c r="A2" t="s">
  424. <v>2</v>
  425. </c>
  426. <c r="B2" t="s">
  427. <v>3</v>
  428. </c>
  429. </row>
  430. </sheetData>
  431. <pageMargins left="0.7" right="0.7"
  432. top="0.78740157499999996"
  433. bottom="0.78740157499999996"
  434. header="0.3"
  435. footer="0.3"/>
  436. </worksheet>`)
  437. worksheet := new(xlsxWorksheet)
  438. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  439. c.Assert(err, IsNil)
  440. sst := new(xlsxSST)
  441. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  442. c.Assert(err, IsNil)
  443. file := new(File)
  444. file.referenceTable = MakeSharedStringRefTable(sst)
  445. sheet := new(Sheet)
  446. // Discarding all return values; this test is a regression for
  447. // a panic due to an "index out of range."
  448. readRowsFromSheet(worksheet, file, sheet)
  449. }
  450. func (l *LibSuite) TestReadRowsFromSheetWithLeadingEmptyRows(c *C) {
  451. var sharedstringsXML = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  452. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="2" uniqueCount="2"><si><t>ABC</t></si><si><t>DEF</t></si></sst>`)
  453. var sheetxml = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  454. <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">
  455. <dimension ref="A4:A5"/>
  456. <sheetViews>
  457. <sheetView tabSelected="1" workbookViewId="0">
  458. <selection activeCell="A2" sqref="A2"/>
  459. </sheetView>
  460. </sheetViews>
  461. <sheetFormatPr baseColWidth="10" defaultRowHeight="15" x14ac:dyDescent="0"/>
  462. <sheetData>
  463. <row r="4" spans="1:1">
  464. <c r="A4" t="s">
  465. <v>0</v>
  466. </c>
  467. </row>
  468. <row r="5" spans="1:1">
  469. <c r="A5" t="s">
  470. <v>1</v>
  471. </c>
  472. </row>
  473. </sheetData>
  474. <pageMargins left="0.75" right="0.75" top="1" bottom="1" header="0.5" footer="0.5"/>
  475. <pageSetup paperSize="9" orientation="portrait" horizontalDpi="4294967292" verticalDpi="4294967292"/>
  476. <extLst>
  477. <ext uri="{64002731-A6B0-56B0-2670-7721B7C09600}" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main">
  478. <mx:PLV Mode="0" OnePage="0" WScale="0"/>
  479. </ext>
  480. </extLst>
  481. </worksheet>
  482. `)
  483. worksheet := new(xlsxWorksheet)
  484. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  485. c.Assert(err, IsNil)
  486. sst := new(xlsxSST)
  487. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  488. c.Assert(err, IsNil)
  489. file := new(File)
  490. file.referenceTable = MakeSharedStringRefTable(sst)
  491. sheet := new(Sheet)
  492. rows, _, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  493. c.Assert(maxRows, Equals, 5)
  494. c.Assert(maxCols, Equals, 1)
  495. c.Assert(len(rows[0].Cells), Equals, 0)
  496. c.Assert(len(rows[1].Cells), Equals, 0)
  497. c.Assert(len(rows[2].Cells), Equals, 0)
  498. c.Assert(len(rows[3].Cells), Equals, 1)
  499. c.Assert(rows[3].Cells[0].String(), Equals, "ABC")
  500. c.Assert(len(rows[4].Cells), Equals, 1)
  501. c.Assert(rows[4].Cells[0].String(), Equals, "DEF")
  502. }
  503. func (l *LibSuite) TestReadRowsFromSheetWithLeadingEmptyCols(c *C) {
  504. var sharedstringsXML = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  505. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="2" uniqueCount="2"><si><t>ABC</t></si><si><t>DEF</t></si></sst>`)
  506. var sheetxml = bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  507. <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">
  508. <dimension ref="C1:D2"/>
  509. <sheetViews>
  510. <sheetView tabSelected="1" workbookViewId="0">
  511. <selection activeCell="A2" sqref="A2"/>
  512. </sheetView>
  513. </sheetViews>
  514. <sheetFormatPr baseColWidth="10" defaultRowHeight="15" x14ac:dyDescent="0"/>
  515. <cols>
  516. <col min="3" max="3" width="17" customWidth="1"/>
  517. <col min="4" max="4" width="18" customWidth="1"/>
  518. </cols>
  519. <sheetData>
  520. <row r="1" spans="3:4">
  521. <c r="C1" t="s"><v>0</v></c>
  522. <c r="D1" t="s"><v>1</v></c>
  523. </row>
  524. <row r="2" spans="3:4">
  525. <c r="C2" t="s"><v>0</v></c>
  526. <c r="D2" t="s"><v>1</v></c>
  527. </row>
  528. </sheetData>
  529. <pageMargins left="0.75" right="0.75" top="1" bottom="1" header="0.5" footer="0.5"/>
  530. <pageSetup paperSize="9" orientation="portrait" horizontalDpi="4294967292" verticalDpi="4294967292"/>
  531. <extLst>
  532. <ext uri="{64002731-A6B0-56B0-2670-7721B7C09600}" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main">
  533. <mx:PLV Mode="0" OnePage="0" WScale="0"/>
  534. </ext>
  535. </extLst>
  536. </worksheet>
  537. `)
  538. worksheet := new(xlsxWorksheet)
  539. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  540. c.Assert(err, IsNil)
  541. sst := new(xlsxSST)
  542. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  543. c.Assert(err, IsNil)
  544. file := new(File)
  545. file.referenceTable = MakeSharedStringRefTable(sst)
  546. sheet := new(Sheet)
  547. rows, cols, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  548. c.Assert(maxRows, Equals, 2)
  549. c.Assert(maxCols, Equals, 4)
  550. c.Assert(len(rows[0].Cells), Equals, 4)
  551. c.Assert(rows[0].Cells[0].String(), Equals, "")
  552. c.Assert(rows[0].Cells[1].String(), Equals, "")
  553. c.Assert(rows[0].Cells[2].String(), Equals, "ABC")
  554. c.Assert(rows[0].Cells[3].String(), Equals, "DEF")
  555. c.Assert(len(rows[1].Cells), Equals, 4)
  556. c.Assert(rows[1].Cells[0].String(), Equals, "")
  557. c.Assert(rows[1].Cells[1].String(), Equals, "")
  558. c.Assert(rows[1].Cells[2].String(), Equals, "ABC")
  559. c.Assert(rows[1].Cells[3].String(), Equals, "DEF")
  560. c.Assert(len(cols), Equals, 4)
  561. c.Assert(cols[0].Width, Equals, 0.0)
  562. c.Assert(cols[1].Width, Equals, 0.0)
  563. c.Assert(cols[2].Width, Equals, 17.0)
  564. c.Assert(cols[3].Width, Equals, 18.0)
  565. }
  566. func (l *LibSuite) TestReadRowsFromSheetWithEmptyCells(c *C) {
  567. var sharedstringsXML = bytes.NewBufferString(`
  568. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  569. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="8" uniqueCount="5">
  570. <si>
  571. <t>Bob</t>
  572. </si>
  573. <si>
  574. <t>Alice</t>
  575. </si>
  576. <si>
  577. <t>Sue</t>
  578. </si>
  579. <si>
  580. <t>Yes</t>
  581. </si>
  582. <si>
  583. <t>No</t>
  584. </si>
  585. </sst>
  586. `)
  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. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  643. c.Assert(err, IsNil)
  644. sst := new(xlsxSST)
  645. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  646. c.Assert(err, IsNil)
  647. file := new(File)
  648. file.referenceTable = MakeSharedStringRefTable(sst)
  649. sheet := new(Sheet)
  650. rows, cols, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  651. c.Assert(maxRows, Equals, 3)
  652. c.Assert(maxCols, Equals, 3)
  653. row := rows[2]
  654. c.Assert(row.Sheet, Equals, sheet)
  655. c.Assert(len(row.Cells), Equals, 3)
  656. cell1 := row.Cells[0]
  657. c.Assert(cell1.Value, Equals, "No")
  658. cell2 := row.Cells[1]
  659. c.Assert(cell2.Value, Equals, "")
  660. cell3 := row.Cells[2]
  661. c.Assert(cell3.Value, Equals, "Yes")
  662. col := cols[0]
  663. c.Assert(col.Min, Equals, 0)
  664. c.Assert(col.Max, Equals, 0)
  665. c.Assert(col.Hidden, Equals, false)
  666. }
  667. func (l *LibSuite) TestReadRowsFromSheetWithTrailingEmptyCells(c *C) {
  668. var row *Row
  669. var cell1, cell2, cell3, cell4 *Cell
  670. var sharedstringsXML = bytes.NewBufferString(`
  671. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  672. <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>`)
  673. var sheetxml = bytes.NewBufferString(`
  674. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  675. <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>
  676. `)
  677. worksheet := new(xlsxWorksheet)
  678. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  679. c.Assert(err, IsNil)
  680. sst := new(xlsxSST)
  681. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  682. c.Assert(err, IsNil)
  683. file := new(File)
  684. file.referenceTable = MakeSharedStringRefTable(sst)
  685. sheet := new(Sheet)
  686. rows, _, maxCol, maxRow := readRowsFromSheet(worksheet, file, sheet)
  687. c.Assert(maxCol, Equals, 4)
  688. c.Assert(maxRow, Equals, 8)
  689. row = rows[0]
  690. c.Assert(row.Sheet, Equals, sheet)
  691. c.Assert(len(row.Cells), Equals, 4)
  692. cell1 = row.Cells[0]
  693. c.Assert(cell1.Value, Equals, "A")
  694. cell2 = row.Cells[1]
  695. c.Assert(cell2.Value, Equals, "B")
  696. cell3 = row.Cells[2]
  697. c.Assert(cell3.Value, Equals, "C")
  698. cell4 = row.Cells[3]
  699. c.Assert(cell4.Value, Equals, "D")
  700. row = rows[1]
  701. c.Assert(row.Sheet, Equals, sheet)
  702. c.Assert(len(row.Cells), Equals, 4)
  703. cell1 = row.Cells[0]
  704. c.Assert(cell1.Value, Equals, "1")
  705. cell2 = row.Cells[1]
  706. c.Assert(cell2.Value, Equals, "")
  707. cell3 = row.Cells[2]
  708. c.Assert(cell3.Value, Equals, "")
  709. cell4 = row.Cells[3]
  710. c.Assert(cell4.Value, Equals, "")
  711. }
  712. func (l *LibSuite) TestReadRowsFromSheetWithMultipleSpans(c *C) {
  713. var sharedstringsXML = bytes.NewBufferString(`
  714. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  715. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="4" uniqueCount="4">
  716. <si>
  717. <t>Foo</t>
  718. </si>
  719. <si>
  720. <t>Bar</t>
  721. </si>
  722. <si>
  723. <t xml:space="preserve">Baz </t>
  724. </si>
  725. <si>
  726. <t>Quuk</t>
  727. </si>
  728. </sst>`)
  729. var sheetxml = bytes.NewBufferString(`
  730. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  731. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  732. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  733. <dimension ref="A1:D2"/>
  734. <sheetViews>
  735. <sheetView tabSelected="1" workbookViewId="0">
  736. <selection activeCell="C2" sqref="C2"/>
  737. </sheetView>
  738. </sheetViews>
  739. <sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  740. <sheetData>
  741. <row r="1" spans="1:2 3:4">
  742. <c r="A1" t="s">
  743. <v>0</v>
  744. </c>
  745. <c r="B1" t="s">
  746. <v>1</v>
  747. </c>
  748. <c r="C1" t="s">
  749. <v>0</v>
  750. </c>
  751. <c r="D1" t="s">
  752. <v>1</v>
  753. </c>
  754. </row>
  755. <row r="2" spans="1:2 3:4">
  756. <c r="A2" t="s">
  757. <v>2</v>
  758. </c>
  759. <c r="B2" t="s">
  760. <v>3</v>
  761. </c>
  762. <c r="C2" t="s">
  763. <v>2</v>
  764. </c>
  765. <c r="D2" t="s">
  766. <v>3</v>
  767. </c>
  768. </row>
  769. </sheetData>
  770. <pageMargins left="0.7" right="0.7"
  771. top="0.78740157499999996"
  772. bottom="0.78740157499999996"
  773. header="0.3"
  774. footer="0.3"/>
  775. </worksheet>`)
  776. worksheet := new(xlsxWorksheet)
  777. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  778. c.Assert(err, IsNil)
  779. sst := new(xlsxSST)
  780. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  781. c.Assert(err, IsNil)
  782. file := new(File)
  783. file.referenceTable = MakeSharedStringRefTable(sst)
  784. sheet := new(Sheet)
  785. rows, _, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  786. c.Assert(maxRows, Equals, 2)
  787. c.Assert(maxCols, Equals, 4)
  788. row := rows[0]
  789. c.Assert(row.Sheet, Equals, sheet)
  790. c.Assert(len(row.Cells), Equals, 4)
  791. cell1 := row.Cells[0]
  792. c.Assert(cell1.Value, Equals, "Foo")
  793. cell2 := row.Cells[1]
  794. c.Assert(cell2.Value, Equals, "Bar")
  795. cell3 := row.Cells[2]
  796. c.Assert(cell3.Value, Equals, "Foo")
  797. cell4 := row.Cells[3]
  798. c.Assert(cell4.Value, Equals, "Bar")
  799. }
  800. func (l *LibSuite) TestReadRowsFromSheetWithMultipleTypes(c *C) {
  801. var sharedstringsXML = bytes.NewBufferString(`
  802. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  803. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="4" uniqueCount="4">
  804. <si>
  805. <t>Hello World</t>
  806. </si>
  807. </sst>`)
  808. var sheetxml = bytes.NewBufferString(`
  809. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  810. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  811. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  812. <dimension ref="A1:F1"/>
  813. <sheetViews>
  814. <sheetView tabSelected="1" workbookViewId="0">
  815. <selection activeCell="C1" sqref="C1"/>
  816. </sheetView>
  817. </sheetViews>
  818. <sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  819. <sheetData>
  820. <row r="1" spans="1:6">
  821. <c r="A1" t="s">
  822. <v>0</v>
  823. </c>
  824. <c r="B1">
  825. <v>12345</v>
  826. </c>
  827. <c r="C1">
  828. <v>1.024</v>
  829. </c>
  830. <c r="D1" t="b">
  831. <v>1</v>
  832. </c>
  833. <c r="E1">
  834. <f>10+20</f>
  835. <v>30</v>
  836. </c>
  837. <c r="F1" t="e">
  838. <f>10/0</f>
  839. <v>#DIV/0!</v>
  840. </c>
  841. </row>
  842. </sheetData>
  843. <pageMargins left="0.7" right="0.7"
  844. top="0.78740157499999996"
  845. bottom="0.78740157499999996"
  846. header="0.3"
  847. footer="0.3"/>
  848. </worksheet>`)
  849. worksheet := new(xlsxWorksheet)
  850. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  851. c.Assert(err, IsNil)
  852. sst := new(xlsxSST)
  853. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  854. c.Assert(err, IsNil)
  855. file := new(File)
  856. file.referenceTable = MakeSharedStringRefTable(sst)
  857. sheet := new(Sheet)
  858. rows, _, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  859. c.Assert(maxRows, Equals, 1)
  860. c.Assert(maxCols, Equals, 6)
  861. row := rows[0]
  862. c.Assert(row.Sheet, Equals, sheet)
  863. c.Assert(len(row.Cells), Equals, 6)
  864. cell1 := row.Cells[0]
  865. c.Assert(cell1.Type(), Equals, CellTypeString)
  866. c.Assert(cell1.String(), Equals, "Hello World")
  867. cell2 := row.Cells[1]
  868. c.Assert(cell2.Type(), Equals, CellTypeNumeric)
  869. intValue, _ := cell2.Int()
  870. c.Assert(intValue, Equals, 12345)
  871. cell3 := row.Cells[2]
  872. c.Assert(cell3.Type(), Equals, CellTypeNumeric)
  873. float, _ := cell3.Float()
  874. c.Assert(float, Equals, 1.024)
  875. cell4 := row.Cells[3]
  876. c.Assert(cell4.Type(), Equals, CellTypeBool)
  877. c.Assert(cell4.Bool(), Equals, true)
  878. cell5 := row.Cells[4]
  879. c.Assert(cell5.Type(), Equals, CellTypeFormula)
  880. c.Assert(cell5.Formula(), Equals, "10+20")
  881. c.Assert(cell5.Value, Equals, "30")
  882. cell6 := row.Cells[5]
  883. c.Assert(cell6.Type(), Equals, CellTypeError)
  884. c.Assert(cell6.Formula(), Equals, "10/0")
  885. c.Assert(cell6.Value, Equals, "#DIV/0!")
  886. }
  887. func (l *LibSuite) TestReadRowsFromSheetWithHiddenColumn(c *C) {
  888. var sharedstringsXML = bytes.NewBufferString(`
  889. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  890. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  891. <si><t>This is a test.</t></si>
  892. <si><t>This should be invisible.</t></si>
  893. </sst>`)
  894. var sheetxml = bytes.NewBufferString(`
  895. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  896. <worksheet xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main"
  897. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main"
  898. xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  899. <sheetViews><sheetView workbookViewId="0"/>
  900. </sheetViews>
  901. <sheetFormatPr customHeight="1" defaultColWidth="14.43" defaultRowHeight="15.75"/>
  902. <cols>
  903. <col hidden="1" max="2" min="2"/>
  904. </cols>
  905. <sheetData>
  906. <row r="1">
  907. <c r="A1" s="1" t="s"><v>0</v></c>
  908. <c r="B1" s="1" t="s"><v>1</v></c>
  909. </row>
  910. </sheetData><drawing r:id="rId1"/></worksheet>`)
  911. worksheet := new(xlsxWorksheet)
  912. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  913. c.Assert(err, IsNil)
  914. sst := new(xlsxSST)
  915. err = xml.NewDecoder(sharedstringsXML).Decode(sst)
  916. c.Assert(err, IsNil)
  917. file := new(File)
  918. file.referenceTable = MakeSharedStringRefTable(sst)
  919. sheet := new(Sheet)
  920. rows, _, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  921. c.Assert(maxRows, Equals, 1)
  922. c.Assert(maxCols, Equals, 2)
  923. row := rows[0]
  924. c.Assert(row.Sheet, Equals, sheet)
  925. c.Assert(len(row.Cells), Equals, 2)
  926. cell1 := row.Cells[0]
  927. c.Assert(cell1.Type(), Equals, CellTypeString)
  928. c.Assert(cell1.String(), Equals, "This is a test.")
  929. c.Assert(cell1.Hidden, Equals, false)
  930. cell2 := row.Cells[1]
  931. c.Assert(cell2.Type(), Equals, CellTypeString)
  932. c.Assert(cell2.String(), Equals, "This should be invisible.")
  933. c.Assert(cell2.Hidden, Equals, true)
  934. }
  935. // When converting the xlsxRow to a Row we create a as many cells as we find.
  936. func (l *LibSuite) TestReadRowFromRaw(c *C) {
  937. var rawRow xlsxRow
  938. var cell xlsxC
  939. var row *Row
  940. rawRow = xlsxRow{}
  941. cell = xlsxC{R: "A1"}
  942. cell = xlsxC{R: "A2"}
  943. rawRow.C = append(rawRow.C, cell)
  944. sheet := new(Sheet)
  945. row = makeRowFromRaw(rawRow, sheet)
  946. c.Assert(row, NotNil)
  947. c.Assert(row.Cells, HasLen, 1)
  948. c.Assert(row.Sheet, Equals, sheet)
  949. }
  950. // When a cell claims it is at a position greater than its ordinal
  951. // position in the file we make up the missing cells.
  952. func (l *LibSuite) TestReadRowFromRawWithMissingCells(c *C) {
  953. var rawRow xlsxRow
  954. var cell xlsxC
  955. var row *Row
  956. rawRow = xlsxRow{}
  957. cell = xlsxC{R: "A1"}
  958. rawRow.C = append(rawRow.C, cell)
  959. cell = xlsxC{R: "E1"}
  960. rawRow.C = append(rawRow.C, cell)
  961. sheet := new(Sheet)
  962. row = makeRowFromRaw(rawRow, sheet)
  963. c.Assert(row, NotNil)
  964. c.Assert(row.Cells, HasLen, 5)
  965. c.Assert(row.Sheet, Equals, sheet)
  966. }
  967. // We can cope with missing coordinate references
  968. func (l *LibSuite) TestReadRowFromRawWithPartialCoordinates(c *C) {
  969. var rawRow xlsxRow
  970. var cell xlsxC
  971. var row *Row
  972. rawRow = xlsxRow{}
  973. cell = xlsxC{R: "A1"}
  974. rawRow.C = append(rawRow.C, cell)
  975. cell = xlsxC{}
  976. rawRow.C = append(rawRow.C, cell)
  977. cell = xlsxC{R: "Z:1"}
  978. rawRow.C = append(rawRow.C, cell)
  979. cell = xlsxC{}
  980. rawRow.C = append(rawRow.C, cell)
  981. sheet := new(Sheet)
  982. row = makeRowFromRaw(rawRow, sheet)
  983. c.Assert(row, NotNil)
  984. c.Assert(row.Cells, HasLen, 27)
  985. c.Assert(row.Sheet, Equals, sheet)
  986. }
  987. func (l *LibSuite) TestSharedFormulas(c *C) {
  988. var sheetxml = bytes.NewBufferString(`
  989. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  990. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  991. xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  992. <dimension ref="A1:C2"/>
  993. <sheetViews>
  994. <sheetView tabSelected="1" workbookViewId="0">
  995. <selection activeCell="C1" sqref="C1"/>
  996. </sheetView>
  997. </sheetViews>
  998. <sheetFormatPr baseColWidth="10" defaultRowHeight="15"/>
  999. <sheetData>
  1000. <row r="1" spans="1:3">
  1001. <c r="A1">
  1002. <v>1</v>
  1003. </c>
  1004. <c r="B1">
  1005. <v>2</v>
  1006. </c>
  1007. <c r="C1">
  1008. <v>3</v>
  1009. </c>
  1010. </row>
  1011. <row r="2" spans="1:3">
  1012. <c r="A2">
  1013. <v>2</v>
  1014. <f t="shared" ref="A2:C2" si="0">2*A1</f>
  1015. </c>
  1016. <c r="B2">
  1017. <v>4</v>
  1018. <f t="shared" si="0"/>
  1019. </c>
  1020. <c r="C2">
  1021. <v>6</v>
  1022. <f t="shared" si="0"/>
  1023. </c>
  1024. </row>
  1025. </sheetData>
  1026. <pageMargins left="0.7" right="0.7"
  1027. top="0.78740157499999996"
  1028. bottom="0.78740157499999996"
  1029. header="0.3"
  1030. footer="0.3"/>
  1031. </worksheet>`)
  1032. worksheet := new(xlsxWorksheet)
  1033. err := xml.NewDecoder(sheetxml).Decode(worksheet)
  1034. c.Assert(err, IsNil)
  1035. file := new(File)
  1036. sheet := new(Sheet)
  1037. rows, _, maxCols, maxRows := readRowsFromSheet(worksheet, file, sheet)
  1038. c.Assert(maxCols, Equals, 3)
  1039. c.Assert(maxRows, Equals, 2)
  1040. row := rows[1]
  1041. c.Assert(row.Cells[1].Formula(), Equals, "2*B1")
  1042. c.Assert(row.Cells[2].Formula(), Equals, "2*C1")
  1043. }
  1044. // Test shared formulas that have absolute references ($) in them
  1045. func (l *LibSuite) TestSharedFormulasWithAbsoluteReferences(c *C) {
  1046. formulas := []string{
  1047. "A1",
  1048. "$A1",
  1049. "A$1",
  1050. "$A$1",
  1051. "A1+B1",
  1052. "$A1+B1",
  1053. "$A$1+B1",
  1054. "A1+$B1",
  1055. "A1+B$1",
  1056. "A1+$B$1",
  1057. "$A$1+$B$1",
  1058. }
  1059. expected := []string{
  1060. "B2",
  1061. "$A2",
  1062. "B$1",
  1063. "$A$1",
  1064. "B2+C2",
  1065. "$A2+C2",
  1066. "$A$1+C2",
  1067. "B2+$B2",
  1068. "B2+C$1",
  1069. "B2+$B$1",
  1070. "$A$1+$B$1",
  1071. }
  1072. anchorCell := "C4"
  1073. sharedFormulas := map[int]sharedFormula{}
  1074. x, y, _ := getCoordsFromCellIDString(anchorCell)
  1075. for i, formula := range formulas {
  1076. res := formula
  1077. sharedFormulas[i] = sharedFormula{x, y, res}
  1078. }
  1079. for i, formula := range formulas {
  1080. testCell := xlsxC{
  1081. R: "D5",
  1082. F: &xlsxF{
  1083. Content: formula,
  1084. T: "shared",
  1085. Si: i,
  1086. },
  1087. }
  1088. c.Assert(formulaForCell(testCell, sharedFormulas), Equals, expected[i])
  1089. }
  1090. }
  1091. // Avoid panic when cell.F.T is "e" (for error)
  1092. func (l *LibSuite) TestFormulaForCellPanic(c *C) {
  1093. cell := xlsxC{R: "A1"}
  1094. // This line would panic before the fix.
  1095. sharedFormulas := make(map[int]sharedFormula)
  1096. // Not really an important test; getting here without a
  1097. // panic is the real win.
  1098. c.Assert(formulaForCell(cell, sharedFormulas), Equals, "")
  1099. }
  1100. func (l *LibSuite) TestRowNotOverwrittenWhenFollowedByEmptyRow(c *C) {
  1101. sheetXML := bytes.NewBufferString(`
  1102. <?xml version="1.0" encoding="UTF-8"?>
  1103. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
  1104. <sheetViews>
  1105. <sheetView workbookViewId="0" />
  1106. </sheetViews>
  1107. <sheetFormatPr customHeight="1" defaultColWidth="14.43" defaultRowHeight="15.75" />
  1108. <sheetData>
  1109. <row r="2">
  1110. <c r="A2" t="str">
  1111. <f t="shared" ref="A2" si="1">RANDBETWEEN(1,100)</f>
  1112. <v>66</v>
  1113. </c>
  1114. </row>
  1115. <row r="3">
  1116. <c r="A3" t="str">
  1117. <f t="shared" ref="A3" si="2">RANDBETWEEN(1,100)</f>
  1118. <v>30</v>
  1119. </c>
  1120. </row>
  1121. <row r="4">
  1122. <c r="A4" t="str">
  1123. <f t="shared" ref="A4" si="3">RANDBETWEEN(1,100)</f>
  1124. <v>75</v>
  1125. </c>
  1126. </row>
  1127. <row r="7">
  1128. <c r="A7" s="1" t="str">
  1129. <f t="shared" ref="A7" si="4">A4/A2</f>
  1130. <v>1.14</v>
  1131. </c>
  1132. </row>
  1133. </sheetData>
  1134. <drawing r:id="rId1" />
  1135. </worksheet>
  1136. `)
  1137. sharedstringsXML := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"/>`)
  1138. worksheet := new(xlsxWorksheet)
  1139. xml.NewDecoder(sheetXML).Decode(worksheet)
  1140. sst := new(xlsxSST)
  1141. xml.NewDecoder(sharedstringsXML).Decode(sst)
  1142. file := new(File)
  1143. file.referenceTable = MakeSharedStringRefTable(sst)
  1144. sheet := new(Sheet)
  1145. rows, _, _, _ := readRowsFromSheet(worksheet, file, sheet)
  1146. cells := rows[3].Cells
  1147. c.Assert(cells, HasLen, 1)
  1148. c.Assert(cells[0].Value, Equals, "75")
  1149. }
  1150. // This was a specific issue raised by a user.
  1151. func (l *LibSuite) TestRoundTripFileWithNoSheetCols(c *C) {
  1152. originalXlFile, err := OpenFile("testdocs/original.xlsx")
  1153. c.Assert(err, IsNil)
  1154. originalXlFile.Save("testdocs/after_write.xlsx")
  1155. _, err = OpenFile("testdocs/after_write.xlsx")
  1156. c.Assert(err, IsNil)
  1157. os.Remove("testdocs/after_write.xlsx")
  1158. }