/* vim: set ts=2:*/ /*jshint eqnull:true */ var XLSX = (function(){ var debug = 0; var ct2type = { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks", "application/vnd.openxmlformats-package.core-properties+xml": "coreprops", "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops", "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml":"sheets", "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml": "strs", "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml":"styles", "application/vnd.openxmlformats-officedocument.theme+xml":"themes", "foo": "bar" }; var WBPropsDef = { allowRefreshQuery: '0', autoCompressPictures: '1', backupFile: '0', checkCompatibility: '0', codeName: '', date1904: '0', dateCompatibility: '1', //defaultThemeVersion: '0', filterPrivacy: '0', hidePivotFieldList: '0', promptedSolutions: '0', publishItems: '0', refreshAllConnections: false, saveExternalLinkValues: '1', showBorderUnselectedTables: '1', showInkAnnotation: '1', showObjects: 'all', showPivotChartFilter: '0' //updateLinks: 'userSet' }; var WBViewDef = { activeTab: '0', autoFilterDateGrouping: '1', firstSheet: '0', minimized: '0', showHorizontalScroll: '1', showSheetTabs: '1', showVerticalScroll: '1', tabRatio: '600', visibility: 'visible' //window{Height,Width}, {x,y}Window }; var SheetDef = { state: 'visible' }; var CalcPrDef = { calcCompleted: '1', calcMode: 'auto', calcOnSave: '1', concurrentCalc: '1', fullCalcOnLoad: '0', iterate: 'false', iterateCount: '100', iterateDelta: '0.001', refMode: 'A1' }; var XMLNS_CT = 'http://schemas.openxmlformats.org/package/2006/content-types'; var XMLNS_WB = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'; var encodings = { '>': '>', '<': '<', '&': '&' }; function unescapexml(text){ var s = text + ''; for(var y in encodings) s = s.replace(new RegExp(y,'g'), encodings[y]); return s; } function parsexmltag(tag) { var words = tag.split(/\s+/); var z = {'0': words[0]}; if(words.length === 1) return z; tag.match(/(\w+)="([^"]*)"/g).map( function(x){var y=x.match(/(\w+)="([^"]*)"/); z[y[1]] = y[2]; }); return z; } var strs = {}; // shared strings function parseSheet(data) { //TODO: use a real xml parser var s = {}; s["!ref"] = data.match(//)[1]; //s.rows = {}; //s.cells = {}; var q = ["v","f"]; data.match(/(.*)<\/sheetData>/)[1].split("").forEach(function(x) { if(x === "") return; var row = parsexmltag(x.match(/]*>/)[0]); //s.rows[row.r]=row.spans; var cells = x.substr(x.indexOf('>')+1).split(""); cells.forEach(function(c) { if(c === "") return; var cell = parsexmltag(c.match(/]*>/)[0]); delete cell[0]; var d = c.substr(c.indexOf('>')+1); var p = {}; q.forEach(function(f){var x=d.match(matchtag(f));if(x)p[f]=unescapexml(x[1]);}); p.t = (cell.t ? cell.t : "n"); // default is "n" in schema switch(p.t) { case 'n': p.v = parseFloat(p.v); break; case 's': p.v = strs[parseInt(p.v, 10)].t; break; case 'str': break; // normal string default: throw "Unrecognized cell type: " + p.t; } //s.cells[cell.r] = p; s[cell.r] = p; }); }); if(debug) s.rawdata = data; return s; } // matches ... extracts content function matchtag(f,g) {return new RegExp('<' + f + '>(.*)',g||"");} function parseStrs(data) { var s = []; var sst = data.match(new RegExp("]*)>(.*)<\/sst>")); s = sst[2].replace(//g,"").split(/<\/si>/).map(function(x) { var z = {}; var y=x.match(/<(.*)>(.*)<\/.*/); if(x) z[y[1]]=unescapexml(y[2]); return z;}); sst = parsexmltag(sst[1]); s.count = sst.count; s.uniqueCount = sst.uniqueCount; if(debug) s.rawdata = data; return s; } function parseProps(data) { var p = { Company:'' }, q = {}; var strings = ["Application", "DocSecurity", "Company", "AppVersion"]; var bools = ["HyperlinksChanged","SharedDoc","LinksUpToDate","ScaleCrop"]; var xtra = ["HeadingPairs", "TitlesOfParts","dc:creator","cp:lastModifiedBy","dcterms:created", "dcterms:modified"]; strings.forEach(function(f){p[f] = data.match(matchtag(f))[1];}); bools.forEach(function(f){p[f] = data.match(matchtag(f))[1] == "true";}); xtra.forEach(function(f){q[f] = data.match(new RegExp("<" + f + "[^>]*>(.*)<\/" + f + ">"))[1];}); p["Worksheets"] = parseInt(q["HeadingPairs"].match(new RegExp("(.*)<\/vt:i4>"))[1], 10); p["SheetNames"] = q["TitlesOfParts"].match(new RegExp("([^<]*)<\/vt:lpstr>","g")).map(function(x){return x.match(new RegExp("([^<]*)<\/vt:lpstr>"))[1];}); p["Creator"] = q["dc:creator"]; p["LastModifiedBy"] = q["cp:lastModifiedBy"]; p["CreatedDate"] = new Date(q["dcterms:created"]); p["ModifiedDate"] = new Date(q["dcterms:modified"]); if(debug) p.rawdata = data; return p; } function parseDeps(data) { var d = []; var l = 0, i = 1; data.match(/<[^>]*>/g).forEach(function(x) { var y = parsexmltag(x); switch(y[0]) { case ']*>/g).forEach(function(x) { var y = parsexmltag(x); switch(y[0]) { case ' 0 ? ct.calcchains[0] : ""; delete ct.calcchains; if(debug) ct.rawdata = data; return ct; } function parseWB(data) { var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" }; data.match(/<[^>]*>/g).forEach(function(x) { var y = parsexmltag(x); switch(y[0]) { case '': case '': break; // aggregate workbookView case '': case '': break; // aggregate sheet case '': case '': case '': break; case '': break; case '