/* 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 = {};
var ref = data.match(//);
if(ref) s["!ref"] = ref[1];
var refguess = {s: {r:1000000, c:1000000}, e: {r:0, c:0} };
//s.rows = {};
//s.cells = {};
var q = ["v","f"];
if(!data.match(//))
data.match(/(.*)<\/sheetData>/)[1].split("").forEach(function(x) { if(x === "") return;
var row = parsexmltag(x.match(/]*>/)[0]); //s.rows[row.r]=row.spans;
if(refguess.s.r > row.r - 1) refguess.s.r = row.r - 1;
if(refguess.e.r < row.r - 1) refguess.e.r = row.r - 1;
var cells = x.substr(x.indexOf('>')+1).split(/<\/c>|\/>/);
cells.forEach(function(c, idx) { if(c === "") return;
if(refguess.s.c > idx) refguess.s.c = idx;
if(refguess.e.c < idx) refguess.e.c = idx;
var cell = parsexmltag((c.match(/]*>/)||[c])[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]);});
/* SCHEMA IS ACTUALLY INCORRECT HERE. IF A CELL HAS NO T, EMIT "" */
if(cell.t === undefined) { p.t = "str"; p.v = undefined; }
else 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(!s["!ref"]) s["!ref"] = encode_range(refguess);
if(debug) s.rawdata = data;
return s;
}
// matches ... extracts content
function matchtag(f,g) {return new RegExp('<' + f + '>([\\s\\S]*)' + f + '>',g||"");}
function parseStrs(data) {
var s = [];
var sst = data.match(new RegExp("]*)>([\\s\\S]*)<\/sst>","m"));
if(sst) {
s = sst[2].replace(//g,"").split(/<\/si>/).map(function(x) { var z = {};
var y=x.match(/<(.*)>([\s\S]*)<\/.*/); if(y) 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) {
var cur = data.match(new RegExp("<" + f + "[^>]*>(.*)<\/" + f + ">"));
if(cur && cur.length > 0) q[f] = cur[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 '': delete y[0]; wb.WBProps = y; break;
case '': case '': break; // aggregate workbookView
case '': case '': break; // aggregate sheet
case '': case '': case '': break;
case '': break;
case '': delete y[0]; wb.CalcPr = y; break;
case '': break;
case '