file_test.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. package xlsx
  2. import (
  3. "encoding/xml"
  4. "path/filepath"
  5. . "gopkg.in/check.v1"
  6. )
  7. type FileSuite struct{}
  8. var _ = Suite(&FileSuite{})
  9. // Test we can correctly open a XSLX file and return a xlsx.File
  10. // struct.
  11. func (l *FileSuite) TestOpenFile(c *C) {
  12. var xlsxFile *File
  13. var error error
  14. xlsxFile, error = OpenFile("./testdocs/testfile.xlsx")
  15. c.Assert(error, IsNil)
  16. c.Assert(xlsxFile, NotNil)
  17. }
  18. func (l *FileSuite) TestOpenFileWithoutStyleAndSharedStrings(c *C) {
  19. var xlsxFile *File
  20. var error error
  21. xlsxFile, error = OpenFile("./testdocs/noStylesAndSharedStringsTest.xlsx")
  22. c.Assert(error, IsNil)
  23. c.Assert(xlsxFile, NotNil)
  24. }
  25. // Test that we can correctly extract a reference table from the
  26. // sharedStrings.xml file embedded in the XLSX file and return a
  27. // reference table of string values from it.
  28. func (l *FileSuite) TestReadSharedStringsFromZipFile(c *C) {
  29. var xlsxFile *File
  30. var err error
  31. xlsxFile, err = OpenFile("./testdocs/testfile.xlsx")
  32. c.Assert(err, IsNil)
  33. c.Assert(xlsxFile.referenceTable, NotNil)
  34. }
  35. // Helper function used to test contents of a given xlsxXf against
  36. // expectations.
  37. func testXf(c *C, result, expected *xlsxXf) {
  38. c.Assert(result.ApplyAlignment, Equals, expected.ApplyAlignment)
  39. c.Assert(result.ApplyBorder, Equals, expected.ApplyBorder)
  40. c.Assert(result.ApplyFont, Equals, expected.ApplyFont)
  41. c.Assert(result.ApplyFill, Equals, expected.ApplyFill)
  42. c.Assert(result.ApplyProtection, Equals, expected.ApplyProtection)
  43. c.Assert(result.BorderId, Equals, expected.BorderId)
  44. c.Assert(result.FillId, Equals, expected.FillId)
  45. c.Assert(result.FontId, Equals, expected.FontId)
  46. c.Assert(result.NumFmtId, Equals, expected.NumFmtId)
  47. }
  48. // We can correctly extract a style table from the style.xml file
  49. // embedded in the XLSX file and return a styles struct from it.
  50. func (l *FileSuite) TestReadStylesFromZipFile(c *C) {
  51. var xlsxFile *File
  52. var err error
  53. var fontCount, fillCount, borderCount, cellStyleXfCount, cellXfCount int
  54. var font xlsxFont
  55. var fill xlsxFill
  56. var border xlsxBorder
  57. var xf xlsxXf
  58. xlsxFile, err = OpenFile("./testdocs/testfile.xlsx")
  59. c.Assert(err, IsNil)
  60. c.Assert(xlsxFile.styles, NotNil)
  61. fontCount = len(xlsxFile.styles.Fonts.Font)
  62. c.Assert(fontCount, Equals, 4)
  63. font = xlsxFile.styles.Fonts.Font[0]
  64. c.Assert(font.Sz.Val, Equals, "11")
  65. c.Assert(font.Name.Val, Equals, "Calibri")
  66. fillCount = xlsxFile.styles.Fills.Count
  67. c.Assert(fillCount, Equals, 3)
  68. fill = xlsxFile.styles.Fills.Fill[2]
  69. c.Assert(fill.PatternFill.PatternType, Equals, "solid")
  70. borderCount = xlsxFile.styles.Borders.Count
  71. c.Assert(borderCount, Equals, 2)
  72. border = xlsxFile.styles.Borders.Border[1]
  73. c.Assert(border.Left.Style, Equals, "thin")
  74. c.Assert(border.Right.Style, Equals, "thin")
  75. c.Assert(border.Top.Style, Equals, "thin")
  76. c.Assert(border.Bottom.Style, Equals, "thin")
  77. cellStyleXfCount = xlsxFile.styles.CellStyleXfs.Count
  78. c.Assert(cellStyleXfCount, Equals, 20)
  79. xf = xlsxFile.styles.CellStyleXfs.Xf[0]
  80. expectedXf := &xlsxXf{
  81. ApplyAlignment: true,
  82. ApplyBorder: true,
  83. ApplyFont: true,
  84. ApplyFill: false,
  85. ApplyProtection: true,
  86. BorderId: 0,
  87. FillId: 0,
  88. FontId: 0,
  89. NumFmtId: 164}
  90. testXf(c, &xf, expectedXf)
  91. cellXfCount = xlsxFile.styles.CellXfs.Count
  92. c.Assert(cellXfCount, Equals, 3)
  93. xf = xlsxFile.styles.CellXfs.Xf[0]
  94. expectedXf = &xlsxXf{
  95. ApplyAlignment: false,
  96. ApplyBorder: false,
  97. ApplyFont: false,
  98. ApplyFill: false,
  99. ApplyProtection: false,
  100. BorderId: 0,
  101. FillId: 0,
  102. FontId: 0,
  103. NumFmtId: 164}
  104. testXf(c, &xf, expectedXf)
  105. }
  106. // We can correctly extract a map of relationship Ids to the worksheet files in
  107. // which they are contained from the XLSX file.
  108. func (l *FileSuite) TestReadWorkbookRelationsFromZipFile(c *C) {
  109. var xlsxFile *File
  110. var err error
  111. xlsxFile, err = OpenFile("./testdocs/testfile.xlsx")
  112. c.Assert(err, IsNil)
  113. c.Assert(len(xlsxFile.Sheets), Equals, 3)
  114. sheet, ok := xlsxFile.Sheet["Tabelle1"]
  115. c.Assert(ok, Equals, true)
  116. c.Assert(sheet, NotNil)
  117. }
  118. // Style information is correctly extracted from the zipped XLSX file.
  119. func (l *FileSuite) TestGetStyleFromZipFile(c *C) {
  120. var xlsxFile *File
  121. var err error
  122. var style Style
  123. xlsxFile, err = OpenFile("./testdocs/testfile.xlsx")
  124. c.Assert(err, IsNil)
  125. sheetCount := len(xlsxFile.Sheets)
  126. c.Assert(sheetCount, Equals, 3)
  127. tabelle1 := xlsxFile.Sheet["Tabelle1"]
  128. row0 := tabelle1.Rows[0]
  129. cellFoo := row0.Cells[0]
  130. style = cellFoo.GetStyle()
  131. c.Assert(cellFoo.String(), Equals, "Foo")
  132. c.Assert(style.Fill.BgColor, Equals, "FF33CCCC")
  133. c.Assert(style.ApplyFill, Equals, false)
  134. c.Assert(style.ApplyFont, Equals, true)
  135. row1 := tabelle1.Rows[1]
  136. cellQuuk := row1.Cells[1]
  137. style = cellQuuk.GetStyle()
  138. c.Assert(cellQuuk.String(), Equals, "Quuk")
  139. c.Assert(style.Border.Left, Equals, "thin")
  140. c.Assert(style.ApplyBorder, Equals, true)
  141. cellBar := row0.Cells[1]
  142. c.Assert(cellBar.String(), Equals, "Bar")
  143. c.Assert(cellBar.GetStyle().Fill.BgColor, Equals, "")
  144. }
  145. // Test we can create a File object from scratch
  146. func (l *FileSuite) TestCreateFile(c *C) {
  147. var xlsxFile *File
  148. xlsxFile = NewFile()
  149. c.Assert(xlsxFile, NotNil)
  150. }
  151. // Test that when we open a real XLSX file we create xlsx.Sheet
  152. // objects for the sheets inside the file and that these sheets are
  153. // themselves correct.
  154. func (l *FileSuite) TestCreateSheet(c *C) {
  155. var xlsxFile *File
  156. var err error
  157. var sheet *Sheet
  158. var row *Row
  159. xlsxFile, err = OpenFile("./testdocs/testfile.xlsx")
  160. c.Assert(err, IsNil)
  161. c.Assert(xlsxFile, NotNil)
  162. sheetLen := len(xlsxFile.Sheets)
  163. c.Assert(sheetLen, Equals, 3)
  164. sheet = xlsxFile.Sheet["Tabelle1"]
  165. rowLen := len(sheet.Rows)
  166. c.Assert(rowLen, Equals, 2)
  167. row = sheet.Rows[0]
  168. c.Assert(len(row.Cells), Equals, 2)
  169. cell := row.Cells[0]
  170. cellstring := cell.String()
  171. c.Assert(cellstring, Equals, "Foo")
  172. }
  173. // Test that we can add a sheet to a File
  174. func (l *FileSuite) TestAddSheet(c *C) {
  175. var f *File
  176. f = NewFile()
  177. sheet := f.AddSheet("MySheet")
  178. c.Assert(sheet, NotNil)
  179. c.Assert(len(f.Sheets), Equals, 1)
  180. c.Assert(f.Sheet["MySheet"], Equals, sheet)
  181. }
  182. // Test that we can get the Nth sheet
  183. func (l *FileSuite) TestNthSheet(c *C) {
  184. var f *File
  185. f = NewFile()
  186. sheet := f.AddSheet("MySheet")
  187. sheetByIndex := f.Sheets[0]
  188. sheetByName := f.Sheet["MySheet"]
  189. c.Assert(sheetByIndex, NotNil)
  190. c.Assert(sheetByIndex, Equals, sheet)
  191. c.Assert(sheetByIndex, Equals, sheetByName)
  192. }
  193. // Test that we can create a Workbook and marshal it to XML.
  194. func (l *FileSuite) TestMarshalWorkbook(c *C) {
  195. var f *File
  196. f = NewFile()
  197. f.AddSheet("MyFirstSheet")
  198. f.AddSheet("MySecondSheet")
  199. workbook := f.makeWorkbook()
  200. workbook.Sheets.Sheet[0] = xlsxSheet{
  201. Name: "MyFirstSheet",
  202. SheetId: "1",
  203. Id: "rId1",
  204. State: "visible"}
  205. workbook.Sheets.Sheet[1] = xlsxSheet{
  206. Name: "MySecondSheet",
  207. SheetId: "2",
  208. Id: "rId2",
  209. State: "visible"}
  210. expectedWorkbook := `<?xml version="1.0" encoding="UTF-8"?>
  211. <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><fileVersion appName="Go XLSX"></fileVersion><workbookPr showObjects="all" date1904="false"></workbookPr><workbookProtection></workbookProtection><bookViews><workbookView showHorizontalScroll="true" showVerticalScroll="true" showSheetTabs="true" tabRatio="204" windowHeight="8192" windowWidth="16384" xWindow="0" yWindow="0"></workbookView></bookViews><sheets><sheet name="MyFirstSheet" sheetId="1" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId1" state="visible"></sheet><sheet name="MySecondSheet" sheetId="2" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId2" state="visible"></sheet></sheets><definedNames></definedNames><calcPr iterateCount="100" refMode="A1" iterateDelta="0.001"></calcPr></workbook>`
  212. output, err := xml.Marshal(workbook)
  213. c.Assert(err, IsNil)
  214. stringOutput := xml.Header + string(output)
  215. c.Assert(stringOutput, Equals, expectedWorkbook)
  216. }
  217. // Test that we can marshall a File to a collection of xml files
  218. func (l *FileSuite) TestMarshalFile(c *C) {
  219. var f *File
  220. f = NewFile()
  221. sheet1 := f.AddSheet("MySheet")
  222. row1 := sheet1.AddRow()
  223. cell1 := row1.AddCell()
  224. cell1.Value = "A cell!"
  225. sheet2 := f.AddSheet("AnotherSheet")
  226. row2 := sheet2.AddRow()
  227. cell2 := row2.AddCell()
  228. cell2.Value = "A cell!"
  229. parts, err := f.MarshallParts()
  230. c.Assert(err, IsNil)
  231. c.Assert(len(parts), Equals, 11)
  232. // sheets
  233. expectedSheet1 := `<?xml version="1.0" encoding="UTF-8"?>
  234. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetPr filterMode="false"><pageSetUpPr fitToPage="false"></pageSetUpPr></sheetPr><sheetViews><sheetView windowProtection="false" showFormulas="false" showGridLines="true" showRowColHeaders="true" showZeros="true" rightToLeft="false" tabSelected="true" showOutlineSymbols="true" defaultGridColor="true" view="normal" topLeftCell="A1" colorId="64" zoomScale="100" zoomScaleNormal="100" zoomScalePageLayoutView="100" workbookViewId="0"><selection pane="topLeft" activeCell="A1" activeCellId="0" sqref="A1"></selection></sheetView></sheetViews><sheetFormatPr defaultRowHeight="12.85"></sheetFormatPr><dimension ref="A1"></dimension><cols><col collapsed="false" hidden="false" max="1" min="1" style="0" width="9.5"></col></cols><printOptions headings="false" gridLines="false" gridLinesSet="true" horizontalCentered="false" verticalCentered="false"></printOptions><pageMargins left="0.7875" right="0.7875" top="1.05277777777778" bottom="1.05277777777778" header="0.7875" footer="0.7875"></pageMargins><pageSetup paperSize="9" scale="100" firstPageNumber="1" fitToWidth="1" fitToHeight="1" pageOrder="downThenOver" orientation="portrait" usePrinterDefaults="false" blackAndWhite="false" draft="false" cellComments="none" useFirstPageNumber="true" horizontalDpi="300" verticalDpi="300" copies="1"></pageSetup><sheetData><row r="1"><c r="A1" s="0" t="s"><v>0</v></c></row></sheetData><headerFooter differentFirst="false" differentOddEven="false"><oddHeader>&amp;C&amp;&#34;Times New Roman,Regular&#34;&amp;12&amp;A</oddHeader><oddFooter>&amp;C&amp;&#34;Times New Roman,Regular&#34;&amp;12Page &amp;P</oddFooter></headerFooter></worksheet>`
  235. c.Assert(parts["xl/worksheets/sheet1.xml"], Equals, expectedSheet1)
  236. expectedSheet2 := `<?xml version="1.0" encoding="UTF-8"?>
  237. <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetPr filterMode="false"><pageSetUpPr fitToPage="false"></pageSetUpPr></sheetPr><sheetViews><sheetView windowProtection="false" showFormulas="false" showGridLines="true" showRowColHeaders="true" showZeros="true" rightToLeft="false" tabSelected="true" showOutlineSymbols="true" defaultGridColor="true" view="normal" topLeftCell="A1" colorId="64" zoomScale="100" zoomScaleNormal="100" zoomScalePageLayoutView="100" workbookViewId="0"><selection pane="topLeft" activeCell="A1" activeCellId="0" sqref="A1"></selection></sheetView></sheetViews><sheetFormatPr defaultRowHeight="12.85"></sheetFormatPr><dimension ref="A1"></dimension><cols><col collapsed="false" hidden="false" max="1" min="1" style="0" width="9.5"></col></cols><printOptions headings="false" gridLines="false" gridLinesSet="true" horizontalCentered="false" verticalCentered="false"></printOptions><pageMargins left="0.7875" right="0.7875" top="1.05277777777778" bottom="1.05277777777778" header="0.7875" footer="0.7875"></pageMargins><pageSetup paperSize="9" scale="100" firstPageNumber="1" fitToWidth="1" fitToHeight="1" pageOrder="downThenOver" orientation="portrait" usePrinterDefaults="false" blackAndWhite="false" draft="false" cellComments="none" useFirstPageNumber="true" horizontalDpi="300" verticalDpi="300" copies="1"></pageSetup><sheetData><row r="1"><c r="A1" s="1" t="s"><v>0</v></c></row></sheetData><headerFooter differentFirst="false" differentOddEven="false"><oddHeader>&amp;C&amp;&#34;Times New Roman,Regular&#34;&amp;12&amp;A</oddHeader><oddFooter>&amp;C&amp;&#34;Times New Roman,Regular&#34;&amp;12Page &amp;P</oddFooter></headerFooter></worksheet>`
  238. c.Assert(parts["xl/worksheets/sheet2.xml"], Equals, expectedSheet2)
  239. // .rels.xml
  240. expectedRels := `<?xml version="1.0" encoding="UTF-8"?>
  241. <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  242. <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
  243. <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
  244. <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
  245. </Relationships>`
  246. c.Assert(parts["_rels/.rels"], Equals, expectedRels)
  247. // app.xml
  248. expectedApp := `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  249. <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
  250. <TotalTime>0</TotalTime>
  251. <Application>Go XLSX</Application>
  252. </Properties>`
  253. c.Assert(parts["docProps/app.xml"], Equals, expectedApp)
  254. // core.xml
  255. expectedCore := `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  256. <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></cp:coreProperties>`
  257. c.Assert(parts["docProps/core.xml"], Equals, expectedCore)
  258. // theme1.xml
  259. expectedTheme := `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  260. <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office-Design">
  261. <a:themeElements>
  262. <a:clrScheme name="Office">
  263. <a:dk1>
  264. <a:sysClr val="windowText" lastClr="000000"/>
  265. </a:dk1>
  266. <a:lt1>
  267. <a:sysClr val="window" lastClr="FFFFFF"/>
  268. </a:lt1>
  269. <a:dk2>
  270. <a:srgbClr val="1F497D"/>
  271. </a:dk2>
  272. <a:lt2>
  273. <a:srgbClr val="EEECE1"/>
  274. </a:lt2>
  275. <a:accent1>
  276. <a:srgbClr val="4F81BD"/>
  277. </a:accent1>
  278. <a:accent2>
  279. <a:srgbClr val="C0504D"/>
  280. </a:accent2>
  281. <a:accent3>
  282. <a:srgbClr val="9BBB59"/>
  283. </a:accent3>
  284. <a:accent4>
  285. <a:srgbClr val="8064A2"/>
  286. </a:accent4>
  287. <a:accent5>
  288. <a:srgbClr val="4BACC6"/>
  289. </a:accent5>
  290. <a:accent6>
  291. <a:srgbClr val="F79646"/>
  292. </a:accent6>
  293. <a:hlink>
  294. <a:srgbClr val="0000FF"/>
  295. </a:hlink>
  296. <a:folHlink>
  297. <a:srgbClr val="800080"/>
  298. </a:folHlink>
  299. </a:clrScheme>
  300. <a:fontScheme name="Office">
  301. <a:majorFont>
  302. <a:latin typeface="Cambria"/>
  303. <a:ea typeface=""/>
  304. <a:cs typeface=""/>
  305. <a:font script="Jpan" typeface="MS Pゴシック"/>
  306. <a:font script="Hang" typeface="맑은 고딕"/>
  307. <a:font script="Hans" typeface="宋体"/>
  308. <a:font script="Hant" typeface="新細明體"/>
  309. <a:font script="Arab" typeface="Times New Roman"/>
  310. <a:font script="Hebr" typeface="Times New Roman"/>
  311. <a:font script="Thai" typeface="Tahoma"/>
  312. <a:font script="Ethi" typeface="Nyala"/>
  313. <a:font script="Beng" typeface="Vrinda"/>
  314. <a:font script="Gujr" typeface="Shruti"/>
  315. <a:font script="Khmr" typeface="MoolBoran"/>
  316. <a:font script="Knda" typeface="Tunga"/>
  317. <a:font script="Guru" typeface="Raavi"/>
  318. <a:font script="Cans" typeface="Euphemia"/>
  319. <a:font script="Cher" typeface="Plantagenet Cherokee"/>
  320. <a:font script="Yiii" typeface="Microsoft Yi Baiti"/>
  321. <a:font script="Tibt" typeface="Microsoft Himalaya"/>
  322. <a:font script="Thaa" typeface="MV Boli"/>
  323. <a:font script="Deva" typeface="Mangal"/>
  324. <a:font script="Telu" typeface="Gautami"/>
  325. <a:font script="Taml" typeface="Latha"/>
  326. <a:font script="Syrc" typeface="Estrangelo Edessa"/>
  327. <a:font script="Orya" typeface="Kalinga"/>
  328. <a:font script="Mlym" typeface="Kartika"/>
  329. <a:font script="Laoo" typeface="DokChampa"/>
  330. <a:font script="Sinh" typeface="Iskoola Pota"/>
  331. <a:font script="Mong" typeface="Mongolian Baiti"/>
  332. <a:font script="Viet" typeface="Times New Roman"/>
  333. <a:font script="Uigh" typeface="Microsoft Uighur"/>
  334. <a:font script="Geor" typeface="Sylfaen"/>
  335. </a:majorFont>
  336. <a:minorFont>
  337. <a:latin typeface="Calibri"/>
  338. <a:ea typeface=""/>
  339. <a:cs typeface=""/>
  340. <a:font script="Jpan" typeface="MS Pゴシック"/>
  341. <a:font script="Hang" typeface="맑은 고딕"/>
  342. <a:font script="Hans" typeface="宋体"/>
  343. <a:font script="Hant" typeface="新細明體"/>
  344. <a:font script="Arab" typeface="Arial"/>
  345. <a:font script="Hebr" typeface="Arial"/>
  346. <a:font script="Thai" typeface="Tahoma"/>
  347. <a:font script="Ethi" typeface="Nyala"/>
  348. <a:font script="Beng" typeface="Vrinda"/>
  349. <a:font script="Gujr" typeface="Shruti"/>
  350. <a:font script="Khmr" typeface="DaunPenh"/>
  351. <a:font script="Knda" typeface="Tunga"/>
  352. <a:font script="Guru" typeface="Raavi"/>
  353. <a:font script="Cans" typeface="Euphemia"/>
  354. <a:font script="Cher" typeface="Plantagenet Cherokee"/>
  355. <a:font script="Yiii" typeface="Microsoft Yi Baiti"/>
  356. <a:font script="Tibt" typeface="Microsoft Himalaya"/>
  357. <a:font script="Thaa" typeface="MV Boli"/>
  358. <a:font script="Deva" typeface="Mangal"/>
  359. <a:font script="Telu" typeface="Gautami"/>
  360. <a:font script="Taml" typeface="Latha"/>
  361. <a:font script="Syrc" typeface="Estrangelo Edessa"/>
  362. <a:font script="Orya" typeface="Kalinga"/>
  363. <a:font script="Mlym" typeface="Kartika"/>
  364. <a:font script="Laoo" typeface="DokChampa"/>
  365. <a:font script="Sinh" typeface="Iskoola Pota"/>
  366. <a:font script="Mong" typeface="Mongolian Baiti"/>
  367. <a:font script="Viet" typeface="Arial"/>
  368. <a:font script="Uigh" typeface="Microsoft Uighur"/>
  369. <a:font script="Geor" typeface="Sylfaen"/>
  370. </a:minorFont>
  371. </a:fontScheme>
  372. <a:fmtScheme name="Office">
  373. <a:fillStyleLst>
  374. <a:solidFill>
  375. <a:schemeClr val="phClr"/>
  376. </a:solidFill>
  377. <a:gradFill rotWithShape="1">
  378. <a:gsLst>
  379. <a:gs pos="0">
  380. <a:schemeClr val="phClr">
  381. <a:tint val="50000"/>
  382. <a:satMod val="300000"/>
  383. </a:schemeClr>
  384. </a:gs>
  385. <a:gs pos="35000">
  386. <a:schemeClr val="phClr">
  387. <a:tint val="37000"/>
  388. <a:satMod val="300000"/>
  389. </a:schemeClr>
  390. </a:gs>
  391. <a:gs pos="100000">
  392. <a:schemeClr val="phClr">
  393. <a:tint val="15000"/>
  394. <a:satMod val="350000"/>
  395. </a:schemeClr>
  396. </a:gs>
  397. </a:gsLst>
  398. <a:lin ang="16200000" scaled="1"/>
  399. </a:gradFill>
  400. <a:gradFill rotWithShape="1">
  401. <a:gsLst>
  402. <a:gs pos="0">
  403. <a:schemeClr val="phClr">
  404. <a:tint val="100000"/>
  405. <a:shade val="100000"/>
  406. <a:satMod val="130000"/>
  407. </a:schemeClr>
  408. </a:gs>
  409. <a:gs pos="100000">
  410. <a:schemeClr val="phClr">
  411. <a:tint val="50000"/>
  412. <a:shade val="100000"/>
  413. <a:satMod val="350000"/>
  414. </a:schemeClr>
  415. </a:gs>
  416. </a:gsLst>
  417. <a:lin ang="16200000" scaled="0"/>
  418. </a:gradFill>
  419. </a:fillStyleLst>
  420. <a:lnStyleLst>
  421. <a:ln w="9525" cap="flat" cmpd="sng" algn="ctr">
  422. <a:solidFill>
  423. <a:schemeClr val="phClr">
  424. <a:shade val="95000"/>
  425. <a:satMod val="105000"/>
  426. </a:schemeClr>
  427. </a:solidFill>
  428. <a:prstDash val="solid"/>
  429. </a:ln>
  430. <a:ln w="25400" cap="flat" cmpd="sng" algn="ctr">
  431. <a:solidFill>
  432. <a:schemeClr val="phClr"/>
  433. </a:solidFill>
  434. <a:prstDash val="solid"/>
  435. </a:ln>
  436. <a:ln w="38100" cap="flat" cmpd="sng" algn="ctr">
  437. <a:solidFill>
  438. <a:schemeClr val="phClr"/>
  439. </a:solidFill>
  440. <a:prstDash val="solid"/>
  441. </a:ln>
  442. </a:lnStyleLst>
  443. <a:effectStyleLst>
  444. <a:effectStyle>
  445. <a:effectLst>
  446. <a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0">
  447. <a:srgbClr val="000000">
  448. <a:alpha val="38000"/>
  449. </a:srgbClr>
  450. </a:outerShdw>
  451. </a:effectLst>
  452. </a:effectStyle>
  453. <a:effectStyle>
  454. <a:effectLst>
  455. <a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0">
  456. <a:srgbClr val="000000">
  457. <a:alpha val="35000"/>
  458. </a:srgbClr>
  459. </a:outerShdw>
  460. </a:effectLst>
  461. </a:effectStyle>
  462. <a:effectStyle>
  463. <a:effectLst>
  464. <a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0">
  465. <a:srgbClr val="000000">
  466. <a:alpha val="35000"/>
  467. </a:srgbClr>
  468. </a:outerShdw>
  469. </a:effectLst>
  470. <a:scene3d>
  471. <a:camera prst="orthographicFront">
  472. <a:rot lat="0" lon="0" rev="0"/>
  473. </a:camera>
  474. <a:lightRig rig="threePt" dir="t">
  475. <a:rot lat="0" lon="0" rev="1200000"/>
  476. </a:lightRig>
  477. </a:scene3d>
  478. <a:sp3d>
  479. <a:bevelT w="63500" h="25400"/>
  480. </a:sp3d>
  481. </a:effectStyle>
  482. </a:effectStyleLst>
  483. <a:bgFillStyleLst>
  484. <a:solidFill>
  485. <a:schemeClr val="phClr"/>
  486. </a:solidFill>
  487. <a:gradFill rotWithShape="1">
  488. <a:gsLst>
  489. <a:gs pos="0">
  490. <a:schemeClr val="phClr">
  491. <a:tint val="40000"/>
  492. <a:satMod val="350000"/>
  493. </a:schemeClr>
  494. </a:gs>
  495. <a:gs pos="40000">
  496. <a:schemeClr val="phClr">
  497. <a:tint val="45000"/>
  498. <a:shade val="99000"/>
  499. <a:satMod val="350000"/>
  500. </a:schemeClr>
  501. </a:gs>
  502. <a:gs pos="100000">
  503. <a:schemeClr val="phClr">
  504. <a:shade val="20000"/>
  505. <a:satMod val="255000"/>
  506. </a:schemeClr>
  507. </a:gs>
  508. </a:gsLst>
  509. <a:path path="circle">
  510. <a:fillToRect l="50000" t="-80000" r="50000" b="180000"/>
  511. </a:path>
  512. </a:gradFill>
  513. <a:gradFill rotWithShape="1">
  514. <a:gsLst>
  515. <a:gs pos="0">
  516. <a:schemeClr val="phClr">
  517. <a:tint val="80000"/>
  518. <a:satMod val="300000"/>
  519. </a:schemeClr>
  520. </a:gs>
  521. <a:gs pos="100000">
  522. <a:schemeClr val="phClr">
  523. <a:shade val="30000"/>
  524. <a:satMod val="200000"/>
  525. </a:schemeClr>
  526. </a:gs>
  527. </a:gsLst>
  528. <a:path path="circle">
  529. <a:fillToRect l="50000" t="50000" r="50000" b="50000"/>
  530. </a:path>
  531. </a:gradFill>
  532. </a:bgFillStyleLst>
  533. </a:fmtScheme>
  534. </a:themeElements>
  535. <a:objectDefaults>
  536. <a:spDef>
  537. <a:spPr/>
  538. <a:bodyPr/>
  539. <a:lstStyle/>
  540. <a:style>
  541. <a:lnRef idx="1">
  542. <a:schemeClr val="accent1"/>
  543. </a:lnRef>
  544. <a:fillRef idx="3">
  545. <a:schemeClr val="accent1"/>
  546. </a:fillRef>
  547. <a:effectRef idx="2">
  548. <a:schemeClr val="accent1"/>
  549. </a:effectRef>
  550. <a:fontRef idx="minor">
  551. <a:schemeClr val="lt1"/>
  552. </a:fontRef>
  553. </a:style>
  554. </a:spDef>
  555. <a:lnDef>
  556. <a:spPr/>
  557. <a:bodyPr/>
  558. <a:lstStyle/>
  559. <a:style>
  560. <a:lnRef idx="2">
  561. <a:schemeClr val="accent1"/>
  562. </a:lnRef>
  563. <a:fillRef idx="0">
  564. <a:schemeClr val="accent1"/>
  565. </a:fillRef>
  566. <a:effectRef idx="1">
  567. <a:schemeClr val="accent1"/>
  568. </a:effectRef>
  569. <a:fontRef idx="minor">
  570. <a:schemeClr val="tx1"/>
  571. </a:fontRef>
  572. </a:style>
  573. </a:lnDef>
  574. </a:objectDefaults>
  575. <a:extraClrSchemeLst/>
  576. </a:theme>`
  577. c.Assert(parts["xl/theme/theme1.xml"], Equals, expectedTheme)
  578. // sharedStrings.xml
  579. expectedXLSXSST := `<?xml version="1.0" encoding="UTF-8"?>
  580. <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1"><si><t>A cell!</t></si></sst>`
  581. c.Assert(parts["xl/sharedStrings.xml"], Equals, expectedXLSXSST)
  582. // workbook.xml.rels
  583. expectedXLSXWorkbookRels := `<?xml version="1.0" encoding="UTF-8"?>
  584. <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Target="worksheets/sheet1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"></Relationship><Relationship Id="rId2" Target="worksheets/sheet2.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"></Relationship><Relationship Id="rId3" Target="sharedStrings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"></Relationship><Relationship Id="rId4" Target="theme/theme1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"></Relationship><Relationship Id="rId5" Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"></Relationship></Relationships>`
  585. c.Assert(parts["xl/_rels/workbook.xml.rels"], Equals, expectedXLSXWorkbookRels)
  586. // workbook.xml
  587. expectedWorkbook := `<?xml version="1.0" encoding="UTF-8"?>
  588. <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><fileVersion appName="Go XLSX"></fileVersion><workbookPr showObjects="all" date1904="false"></workbookPr><workbookProtection></workbookProtection><bookViews><workbookView showHorizontalScroll="true" showVerticalScroll="true" showSheetTabs="true" tabRatio="204" windowHeight="8192" windowWidth="16384" xWindow="0" yWindow="0"></workbookView></bookViews><sheets><sheet name="MySheet" sheetId="1" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId1" state="visible"></sheet><sheet name="AnotherSheet" sheetId="2" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId2" state="visible"></sheet></sheets><definedNames></definedNames><calcPr iterateCount="100" refMode="A1" iterateDelta="0.001"></calcPr></workbook>`
  589. c.Assert(parts["xl/workbook.xml"], Equals, expectedWorkbook)
  590. // [Content_Types].xml
  591. expectedContentTypes := `<?xml version="1.0" encoding="UTF-8"?>
  592. <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"></Override><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"></Override><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"></Override><Override PartName="/xl/_rels/workbook.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"></Override><Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"></Override><Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"></Override><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"></Override><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"></Override><Override PartName="/xl/worksheets/sheet2.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"></Override><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"></Default><Default Extension="xml" ContentType="application/xml"></Default></Types>`
  593. c.Assert(parts["[Content_Types].xml"], Equals, expectedContentTypes)
  594. // styles.xml
  595. //
  596. // For now we only allow simple string data in the
  597. // spreadsheet. Style support will follow.
  598. expectedStyles := `<?xml version="1.0" encoding="UTF-8"?>
  599. <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><numFmts count="1"><numFmt numFmtId="164" formatCode="GENERAL"/></numFmts><fonts count="2"><font><sz val="12"/><name val="Verdana"/><family val="0"/><charset val="0"/></font><font><sz val="12"/><name val="Verdana"/><family val="0"/><charset val="0"/></font></fonts><cellStyleXfs count="2"><xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="164"><alignment horizontal="" indent="0" shrinkToFit="false" textRotation="0" vertical="" wrapText="false"/></xf><xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="164"><alignment horizontal="" indent="0" shrinkToFit="false" textRotation="0" vertical="" wrapText="false"/></xf></cellStyleXfs><cellXfs count="2"><xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="164"><alignment horizontal="" indent="0" shrinkToFit="false" textRotation="0" vertical="" wrapText="false"/></xf><xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="164"><alignment horizontal="" indent="0" shrinkToFit="false" textRotation="0" vertical="" wrapText="false"/></xf></cellXfs></styleSheet>`
  600. c.Assert(parts["xl/styles.xml"], Equals, expectedStyles)
  601. }
  602. // We can save a File as a valid XLSX file at a given path.
  603. func (l *FileSuite) TestSaveFile(c *C) {
  604. var tmpPath string = c.MkDir()
  605. var f *File
  606. f = NewFile()
  607. sheet1 := f.AddSheet("MySheet")
  608. row1 := sheet1.AddRow()
  609. cell1 := row1.AddCell()
  610. cell1.Value = "A cell!"
  611. sheet2 := f.AddSheet("AnotherSheet")
  612. row2 := sheet2.AddRow()
  613. cell2 := row2.AddCell()
  614. cell2.Value = "A cell!"
  615. xlsxPath := filepath.Join(tmpPath, "TestSaveFile.xlsx")
  616. err := f.Save(xlsxPath)
  617. c.Assert(err, IsNil)
  618. // Let's eat our own dog food
  619. xlsxFile, err := OpenFile(xlsxPath)
  620. c.Assert(err, IsNil)
  621. c.Assert(xlsxFile, NotNil)
  622. c.Assert(len(xlsxFile.Sheets), Equals, 2)
  623. sheet1, ok := xlsxFile.Sheet["MySheet"]
  624. c.Assert(ok, Equals, true)
  625. c.Assert(len(sheet1.Rows), Equals, 1)
  626. row1 = sheet1.Rows[0]
  627. c.Assert(len(row1.Cells), Equals, 1)
  628. cell1 = row1.Cells[0]
  629. c.Assert(cell1.Value, Equals, "A cell!")
  630. }
  631. type SliceReaderSuite struct{}
  632. var _ = Suite(&SliceReaderSuite{})
  633. func (s *SliceReaderSuite) TestFileToSlice(c *C) {
  634. output, err := FileToSlice("./testdocs/testfile.xlsx")
  635. c.Assert(err, IsNil)
  636. fileToSliceCheckOutput(c, output)
  637. }
  638. func (s *SliceReaderSuite) TestFileObjToSlice(c *C) {
  639. f, err := OpenFile("./testdocs/testfile.xlsx")
  640. output, err := f.ToSlice()
  641. c.Assert(err, IsNil)
  642. fileToSliceCheckOutput(c, output)
  643. }
  644. func fileToSliceCheckOutput(c *C, output [][][]string) {
  645. c.Assert(len(output), Equals, 3)
  646. c.Assert(len(output[0]), Equals, 2)
  647. c.Assert(len(output[0][0]), Equals, 2)
  648. c.Assert(output[0][0][0], Equals, "Foo")
  649. c.Assert(output[0][0][1], Equals, "Bar")
  650. c.Assert(len(output[0][1]), Equals, 2)
  651. c.Assert(output[0][1][0], Equals, "Baz")
  652. c.Assert(output[0][1][1], Equals, "Quuk")
  653. c.Assert(len(output[1]), Equals, 0)
  654. c.Assert(len(output[2]), Equals, 0)
  655. }