version bump 0.17.0

- Explicit errors on inconsistent XLS records
- DBF cap worksheet to 1<<20 rows
This commit is contained in:
Jeremy Mill 2021-05-13 15:02:31 -04:00
parent 6c5db3663c
commit 3542d62fff
24 changed files with 1772 additions and 112 deletions

@ -39,6 +39,7 @@ tmp
.gitattributes
.fossaignore
.spelling
.eslintignore
.eslintrc
.jshintrc
CONTRIBUTING.md

@ -4,6 +4,7 @@
/* vim: set ts=2 ft=javascript: */
var n = "xlsx";
var X = require('../');
try { X = require('../xlsx.flow'); } catch(e) {}
require('exit-on-epipe');
var fs = require('fs'), program = require('commander');
program

@ -1 +1 @@
XLSX.version = '0.16.9';
XLSX.version = '0.17.0';

@ -1,6 +1,6 @@
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/mg;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;

@ -177,7 +177,10 @@ var write_UncheckedRfX = write_RfX;
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data/*::, length*/) { return data.read_shift(8, 'f'); }
function parse_Xnum(data/*::, length*/) {
if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
return data.read_shift(8, 'f');
}
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
/* [MS-XLSB] 2.4.324 BrtColor */

@ -697,7 +697,7 @@ function parse_Lbl(blob, length, opts) {
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
return {
chKey: chKey,
Name: name,

@ -85,7 +85,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
if(ft == 0x02) nrow = d.read_shift(2);
/*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
if(ft != 0x02) nrow = d.read_shift(4);
if(ft != 0x02) nrow = d.read_shift(4); if(nrow > 1048576) nrow = 1e6;
if(ft != 0x02) fpos = d.read_shift(2);
var rlen = d.read_shift(2);
@ -822,7 +822,6 @@ var PRN = (function() {
}
// If line ends in \r OR \n
else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
//
sep = str.charAt(4); str = str.slice(6);
}
}

@ -238,6 +238,8 @@ function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}

@ -38,10 +38,12 @@ function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
break;
case 'BoundSheet8':
break;
default:
if(d.length === 0) break;
opts.enc.insitu(d);
}
bufs.push(d);
@ -52,8 +54,11 @@ function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(next.n == 'ContinueFrt') start += 4;
else if(next.n.slice(0,11) == 'ContinueFrt') start += 12;
bufs.push(blob.slice(start,blob.l+4+l));
else if(next.n.slice(0,11) == 'ContinueFrt') {
start += 12;
}
d = blob.slice(start,blob.l+4+l);
bufs.push(d);
blob.l += 4+l;
next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
}
@ -61,6 +66,7 @@ function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
prep_blob(b, 0);
var ll = 0; b.lens = [];
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}

26
dist/xlsx.core.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.core.min.map generated vendored

File diff suppressed because one or more lines are too long

32
dist/xlsx.extendscript.js generated vendored

@ -9161,7 +9161,7 @@ module.exports = ZStream;
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){
XLSX.version = '0.16.9';
XLSX.version = '0.17.0';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true, window */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -12154,7 +12154,7 @@ function resolve_path(path, base) {
}
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/mg;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
@ -13146,7 +13146,10 @@ var write_UncheckedRfX = write_RfX;
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data) { return data.read_shift(8, 'f'); }
function parse_Xnum(data) {
if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
return data.read_shift(8, 'f');
}
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
/* [MS-XLSB] 2.4.324 BrtColor */
@ -15676,7 +15679,7 @@ function parse_Lbl(blob, length, opts) {
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
return {
chKey: chKey,
Name: name,
@ -16142,7 +16145,7 @@ function dbf_to_aoa(buf, opts) {
var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
if(ft == 0x02) nrow = d.read_shift(2);
/*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
if(ft != 0x02) nrow = d.read_shift(4);
if(ft != 0x02) nrow = d.read_shift(4); if(nrow > 1048576) nrow = 1e6;
if(ft != 0x02) fpos = d.read_shift(2);
var rlen = d.read_shift(2);
@ -16878,7 +16881,6 @@ var PRN = (function() {
}
// If line ends in \r OR \n
else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
//
sep = str.charAt(4); str = str.slice(6);
}
}
@ -22598,6 +22600,8 @@ function parse_ws_xml_sheetviews(data, wb) {
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
@ -26045,10 +26049,12 @@ function slurp(R, blob, length, opts) {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
break;
case 'BoundSheet8':
break;
default:
if(d.length === 0) break;
opts.enc.insitu(d);
}
bufs.push(d);
@ -26059,8 +26065,11 @@ function slurp(R, blob, length, opts) {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(next.n == 'ContinueFrt') start += 4;
else if(next.n.slice(0,11) == 'ContinueFrt') start += 12;
bufs.push(blob.slice(start,blob.l+4+l));
else if(next.n.slice(0,11) == 'ContinueFrt') {
start += 12;
}
d = blob.slice(start,blob.l+4+l);
bufs.push(d);
blob.l += 4+l;
next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
}
@ -26068,6 +26077,7 @@ function slurp(R, blob, length, opts) {
prep_blob(b, 0);
var ll = 0; b.lens = [];
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}

24
dist/xlsx.full.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.full.min.map generated vendored

File diff suppressed because one or more lines are too long

32
dist/xlsx.js generated vendored

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){
XLSX.version = '0.16.9';
XLSX.version = '0.17.0';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true, window */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -2997,7 +2997,7 @@ function resolve_path(path, base) {
}
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/mg;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
@ -3989,7 +3989,10 @@ var write_UncheckedRfX = write_RfX;
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data) { return data.read_shift(8, 'f'); }
function parse_Xnum(data) {
if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
return data.read_shift(8, 'f');
}
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
/* [MS-XLSB] 2.4.324 BrtColor */
@ -6519,7 +6522,7 @@ function parse_Lbl(blob, length, opts) {
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
return {
chKey: chKey,
Name: name,
@ -6985,7 +6988,7 @@ function dbf_to_aoa(buf, opts) {
var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
if(ft == 0x02) nrow = d.read_shift(2);
/*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
if(ft != 0x02) nrow = d.read_shift(4);
if(ft != 0x02) nrow = d.read_shift(4); if(nrow > 1048576) nrow = 1e6;
if(ft != 0x02) fpos = d.read_shift(2);
var rlen = d.read_shift(2);
@ -7721,7 +7724,6 @@ var PRN = (function() {
}
// If line ends in \r OR \n
else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
//
sep = str.charAt(4); str = str.slice(6);
}
}
@ -13441,6 +13443,8 @@ function parse_ws_xml_sheetviews(data, wb) {
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
@ -16888,10 +16892,12 @@ function slurp(R, blob, length, opts) {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
break;
case 'BoundSheet8':
break;
default:
if(d.length === 0) break;
opts.enc.insitu(d);
}
bufs.push(d);
@ -16902,8 +16908,11 @@ function slurp(R, blob, length, opts) {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(next.n == 'ContinueFrt') start += 4;
else if(next.n.slice(0,11) == 'ContinueFrt') start += 12;
bufs.push(blob.slice(start,blob.l+4+l));
else if(next.n.slice(0,11) == 'ContinueFrt') {
start += 12;
}
d = blob.slice(start,blob.l+4+l);
bufs.push(d);
blob.l += 4+l;
next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
}
@ -16911,6 +16920,7 @@ function slurp(R, blob, length, opts) {
prep_blob(b, 0);
var ll = 0; b.lens = [];
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}

24
dist/xlsx.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map generated vendored

File diff suppressed because one or more lines are too long

15
dist/xlsx.mini.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.mini.min.map generated vendored

File diff suppressed because one or more lines are too long

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.16.9",
"version": "0.17.0",
"author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){
XLSX.version = '0.16.9';
XLSX.version = '0.17.0';
var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */
/*global cptable:true, window */
@ -3078,7 +3078,7 @@ function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {
}
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/mg;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
@ -4082,7 +4082,10 @@ var write_UncheckedRfX = write_RfX;
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data/*::, length*/) { return data.read_shift(8, 'f'); }
function parse_Xnum(data/*::, length*/) {
if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
return data.read_shift(8, 'f');
}
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
/* [MS-XLSB] 2.4.324 BrtColor */
@ -6616,7 +6619,7 @@ function parse_Lbl(blob, length, opts) {
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
return {
chKey: chKey,
Name: name,
@ -7082,7 +7085,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
if(ft == 0x02) nrow = d.read_shift(2);
/*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
if(ft != 0x02) nrow = d.read_shift(4);
if(ft != 0x02) nrow = d.read_shift(4); if(nrow > 1048576) nrow = 1e6;
if(ft != 0x02) fpos = d.read_shift(2);
var rlen = d.read_shift(2);
@ -7819,7 +7822,6 @@ var PRN = (function() {
}
// If line ends in \r OR \n
else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
//
sep = str.charAt(4); str = str.slice(6);
}
}
@ -13543,6 +13545,8 @@ function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
@ -17002,10 +17006,12 @@ function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
break;
case 'BoundSheet8':
break;
default:
if(d.length === 0) break;
opts.enc.insitu(d);
}
bufs.push(d);
@ -17016,8 +17022,11 @@ function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(next.n == 'ContinueFrt') start += 4;
else if(next.n.slice(0,11) == 'ContinueFrt') start += 12;
bufs.push(blob.slice(start,blob.l+4+l));
else if(next.n.slice(0,11) == 'ContinueFrt') {
start += 12;
}
d = blob.slice(start,blob.l+4+l);
bufs.push(d);
blob.l += 4+l;
next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
}
@ -17025,6 +17034,7 @@ function slurp(R, blob, length/*:number*/, opts)/*:any*/ {
prep_blob(b, 0);
var ll = 0; b.lens = [];
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}

32
xlsx.js generated

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){
XLSX.version = '0.16.9';
XLSX.version = '0.17.0';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true, window */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -2997,7 +2997,7 @@ function resolve_path(path, base) {
}
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/mg;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
@ -3989,7 +3989,10 @@ var write_UncheckedRfX = write_RfX;
/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
/* TODO: error checking, NaN and Infinity values are not valid Xnum */
function parse_Xnum(data) { return data.read_shift(8, 'f'); }
function parse_Xnum(data) {
if(data.length - data.l < 8) throw "XLS Xnum Buffer underflow";
return data.read_shift(8, 'f');
}
function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
/* [MS-XLSB] 2.4.324 BrtColor */
@ -6519,7 +6522,7 @@ function parse_Lbl(blob, length, opts) {
var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
var rgce = (target == blob.l || cce === 0 || !(npflen > 0)) ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
return {
chKey: chKey,
Name: name,
@ -6985,7 +6988,7 @@ function dbf_to_aoa(buf, opts) {
var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
if(ft == 0x02) nrow = d.read_shift(2);
/*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
if(ft != 0x02) nrow = d.read_shift(4);
if(ft != 0x02) nrow = d.read_shift(4); if(nrow > 1048576) nrow = 1e6;
if(ft != 0x02) fpos = d.read_shift(2);
var rlen = d.read_shift(2);
@ -7721,7 +7724,6 @@ var PRN = (function() {
}
// If line ends in \r OR \n
else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
//
sep = str.charAt(4); str = str.slice(6);
}
}
@ -13441,6 +13443,8 @@ function parse_ws_xml_sheetviews(data, wb) {
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
@ -16888,10 +16892,12 @@ function slurp(R, blob, length, opts) {
var l = length;
var bufs = [];
var d = blob.slice(blob.l,blob.l+l);
if(opts && opts.enc && opts.enc.insitu) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
if(opts && opts.enc && opts.enc.insitu && d.length > 0) switch(R.n) {
case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': case 'EOF':
break;
case 'BoundSheet8':
break;
default:
if(d.length === 0) break;
opts.enc.insitu(d);
}
bufs.push(d);
@ -16902,8 +16908,11 @@ function slurp(R, blob, length, opts) {
l = __readUInt16LE(blob,blob.l+2);
start = blob.l + 4;
if(next.n == 'ContinueFrt') start += 4;
else if(next.n.slice(0,11) == 'ContinueFrt') start += 12;
bufs.push(blob.slice(start,blob.l+4+l));
else if(next.n.slice(0,11) == 'ContinueFrt') {
start += 12;
}
d = blob.slice(start,blob.l+4+l);
bufs.push(d);
blob.l += 4+l;
next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
}
@ -16911,6 +16920,7 @@ function slurp(R, blob, length, opts) {
prep_blob(b, 0);
var ll = 0; b.lens = [];
for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
if(b.length < length) throw "XLS Record " + (R && R.n || "??") + " Truncated: " + b.length + " < " + length;
return R.f(b, b.length, opts);
}

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){
XLSX.version = '0.16.9';
XLSX.version = '0.17.0';
var current_codepage = 1200, current_ansi = 1252;
var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
@ -3040,7 +3040,7 @@ function resolve_path(path/*:string*/, base/*:string*/)/*:string*/ {
}
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/mg;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
@ -4859,7 +4859,7 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
if(ft == 0x02) nrow = d.read_shift(2);
/*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
if(ft != 0x02) nrow = d.read_shift(4);
if(ft != 0x02) nrow = d.read_shift(4); if(nrow > 1048576) nrow = 1e6;
if(ft != 0x02) fpos = d.read_shift(2);
var rlen = d.read_shift(2);
@ -5596,7 +5596,6 @@ var PRN = (function() {
}
// If line ends in \r OR \n
else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
//
sep = str.charAt(4); str = str.slice(6);
}
}
@ -7464,6 +7463,8 @@ function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
@ -8700,6 +8701,809 @@ function get_get_computed_style_function(element/*:HTMLElement*/)/*:?function*/
if(typeof getComputedStyle === 'function') return getComputedStyle;
return null;
}
/* OpenDocument */
var parse_content_xml = (function() {
var parse_text_p = function(text/*:string*//*::, tag*/)/*:Array<any>*/ {
/* 6.1.2 White Space Characters */
var fixed = text
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n");
var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
return [v];
};
var number_formats = {
/* ods name: [short ssf fmt, long ssf fmt] */
day: ["d", "dd"],
month: ["m", "mm"],
year: ["y", "yy"],
hours: ["h", "hh"],
minutes: ["m", "mm"],
seconds: ["s", "ss"],
"am-pm": ["A/P", "AM/PM"],
"day-of-week": ["ddd", "dddd"],
era: ["e", "ee"],
/* there is no native representation of LO "Q" format */
quarter: ["\\Qm", "m\\\"th quarter\""]
};
return function pcx(d/*:string*/, _opts)/*:Workbook*/ {
var opts = _opts || {};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var str = xlml_normalize(d);
var state/*:Array<any>*/ = [], tmp;
var tag/*:: = {}*/;
var NFtag = {name:""}, NF = "", pidx = 0;
var sheetag/*:: = {name:"", '名称':""}*/;
var rowtag/*:: = {'行号':""}*/;
var Sheets = {}, SheetNames/*:Array<string>*/ = [];
var ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
var ctag = ({value:""}/*:any*/);
var textp = "", textpidx = 0, textptag/*:: = {}*/;
var textR = [];
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var row_ol = 0;
var number_format_map = {};
var merges/*:Array<Range>*/ = [], mrange = {}, mR = 0, mC = 0;
var rowinfo/*:Array<RowInfo>*/ = [], rowpeat = 1, colpeat = 1;
var arrayf/*:Array<[Range, string]>*/ = [];
var WB = {Names:[]};
var atag = ({}/*:any*/);
var _Ref/*:[string, string]*/ = ["", ""];
var comments/*:Array<Comment>*/ = [], comment/*:Comment*/ = ({}/*:any*/);
var creator = "", creatoridx = 0;
var isstub = false, intable = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
if(Rn[1]==='/') {
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
else ws['!ref'] = "A1:A1";
if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) {
ws['!fullref'] = ws['!ref'];
range.e.r = opts.sheetRows - 1;
ws['!ref'] = encode_range(range);
}
if(merges.length) ws['!merges'] = merges;
if(rowinfo.length) ws["!rows"] = rowinfo;
sheetag.name = sheetag['名称'] || sheetag.name;
if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
SheetNames.push(sheetag.name);
Sheets[sheetag.name] = ws;
intable = false;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
sheetag = parsexmltag(Rn[0], false);
R = C = -1;
range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
ws = opts.dense ? ([]/*:any*/) : ({}/*:any*/); merges = [];
rowinfo = [];
intable = true;
}
break;
case 'table-row-group': // 9.1.9 <table:table-row-group>
if(Rn[1] === "/") --row_ol; else ++row_ol;
break;
case 'table-row': case '行': // 9.1.3 <table:table-row>
if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; }
rowtag = parsexmltag(Rn[0], false);
if(rowtag['行号']) R = rowtag['行号'] - 1; else if(R == -1) R = 0;
rowpeat = +rowtag['number-rows-repeated'] || 1;
/* TODO: remove magic */
if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol};
C = -1; break;
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
if(Rn[1] !== '/') ++C;
if(opts.sheetStubs) {
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
else ws[encode_cell({r:R,c:C})] = {t:'z'};
}
textp = ""; textR = [];
break; /* stub */
case 'table-cell': case '数据':
if(Rn[0].charAt(Rn[0].length-2) === '/') {
++C;
ctag = parsexmltag(Rn[0], false);
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
q = ({t:'z', v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
if((ctag['数据类型'] || ctag['value-type']) == "string") {
q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
if(opts.dense) {
if(!ws[R]) ws[R] = [];
ws[R][C] = q;
} else {
ws[encode_cell({r:R,c:C})] = q;
}
}
C+= colpeat-1;
} else if(Rn[1]!=='/') {
++C;
colpeat = 1;
var rptR = rowpeat ? R + rowpeat - 1 : R;
if(C > range.e.c) range.e.c = C;
if(C < range.s.c) range.s.c = C;
if(R < range.s.r) range.s.r = R;
if(rptR > range.e.r) range.e.r = rptR;
ctag = parsexmltag(Rn[0], false);
comments = []; comment = ({}/*:any*/);
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:"",c:[]*/}/*:any*/);
if(opts.cellFormula) {
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
q.F = encode_range(mrange);
arrayf.push([mrange, q.F]);
}
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
else for(i = 0; i < arrayf.length; ++i)
if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
q.F = arrayf[i][1];
}
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
merges.push(mrange);
}
/* 19.675.2 table:number-columns-repeated */
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
/* 19.385 office:value-type */
switch(q.t) {
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
q.z = 'm/d/yy'; break;
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
default:
if(q.t === 'string' || q.t === 'text' || !q.t) {
q.t = 's';
if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; }
} else throw new Error('Unsupported value type ' + q.t);
}
} else {
isstub = false;
if(q.t === 's') {
q.v = textp || '';
if(textR.length) q.R = textR;
isstub = textpidx == 0;
}
if(atag.Target) q.l = atag;
if(comments.length > 0) { q.c = comments; comments = []; }
if(textp && opts.cellText !== false) q.w = textp;
if(isstub) { q.t = "z"; delete q.v; }
if(!isstub || opts.sheetStubs) {
if(!(opts.sheetRows && opts.sheetRows <= R)) {
for(var rpt = 0; rpt < rowpeat; ++rpt) {
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
if(opts.dense) {
if(!ws[R + rpt]) ws[R + rpt] = [];
ws[R + rpt][C] = rpt == 0 ? q : dup(q);
while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
} else {
ws[encode_cell({r:R + rpt,c:C})] = q;
while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
}
if(range.e.c <= C) range.e.c = C;
}
}
}
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
C += colpeat-1; colpeat = 0;
q = {/*:: t:"", v:null, z:null, w:"",c:[]*/};
textp = ""; textR = [];
}
atag = ({}/*:any*/);
break; // 9.1.4 <table:table-cell>
/* pure state */
case 'document': // TODO: <office:document> is the root for FODS
case 'document-content': case '电子表格文档': // 3.1.3.2 <office:document-content>
case 'spreadsheet': case '主体': // 3.7 <office:spreadsheet>
case 'scripts': // 3.12 <office:scripts>
case 'styles': // TODO <office:styles>
case 'font-face-decls': // 3.14 <office:font-face-decls>
case 'master-styles': //3.15.4 <office:master-styles> -- relevant for FODS
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
break;
case 'annotation': // 14.1 <office:annotation>
if(Rn[1]==='/'){
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
comment.t = textp;
if(textR.length) /*::(*/comment/*:: :any)*/.R = textR;
comment.a = creator;
comments.push(comment);
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
creator = ""; creatoridx = 0;
textp = ""; textpidx = 0; textR = [];
break;
case 'creator': // 4.3.2.7 <dc:creator>
if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); }
else creatoridx = Rn.index + Rn[0].length;
break;
/* ignore state */
case 'meta': case '元数据': // TODO: <office:meta> <uof:元数据> FODS/UOF
case 'settings': // TODO: <office:settings>
case 'config-item-set': // TODO: <office:config-item-set>
case 'config-item-map-indexed': // TODO: <office:config-item-map-indexed>
case 'config-item-map-entry': // TODO: <office:config-item-map-entry>
case 'config-item-map-named': // TODO: <office:config-item-map-entry>
case 'shapes': // 9.2.8 <table:shapes>
case 'frame': // 10.4.2 <draw:frame>
case 'text-box': // 10.4.3 <draw:text-box>
case 'image': // 10.4.4 <draw:image>
case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
case 'list-style': // 16.30 <text:list-style>
case 'form': // 13.13 <form:form>
case 'dde-links': // 9.8 <table:dde-links>
case 'event-listeners': // TODO
case 'chart': // TODO
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
textp = ""; textpidx = 0; textR = [];
break;
case 'scientific-number': // TODO: <number:scientific-number>
break;
case 'currency-symbol': // TODO: <number:currency-symbol>
break;
case 'currency-style': // TODO: <number:currency-style>
break;
case 'number-style': // 16.27.2 <number:number-style>
case 'percentage-style': // 16.27.9 <number:percentage-style>
case 'date-style': // 16.27.10 <number:date-style>
case 'time-style': // 16.27.18 <number:time-style>
if(Rn[1]==='/'){
number_format_map[NFtag.name] = NF;
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
NF = "";
NFtag = parsexmltag(Rn[0], false);
state.push([Rn[3], true]);
} break;
case 'script': break; // 3.13 <office:script>
case 'libraries': break; // TODO: <ooo:libraries>
case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
case 'default-style': // TODO: <style:default-style>
case 'page-layout': break; // TODO: <style:page-layout>
case 'style': // 16.2 <style:style>
break;
case 'map': break; // 16.3 <style:map>
case 'font-face': break; // 16.21 <style:font-face>
case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
case 'table-properties': break; // 17.15 <style:table-properties>
case 'table-column-properties': break; // 17.16 <style:table-column-properties>
case 'table-row-properties': break; // 17.17 <style:table-row-properties>
case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
case 'number': // 16.27.3 <number:number>
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'fraction': break; // TODO 16.27.6 <number:fraction>
case 'day': // 16.27.11 <number:day>
case 'month': // 16.27.12 <number:month>
case 'year': // 16.27.13 <number:year>
case 'era': // 16.27.14 <number:era>
case 'day-of-week': // 16.27.15 <number:day-of-week>
case 'week-of-year': // 16.27.16 <number:week-of-year>
case 'quarter': // 16.27.17 <number:quarter>
case 'hours': // 16.27.19 <number:hours>
case 'minutes': // 16.27.20 <number:minutes>
case 'seconds': // 16.27.21 <number:seconds>
case 'am-pm': // 16.27.22 <number:am-pm>
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'boolean-style': break; // 16.27.23 <number:boolean-style>
case 'boolean': break; // 16.27.24 <number:boolean>
case 'text-style': break; // 16.27.25 <number:text-style>
case 'text': // 16.27.26 <number:text>
if(Rn[0].slice(-2) === "/>") break;
else if(Rn[1]==="/") switch(state[state.length-1][0]) {
case 'number-style':
case 'date-style':
case 'time-style':
NF += str.slice(pidx, Rn.index);
break;
}
else pidx = Rn.index + Rn[0].length;
break;
case 'named-range': // 9.4.12 <table:named-range>
tag = parsexmltag(Rn[0], false);
_Ref = ods_to_csf_3D(tag['cell-range-address']);
var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]}/*:any*/);
if(intable) nrange.Sheet = SheetNames.length;
WB.Names.push(nrange);
break;
case 'text-content': break; // 16.27.27 <number:text-content>
case 'text-properties': break; // 16.27.27 <style:text-properties>
case 'embedded-text': break; // 16.27.4 <number:embedded-text>
case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3
case 'forms': break; // 12.25.2 13.2
case 'table-column': break; // 9.1.6 <table:table-column>
case 'table-header-rows': break; // 9.1.7 <table:table-header-rows>
case 'table-rows': break; // 9.1.12 <table:table-rows>
/* TODO: outline levels */
case 'table-column-group': break; // 9.1.10 <table:table-column-group>
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
case 'table-columns': break; // 9.1.12 <table:table-columns>
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
case 'named-expressions': break; // 9.4.11 <table:named-expressions>
case 'label-range': break; // 9.4.9 <table:label-range>
case 'label-ranges': break; // 9.4.10 <table:label-ranges>
case 'named-expression': break; // 9.4.13 <table:named-expression>
case 'sort': break; // 9.4.19 <table:sort>
case 'sort-by': break; // 9.4.20 <table:sort-by>
case 'sort-groups': break; // 9.4.22 <table:sort-groups>
case 'tab': break; // 6.1.4 <text:tab>
case 'line-break': break; // 6.1.5 <text:line-break>
case 'span': break; // 6.1.7 <text:span>
case 'p': case '文本串': // 5.1.3 <text:p>
if(['master-styles'].indexOf(state[state.length-1][0]) > -1) break;
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
break; // <text:p>
case 's': break; // <text:s>
case 'database-range': // 9.4.15 <table:database-range>
if(Rn[1]==='/') break;
try {
_Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
} catch(e) {/* empty */}
break;
case 'date': break; // <*:date>
case 'object': break; // 10.4.6.2 <draw:object>
case 'title': case '标题': break; // <*:title> OR <uof:标题>
case 'desc': break; // <*:desc>
case 'binary-data': break; // 10.4.5 TODO: b64 blob
/* 9.2 Advanced Tables */
case 'table-source': break; // 9.2.6
case 'scenario': break; // 9.2.6
case 'iteration': break; // 9.4.3 <table:iteration>
case 'content-validations': break; // 9.4.4 <table:
case 'content-validation': break; // 9.4.5 <table:
case 'help-message': break; // 9.4.6 <table:
case 'error-message': break; // 9.4.7 <table:
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
case 'filter': break; // 9.5.2 <table:filter>
case 'filter-and': break; // 9.5.3 <table:filter-and>
case 'filter-or': break; // 9.5.4 <table:filter-or>
case 'filter-condition': break; // 9.5.5 <table:filter-condition>
case 'list-level-style-bullet': break; // 16.31 <text:
case 'list-level-style-number': break; // 16.32 <text:
case 'list-level-properties': break; // 17.19 <style:
/* 7.3 Document Fields */
case 'sender-firstname': // 7.3.6.2
case 'sender-lastname': // 7.3.6.3
case 'sender-initials': // 7.3.6.4
case 'sender-title': // 7.3.6.5
case 'sender-position': // 7.3.6.6
case 'sender-email': // 7.3.6.7
case 'sender-phone-private': // 7.3.6.8
case 'sender-fax': // 7.3.6.9
case 'sender-company': // 7.3.6.10
case 'sender-phone-work': // 7.3.6.11
case 'sender-street': // 7.3.6.12
case 'sender-city': // 7.3.6.13
case 'sender-postal-code': // 7.3.6.14
case 'sender-country': // 7.3.6.15
case 'sender-state-or-province': // 7.3.6.16
case 'author-name': // 7.3.7.1
case 'author-initials': // 7.3.7.2
case 'chapter': // 7.3.8
case 'file-name': // 7.3.9
case 'template-name': // 7.3.9
case 'sheet-name': // 7.3.9
break;
case 'event-listener':
break;
/* TODO: FODS Properties */
case 'initial-creator':
case 'creation-date':
case 'print-date':
case 'generator':
case 'document-statistic':
case 'user-defined':
case 'editing-duration':
case 'editing-cycles':
break;
/* TODO: FODS Config */
case 'config-item':
break;
/* TODO: style tokens */
case 'page-number': break; // TODO <text:page-number>
case 'page-count': break; // TODO <text:page-count>
case 'time': break; // TODO <text:time>
/* 9.3 Advanced Table Cells */
case 'cell-range-source': break; // 9.3.1 <table:
case 'detective': break; // 9.3.2 <table:
case 'operation': break; // 9.3.3 <table:
case 'highlighted-range': break; // 9.3.4 <table:
/* 9.6 Data Pilot Tables <table: */
case 'data-pilot-table': // 9.6.3
case 'source-cell-range': // 9.6.5
case 'source-service': // 9.6.6
case 'data-pilot-field': // 9.6.7
case 'data-pilot-level': // 9.6.8
case 'data-pilot-subtotals': // 9.6.9
case 'data-pilot-subtotal': // 9.6.10
case 'data-pilot-members': // 9.6.11
case 'data-pilot-member': // 9.6.12
case 'data-pilot-display-info': // 9.6.13
case 'data-pilot-sort-info': // 9.6.14
case 'data-pilot-layout-info': // 9.6.15
case 'data-pilot-field-reference': // 9.6.16
case 'data-pilot-groups': // 9.6.17
case 'data-pilot-group': // 9.6.18
case 'data-pilot-group-member': // 9.6.19
break;
/* 10.3 Drawing Shapes */
case 'rect': // 10.3.2
break;
/* 14.6 DDE Connections */
case 'dde-connection-decls': // 14.6.2 <text:
case 'dde-connection-decl': // 14.6.3 <text:
case 'dde-link': // 14.6.4 <table:
case 'dde-source': // 14.6.5 <office:
break;
case 'properties': break; // 13.7 <form:properties>
case 'property': break; // 13.8 <form:property>
case 'a': // 6.1.8 hyperlink
if(Rn[1]!== '/') {
atag = parsexmltag(Rn[0], false);
if(!atag.href) break;
atag.Target = atag.href; delete atag.href;
if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) {
_Ref = ods_to_csf_3D(atag.Target.slice(1));
atag.Target = "#" + _Ref[0] + "!" + _Ref[1];
}
}
break;
/* non-standard */
case 'table-protection': break;
case 'data-pilot-grand-total': break; // <table:
case 'office-document-common-attrs': break; // bare
default: switch(Rn[2]) {
case 'dc:': // TODO: properties
case 'calcext:': // ignore undocumented extensions
case 'loext:': // ignore undocumented extensions
case 'ooo:': // ignore undocumented extensions
case 'chartooo:': // ignore undocumented extensions
case 'draw:': // TODO: drawing
case 'style:': // TODO: styles
case 'chart:': // TODO: charts
case 'form:': // TODO: forms
case 'uof:': // TODO: uof
case '表:': // TODO: uof
case '字:': // TODO: uof
break;
default: if(opts.WTF) throw new Error(Rn);
}
}
var out/*:Workbook*/ = ({
Sheets: Sheets,
SheetNames: SheetNames,
Workbook: WB
}/*:any*/);
if(opts.bookSheets) delete /*::(*/out/*:: :any)*/.Sheets;
return out;
};
})();
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
opts = opts || ({}/*:any*/);
var ods = !!safegetzipfile(zip, 'objectdata');
if(ods) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
var wb = parse_content_xml(ods ? content : utf8read(content), opts);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
return wb;
}
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
return parse_content_xml(data, opts);
}
/* OpenDocument */
var write_styles_ods/*:{(wb:any, opts:any):string}*/ = (function() {
var payload = '<office:document-styles ' + wxt_helper({
'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
'xmlns:xlink': "http://www.w3.org/1999/xlink",
'xmlns:dc': "http://purl.org/dc/elements/1.1/",
'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
'office:version': "1.2"
}) + '></office:document-styles>';
return function wso(/*::wb, opts*/) {
return XML_HEADER + payload;
};
})();
var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
/* 6.1.2 White Space Characters */
var write_text_p = function(text/*:string*/)/*:string*/ {
return escapexml(text)
.replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
.replace(/\t/g, "<text:tab/>")
.replace(/\n/g, "<text:line-break/>")
.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
};
var null_cell_xml = ' <table:table-cell />\n';
var covered_cell_xml = ' <table:covered-table-cell/>\n';
var write_ws = function(ws, wb/*:Workbook*/, i/*:number*//*::, opts*/)/*:string*/ {
/* Section 9 Tables */
var o/*:Array<string>*/ = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
var R=0,C=0, range = decode_range(ws['!ref']);
var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
var dense = Array.isArray(ws);
for(R = 0; R < range.s.r; ++R) o.push(' <table:table-row></table:table-row>\n');
for(; R <= range.e.r; ++R) {
o.push(' <table:table-row>\n');
for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
for(; C <= range.e.c; ++C) {
var skip = false, ct = {}, textp = "";
for(mi = 0; mi != marr.length; ++mi) {
if(marr[mi].s.c > C) continue;
if(marr[mi].s.r > R) continue;
if(marr[mi].e.c < C) continue;
if(marr[mi].e.r < R) continue;
if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1);
ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
break;
}
if(skip) { o.push(covered_cell_xml); continue; }
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
if(cell && cell.f) {
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
if(cell.F) {
if(cell.F.slice(0, ref.length) == ref) {
var _Fref = decode_range(cell.F);
ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1);
ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1);
}
}
}
if(!cell) { o.push(null_cell_xml); continue; }
switch(cell.t) {
case 'b':
textp = (cell.v ? 'TRUE' : 'FALSE');
ct['office:value-type'] = "boolean";
ct['office:boolean-value'] = (cell.v ? 'true' : 'false');
break;
case 'n':
textp = (cell.w||String(cell.v||0));
ct['office:value-type'] = "float";
ct['office:value'] = (cell.v||0);
break;
case 's': case 'str':
textp = cell.v == null ? "" : cell.v;
ct['office:value-type'] = "string";
break;
case 'd':
textp = (cell.w||(parseDate(cell.v).toISOString()));
ct['office:value-type'] = "date";
ct['office:date-value'] = (parseDate(cell.v).toISOString());
ct['table:style-name'] = "ce1";
break;
//case 'e':
default: o.push(null_cell_xml); continue;
}
var text_p = write_text_p(textp);
if(cell.l && cell.l.Target) {
var _tgt = cell.l.Target; _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
text_p = writextag('text:a', text_p, {'xlink:href': _tgt});
}
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
}
o.push(' </table:table-row>\n');
}
o.push(' </table:table>\n');
return o.join("");
};
var write_automatic_styles_ods = function(o/*:Array<string>*/) {
o.push(' <office:automatic-styles>\n');
o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
o.push(' <number:month number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:day number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:year/>\n');
o.push(' </number:date-style>\n');
/* table */
o.push(' <style:style style:name="ta1" style:family="table">\n'); // style:master-page-name="mp1">\n');
o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
o.push(' </style:style>\n');
/* table cells, text */
o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
/* page-layout */
o.push(' </office:automatic-styles>\n');
};
return function wcx(wb, opts) {
var o = [XML_HEADER];
/* 3.1.3.2 */
var attr = wxt_helper({
'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
'xmlns:xlink': "http://www.w3.org/1999/xlink",
'xmlns:dc': "http://purl.org/dc/elements/1.1/",
'xmlns:meta': "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
'xmlns:presentation': "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
'xmlns:chart': "urn:oasis:names:tc:opendocument:xmlns:chart:1.0",
'xmlns:dr3d': "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",
'xmlns:math': "http://www.w3.org/1998/Math/MathML",
'xmlns:form': "urn:oasis:names:tc:opendocument:xmlns:form:1.0",
'xmlns:script': "urn:oasis:names:tc:opendocument:xmlns:script:1.0",
'xmlns:ooo': "http://openoffice.org/2004/office",
'xmlns:ooow': "http://openoffice.org/2004/writer",
'xmlns:oooc': "http://openoffice.org/2004/calc",
'xmlns:dom': "http://www.w3.org/2001/xml-events",
'xmlns:xforms': "http://www.w3.org/2002/xforms",
'xmlns:xsd': "http://www.w3.org/2001/XMLSchema",
'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance",
'xmlns:sheet': "urn:oasis:names:tc:opendocument:sh33tjs:1.0",
'xmlns:rpt': "http://openoffice.org/2005/report",
'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
'xmlns:xhtml': "http://www.w3.org/1999/xhtml",
'xmlns:grddl': "http://www.w3.org/2003/g/data-view#",
'xmlns:tableooo': "http://openoffice.org/2009/table",
'xmlns:drawooo': "http://openoffice.org/2010/draw",
'xmlns:calcext': "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0",
'xmlns:loext': "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
'xmlns:field': "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0",
'xmlns:formx': "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0",
'xmlns:css3t': "http://www.w3.org/TR/css3-text/",
'office:version': "1.2"
});
var fods = wxt_helper({
'xmlns:config': "urn:oasis:names:tc:opendocument:xmlns:config:1.0",
'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
});
if(opts.bookType == "fods") o.push('<office:document' + attr + fods + '>\n');
else o.push('<office:document-content' + attr + '>\n');
write_automatic_styles_ods(o);
o.push(' <office:body>\n');
o.push(' <office:spreadsheet>\n');
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
o.push(' </office:spreadsheet>\n');
o.push(' </office:body>\n');
if(opts.bookType == "fods") o.push('</office:document>');
else o.push('</office:document-content>');
return o.join("");
};
})();
function write_ods(wb/*:any*/, opts/*:any*/) {
if(opts.bookType == "fods") return write_content_ods(wb, opts);
/*:: if(!jszip) throw new Error("JSZip is not available"); */
var zip = zip_new();
var f = "";
var manifest/*:Array<Array<string> >*/ = [];
var rdf/*:Array<[string, string]>*/ = [];
/* Part 3 Section 3.3 MIME Media Type */
f = "mimetype";
zip_add_file(zip, f, "application/vnd.oasis.opendocument.spreadsheet");
/* Part 1 Section 2.2 Documents */
f = "content.xml";
zip_add_file(zip, f, write_content_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "ContentFile"]);
/* TODO: these are hard-coded styles to satiate excel */
f = "styles.xml";
zip_add_file(zip, f, write_styles_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "StylesFile"]);
/* TODO: this is hard-coded to satiate excel */
f = "meta.xml";
zip_add_file(zip, f, write_meta_ods(/*::wb, opts*/));
manifest.push([f, "text/xml"]);
rdf.push([f, "MetadataFile"]);
/* Part 3 Section 6 Metadata Manifest File */
f = "manifest.rdf";
zip_add_file(zip, f, write_rdf(rdf/*, opts*/));
manifest.push([f, "application/rdf+xml"]);
/* Part 3 Section 4 Manifest File */
f = "META-INF/manifest.xml";
zip_add_file(zip, f, write_manifest(manifest/*, opts*/));
return zip;
}
function write_sheet_index(wb/*:Workbook*/, sheet/*:?string*/)/*:number*/ {
if(!sheet) return 0;
var idx = wb.SheetNames.indexOf(sheet);

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
function make_xlsx_lib(XLSX){
XLSX.version = '0.16.9';
XLSX.version = '0.17.0';
var current_codepage = 1200, current_ansi = 1252;
var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
@ -2961,7 +2961,7 @@ function resolve_path(path, base) {
}
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/mg;
var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s*[\/\?]?>/mg;
if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
@ -4769,7 +4769,7 @@ function dbf_to_aoa(buf, opts) {
var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
if(ft == 0x02) nrow = d.read_shift(2);
/*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
if(ft != 0x02) nrow = d.read_shift(4);
if(ft != 0x02) nrow = d.read_shift(4); if(nrow > 1048576) nrow = 1e6;
if(ft != 0x02) fpos = d.read_shift(2);
var rlen = d.read_shift(2);
@ -5505,7 +5505,6 @@ var PRN = (function() {
}
// If line ends in \r OR \n
else if(str.charCodeAt(5) == 13 || str.charCodeAt(5) == 10 ) {
//
sep = str.charAt(4); str = str.slice(6);
}
}
@ -7373,6 +7372,8 @@ function parse_ws_xml_sheetviews(data, wb) {
// $FlowIgnore
if(!wb.Views[i]) wb.Views[i] = {};
// $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
});
}
@ -8607,6 +8608,808 @@ function get_get_computed_style_function(element) {
if(typeof getComputedStyle === 'function') return getComputedStyle;
return null;
}
/* OpenDocument */
var parse_content_xml = (function() {
var parse_text_p = function(text) {
/* 6.1.2 White Space Characters */
var fixed = text
.replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
.replace(/<text:s\/>/g," ")
.replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
.replace(/<text:tab[^>]*\/>/g,"\t")
.replace(/<text:line-break\/>/g,"\n");
var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
return [v];
};
var number_formats = {
/* ods name: [short ssf fmt, long ssf fmt] */
day: ["d", "dd"],
month: ["m", "mm"],
year: ["y", "yy"],
hours: ["h", "hh"],
minutes: ["m", "mm"],
seconds: ["s", "ss"],
"am-pm": ["A/P", "AM/PM"],
"day-of-week": ["ddd", "dddd"],
era: ["e", "ee"],
/* there is no native representation of LO "Q" format */
quarter: ["\\Qm", "m\\\"th quarter\""]
};
return function pcx(d, _opts) {
var opts = _opts || {};
if(DENSE != null && opts.dense == null) opts.dense = DENSE;
var str = xlml_normalize(d);
var state = [], tmp;
var tag;
var NFtag = {name:""}, NF = "", pidx = 0;
var sheetag;
var rowtag;
var Sheets = {}, SheetNames = [];
var ws = opts.dense ? ([]) : ({});
var Rn, q;
var ctag = ({value:""});
var textp = "", textpidx = 0, textptag;
var textR = [];
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
var row_ol = 0;
var number_format_map = {};
var merges = [], mrange = {}, mR = 0, mC = 0;
var rowinfo = [], rowpeat = 1, colpeat = 1;
var arrayf = [];
var WB = {Names:[]};
var atag = ({});
var _Ref = ["", ""];
var comments = [], comment = ({});
var creator = "", creatoridx = 0;
var isstub = false, intable = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
if(Rn[1]==='/') {
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
else ws['!ref'] = "A1:A1";
if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) {
ws['!fullref'] = ws['!ref'];
range.e.r = opts.sheetRows - 1;
ws['!ref'] = encode_range(range);
}
if(merges.length) ws['!merges'] = merges;
if(rowinfo.length) ws["!rows"] = rowinfo;
sheetag.name = sheetag['名称'] || sheetag.name;
if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
SheetNames.push(sheetag.name);
Sheets[sheetag.name] = ws;
intable = false;
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
sheetag = parsexmltag(Rn[0], false);
R = C = -1;
range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
ws = opts.dense ? ([]) : ({}); merges = [];
rowinfo = [];
intable = true;
}
break;
case 'table-row-group': // 9.1.9 <table:table-row-group>
if(Rn[1] === "/") --row_ol; else ++row_ol;
break;
case 'table-row': case '行': // 9.1.3 <table:table-row>
if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; }
rowtag = parsexmltag(Rn[0], false);
if(rowtag['行号']) R = rowtag['行号'] - 1; else if(R == -1) R = 0;
rowpeat = +rowtag['number-rows-repeated'] || 1;
/* TODO: remove magic */
if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol};
C = -1; break;
case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
if(Rn[1] !== '/') ++C;
if(opts.sheetStubs) {
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
else ws[encode_cell({r:R,c:C})] = {t:'z'};
}
textp = ""; textR = [];
break; /* stub */
case 'table-cell': case '数据':
if(Rn[0].charAt(Rn[0].length-2) === '/') {
++C;
ctag = parsexmltag(Rn[0], false);
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
q = ({t:'z', v:null});
if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
if((ctag['数据类型'] || ctag['value-type']) == "string") {
q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
if(opts.dense) {
if(!ws[R]) ws[R] = [];
ws[R][C] = q;
} else {
ws[encode_cell({r:R,c:C})] = q;
}
}
C+= colpeat-1;
} else if(Rn[1]!=='/') {
++C;
colpeat = 1;
var rptR = rowpeat ? R + rowpeat - 1 : R;
if(C > range.e.c) range.e.c = C;
if(C < range.s.c) range.s.c = C;
if(R < range.s.r) range.s.r = R;
if(rptR > range.e.r) range.e.r = rptR;
ctag = parsexmltag(Rn[0], false);
comments = []; comment = ({});
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
if(opts.cellFormula) {
if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
q.F = encode_range(mrange);
arrayf.push([mrange, q.F]);
}
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
else for(i = 0; i < arrayf.length; ++i)
if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
q.F = arrayf[i][1];
}
if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
mR = parseInt(ctag['number-rows-spanned'],10) || 0;
mC = parseInt(ctag['number-columns-spanned'],10) || 0;
mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
merges.push(mrange);
}
/* 19.675.2 table:number-columns-repeated */
if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
/* 19.385 office:value-type */
switch(q.t) {
case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
q.z = 'm/d/yy'; break;
case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break;
case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
default:
if(q.t === 'string' || q.t === 'text' || !q.t) {
q.t = 's';
if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; }
} else throw new Error('Unsupported value type ' + q.t);
}
} else {
isstub = false;
if(q.t === 's') {
q.v = textp || '';
if(textR.length) q.R = textR;
isstub = textpidx == 0;
}
if(atag.Target) q.l = atag;
if(comments.length > 0) { q.c = comments; comments = []; }
if(textp && opts.cellText !== false) q.w = textp;
if(isstub) { q.t = "z"; delete q.v; }
if(!isstub || opts.sheetStubs) {
if(!(opts.sheetRows && opts.sheetRows <= R)) {
for(var rpt = 0; rpt < rowpeat; ++rpt) {
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
if(opts.dense) {
if(!ws[R + rpt]) ws[R + rpt] = [];
ws[R + rpt][C] = rpt == 0 ? q : dup(q);
while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
} else {
ws[encode_cell({r:R + rpt,c:C})] = q;
while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
}
if(range.e.c <= C) range.e.c = C;
}
}
}
colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
C += colpeat-1; colpeat = 0;
q = {};
textp = ""; textR = [];
}
atag = ({});
break; // 9.1.4 <table:table-cell>
/* pure state */
case 'document': // TODO: <office:document> is the root for FODS
case 'document-content': case '电子表格文档': // 3.1.3.2 <office:document-content>
case 'spreadsheet': case '主体': // 3.7 <office:spreadsheet>
case 'scripts': // 3.12 <office:scripts>
case 'styles': // TODO <office:styles>
case 'font-face-decls': // 3.14 <office:font-face-decls>
case 'master-styles': //3.15.4 <office:master-styles> -- relevant for FODS
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
break;
case 'annotation': // 14.1 <office:annotation>
if(Rn[1]==='/'){
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
comment.t = textp;
if(textR.length) comment.R = textR;
comment.a = creator;
comments.push(comment);
}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
creator = ""; creatoridx = 0;
textp = ""; textpidx = 0; textR = [];
break;
case 'creator': // 4.3.2.7 <dc:creator>
if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); }
else creatoridx = Rn.index + Rn[0].length;
break;
/* ignore state */
case 'meta': case '元数据': // TODO: <office:meta> <uof:元数据> FODS/UOF
case 'settings': // TODO: <office:settings>
case 'config-item-set': // TODO: <office:config-item-set>
case 'config-item-map-indexed': // TODO: <office:config-item-map-indexed>
case 'config-item-map-entry': // TODO: <office:config-item-map-entry>
case 'config-item-map-named': // TODO: <office:config-item-map-entry>
case 'shapes': // 9.2.8 <table:shapes>
case 'frame': // 10.4.2 <draw:frame>
case 'text-box': // 10.4.3 <draw:text-box>
case 'image': // 10.4.4 <draw:image>
case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
case 'list-style': // 16.30 <text:list-style>
case 'form': // 13.13 <form:form>
case 'dde-links': // 9.8 <table:dde-links>
case 'event-listeners': // TODO
case 'chart': // TODO
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
textp = ""; textpidx = 0; textR = [];
break;
case 'scientific-number': // TODO: <number:scientific-number>
break;
case 'currency-symbol': // TODO: <number:currency-symbol>
break;
case 'currency-style': // TODO: <number:currency-style>
break;
case 'number-style': // 16.27.2 <number:number-style>
case 'percentage-style': // 16.27.9 <number:percentage-style>
case 'date-style': // 16.27.10 <number:date-style>
case 'time-style': // 16.27.18 <number:time-style>
if(Rn[1]==='/'){
number_format_map[NFtag.name] = NF;
if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
} else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
NF = "";
NFtag = parsexmltag(Rn[0], false);
state.push([Rn[3], true]);
} break;
case 'script': break; // 3.13 <office:script>
case 'libraries': break; // TODO: <ooo:libraries>
case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
case 'default-style': // TODO: <style:default-style>
case 'page-layout': break; // TODO: <style:page-layout>
case 'style': // 16.2 <style:style>
break;
case 'map': break; // 16.3 <style:map>
case 'font-face': break; // 16.21 <style:font-face>
case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
case 'table-properties': break; // 17.15 <style:table-properties>
case 'table-column-properties': break; // 17.16 <style:table-column-properties>
case 'table-row-properties': break; // 17.17 <style:table-row-properties>
case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
case 'number': // 16.27.3 <number:number>
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'fraction': break; // TODO 16.27.6 <number:fraction>
case 'day': // 16.27.11 <number:day>
case 'month': // 16.27.12 <number:month>
case 'year': // 16.27.13 <number:year>
case 'era': // 16.27.14 <number:era>
case 'day-of-week': // 16.27.15 <number:day-of-week>
case 'week-of-year': // 16.27.16 <number:week-of-year>
case 'quarter': // 16.27.17 <number:quarter>
case 'hours': // 16.27.19 <number:hours>
case 'minutes': // 16.27.20 <number:minutes>
case 'seconds': // 16.27.21 <number:seconds>
case 'am-pm': // 16.27.22 <number:am-pm>
switch(state[state.length-1][0]) {
case 'time-style':
case 'date-style':
tag = parsexmltag(Rn[0], false);
NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
} break;
case 'boolean-style': break; // 16.27.23 <number:boolean-style>
case 'boolean': break; // 16.27.24 <number:boolean>
case 'text-style': break; // 16.27.25 <number:text-style>
case 'text': // 16.27.26 <number:text>
if(Rn[0].slice(-2) === "/>") break;
else if(Rn[1]==="/") switch(state[state.length-1][0]) {
case 'number-style':
case 'date-style':
case 'time-style':
NF += str.slice(pidx, Rn.index);
break;
}
else pidx = Rn.index + Rn[0].length;
break;
case 'named-range': // 9.4.12 <table:named-range>
tag = parsexmltag(Rn[0], false);
_Ref = ods_to_csf_3D(tag['cell-range-address']);
var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]});
if(intable) nrange.Sheet = SheetNames.length;
WB.Names.push(nrange);
break;
case 'text-content': break; // 16.27.27 <number:text-content>
case 'text-properties': break; // 16.27.27 <style:text-properties>
case 'embedded-text': break; // 16.27.4 <number:embedded-text>
case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3
case 'forms': break; // 12.25.2 13.2
case 'table-column': break; // 9.1.6 <table:table-column>
case 'table-header-rows': break; // 9.1.7 <table:table-header-rows>
case 'table-rows': break; // 9.1.12 <table:table-rows>
/* TODO: outline levels */
case 'table-column-group': break; // 9.1.10 <table:table-column-group>
case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
case 'table-columns': break; // 9.1.12 <table:table-columns>
case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
case 'graphic-properties': break; // 17.21 <style:graphic-properties>
case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
case 'named-expressions': break; // 9.4.11 <table:named-expressions>
case 'label-range': break; // 9.4.9 <table:label-range>
case 'label-ranges': break; // 9.4.10 <table:label-ranges>
case 'named-expression': break; // 9.4.13 <table:named-expression>
case 'sort': break; // 9.4.19 <table:sort>
case 'sort-by': break; // 9.4.20 <table:sort-by>
case 'sort-groups': break; // 9.4.22 <table:sort-groups>
case 'tab': break; // 6.1.4 <text:tab>
case 'line-break': break; // 6.1.5 <text:line-break>
case 'span': break; // 6.1.7 <text:span>
case 'p': case '文本串': // 5.1.3 <text:p>
if(['master-styles'].indexOf(state[state.length-1][0]) > -1) break;
if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
} else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
break; // <text:p>
case 's': break; // <text:s>
case 'database-range': // 9.4.15 <table:database-range>
if(Rn[1]==='/') break;
try {
_Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
} catch(e) {/* empty */}
break;
case 'date': break; // <*:date>
case 'object': break; // 10.4.6.2 <draw:object>
case 'title': case '标题': break; // <*:title> OR <uof:标题>
case 'desc': break; // <*:desc>
case 'binary-data': break; // 10.4.5 TODO: b64 blob
/* 9.2 Advanced Tables */
case 'table-source': break; // 9.2.6
case 'scenario': break; // 9.2.6
case 'iteration': break; // 9.4.3 <table:iteration>
case 'content-validations': break; // 9.4.4 <table:
case 'content-validation': break; // 9.4.5 <table:
case 'help-message': break; // 9.4.6 <table:
case 'error-message': break; // 9.4.7 <table:
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
case 'filter': break; // 9.5.2 <table:filter>
case 'filter-and': break; // 9.5.3 <table:filter-and>
case 'filter-or': break; // 9.5.4 <table:filter-or>
case 'filter-condition': break; // 9.5.5 <table:filter-condition>
case 'list-level-style-bullet': break; // 16.31 <text:
case 'list-level-style-number': break; // 16.32 <text:
case 'list-level-properties': break; // 17.19 <style:
/* 7.3 Document Fields */
case 'sender-firstname': // 7.3.6.2
case 'sender-lastname': // 7.3.6.3
case 'sender-initials': // 7.3.6.4
case 'sender-title': // 7.3.6.5
case 'sender-position': // 7.3.6.6
case 'sender-email': // 7.3.6.7
case 'sender-phone-private': // 7.3.6.8
case 'sender-fax': // 7.3.6.9
case 'sender-company': // 7.3.6.10
case 'sender-phone-work': // 7.3.6.11
case 'sender-street': // 7.3.6.12
case 'sender-city': // 7.3.6.13
case 'sender-postal-code': // 7.3.6.14
case 'sender-country': // 7.3.6.15
case 'sender-state-or-province': // 7.3.6.16
case 'author-name': // 7.3.7.1
case 'author-initials': // 7.3.7.2
case 'chapter': // 7.3.8
case 'file-name': // 7.3.9
case 'template-name': // 7.3.9
case 'sheet-name': // 7.3.9
break;
case 'event-listener':
break;
/* TODO: FODS Properties */
case 'initial-creator':
case 'creation-date':
case 'print-date':
case 'generator':
case 'document-statistic':
case 'user-defined':
case 'editing-duration':
case 'editing-cycles':
break;
/* TODO: FODS Config */
case 'config-item':
break;
/* TODO: style tokens */
case 'page-number': break; // TODO <text:page-number>
case 'page-count': break; // TODO <text:page-count>
case 'time': break; // TODO <text:time>
/* 9.3 Advanced Table Cells */
case 'cell-range-source': break; // 9.3.1 <table:
case 'detective': break; // 9.3.2 <table:
case 'operation': break; // 9.3.3 <table:
case 'highlighted-range': break; // 9.3.4 <table:
/* 9.6 Data Pilot Tables <table: */
case 'data-pilot-table': // 9.6.3
case 'source-cell-range': // 9.6.5
case 'source-service': // 9.6.6
case 'data-pilot-field': // 9.6.7
case 'data-pilot-level': // 9.6.8
case 'data-pilot-subtotals': // 9.6.9
case 'data-pilot-subtotal': // 9.6.10
case 'data-pilot-members': // 9.6.11
case 'data-pilot-member': // 9.6.12
case 'data-pilot-display-info': // 9.6.13
case 'data-pilot-sort-info': // 9.6.14
case 'data-pilot-layout-info': // 9.6.15
case 'data-pilot-field-reference': // 9.6.16
case 'data-pilot-groups': // 9.6.17
case 'data-pilot-group': // 9.6.18
case 'data-pilot-group-member': // 9.6.19
break;
/* 10.3 Drawing Shapes */
case 'rect': // 10.3.2
break;
/* 14.6 DDE Connections */
case 'dde-connection-decls': // 14.6.2 <text:
case 'dde-connection-decl': // 14.6.3 <text:
case 'dde-link': // 14.6.4 <table:
case 'dde-source': // 14.6.5 <office:
break;
case 'properties': break; // 13.7 <form:properties>
case 'property': break; // 13.8 <form:property>
case 'a': // 6.1.8 hyperlink
if(Rn[1]!== '/') {
atag = parsexmltag(Rn[0], false);
if(!atag.href) break;
atag.Target = atag.href; delete atag.href;
if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) {
_Ref = ods_to_csf_3D(atag.Target.slice(1));
atag.Target = "#" + _Ref[0] + "!" + _Ref[1];
}
}
break;
/* non-standard */
case 'table-protection': break;
case 'data-pilot-grand-total': break; // <table:
case 'office-document-common-attrs': break; // bare
default: switch(Rn[2]) {
case 'dc:': // TODO: properties
case 'calcext:': // ignore undocumented extensions
case 'loext:': // ignore undocumented extensions
case 'ooo:': // ignore undocumented extensions
case 'chartooo:': // ignore undocumented extensions
case 'draw:': // TODO: drawing
case 'style:': // TODO: styles
case 'chart:': // TODO: charts
case 'form:': // TODO: forms
case 'uof:': // TODO: uof
case '表:': // TODO: uof
case '字:': // TODO: uof
break;
default: if(opts.WTF) throw new Error(Rn);
}
}
var out = ({
Sheets: Sheets,
SheetNames: SheetNames,
Workbook: WB
});
if(opts.bookSheets) delete out.Sheets;
return out;
};
})();
function parse_ods(zip, opts) {
opts = opts || ({});
var ods = !!safegetzipfile(zip, 'objectdata');
if(ods) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
var content = getzipstr(zip, 'content.xml');
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
var wb = parse_content_xml(ods ? content : utf8read(content), opts);
if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
return wb;
}
function parse_fods(data, opts) {
return parse_content_xml(data, opts);
}
/* OpenDocument */
var write_styles_ods = (function() {
var payload = '<office:document-styles ' + wxt_helper({
'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
'xmlns:xlink': "http://www.w3.org/1999/xlink",
'xmlns:dc': "http://purl.org/dc/elements/1.1/",
'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
'office:version': "1.2"
}) + '></office:document-styles>';
return function wso() {
return XML_HEADER + payload;
};
})();
var write_content_ods = (function() {
/* 6.1.2 White Space Characters */
var write_text_p = function(text) {
return escapexml(text)
.replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
.replace(/\t/g, "<text:tab/>")
.replace(/\n/g, "<text:line-break/>")
.replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
};
var null_cell_xml = ' <table:table-cell />\n';
var covered_cell_xml = ' <table:covered-table-cell/>\n';
var write_ws = function(ws, wb, i) {
/* Section 9 Tables */
var o = [];
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
var R=0,C=0, range = decode_range(ws['!ref']);
var marr = ws['!merges'] || [], mi = 0;
var dense = Array.isArray(ws);
for(R = 0; R < range.s.r; ++R) o.push(' <table:table-row></table:table-row>\n');
for(; R <= range.e.r; ++R) {
o.push(' <table:table-row>\n');
for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
for(; C <= range.e.c; ++C) {
var skip = false, ct = {}, textp = "";
for(mi = 0; mi != marr.length; ++mi) {
if(marr[mi].s.c > C) continue;
if(marr[mi].s.r > R) continue;
if(marr[mi].e.c < C) continue;
if(marr[mi].e.r < R) continue;
if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1);
ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
break;
}
if(skip) { o.push(covered_cell_xml); continue; }
var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
if(cell && cell.f) {
ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
if(cell.F) {
if(cell.F.slice(0, ref.length) == ref) {
var _Fref = decode_range(cell.F);
ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1);
ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1);
}
}
}
if(!cell) { o.push(null_cell_xml); continue; }
switch(cell.t) {
case 'b':
textp = (cell.v ? 'TRUE' : 'FALSE');
ct['office:value-type'] = "boolean";
ct['office:boolean-value'] = (cell.v ? 'true' : 'false');
break;
case 'n':
textp = (cell.w||String(cell.v||0));
ct['office:value-type'] = "float";
ct['office:value'] = (cell.v||0);
break;
case 's': case 'str':
textp = cell.v == null ? "" : cell.v;
ct['office:value-type'] = "string";
break;
case 'd':
textp = (cell.w||(parseDate(cell.v).toISOString()));
ct['office:value-type'] = "date";
ct['office:date-value'] = (parseDate(cell.v).toISOString());
ct['table:style-name'] = "ce1";
break;
//case 'e':
default: o.push(null_cell_xml); continue;
}
var text_p = write_text_p(textp);
if(cell.l && cell.l.Target) {
var _tgt = cell.l.Target; _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
text_p = writextag('text:a', text_p, {'xlink:href': _tgt});
}
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
}
o.push(' </table:table-row>\n');
}
o.push(' </table:table>\n');
return o.join("");
};
var write_automatic_styles_ods = function(o) {
o.push(' <office:automatic-styles>\n');
o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
o.push(' <number:month number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:day number:style="long"/>\n');
o.push(' <number:text>/</number:text>\n');
o.push(' <number:year/>\n');
o.push(' </number:date-style>\n');
/* table */
o.push(' <style:style style:name="ta1" style:family="table">\n'); // style:master-page-name="mp1">\n');
o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
o.push(' </style:style>\n');
/* table cells, text */
o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
/* page-layout */
o.push(' </office:automatic-styles>\n');
};
return function wcx(wb, opts) {
var o = [XML_HEADER];
/* 3.1.3.2 */
var attr = wxt_helper({
'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
'xmlns:xlink': "http://www.w3.org/1999/xlink",
'xmlns:dc': "http://purl.org/dc/elements/1.1/",
'xmlns:meta': "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
'xmlns:presentation': "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
'xmlns:chart': "urn:oasis:names:tc:opendocument:xmlns:chart:1.0",
'xmlns:dr3d': "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",
'xmlns:math': "http://www.w3.org/1998/Math/MathML",
'xmlns:form': "urn:oasis:names:tc:opendocument:xmlns:form:1.0",
'xmlns:script': "urn:oasis:names:tc:opendocument:xmlns:script:1.0",
'xmlns:ooo': "http://openoffice.org/2004/office",
'xmlns:ooow': "http://openoffice.org/2004/writer",
'xmlns:oooc': "http://openoffice.org/2004/calc",
'xmlns:dom': "http://www.w3.org/2001/xml-events",
'xmlns:xforms': "http://www.w3.org/2002/xforms",
'xmlns:xsd': "http://www.w3.org/2001/XMLSchema",
'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance",
'xmlns:sheet': "urn:oasis:names:tc:opendocument:sh33tjs:1.0",
'xmlns:rpt': "http://openoffice.org/2005/report",
'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
'xmlns:xhtml': "http://www.w3.org/1999/xhtml",
'xmlns:grddl': "http://www.w3.org/2003/g/data-view#",
'xmlns:tableooo': "http://openoffice.org/2009/table",
'xmlns:drawooo': "http://openoffice.org/2010/draw",
'xmlns:calcext': "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0",
'xmlns:loext': "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
'xmlns:field': "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0",
'xmlns:formx': "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0",
'xmlns:css3t': "http://www.w3.org/TR/css3-text/",
'office:version': "1.2"
});
var fods = wxt_helper({
'xmlns:config': "urn:oasis:names:tc:opendocument:xmlns:config:1.0",
'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
});
if(opts.bookType == "fods") o.push('<office:document' + attr + fods + '>\n');
else o.push('<office:document-content' + attr + '>\n');
write_automatic_styles_ods(o);
o.push(' <office:body>\n');
o.push(' <office:spreadsheet>\n');
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
o.push(' </office:spreadsheet>\n');
o.push(' </office:body>\n');
if(opts.bookType == "fods") o.push('</office:document>');
else o.push('</office:document-content>');
return o.join("");
};
})();
function write_ods(wb, opts) {
if(opts.bookType == "fods") return write_content_ods(wb, opts);
var zip = zip_new();
var f = "";
var manifest = [];
var rdf = [];
/* Part 3 Section 3.3 MIME Media Type */
f = "mimetype";
zip_add_file(zip, f, "application/vnd.oasis.opendocument.spreadsheet");
/* Part 1 Section 2.2 Documents */
f = "content.xml";
zip_add_file(zip, f, write_content_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "ContentFile"]);
/* TODO: these are hard-coded styles to satiate excel */
f = "styles.xml";
zip_add_file(zip, f, write_styles_ods(wb, opts));
manifest.push([f, "text/xml"]);
rdf.push([f, "StylesFile"]);
/* TODO: this is hard-coded to satiate excel */
f = "meta.xml";
zip_add_file(zip, f, write_meta_ods());
manifest.push([f, "text/xml"]);
rdf.push([f, "MetadataFile"]);
/* Part 3 Section 6 Metadata Manifest File */
f = "manifest.rdf";
zip_add_file(zip, f, write_rdf(rdf/*, opts*/));
manifest.push([f, "application/rdf+xml"]);
/* Part 3 Section 4 Manifest File */
f = "META-INF/manifest.xml";
zip_add_file(zip, f, write_manifest(manifest/*, opts*/));
return zip;
}
function write_sheet_index(wb, sheet) {
if(!sheet) return 0;
var idx = wb.SheetNames.indexOf(sheet);