lib_test.go 40 KB

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