forked from sheetjs/sheetjs
version bump 0.9.0: merged ODS into XLSX
The optional ODS module has been completely merged into xlsx.js and the corresponding scripts have been removed. The new xlsx.js file provides appropriate ODS exports, so fixing is a matter of removing ods.js refs.
This commit is contained in:
parent
7b6fb7b327
commit
54b528eaed
@ -1,6 +1,7 @@
|
||||
[ignore]
|
||||
.*/node_modules/.*
|
||||
.*/dist/.*
|
||||
.*/tmp/.*
|
||||
.*/test.js
|
||||
|
||||
.*/bits/.*
|
||||
@ -11,8 +12,6 @@
|
||||
.*/demo/browser.js
|
||||
.*/shim.js
|
||||
|
||||
.*/odsbits/.*
|
||||
.*/ods.js
|
||||
.*/xlsx.js
|
||||
.*/xlsxworker.js
|
||||
.*/xlsxworker1.js
|
||||
@ -27,7 +26,6 @@ xlsxworker.flow.js
|
||||
xlsxworker1.flow.js
|
||||
xlsxworker2.flow.js
|
||||
xlsx.flow.js
|
||||
ods.flow.js
|
||||
.*/bin/.*.njs
|
||||
.*/demo/browser.flow.js
|
||||
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,3 +18,4 @@ tmp
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
*.exe
|
||||
|
12
CHANGELOG.md
Normal file
12
CHANGELOG.md
Normal file
@ -0,0 +1,12 @@
|
||||
# CHANGELOG
|
||||
|
||||
This log is intended to keep track of backwards-incompatible changes, including
|
||||
but not limited to API changes and file location changes. Minor behavioral
|
||||
changes may not be included if they are not expected to break existing code.
|
||||
|
||||
|
||||
## 0.9.0 (2017-03-09)
|
||||
|
||||
* Removed ods.js source. The xlsx.js source absorbed the ODS logic and exposes
|
||||
the ODS variable, so projects should remove references to ods.js
|
||||
|
25
Makefile
25
Makefile
@ -3,7 +3,7 @@ LIB=xlsx
|
||||
FMT=xlsx xlsm xlsb ods xls xml misc full
|
||||
REQS=jszip.js
|
||||
ADDONS=dist/cpexcel.js
|
||||
AUXTARGETS=ods.js
|
||||
AUXTARGETS=
|
||||
CMDS=bin/xlsx.njs
|
||||
HTMLLINT=index.html
|
||||
|
||||
@ -62,23 +62,18 @@ dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
|
||||
cat <(head -n 1 bits/00_header.js) $(REQS) $(ADDONS) $(TARGET) $(AUXTARGETS) > demos/requirejs/$(LIB).full.js
|
||||
|
||||
.PHONY: dist-deps
|
||||
dist-deps: ods.js ## Copy dependencies for distribution
|
||||
dist-deps: ## Copy dependencies for distribution
|
||||
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
|
||||
cp jszip.js dist/jszip.js
|
||||
cp ods.js dist/ods.js
|
||||
uglifyjs $(UGLIFYOPTS) ods.js -o dist/ods.min.js --source-map dist/ods.min.map --preamble "$$(head -n 1 bits/00_header.js)"
|
||||
misc/strip_sourcemap.sh dist/ods.min.js
|
||||
|
||||
.PHONY: aux
|
||||
aux: $(AUXTARGETS)
|
||||
|
||||
.PHONY: ods
|
||||
ods: ods.js
|
||||
|
||||
ODSDEPS=$(sort $(wildcard odsbits/*.js))
|
||||
ods.flow.js: $(ODSDEPS) ## Build ODS support library
|
||||
cat $^ | tr -d '\15\32' > $@
|
||||
.PHONY: nexe
|
||||
nexe: xlsx.exe
|
||||
|
||||
xlsx.exe: bin/xlsx.js xlsx.js
|
||||
nexe -i bin/xlsx.njs -o xlsx.exe
|
||||
|
||||
## Testing
|
||||
|
||||
@ -92,6 +87,9 @@ TESTFMT=$(patsubst %,test_%,$(FMT))
|
||||
$(TESTFMT): test_%:
|
||||
FMTS=$* make test
|
||||
|
||||
.PHONY: demos
|
||||
demos: demo-browserify demo-webpack demo-requirejs
|
||||
|
||||
.PHONY: demo-browserify
|
||||
demo-browserify: ## Run browserify demo build
|
||||
make -C demos/browserify
|
||||
@ -102,6 +100,11 @@ demo-webpack: ## Run webpack demo build
|
||||
make -C demos/webpack
|
||||
@echo "start a local server and go to demos/webpack/webpack.html"
|
||||
|
||||
.PHONY: demo-requirejs
|
||||
demo-requirejs: ## Run requirejs demo build
|
||||
make -C demos/requirejs
|
||||
@echo "start a local server and go to demos/requirejs/requirejs.html"
|
||||
|
||||
## Code Checking
|
||||
|
||||
.PHONY: lint
|
||||
|
@ -67,8 +67,6 @@ be included directly:
|
||||
```html
|
||||
<!-- international support from js-codepage -->
|
||||
<script src="dist/cpexcel.js"></script>
|
||||
<!-- ODS support -->
|
||||
<script src="dist/ods.js"></script>
|
||||
```
|
||||
|
||||
An appropriate version for each dependency is included in the dist/ directory.
|
||||
|
@ -2,5 +2,6 @@
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true */
|
||||
/*exported XLSX */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.8.8';
|
||||
XLSX.version = '0.9.0';
|
||||
|
@ -35,6 +35,33 @@ function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
function cc2str(arr/*:Array<number>*/)/*:string*/ {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
|
@ -22,6 +22,7 @@ function getdatabin(data) {
|
||||
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
|
||||
|
||||
/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
|
||||
/* OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file/*:string*/) {
|
||||
var k = keys(zip.files);
|
||||
var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
|
||||
|
@ -1,4 +1,4 @@
|
||||
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var attregexg=/([^\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
|
||||
@ -7,14 +7,21 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) z[q] = v;
|
||||
else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
|
||||
if(j===q.length) {
|
||||
//if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
//if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
@ -27,3 +28,30 @@ function write_manifest(manifest/*:Array<Array<string> >*/, opts)/*:string*/ {
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base/*:string*/, file/*:string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
@ -249,6 +249,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
case 'n': p.v = parseFloat(p.v); break;
|
||||
case 's':
|
||||
sstr = strs[parseInt(p.v, 10)];
|
||||
if(typeof p.v == 'undefined') {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
}
|
||||
p.v = sstr.t;
|
||||
p.r = sstr.r;
|
||||
if(opts.cellHTML) p.h = sstr.h;
|
||||
|
@ -85,6 +85,7 @@ function process_style_xlml(styles, stag, opts) {
|
||||
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o)/*:Workbook*/ {
|
||||
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
|
||||
var interiors = [];
|
||||
var i = 0;
|
||||
if(sid === undefined && row) sid = row.StyleID;
|
||||
if(sid === undefined && csty) sid = csty.StyleID;
|
||||
while(styles[sid] !== undefined) {
|
||||
@ -150,13 +151,15 @@ function xlml_clean_comment(comment/*:any*/) {
|
||||
}
|
||||
|
||||
function xlml_normalize(d)/*:string*/ {
|
||||
if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(typeof d === 'string') return d;
|
||||
throw new Error("Bad input format: expected Buffer or string");
|
||||
}
|
||||
|
||||
/* TODO: Everything */
|
||||
var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
/* UOS uses CJK in tags */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
||||
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
||||
var str = debom(xlml_normalize(d));
|
||||
if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts);
|
||||
|
@ -1,5 +1,9 @@
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
var number_formats = {
|
||||
/* ods name: [short ssf fmt, long ssf fmt] */
|
||||
day: ["d", "dd"],
|
||||
@ -35,7 +39,7 @@ var parse_content_xml = (function() {
|
||||
|
||||
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'] = get_utils().encode_range(range);
|
||||
if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
|
||||
if(merges.length) ws['!merges'] = merges;
|
||||
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
|
||||
SheetNames.push(sheetag.name);
|
||||
@ -76,7 +80,7 @@ var parse_content_xml = (function() {
|
||||
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 = get_utils().encode_range(mrange);
|
||||
q.F = encode_range(mrange);
|
||||
arrayf.push([mrange, q.F]);
|
||||
}
|
||||
if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
|
||||
@ -119,8 +123,8 @@ var parse_content_xml = (function() {
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
@ -4,13 +4,13 @@ var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
|
||||
var R=0,C=0, range = get_utils().decode_range(ws['!ref']);
|
||||
var R=0,C=0, range = decode_range(ws['!ref']);
|
||||
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 ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
var ref = encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
|
||||
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
|
@ -1,21 +1,44 @@
|
||||
/* Helper functions to call out to ODS */
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
function get_ods() {
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./ods.js');
|
||||
return ODS;
|
||||
}
|
||||
function parse_ods(zip, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_ods(zip, opts);
|
||||
}
|
||||
function write_ods(wb, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.write_ods(wb, opts);
|
||||
}
|
||||
function parse_fods(data, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_fods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_fods(data, opts);
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
XLSX.parse_xlscfb = parse_xlscfb;
|
||||
XLSX.parse_ods = parse_ods;
|
||||
XLSX.parse_fods = parse_fods;
|
||||
XLSX.write_ods = write_ods;
|
||||
XLSX.parse_zip = parse_zip;
|
||||
XLSX.read = readSync; //xlsread
|
||||
XLSX.readFile = readFileSync; //readFile
|
||||
|
@ -1,2 +1,5 @@
|
||||
})(typeof exports !== 'undefined' ? exports : XLSX);
|
||||
/*exported XLS */
|
||||
var XLS = XLSX;
|
||||
/*exported ODS */
|
||||
var ODS = XLSX;
|
||||
|
@ -41,6 +41,8 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c
|
||||
<br />
|
||||
<script src="browserify.min.js"></script>
|
||||
<script>
|
||||
/*jshint browser:true */
|
||||
/*global require */
|
||||
var X = require('xlsx');
|
||||
var XW = {
|
||||
/* worker message */
|
||||
|
@ -7,4 +7,4 @@ $(TOOL).min.js: $(TOOL).js
|
||||
|
||||
.PHONY: $(TOOL).js
|
||||
$(TOOL).js:
|
||||
webpack main.js --output-filename $@ --display-modules
|
||||
webpack main.js --output-filename $@ --display-modules --profile
|
||||
|
@ -12,8 +12,7 @@ module.exports = {
|
||||
},
|
||||
externals: [
|
||||
{
|
||||
'./cptable': 'var cptable',
|
||||
'../xlsx.js': 'var _XLSX'
|
||||
'./cptable': 'var cptable'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c
|
||||
<br />
|
||||
<script src="webpack.min.js"></script>
|
||||
<script>
|
||||
/*jshint browser:true */
|
||||
/*global XLSX */
|
||||
var X = XLSX;
|
||||
var XW = {
|
||||
/* worker message */
|
||||
|
745
dist/ods.js
vendored
745
dist/ods.js
vendored
@ -1,745 +0,0 @@
|
||||
/* ods.js (C) 2014-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
var ODS = {};
|
||||
(function make_ods(ODS) {
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
var get_utils = function() {
|
||||
if(typeof XLSX !== 'undefined') return XLSX.utils;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') try {
|
||||
return require('../xlsx.js').utils;
|
||||
} catch(e) {
|
||||
return require('./xlsx.js').utils;
|
||||
}
|
||||
throw new Error("Cannot find XLSX utils");
|
||||
};
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
return o;
|
||||
}
|
||||
|
||||
function dup(o) {
|
||||
if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o));
|
||||
if(typeof o != 'object' || !o) return o;
|
||||
var out = {};
|
||||
for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
|
||||
return out;
|
||||
}
|
||||
function getdatastr(data) {
|
||||
if(!data) return null;
|
||||
if(data.data) return data.data;
|
||||
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer().toString('binary');
|
||||
if(data.asBinary) return data.asBinary();
|
||||
if(data._data && data._data.getContent) return cc2str(Array.prototype.slice.call(data._data.getContent(),0));
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ODS and friends only use text files in container */
|
||||
function getdata(data) { return getdatastr(data); }
|
||||
|
||||
/* NOTE: unlike ECMA-376, OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file) {
|
||||
var f = file; if(zip.files[f]) return zip.files[f];
|
||||
f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
|
||||
f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
|
||||
return null;
|
||||
}
|
||||
|
||||
function getzipfile(zip, file) {
|
||||
var o = safegetzipfile(zip, file);
|
||||
if(o == null) throw new Error("Cannot find file " + file + " in zip");
|
||||
return o;
|
||||
}
|
||||
|
||||
function getzipdata(zip, file, safe) {
|
||||
if(!safe) return getdata(getzipfile(zip, file));
|
||||
if(!file) return null;
|
||||
try { return getzipdata(zip, file); } catch(e) { return null; }
|
||||
}
|
||||
|
||||
var _fs, jszip;
|
||||
if(typeof JSZip !== 'undefined') jszip = JSZip;
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
|
||||
_fs = require('fs');
|
||||
}
|
||||
}
|
||||
var attregexg=/[^\s?>\/]+=["'][^"]*['"]/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag, skip_root) {
|
||||
var z = [];
|
||||
var eq = 0, c = 0;
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) {
|
||||
if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_"));
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
if(z[k] && q.substr(j-3,3) == "ext") continue;
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
|
||||
|
||||
var encodings = {
|
||||
'"': '"',
|
||||
''': "'",
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencoding = {
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencstr = "&<>'\"".split("");
|
||||
|
||||
// TODO: CP remap (need to read file version to determine OS)
|
||||
/* 22.4.2.4 bstr (Basic String) */
|
||||
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]{4})_/g;
|
||||
function unescapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
|
||||
}
|
||||
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
|
||||
function escapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
|
||||
}
|
||||
|
||||
function parsexmlbool(value) {
|
||||
switch(value) {
|
||||
case '1': case 'true': case 'TRUE': return true;
|
||||
/* case '0': case 'false': case 'FALSE':*/
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
function datenum(v, date1904) {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch += 1462*24*60*60*1000;
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
|
||||
/* copied from js-xls (C) SheetJS Apache2 license */
|
||||
function xlml_normalize(d) {
|
||||
if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(typeof d === 'string') return d;
|
||||
throw "badf";
|
||||
}
|
||||
|
||||
/* UOS uses CJK in tags, original regex /<(\/?)([a-z0-9]*:|)([\w-]+)[^>]*>/ */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file, res, tag) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base, file) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
var utf8read = function utf8reada(orig) {
|
||||
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
|
||||
while (i < orig.length) {
|
||||
c = orig.charCodeAt(i++);
|
||||
if (c < 128) { out += String.fromCharCode(c); continue; }
|
||||
d = orig.charCodeAt(i++);
|
||||
if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
|
||||
e = orig.charCodeAt(i++);
|
||||
if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
|
||||
f = orig.charCodeAt(i++);
|
||||
w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
|
||||
out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
|
||||
out += String.fromCharCode(0xDC00 + (w&1023));
|
||||
}
|
||||
return out;
|
||||
};
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f) {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
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"]
|
||||
};
|
||||
|
||||
return function pcx(d, _opts) {
|
||||
var opts = _opts || {};
|
||||
var str = xlml_normalize(d);
|
||||
var state = [], tmp;
|
||||
var tag;
|
||||
var NFtag = {name:""}, NF = "", pidx = 0;
|
||||
var sheetag;
|
||||
var rowtag;
|
||||
var Sheets = {}, SheetNames = [], ws = {};
|
||||
var Rn, q;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
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'] = get_utils().encode_range(range);
|
||||
if(merges.length) ws['!merges'] = merges;
|
||||
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
|
||||
SheetNames.push(sheetag.name);
|
||||
Sheets[sheetag.name] = ws;
|
||||
}
|
||||
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 = {}; merges = [];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'table-row': case '行': // 9.1.3 <table:table-row>
|
||||
if(Rn[1] === '/') break;
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
|
||||
else ++C;
|
||||
}
|
||||
else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
rept = 1;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
if(R > range.e.r) range.e.r = R;
|
||||
if(C < range.s.c) range.s.c = C;
|
||||
if(R < range.s.r) range.s.r = R;
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
|
||||
if(opts.cellFormula) {
|
||||
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 = get_utils().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']) rept = 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 = 'n'; q.v = datenum(new Date(ctag['date-value'])); 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 = ctag['string-value'];
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {};
|
||||
textp = "";
|
||||
}
|
||||
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>
|
||||
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;
|
||||
|
||||
/* 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 'annotation': // 14.1 <office:annotation>
|
||||
case 'event-listeners': // 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;
|
||||
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 'master-styles': break; // TODO: <office:automatic-styles>
|
||||
|
||||
case 'default-style': // TODO: <style:default-style>
|
||||
case 'page-layout': break; // TODO: <style:page-layout>
|
||||
case 'style': break; // 16.2 <style:style>
|
||||
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 'text-content': break; // 16.27.27 <number:text-content>
|
||||
case 'text-properties': break; // 16.27.27 <style:text-properties>
|
||||
|
||||
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 '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 'named-range': break; // 9.4.12 <table:named-range>
|
||||
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 'span': break; // <text:span>
|
||||
case 'line-break': break; // 6.1.5 <text:line-break>
|
||||
case 'p': case '文本串':
|
||||
if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
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 'table-source': 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 'error-message': break; // 9.4.7 <table:
|
||||
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
|
||||
case 'database-range': break; // 9.4.15 <table:database-range>
|
||||
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': // TODO
|
||||
/* TODO: FODS Properties */
|
||||
case 'initial-creator':
|
||||
case 'creator':
|
||||
case 'creation-date':
|
||||
case 'generator':
|
||||
case 'document-statistic':
|
||||
case 'user-defined':
|
||||
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.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': break; // 6.1.8 hyperlink
|
||||
|
||||
/* non-standard */
|
||||
case 'table-protection': break;
|
||||
case 'data-pilot-grand-total': break; // <table:
|
||||
default:
|
||||
if(Rn[2] === 'dc:') break; // TODO: properties
|
||||
if(Rn[2] === 'draw:') break; // TODO: drawing
|
||||
if(Rn[2] === 'style:') break; // TODO: styles
|
||||
if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'loext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'uof:') break; // TODO: uof
|
||||
if(Rn[2] === '表:') break; // TODO: uof
|
||||
if(Rn[2] === '字:') break; // TODO: uof
|
||||
if(opts.WTF) throw Rn;
|
||||
}
|
||||
var out = {
|
||||
Sheets: Sheets,
|
||||
SheetNames: SheetNames
|
||||
};
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var write_ws = function(ws, wb, i, opts) {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
|
||||
var R=0,C=0, range = get_utils().decode_range(ws['!ref']);
|
||||
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 ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
|
||||
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
case 's': case 'str': o.push(' <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
//case 'd': // TODO
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
o.push(' </table:table>\n');
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
return function wcx(wb, opts) {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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:table="urn:oasis:names:tc:opendocument:xmlns:table: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:config="urn:oasis:names:tc:opendocument:xmlns:config: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: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" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
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("");
|
||||
};
|
||||
})();
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip, opts) {
|
||||
opts = opts || ({});
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
|
||||
function parse_fods(data, opts) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
function write_ods(wb, opts) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
ODS.parse_ods = parse_ods;
|
||||
ODS.write_ods = write_ods;
|
||||
ODS.parse_fods = parse_fods;
|
||||
})(typeof exports !== 'undefined' ? exports : ODS);
|
2
dist/ods.min.js
vendored
2
dist/ods.min.js
vendored
File diff suppressed because one or more lines are too long
1
dist/ods.min.map
vendored
1
dist/ods.min.map
vendored
File diff suppressed because one or more lines are too long
22
dist/xlsx.core.min.js
vendored
22
dist/xlsx.core.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.core.min.map
vendored
2
dist/xlsx.core.min.map
vendored
File diff suppressed because one or more lines are too long
24
dist/xlsx.full.min.js
vendored
24
dist/xlsx.full.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.full.min.map
vendored
2
dist/xlsx.full.min.map
vendored
File diff suppressed because one or more lines are too long
622
dist/xlsx.js
vendored
622
dist/xlsx.js
vendored
@ -2,9 +2,10 @@
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true */
|
||||
/*exported XLSX */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.8.8';
|
||||
XLSX.version = '0.9.0';
|
||||
var current_codepage = 1200, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
|
||||
@ -1299,6 +1300,33 @@ function datenum(v, date1904) {
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
@ -1344,6 +1372,7 @@ function getdatabin(data) {
|
||||
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
|
||||
|
||||
/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
|
||||
/* OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file) {
|
||||
var k = keys(zip.files);
|
||||
var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
|
||||
@ -1380,7 +1409,7 @@ if (typeof exports !== 'undefined') {
|
||||
_fs = require('fs');
|
||||
}
|
||||
}
|
||||
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var attregexg=/([^\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag, skip_root) {
|
||||
@ -1389,14 +1418,21 @@ function parsexmltag(tag, skip_root) {
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) z[q] = v;
|
||||
else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
|
||||
if(j===q.length) {
|
||||
//if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
//if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
@ -2640,6 +2676,63 @@ function write_rels(rels) {
|
||||
if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file, res, tag) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base, file) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
/* ECMA-376 Part II 11.1 Core Properties Part */
|
||||
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
|
||||
var CORE_PROPS = [
|
||||
@ -7833,6 +7926,17 @@ var XLSXFutureFunctions = {
|
||||
"_xlfn.Z.TEST": "Z.TEST"
|
||||
};
|
||||
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f) {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var strs = {}; // shared strings
|
||||
var _ssfopts = {}; // spreadsheet formatting options
|
||||
|
||||
@ -8141,6 +8245,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
case 'n': p.v = parseFloat(p.v); break;
|
||||
case 's':
|
||||
sstr = strs[parseInt(p.v, 10)];
|
||||
if(typeof p.v == 'undefined') {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
}
|
||||
p.v = sstr.t;
|
||||
p.r = sstr.r;
|
||||
if(opts.cellHTML) p.h = sstr.h;
|
||||
@ -9412,6 +9520,7 @@ function process_style_xlml(styles, stag, opts) {
|
||||
function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o) {
|
||||
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
|
||||
var interiors = [];
|
||||
var i = 0;
|
||||
if(sid === undefined && row) sid = row.StyleID;
|
||||
if(sid === undefined && csty) sid = csty.StyleID;
|
||||
while(styles[sid] !== undefined) {
|
||||
@ -9483,7 +9592,9 @@ function xlml_normalize(d) {
|
||||
}
|
||||
|
||||
/* TODO: Everything */
|
||||
var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
/* UOS uses CJK in tags */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
||||
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
function parse_xlml_xml(d, opts) {
|
||||
var str = debom(xlml_normalize(d));
|
||||
if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts);
|
||||
@ -12145,6 +12256,443 @@ function parse_html(str, opts) {
|
||||
ws['!ref'] = encode_range(range);
|
||||
return o;
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
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"]
|
||||
};
|
||||
|
||||
return function pcx(d, _opts) {
|
||||
var opts = _opts || {};
|
||||
var str = xlml_normalize(d);
|
||||
var state = [], tmp;
|
||||
var tag;
|
||||
var NFtag = {name:""}, NF = "", pidx = 0;
|
||||
var sheetag;
|
||||
var rowtag;
|
||||
var Sheets = {}, SheetNames = [], ws = {};
|
||||
var Rn, q;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
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);
|
||||
if(merges.length) ws['!merges'] = merges;
|
||||
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
|
||||
SheetNames.push(sheetag.name);
|
||||
Sheets[sheetag.name] = ws;
|
||||
}
|
||||
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 = {}; merges = [];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'table-row': case '行': // 9.1.3 <table:table-row>
|
||||
if(Rn[1] === '/') break;
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
|
||||
else ++C;
|
||||
}
|
||||
else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
rept = 1;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
if(R > range.e.r) range.e.r = R;
|
||||
if(C < range.s.c) range.s.c = C;
|
||||
if(R < range.s.r) range.s.r = R;
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
|
||||
if(opts.cellFormula) {
|
||||
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']) rept = 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 = 'n'; q.v = datenum(new Date(ctag['date-value'])); 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 = ctag['string-value'];
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {};
|
||||
textp = "";
|
||||
}
|
||||
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>
|
||||
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;
|
||||
|
||||
/* 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 'annotation': // 14.1 <office:annotation>
|
||||
case 'event-listeners': // 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;
|
||||
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 'master-styles': break; // TODO: <office:automatic-styles>
|
||||
|
||||
case 'default-style': // TODO: <style:default-style>
|
||||
case 'page-layout': break; // TODO: <style:page-layout>
|
||||
case 'style': break; // 16.2 <style:style>
|
||||
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 'text-content': break; // 16.27.27 <number:text-content>
|
||||
case 'text-properties': break; // 16.27.27 <style:text-properties>
|
||||
|
||||
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 '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 'named-range': break; // 9.4.12 <table:named-range>
|
||||
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 'span': break; // <text:span>
|
||||
case 'line-break': break; // 6.1.5 <text:line-break>
|
||||
case 'p': case '文本串':
|
||||
if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
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 'table-source': 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 'error-message': break; // 9.4.7 <table:
|
||||
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
|
||||
case 'database-range': break; // 9.4.15 <table:database-range>
|
||||
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': // TODO
|
||||
/* TODO: FODS Properties */
|
||||
case 'initial-creator':
|
||||
case 'creator':
|
||||
case 'creation-date':
|
||||
case 'generator':
|
||||
case 'document-statistic':
|
||||
case 'user-defined':
|
||||
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.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': break; // 6.1.8 hyperlink
|
||||
|
||||
/* non-standard */
|
||||
case 'table-protection': break;
|
||||
case 'data-pilot-grand-total': break; // <table:
|
||||
default:
|
||||
if(Rn[2] === 'dc:') break; // TODO: properties
|
||||
if(Rn[2] === 'draw:') break; // TODO: drawing
|
||||
if(Rn[2] === 'style:') break; // TODO: styles
|
||||
if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'loext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'uof:') break; // TODO: uof
|
||||
if(Rn[2] === '表:') break; // TODO: uof
|
||||
if(Rn[2] === '字:') break; // TODO: uof
|
||||
if(opts.WTF) throw Rn;
|
||||
}
|
||||
var out = {
|
||||
Sheets: Sheets,
|
||||
SheetNames: SheetNames
|
||||
};
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var write_ws = function(ws, wb, i, opts) {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
|
||||
var R=0,C=0, range = decode_range(ws['!ref']);
|
||||
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 ref = encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
|
||||
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
case 's': case 'str': o.push(' <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
//case 'd': // TODO
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
o.push(' </table:table>\n');
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
return function wcx(wb, opts) {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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:table="urn:oasis:names:tc:opendocument:xmlns:table: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:config="urn:oasis:names:tc:opendocument:xmlns:config: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: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" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
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("");
|
||||
};
|
||||
})();
|
||||
/* actual implementation in utils, wrappers are for read/write */
|
||||
function write_csv_str(wb, o) {
|
||||
var idx = 0;
|
||||
@ -12152,26 +12700,48 @@ function write_csv_str(wb, o) {
|
||||
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
|
||||
return sheet_to_csv(wb.Sheets[wb.SheetNames[idx]], o);
|
||||
}
|
||||
/* Helper functions to call out to ODS */
|
||||
|
||||
function get_ods() {
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./ods.js');
|
||||
return ODS;
|
||||
}
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_ods(zip, opts);
|
||||
}
|
||||
function write_ods(wb, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.write_ods(wb, opts);
|
||||
opts = opts || ({});
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_fods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_fods(data, opts);
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
function write_ods(wb, opts) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
function fix_opts_func(defaults) {
|
||||
return function fix_opts(opts) {
|
||||
@ -12783,6 +13353,9 @@ var utils = {
|
||||
sheet_to_row_object_array: sheet_to_row_object_array
|
||||
};
|
||||
XLSX.parse_xlscfb = parse_xlscfb;
|
||||
XLSX.parse_ods = parse_ods;
|
||||
XLSX.parse_fods = parse_fods;
|
||||
XLSX.write_ods = write_ods;
|
||||
XLSX.parse_zip = parse_zip;
|
||||
XLSX.read = readSync; //xlsread
|
||||
XLSX.readFile = readFileSync; //readFile
|
||||
@ -12794,4 +13367,7 @@ XLSX.utils = utils;
|
||||
XLSX.CFB = CFB;
|
||||
XLSX.SSF = SSF;
|
||||
})(typeof exports !== 'undefined' ? exports : XLSX);
|
||||
/*exported XLS */
|
||||
var XLS = XLSX;
|
||||
/*exported ODS */
|
||||
var ODS = XLSX;
|
||||
|
21
dist/xlsx.min.js
vendored
21
dist/xlsx.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.min.map
vendored
2
dist/xlsx.min.map
vendored
File diff suppressed because one or more lines are too long
@ -44,9 +44,9 @@ Use readAsBinaryString: (when available) <input type="checkbox" name="userabs" c
|
||||
<script src="shim.js"></script>
|
||||
<script src="jszip.js"></script>
|
||||
<script src="xlsx.js"></script>
|
||||
<!-- uncomment the next line here and in xlsxworker.js for ODS support -->
|
||||
<script src="ods.js"></script>
|
||||
<script>
|
||||
/*jshint browser:true */
|
||||
/*global XLSX */
|
||||
var X = XLSX;
|
||||
var XW = {
|
||||
/* worker message */
|
||||
|
@ -6,6 +6,9 @@ declare module '../' { declare var exports:XLSXModule; };
|
||||
|
||||
declare module 'commander' { declare var exports:any; };
|
||||
declare module './jszip.js' { declare var exports:any; };
|
||||
declare module './dist/cpexcel.js' { declare var exports:any; };
|
||||
declare module 'crypto' { declare var exports:any; };
|
||||
declare module 'fs' { declare var exports:any; };
|
||||
|
||||
type ZIP = any;
|
||||
*/
|
||||
|
748
ods.flow.js
748
ods.flow.js
@ -1,748 +0,0 @@
|
||||
/* ods.js (C) 2014-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
var ODS = {};
|
||||
(function make_ods(ODS) {
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
/*:: declare var XLSX: any; */
|
||||
var get_utils = function() {
|
||||
if(typeof XLSX !== 'undefined') return XLSX.utils;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') try {
|
||||
return require('../xlsx.js').utils;
|
||||
} catch(e) {
|
||||
return require('./xlsx.js').utils;
|
||||
}
|
||||
throw new Error("Cannot find XLSX utils");
|
||||
};
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function cc2str(arr)/*:string*/ {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
return o;
|
||||
}
|
||||
|
||||
function dup(o/*:any*/)/*:any*/ {
|
||||
if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o));
|
||||
if(typeof o != 'object' || !o) return o;
|
||||
var out = {};
|
||||
for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
|
||||
return out;
|
||||
}
|
||||
function getdatastr(data)/*:?string*/ {
|
||||
if(!data) return null;
|
||||
if(data.data) return data.data;
|
||||
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer().toString('binary');
|
||||
if(data.asBinary) return data.asBinary();
|
||||
if(data._data && data._data.getContent) return cc2str(Array.prototype.slice.call(data._data.getContent(),0));
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ODS and friends only use text files in container */
|
||||
function getdata(data) { return getdatastr(data); }
|
||||
|
||||
/* NOTE: unlike ECMA-376, OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file/*:string*/) {
|
||||
var f = file; if(zip.files[f]) return zip.files[f];
|
||||
f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
|
||||
f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
|
||||
return null;
|
||||
}
|
||||
|
||||
function getzipfile(zip, file/*:string*/) {
|
||||
var o = safegetzipfile(zip, file);
|
||||
if(o == null) throw new Error("Cannot find file " + file + " in zip");
|
||||
return o;
|
||||
}
|
||||
|
||||
function getzipdata(zip, file/*:string*/, safe/*:?boolean*/) {
|
||||
if(!safe) return getdata(getzipfile(zip, file));
|
||||
if(!file) return null;
|
||||
try { return getzipdata(zip, file); } catch(e) { return null; }
|
||||
}
|
||||
|
||||
var _fs, jszip;
|
||||
/*:: declare var JSZip:any; */
|
||||
if(typeof JSZip !== 'undefined') jszip = JSZip;
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
|
||||
_fs = require('fs');
|
||||
}
|
||||
}
|
||||
var attregexg=/[^\s?>\/]+=["'][^"]*['"]/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag, skip_root) {
|
||||
var z/*:any*/ = [];
|
||||
var eq = 0, c = 0;
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) {
|
||||
if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_"));
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
if(z[k] && q.substr(j-3,3) == "ext") continue;
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
|
||||
|
||||
var encodings = {
|
||||
'"': '"',
|
||||
''': "'",
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencoding = {
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencstr = "&<>'\"".split("");
|
||||
|
||||
// TODO: CP remap (need to read file version to determine OS)
|
||||
/* 22.4.2.4 bstr (Basic String) */
|
||||
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]{4})_/g;
|
||||
function unescapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
|
||||
}
|
||||
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
|
||||
function escapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
|
||||
}
|
||||
|
||||
function parsexmlbool(value) {
|
||||
switch(value) {
|
||||
case '1': case 'true': case 'TRUE': return true;
|
||||
/* case '0': case 'false': case 'FALSE':*/
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch += 1462*24*60*60*1000;
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
|
||||
/* copied from js-xls (C) SheetJS Apache2 license */
|
||||
function xlml_normalize(d)/*:string*/ {
|
||||
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(typeof d === 'string') return d;
|
||||
throw "badf";
|
||||
}
|
||||
|
||||
/* UOS uses CJK in tags, original regex /<(\/?)([a-z0-9]*:|)([\w-]+)[^>]*>/ */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest/*:Array<Array<string> >*/, opts)/*:string*/ {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base/*:string*/, file/*:string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
var utf8read = function utf8reada(orig/*:string*/)/*:string*/ {
|
||||
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
|
||||
while (i < orig.length) {
|
||||
c = orig.charCodeAt(i++);
|
||||
if (c < 128) { out += String.fromCharCode(c); continue; }
|
||||
d = orig.charCodeAt(i++);
|
||||
if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
|
||||
e = orig.charCodeAt(i++);
|
||||
if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
|
||||
f = orig.charCodeAt(i++);
|
||||
w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
|
||||
out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
|
||||
out += String.fromCharCode(0xDC00 + (w&1023));
|
||||
}
|
||||
return out;
|
||||
};
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f/*:string*/)/*:string*/ {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
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"]
|
||||
};
|
||||
|
||||
return function pcx(d, _opts) {
|
||||
var opts = _opts || {};
|
||||
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>*/ = [], ws = {};
|
||||
var Rn, q/*:: = ({t:"", v:null, z:null, w:""}:any)*/;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag/*:: = {}*/;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
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'] = get_utils().encode_range(range);
|
||||
if(merges.length) ws['!merges'] = merges;
|
||||
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
|
||||
SheetNames.push(sheetag.name);
|
||||
Sheets[sheetag.name] = ws;
|
||||
}
|
||||
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 = {}; merges = [];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'table-row': case '行': // 9.1.3 <table:table-row>
|
||||
if(Rn[1] === '/') break;
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
|
||||
else ++C;
|
||||
}
|
||||
else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
rept = 1;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
if(R > range.e.r) range.e.r = R;
|
||||
if(C < range.s.c) range.s.c = C;
|
||||
if(R < range.s.r) range.s.r = R;
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/);
|
||||
if(opts.cellFormula) {
|
||||
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 = get_utils().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']) rept = 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 = 'n'; q.v = datenum(new Date(ctag['date-value'])); 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 = ctag['string-value'];
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {/*:: t:"", v:null, z:null, w:""*/};
|
||||
textp = "";
|
||||
}
|
||||
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>
|
||||
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;
|
||||
|
||||
/* 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 'annotation': // 14.1 <office:annotation>
|
||||
case 'event-listeners': // 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;
|
||||
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 'master-styles': break; // TODO: <office:automatic-styles>
|
||||
|
||||
case 'default-style': // TODO: <style:default-style>
|
||||
case 'page-layout': break; // TODO: <style:page-layout>
|
||||
case 'style': break; // 16.2 <style:style>
|
||||
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 'text-content': break; // 16.27.27 <number:text-content>
|
||||
case 'text-properties': break; // 16.27.27 <style:text-properties>
|
||||
|
||||
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 '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 'named-range': break; // 9.4.12 <table:named-range>
|
||||
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 'span': break; // <text:span>
|
||||
case 'line-break': break; // 6.1.5 <text:line-break>
|
||||
case 'p': case '文本串':
|
||||
if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
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 'table-source': 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 'error-message': break; // 9.4.7 <table:
|
||||
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
|
||||
case 'database-range': break; // 9.4.15 <table:database-range>
|
||||
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': // TODO
|
||||
/* TODO: FODS Properties */
|
||||
case 'initial-creator':
|
||||
case 'creator':
|
||||
case 'creation-date':
|
||||
case 'generator':
|
||||
case 'document-statistic':
|
||||
case 'user-defined':
|
||||
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.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': break; // 6.1.8 hyperlink
|
||||
|
||||
/* non-standard */
|
||||
case 'table-protection': break;
|
||||
case 'data-pilot-grand-total': break; // <table:
|
||||
default:
|
||||
if(Rn[2] === 'dc:') break; // TODO: properties
|
||||
if(Rn[2] === 'draw:') break; // TODO: drawing
|
||||
if(Rn[2] === 'style:') break; // TODO: styles
|
||||
if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'loext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'uof:') break; // TODO: uof
|
||||
if(Rn[2] === '表:') break; // TODO: uof
|
||||
if(Rn[2] === '字:') break; // TODO: uof
|
||||
if(opts.WTF) throw Rn;
|
||||
}
|
||||
var out = {
|
||||
Sheets: Sheets,
|
||||
SheetNames: SheetNames
|
||||
};
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
|
||||
var R=0,C=0, range = get_utils().decode_range(ws['!ref']);
|
||||
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 ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
|
||||
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
case 's': case 'str': o.push(' <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
//case 'd': // TODO
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
o.push(' </table:table>\n');
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
return function wcx(wb, opts) {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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:table="urn:oasis:names:tc:opendocument:xmlns:table: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:config="urn:oasis:names:tc:opendocument:xmlns:config: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: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" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
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("");
|
||||
};
|
||||
})();
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
ODS.parse_ods = parse_ods;
|
||||
ODS.write_ods = write_ods;
|
||||
ODS.parse_fods = parse_fods;
|
||||
})(typeof exports !== 'undefined' ? exports : ODS);
|
745
ods.js
745
ods.js
@ -1,745 +0,0 @@
|
||||
/* ods.js (C) 2014-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
var ODS = {};
|
||||
(function make_ods(ODS) {
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
var get_utils = function() {
|
||||
if(typeof XLSX !== 'undefined') return XLSX.utils;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') try {
|
||||
return require('../xlsx.js').utils;
|
||||
} catch(e) {
|
||||
return require('./xlsx.js').utils;
|
||||
}
|
||||
throw new Error("Cannot find XLSX utils");
|
||||
};
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
return o;
|
||||
}
|
||||
|
||||
function dup(o) {
|
||||
if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o));
|
||||
if(typeof o != 'object' || !o) return o;
|
||||
var out = {};
|
||||
for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
|
||||
return out;
|
||||
}
|
||||
function getdatastr(data) {
|
||||
if(!data) return null;
|
||||
if(data.data) return data.data;
|
||||
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer().toString('binary');
|
||||
if(data.asBinary) return data.asBinary();
|
||||
if(data._data && data._data.getContent) return cc2str(Array.prototype.slice.call(data._data.getContent(),0));
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ODS and friends only use text files in container */
|
||||
function getdata(data) { return getdatastr(data); }
|
||||
|
||||
/* NOTE: unlike ECMA-376, OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file) {
|
||||
var f = file; if(zip.files[f]) return zip.files[f];
|
||||
f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
|
||||
f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
|
||||
return null;
|
||||
}
|
||||
|
||||
function getzipfile(zip, file) {
|
||||
var o = safegetzipfile(zip, file);
|
||||
if(o == null) throw new Error("Cannot find file " + file + " in zip");
|
||||
return o;
|
||||
}
|
||||
|
||||
function getzipdata(zip, file, safe) {
|
||||
if(!safe) return getdata(getzipfile(zip, file));
|
||||
if(!file) return null;
|
||||
try { return getzipdata(zip, file); } catch(e) { return null; }
|
||||
}
|
||||
|
||||
var _fs, jszip;
|
||||
if(typeof JSZip !== 'undefined') jszip = JSZip;
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
|
||||
_fs = require('fs');
|
||||
}
|
||||
}
|
||||
var attregexg=/[^\s?>\/]+=["'][^"]*['"]/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag, skip_root) {
|
||||
var z = [];
|
||||
var eq = 0, c = 0;
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) {
|
||||
if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_"));
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
if(z[k] && q.substr(j-3,3) == "ext") continue;
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
|
||||
|
||||
var encodings = {
|
||||
'"': '"',
|
||||
''': "'",
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencoding = {
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencstr = "&<>'\"".split("");
|
||||
|
||||
// TODO: CP remap (need to read file version to determine OS)
|
||||
/* 22.4.2.4 bstr (Basic String) */
|
||||
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]{4})_/g;
|
||||
function unescapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
|
||||
}
|
||||
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
|
||||
function escapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
|
||||
}
|
||||
|
||||
function parsexmlbool(value) {
|
||||
switch(value) {
|
||||
case '1': case 'true': case 'TRUE': return true;
|
||||
/* case '0': case 'false': case 'FALSE':*/
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
function datenum(v, date1904) {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch += 1462*24*60*60*1000;
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
|
||||
/* copied from js-xls (C) SheetJS Apache2 license */
|
||||
function xlml_normalize(d) {
|
||||
if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(typeof d === 'string') return d;
|
||||
throw "badf";
|
||||
}
|
||||
|
||||
/* UOS uses CJK in tags, original regex /<(\/?)([a-z0-9]*:|)([\w-]+)[^>]*>/ */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file, res, tag) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base, file) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
var utf8read = function utf8reada(orig) {
|
||||
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
|
||||
while (i < orig.length) {
|
||||
c = orig.charCodeAt(i++);
|
||||
if (c < 128) { out += String.fromCharCode(c); continue; }
|
||||
d = orig.charCodeAt(i++);
|
||||
if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
|
||||
e = orig.charCodeAt(i++);
|
||||
if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
|
||||
f = orig.charCodeAt(i++);
|
||||
w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
|
||||
out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
|
||||
out += String.fromCharCode(0xDC00 + (w&1023));
|
||||
}
|
||||
return out;
|
||||
};
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f) {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
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"]
|
||||
};
|
||||
|
||||
return function pcx(d, _opts) {
|
||||
var opts = _opts || {};
|
||||
var str = xlml_normalize(d);
|
||||
var state = [], tmp;
|
||||
var tag;
|
||||
var NFtag = {name:""}, NF = "", pidx = 0;
|
||||
var sheetag;
|
||||
var rowtag;
|
||||
var Sheets = {}, SheetNames = [], ws = {};
|
||||
var Rn, q;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
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'] = get_utils().encode_range(range);
|
||||
if(merges.length) ws['!merges'] = merges;
|
||||
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
|
||||
SheetNames.push(sheetag.name);
|
||||
Sheets[sheetag.name] = ws;
|
||||
}
|
||||
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 = {}; merges = [];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'table-row': case '行': // 9.1.3 <table:table-row>
|
||||
if(Rn[1] === '/') break;
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
|
||||
else ++C;
|
||||
}
|
||||
else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
rept = 1;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
if(R > range.e.r) range.e.r = R;
|
||||
if(C < range.s.c) range.s.c = C;
|
||||
if(R < range.s.r) range.s.r = R;
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
|
||||
if(opts.cellFormula) {
|
||||
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 = get_utils().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']) rept = 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 = 'n'; q.v = datenum(new Date(ctag['date-value'])); 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 = ctag['string-value'];
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[get_utils().encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[get_utils().encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {};
|
||||
textp = "";
|
||||
}
|
||||
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>
|
||||
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;
|
||||
|
||||
/* 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 'annotation': // 14.1 <office:annotation>
|
||||
case 'event-listeners': // 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;
|
||||
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 'master-styles': break; // TODO: <office:automatic-styles>
|
||||
|
||||
case 'default-style': // TODO: <style:default-style>
|
||||
case 'page-layout': break; // TODO: <style:page-layout>
|
||||
case 'style': break; // 16.2 <style:style>
|
||||
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 'text-content': break; // 16.27.27 <number:text-content>
|
||||
case 'text-properties': break; // 16.27.27 <style:text-properties>
|
||||
|
||||
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 '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 'named-range': break; // 9.4.12 <table:named-range>
|
||||
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 'span': break; // <text:span>
|
||||
case 'line-break': break; // 6.1.5 <text:line-break>
|
||||
case 'p': case '文本串':
|
||||
if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
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 'table-source': 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 'error-message': break; // 9.4.7 <table:
|
||||
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
|
||||
case 'database-range': break; // 9.4.15 <table:database-range>
|
||||
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': // TODO
|
||||
/* TODO: FODS Properties */
|
||||
case 'initial-creator':
|
||||
case 'creator':
|
||||
case 'creation-date':
|
||||
case 'generator':
|
||||
case 'document-statistic':
|
||||
case 'user-defined':
|
||||
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.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': break; // 6.1.8 hyperlink
|
||||
|
||||
/* non-standard */
|
||||
case 'table-protection': break;
|
||||
case 'data-pilot-grand-total': break; // <table:
|
||||
default:
|
||||
if(Rn[2] === 'dc:') break; // TODO: properties
|
||||
if(Rn[2] === 'draw:') break; // TODO: drawing
|
||||
if(Rn[2] === 'style:') break; // TODO: styles
|
||||
if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'loext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'uof:') break; // TODO: uof
|
||||
if(Rn[2] === '表:') break; // TODO: uof
|
||||
if(Rn[2] === '字:') break; // TODO: uof
|
||||
if(opts.WTF) throw Rn;
|
||||
}
|
||||
var out = {
|
||||
Sheets: Sheets,
|
||||
SheetNames: SheetNames
|
||||
};
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var write_ws = function(ws, wb, i, opts) {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
|
||||
var R=0,C=0, range = get_utils().decode_range(ws['!ref']);
|
||||
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 ref = get_utils().encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
|
||||
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
case 's': case 'str': o.push(' <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
//case 'd': // TODO
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
o.push(' </table:table>\n');
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
return function wcx(wb, opts) {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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:table="urn:oasis:names:tc:opendocument:xmlns:table: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:config="urn:oasis:names:tc:opendocument:xmlns:config: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: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" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
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("");
|
||||
};
|
||||
})();
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip, opts) {
|
||||
opts = opts || ({});
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
|
||||
function parse_fods(data, opts) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
function write_ods(wb, opts) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
ODS.parse_ods = parse_ods;
|
||||
ODS.write_ods = write_ods;
|
||||
ODS.parse_fods = parse_fods;
|
||||
})(typeof exports !== 'undefined' ? exports : ODS);
|
@ -1 +0,0 @@
|
||||
*.js
|
@ -1,6 +0,0 @@
|
||||
/* ods.js (C) 2014-present SheetJS -- http://sheetjs.com */
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
var ODS = {};
|
||||
(function make_ods(ODS) {
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
@ -1,10 +0,0 @@
|
||||
/*:: declare var XLSX: any; */
|
||||
var get_utils = function() {
|
||||
if(typeof XLSX !== 'undefined') return XLSX.utils;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') try {
|
||||
return require('../xlsx.js').utils;
|
||||
} catch(e) {
|
||||
return require('./xlsx.js').utils;
|
||||
}
|
||||
throw new Error("Cannot find XLSX utils");
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
var has_buf = (typeof Buffer !== 'undefined');
|
||||
|
||||
function cc2str(arr)/*:string*/ {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
return o;
|
||||
}
|
||||
|
||||
function dup(o/*:any*/)/*:any*/ {
|
||||
if(typeof JSON != 'undefined') return JSON.parse(JSON.stringify(o));
|
||||
if(typeof o != 'object' || !o) return o;
|
||||
var out = {};
|
||||
for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
|
||||
return out;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
function getdatastr(data)/*:?string*/ {
|
||||
if(!data) return null;
|
||||
if(data.data) return data.data;
|
||||
if(data.asNodeBuffer && has_buf) return data.asNodeBuffer().toString('binary');
|
||||
if(data.asBinary) return data.asBinary();
|
||||
if(data._data && data._data.getContent) return cc2str(Array.prototype.slice.call(data._data.getContent(),0));
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ODS and friends only use text files in container */
|
||||
function getdata(data) { return getdatastr(data); }
|
||||
|
||||
/* NOTE: unlike ECMA-376, OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file/*:string*/) {
|
||||
var f = file; if(zip.files[f]) return zip.files[f];
|
||||
f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
|
||||
f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
|
||||
return null;
|
||||
}
|
||||
|
||||
function getzipfile(zip, file/*:string*/) {
|
||||
var o = safegetzipfile(zip, file);
|
||||
if(o == null) throw new Error("Cannot find file " + file + " in zip");
|
||||
return o;
|
||||
}
|
||||
|
||||
function getzipdata(zip, file/*:string*/, safe/*:?boolean*/) {
|
||||
if(!safe) return getdata(getzipfile(zip, file));
|
||||
if(!file) return null;
|
||||
try { return getzipdata(zip, file); } catch(e) { return null; }
|
||||
}
|
||||
|
||||
var _fs, jszip;
|
||||
/*:: declare var JSZip:any; */
|
||||
if(typeof JSZip !== 'undefined') jszip = JSZip;
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
|
||||
_fs = require('fs');
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
var attregexg=/[^\s?>\/]+=["'][^"]*['"]/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag, skip_root) {
|
||||
var z/*:any*/ = [];
|
||||
var eq = 0, c = 0;
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) {
|
||||
if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_"));
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
if(z[k] && q.substr(j-3,3) == "ext") continue;
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
|
||||
|
||||
var encodings = {
|
||||
'"': '"',
|
||||
''': "'",
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencoding = {
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
'&': '&'
|
||||
};
|
||||
var rencstr = "&<>'\"".split("");
|
||||
|
||||
// TODO: CP remap (need to read file version to determine OS)
|
||||
/* 22.4.2.4 bstr (Basic String) */
|
||||
var encregex = /&[a-z]*;/g, coderegex = /_x([\da-fA-F]{4})_/g;
|
||||
function unescapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(encregex, function($$) { return encodings[$$]; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
|
||||
}
|
||||
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
|
||||
function escapexml(text){
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).substr(-4) + "_";});
|
||||
}
|
||||
|
||||
function parsexmlbool(value) {
|
||||
switch(value) {
|
||||
case '1': case 'true': case 'TRUE': return true;
|
||||
/* case '0': case 'false': case 'FALSE':*/
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
var epoch = v.getTime();
|
||||
if(date1904) epoch += 1462*24*60*60*1000;
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
|
@ -1,9 +0,0 @@
|
||||
/* copied from js-xls (C) SheetJS Apache2 license */
|
||||
function xlml_normalize(d)/*:string*/ {
|
||||
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(typeof d === 'string') return d;
|
||||
throw "badf";
|
||||
}
|
||||
|
||||
/* UOS uses CJK in tags, original regex /<(\/?)([a-z0-9]*:|)([\w-]+)[^>]*>/ */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
@ -1,26 +0,0 @@
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base/*:string*/, file/*:string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
var utf8read = function utf8reada(orig/*:string*/)/*:string*/ {
|
||||
var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
|
||||
while (i < orig.length) {
|
||||
c = orig.charCodeAt(i++);
|
||||
if (c < 128) { out += String.fromCharCode(c); continue; }
|
||||
d = orig.charCodeAt(i++);
|
||||
if (c>191 && c<224) { out += String.fromCharCode(((c & 31) << 6) | (d & 63)); continue; }
|
||||
e = orig.charCodeAt(i++);
|
||||
if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
|
||||
f = orig.charCodeAt(i++);
|
||||
w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
|
||||
out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
|
||||
out += String.fromCharCode(0xDC00 + (w&1023));
|
||||
}
|
||||
return out;
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
ODS.parse_ods = parse_ods;
|
||||
ODS.write_ods = write_ods;
|
||||
ODS.parse_fods = parse_fods;
|
@ -1 +0,0 @@
|
||||
})(typeof exports !== 'undefined' ? exports : ODS);
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.8.8",
|
||||
"version": "0.9.0",
|
||||
"author": "sheetjs",
|
||||
"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS (ODS/FODS/UOS) spreadsheet parser and writer",
|
||||
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],
|
||||
@ -11,8 +11,7 @@
|
||||
"browser": {
|
||||
"node": false,
|
||||
"crypto": false,
|
||||
"fs": false,
|
||||
"../xlsx.js": false
|
||||
"fs": false
|
||||
},
|
||||
"dependencies": {
|
||||
"exit-on-epipe":"",
|
||||
|
50
test.js
50
test.js
@ -206,9 +206,11 @@ describe('should parse test files', function() {
|
||||
|
||||
describe('parse options', function() {
|
||||
var html_cell_types = ['s'];
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
describe('cell', function() {
|
||||
it('XLSX should generate HTML by default', function() {
|
||||
var wb = X.readFile(paths.cstxlsx);
|
||||
@ -491,14 +493,22 @@ describe('input formats', function() {
|
||||
|
||||
describe('output formats', function() {
|
||||
var wb1, wb2, wb3, wb4;
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.cpxlsx);
|
||||
wb2 = X.readFile(paths.cpxlsb);
|
||||
wb3 = X.readFile(paths.cpxls);
|
||||
wb4 = X.readFile(paths.cpxml);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it('should write binary strings', function() {
|
||||
if(!wb1) {
|
||||
wb1 = X.readFile(paths.cpxlsx);
|
||||
wb2 = X.readFile(paths.cpxlsb);
|
||||
wb3 = X.readFile(paths.cpxls);
|
||||
wb4 = X.readFile(paths.cpxml);
|
||||
}
|
||||
X.write(wb1, {type: 'binary'});
|
||||
X.write(wb2, {type: 'binary'});
|
||||
X.write(wb3, {type: 'binary'});
|
||||
@ -603,12 +613,14 @@ describe('parse features', function() {
|
||||
|
||||
describe('should parse core properties and custom properties', function() {
|
||||
var wb1, wb2;
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
wb1 = X.readFile(paths.cpxlsx);
|
||||
wb2 = X.readFile(paths.cpxlsb);
|
||||
wb3 = X.readFile(paths.cpxls);
|
||||
wb4 = X.readFile(paths.cpxml);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
|
||||
it(N1 + ' should parse core properties', function() { coreprop(wb1); });
|
||||
it(N2 + ' should parse core properties', function() { coreprop(wb2); });
|
||||
@ -658,8 +670,8 @@ describe('parse features', function() {
|
||||
});
|
||||
|
||||
describe('merge cells',function() {
|
||||
var wb1, wb2;
|
||||
before(function() {
|
||||
var wb1, wb2, wb3, wb4, wb5;
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.mcxlsx);
|
||||
wb2 = X.readFile(paths.mcxlsb);
|
||||
@ -667,6 +679,8 @@ describe('parse features', function() {
|
||||
wb4 = X.readFile(paths.mcxls);
|
||||
wb5 = X.readFile(paths.mcxml);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it('should have !merges', function() {
|
||||
assert(wb1.Sheets.Merge['!merges']);
|
||||
assert(wb2.Sheets.Merge['!merges']);
|
||||
@ -682,14 +696,16 @@ describe('parse features', function() {
|
||||
});
|
||||
|
||||
describe('should find hyperlinks', function() {
|
||||
var wb1, wb2;
|
||||
before(function() {
|
||||
var wb1, wb2, wb3, wb4;
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
wb1 = X.readFile(paths.hlxlsx);
|
||||
wb2 = X.readFile(paths.hlxlsb);
|
||||
wb3 = X.readFile(paths.hlxls);
|
||||
wb4 = X.readFile(paths.hlxml);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
|
||||
function hlink(wb) {
|
||||
var ws = wb.Sheets.Sheet1;
|
||||
@ -730,7 +746,7 @@ describe('parse features', function() {
|
||||
|
||||
describe('should correctly handle styles', function() {
|
||||
var wsxls, wsxlsx, rn, rn2;
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
wsxls=X.readFile(paths.cssxls, {cellStyles:true,WTF:1}).Sheets.Sheet1;
|
||||
wsxlsx=X.readFile(paths.cssxlsx, {cellStyles:true,WTF:1}).Sheets.Sheet1;
|
||||
rn = function(range) {
|
||||
@ -742,6 +758,8 @@ describe('parse features', function() {
|
||||
};
|
||||
rn2 = function(r) { return [].concat.apply([], r.split(",").map(rn)); };
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
var ranges = [
|
||||
'A1:D1,F1:G1', 'A2:D2,F2:G2', /* rows */
|
||||
'A3:A10', 'B3:B10', 'E1:E10', 'F6:F8', /* cols */
|
||||
@ -812,12 +830,14 @@ function seq(end, start) {
|
||||
}
|
||||
|
||||
describe('roundtrip features', function() {
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
X = require(modp);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
describe('should parse core properties and custom properties', function() {
|
||||
var wb1, wb2, base = './tmp/cp';
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
wb1 = X.readFile(paths.cpxlsx);
|
||||
wb2 = X.readFile(paths.cpxlsb);
|
||||
fullex.forEach(function(p) {
|
||||
@ -825,6 +845,8 @@ describe('roundtrip features', function() {
|
||||
X.writeFile(wb2, base + '.xlsb' + p);
|
||||
});
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
fullex.forEach(function(p) { ['.xlsm','.xlsb'].forEach(function(q) {
|
||||
it(q + p + ' should roundtrip core and custom properties', function() {
|
||||
var wb = X.readFile(base + q + p);
|
||||
@ -973,7 +995,7 @@ describe('json output', function() {
|
||||
}
|
||||
}
|
||||
var data, ws;
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
data = [
|
||||
[1,2,3],
|
||||
[true, false, null, "sheetjs"],
|
||||
@ -982,6 +1004,8 @@ describe('json output', function() {
|
||||
];
|
||||
ws = sheet_from_array_of_arrays(data);
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
it('should use first-row headers and full sheet by default', function() {
|
||||
var json = X.utils.sheet_to_json(ws);
|
||||
assert.equal(json.length, data.length - 1);
|
||||
@ -1037,7 +1061,7 @@ describe('json output', function() {
|
||||
|
||||
describe('js -> file -> js', function() {
|
||||
var data, ws, wb, BIN="binary";
|
||||
before(function() {
|
||||
var bef = (function() {
|
||||
data = [
|
||||
[1,2,3],
|
||||
[true, false, null, "sheetjs"],
|
||||
@ -1047,6 +1071,8 @@ describe('js -> file -> js', function() {
|
||||
ws = sheet_from_array_of_arrays(data);
|
||||
wb = { SheetNames: ['Sheet1'], Sheets: {Sheet1: ws} };
|
||||
});
|
||||
if(typeof before != 'undefined') before(bef);
|
||||
else it('before', bef);
|
||||
function eqcell(wb1, wb2, s, a) {
|
||||
assert.equal(wb1.Sheets[s][a].v, wb2.Sheets[s][a].v);
|
||||
assert.equal(wb1.Sheets[s][a].t, wb2.Sheets[s][a].t);
|
||||
|
173
tests.lst
173
tests.lst
@ -11,6 +11,7 @@ custom_properties.xlsb
|
||||
defined_names_simple.xlsb
|
||||
formula_stress_test.xlsb
|
||||
formulae_test_simple.xlsb
|
||||
hyperlink_no_rels.xlsb
|
||||
hyperlink_stress_test_2011.xlsb
|
||||
large_strings.xlsb.pending
|
||||
merge_cells.xlsb
|
||||
@ -19,6 +20,7 @@ number_format.xlsb
|
||||
number_format_entities.xlsb
|
||||
number_format_russian.xlsb
|
||||
numfmt_1_russian.xlsb
|
||||
phonetic_text.xlsb
|
||||
pivot_table_named_range.xlsb
|
||||
pivot_table_test.xlsb
|
||||
rich_text_stress.xlsb
|
||||
@ -65,6 +67,7 @@ apachepoi_48539.xlsx
|
||||
apachepoi_48703.xlsx
|
||||
apachepoi_48779.xlsx
|
||||
apachepoi_48923.xlsx
|
||||
apachepoi_48962.xlsx
|
||||
apachepoi_49156.xlsx
|
||||
apachepoi_49273.xlsx
|
||||
apachepoi_49325.xlsx
|
||||
@ -75,6 +78,7 @@ apachepoi_49928.xlsx
|
||||
apachepoi_49966.xlsx
|
||||
apachepoi_50096.xlsx
|
||||
apachepoi_50299.xlsx
|
||||
apachepoi_50755_workday_formula_example.xlsx
|
||||
apachepoi_50784-font_theme_colours.xlsx
|
||||
apachepoi_50786-indexed_colours.xlsx
|
||||
apachepoi_50795.xlsx
|
||||
@ -82,14 +86,20 @@ apachepoi_50846-border_colours.xlsx
|
||||
apachepoi_50867_with_table.xlsx
|
||||
apachepoi_51222.xlsx
|
||||
apachepoi_51470.xlsx
|
||||
apachepoi_51519.xlsx
|
||||
apachepoi_51585.xlsx
|
||||
apachepoi_51626.xlsx
|
||||
apachepoi_51626_contact.xlsx
|
||||
apachepoi_51710.xlsx
|
||||
apachepoi_51850.xlsx
|
||||
apachepoi_51963.xlsx
|
||||
apachepoi_51998.xlsx
|
||||
apachepoi_52348.xlsx
|
||||
apachepoi_52425.xlsx
|
||||
apachepoi_52575_main.xlsx
|
||||
apachepoi_52716.xlsx
|
||||
apachepoi_53101.xlsx
|
||||
apachepoi_53105.xlsx
|
||||
apachepoi_53282.xlsx
|
||||
apachepoi_53282b.xlsx
|
||||
apachepoi_53568.xlsx
|
||||
@ -102,11 +112,13 @@ apachepoi_54084 - Greek - beyond BMP.xlsx
|
||||
apachepoi_54206.xlsx
|
||||
apachepoi_54288-ref.xlsx
|
||||
apachepoi_54288.xlsx
|
||||
apachepoi_54399.xlsx
|
||||
apachepoi_54436.xlsx
|
||||
apachepoi_54524.xlsx
|
||||
apachepoi_54607.xlsx
|
||||
apachepoi_54764-2.xlsx
|
||||
apachepoi_54764.xlsx
|
||||
apachepoi_55406_Conditional_formatting_sample.xlsx
|
||||
apachepoi_55640.xlsx
|
||||
apachepoi_55745.xlsx
|
||||
apachepoi_55850.xlsx
|
||||
@ -122,47 +134,105 @@ apachepoi_56169.xlsx
|
||||
apachepoi_56170.xlsx
|
||||
apachepoi_56274.xlsx
|
||||
apachepoi_56278.xlsx
|
||||
apachepoi_56295.xlsx
|
||||
apachepoi_56315.xlsx
|
||||
apachepoi_56420.xlsx
|
||||
apachepoi_56502.xlsx
|
||||
apachepoi_56511.xlsx
|
||||
apachepoi_56514.xlsx
|
||||
apachepoi_56574.xlsx
|
||||
apachepoi_56644.xlsx
|
||||
apachepoi_56688_1.xlsx
|
||||
apachepoi_56688_2.xlsx
|
||||
apachepoi_56688_3.xlsx
|
||||
apachepoi_56688_4.xlsx
|
||||
# apachepoi_56702.xlsx ## xlsb bad xnum
|
||||
apachepoi_56702.xlsx
|
||||
apachepoi_56730.xlsx
|
||||
apachepoi_56737.xlsx
|
||||
apachepoi_56822-Countifs.xlsx
|
||||
apachepoi_56957.xlsx
|
||||
apachepoi_57171_57163_57165.xlsx
|
||||
apachepoi_57176.xlsx
|
||||
apachepoi_57196.xlsx
|
||||
apachepoi_57236.xlsx
|
||||
apachepoi_57362.xlsx
|
||||
apachepoi_57423.xlsx
|
||||
apachepoi_57482-OnlyNumeric.xlsx
|
||||
apachepoi_57523.xlsx
|
||||
apachepoi_57535.xlsx
|
||||
apachepoi_57798.xlsx
|
||||
apachepoi_57826.xlsx
|
||||
apachepoi_57828.xlsx
|
||||
apachepoi_57838.xlsx
|
||||
apachepoi_57890.xlsx
|
||||
apachepoi_57893-many-merges.xlsx.pending
|
||||
apachepoi_57914.xlsx
|
||||
apachepoi_58315.xlsx
|
||||
apachepoi_58325_db.xlsx
|
||||
apachepoi_58325_lt.xlsx
|
||||
# apachepoi_58616.xlsx # Cannot find Workbook stream
|
||||
apachepoi_58648.xlsx
|
||||
apachepoi_58731.xlsx
|
||||
apachepoi_58747.xlsx
|
||||
apachepoi_58760.xlsx
|
||||
apachepoi_59021.xlsx
|
||||
apachepoi_59026.xlsx
|
||||
apachepoi_59106.xlsx
|
||||
apachepoi_59132.xlsx
|
||||
apachepoi_59264.xlsx
|
||||
apachepoi_59687.xlsx
|
||||
apachepoi_59736.xlsx
|
||||
apachepoi_59746_NoRowNums.xlsx
|
||||
apachepoi_59775.xlsx
|
||||
apachepoi_60255_extra_drawingparts.xlsx
|
||||
apachepoi_60289.xlsx
|
||||
#apachepoi_60825.xlsx # Missing worksheet xml file
|
||||
apachepoi_AverageTaxRates.xlsx
|
||||
apachepoi_Booleans.xlsx
|
||||
apachepoi_BrNotClosed.xlsx
|
||||
apachepoi_ConditionalFormattingSamples.xlsx
|
||||
apachepoi_CustomXMLMapping-singleattributenamespace.xlsx
|
||||
apachepoi_CustomXMLMappings-complex-type.xlsx
|
||||
apachepoi_CustomXMLMappings.xlsx
|
||||
apachepoi_CustomXmlMappings-inverse-order.xlsx
|
||||
apachepoi_DataTableCities.xlsx
|
||||
apachepoi_DataValidationEvaluations.xlsx
|
||||
apachepoi_DataValidations-49244.xlsx
|
||||
apachepoi_DateFormatTests.xlsx
|
||||
apachepoi_ElapsedFormatTests.xlsx
|
||||
apachepoi_ExcelTables.xlsx
|
||||
apachepoi_ForShifting.xlsx
|
||||
apachepoi_FormatChoiceTests.xlsx
|
||||
apachepoi_FormatConditionTests.xlsx
|
||||
apachepoi_FormatKM.xlsx
|
||||
apachepoi_Formatting.xlsx
|
||||
apachepoi_FormulaEvalTestData_Copy.xlsx
|
||||
apachepoi_FormulaSheetRange.xlsx
|
||||
apachepoi_GeneralFormatTests.xlsx
|
||||
apachepoi_GroupTest.xlsx
|
||||
apachepoi_InlineStrings.xlsx
|
||||
apachepoi_Intersection-52111-xssf.xlsx
|
||||
apachepoi_NewStyleConditionalFormattings.xlsx
|
||||
apachepoi_NewlineInFormulas.xlsx
|
||||
apachepoi_NumberFormatApproxTests.xlsx
|
||||
apachepoi_NumberFormatTests.xlsx
|
||||
apachepoi_RepeatingRowsCols.xlsx
|
||||
apachepoi_SampleSS.strict.xlsx
|
||||
apachepoi_SampleSS.xlsx
|
||||
apachepoi_SheetTabColors.xlsx
|
||||
apachepoi_ShrinkToFit.xlsx
|
||||
apachepoi_SimpleMultiCell.xlsx
|
||||
apachepoi_SimpleNormal.xlsx
|
||||
apachepoi_SimpleScatterChart.xlsx
|
||||
apachepoi_SimpleStrict.xlsx
|
||||
apachepoi_SimpleWithComments.xlsx
|
||||
apachepoi_StructuredReferences.xlsx
|
||||
apachepoi_StructuredRefs-lots-with-lookups.xlsx
|
||||
apachepoi_Tables.xlsx
|
||||
apachepoi_TestShiftRowSharedFormula.xlsx
|
||||
apachepoi_TextFormatTests.xlsx
|
||||
apachepoi_Themes.xlsx
|
||||
apachepoi_Themes2.xlsx
|
||||
apachepoi_TwoSheetsNoneHidden.xlsx
|
||||
apachepoi_TwoSheetsOneHidden.xlsx
|
||||
apachepoi_WithChart.xlsx
|
||||
@ -177,21 +247,34 @@ apachepoi_WithTextBox2.xlsx
|
||||
apachepoi_WithThreeCharts.xlsx
|
||||
apachepoi_WithTwoCharts.xlsx
|
||||
apachepoi_WithVariousData.xlsx
|
||||
apachepoi_XSSFSheet.copyRows.xlsx
|
||||
apachepoi_atp.xlsx
|
||||
apachepoi_chartTitle_noTitle.xlsx
|
||||
apachepoi_chartTitle_withTitle.xlsx
|
||||
apachepoi_chart_sheet.xlsx.pending
|
||||
apachepoi_commentTest.xlsx
|
||||
apachepoi_comments.xlsx
|
||||
apachepoi_craftonhills.edu_programreview_report.aspx_goalpriorityreport_0011d159-1eeb-4b63-8833-867b0926e5f3.xlsx
|
||||
apachepoi_evaluate_formula_with_structured_table_references.xlsx
|
||||
apachepoi_headerFooterTest.xlsx
|
||||
apachepoi_noSharedStringTable.xlsx
|
||||
apachepoi_picture.xlsx
|
||||
apachepoi_poc-shared-strings.xlsx
|
||||
apachepoi_poc-xmlbomb.xlsx
|
||||
# apachepoi_protected_passtika.xlsx # password
|
||||
apachepoi_ref-56737.xlsx
|
||||
apachepoi_ref2-56737.xlsx
|
||||
apachepoi_reordered_sheets.xlsx
|
||||
apachepoi_resize_compare.xlsx
|
||||
apachepoi_sample-beta.xlsx
|
||||
apachepoi_sample.strict.xlsx
|
||||
apachepoi_sample.xlsx
|
||||
apachepoi_shared_formulas.xlsx
|
||||
apachepoi_sheetProtection_allLocked.xlsx
|
||||
apachepoi_sheetProtection_not_protected.xlsx
|
||||
apachepoi_styles.xlsx
|
||||
apachepoi_template.xlsx
|
||||
apachepoi_unicodeSheetName.xlsx
|
||||
apachepoi_workbookProtection-sheet_password-2013.xlsx
|
||||
apachepoi_workbookProtection-workbook_password-2013.xlsx
|
||||
apachepoi_workbookProtection-workbook_password_user_range-2010.xlsx
|
||||
@ -219,6 +302,7 @@ excel-reader-xlsx_inline01.xlsx
|
||||
excel-reader-xlsx_libre01.xlsx
|
||||
formula_stress_test.xlsx
|
||||
formulae_test_simple.xlsx
|
||||
hyperlink_no_rels.xlsx
|
||||
hyperlink_stress_test_2011.xlsx
|
||||
interview.xlsx
|
||||
issue.xlsx
|
||||
@ -260,6 +344,7 @@ openpyxl_g_empty_with_no_properties.xlsx
|
||||
openpyxl_g_guess_types.xlsx
|
||||
openpyxl_g_libreoffice_nrt.xlsx
|
||||
openpyxl_g_merge_range.xlsx
|
||||
openpyxl_g_sample.xlsx
|
||||
openpyxl_r_bigfoot.xlsx
|
||||
openpyxl_r_bug137.xlsx
|
||||
openpyxl_r_bug275.xlsx
|
||||
@ -271,8 +356,10 @@ openpyxl_r_contains_chartsheets.xlsx.pending
|
||||
openpyxl_r_date_1900.xlsx
|
||||
openpyxl_r_date_1904.xlsx
|
||||
openpyxl_r_formulae.xlsx
|
||||
openpyxl_r_nonstandard_workbook_name.xlsx
|
||||
openpyxl_r_null_archive.xlsx.pending
|
||||
openpyxl_r_null_file.xlsx.pending
|
||||
phonetic_text.xlsx
|
||||
pivot_table_named_range.xlsx
|
||||
rich_text_stress.xlsx
|
||||
roo_1900_base.xlsx
|
||||
@ -283,25 +370,39 @@ roo_bbu.xlsx
|
||||
roo_boolean.xlsx
|
||||
roo_borders.xlsx
|
||||
roo_bug-numbered-sheet-names.xlsx
|
||||
roo_chart_sheet.xlsx
|
||||
roo_comments-google.xlsx
|
||||
roo_comments.xlsx
|
||||
roo_datetime.xlsx
|
||||
roo_emptysheets.xlsx
|
||||
roo_file_item_error.xlsx
|
||||
roo_formula.xlsx
|
||||
roo_formula_cell_types.xlsx
|
||||
roo_formula_string_error.xlsx
|
||||
roo_header_offset.xlsx
|
||||
roo_hidden_sheets.xlsx
|
||||
roo_html_strings_formatting.xlsx
|
||||
roo_link.xlsx
|
||||
roo_merged_ranges.xlsx
|
||||
roo_name_with_leading_slash.xlsx
|
||||
roo_named_cells.xlsx
|
||||
roo_numbers-export.xlsx
|
||||
roo_numbers1.xlsx
|
||||
roo_numbers1withnull.xlsx
|
||||
roo_numeric-link.xlsx
|
||||
roo_only_one_sheet.xlsx
|
||||
roo_paragraph.xlsx
|
||||
roo_parse_clean_with_unicode.xlsx
|
||||
roo_parse_with_clean_option.xlsx
|
||||
roo_simple_spreadsheet.xlsx
|
||||
roo_style.xlsx
|
||||
roo_style_nodes_with_white_spaces.xlsx
|
||||
roo_time-test.xlsx
|
||||
roo_type_excel.xlsx.pending
|
||||
roo_type_openoffice.xlsx.pending
|
||||
# roo_type_excel.xlsx # incorrect baseline
|
||||
# roo_type_openoffice.xlsx # incorrect baseline
|
||||
roo_whitespace.xlsx
|
||||
roo_x000D.xlsx
|
||||
roo_zero-padded-number.xlsx
|
||||
smart_tags_2007.xlsx
|
||||
spreadsheet-parsexlsx_Test.xlsx
|
||||
spreadsheet-parsexlsx_bug-10.xlsx
|
||||
@ -310,23 +411,45 @@ spreadsheet-parsexlsx_bug-12.xlsx
|
||||
spreadsheet-parsexlsx_bug-13.xlsx
|
||||
spreadsheet-parsexlsx_bug-14.xlsx
|
||||
spreadsheet-parsexlsx_bug-15.xlsx
|
||||
spreadsheet-parsexlsx_bug-16.xlsx
|
||||
spreadsheet-parsexlsx_bug-17a.xlsx
|
||||
spreadsheet-parsexlsx_bug-17b.xlsx
|
||||
spreadsheet-parsexlsx_bug-2.xlsx
|
||||
spreadsheet-parsexlsx_bug-29.xlsx
|
||||
spreadsheet-parsexlsx_bug-3.xlsx
|
||||
spreadsheet-parsexlsx_bug-32-2.xlsx
|
||||
spreadsheet-parsexlsx_bug-32.xlsx
|
||||
spreadsheet-parsexlsx_bug-38.xlsx
|
||||
spreadsheet-parsexlsx_bug-4.xlsx
|
||||
spreadsheet-parsexlsx_bug-41.xlsx
|
||||
spreadsheet-parsexlsx_bug-5.xlsx
|
||||
spreadsheet-parsexlsx_bug-57.xlsx
|
||||
spreadsheet-parsexlsx_bug-6-2.xlsx
|
||||
spreadsheet-parsexlsx_bug-6.xlsx
|
||||
spreadsheet-parsexlsx_bug-61.xlsx
|
||||
spreadsheet-parsexlsx_bug-7.xlsx
|
||||
spreadsheet-parsexlsx_bug-8.xlsx
|
||||
spreadsheet-parsexlsx_bug-lock.xlsx
|
||||
spreadsheet-parsexlsx_column-formats.xlsx
|
||||
# spreadsheet-parsexlsx_encryption-agile-123q.xlsx
|
||||
# spreadsheet-parsexlsx_encryption-standard-default-password.xlsx
|
||||
spreadsheet-parsexlsx_hidden-row-and-column.xlsx
|
||||
spreadsheet-parsexlsx_hidden-sheet.xlsx
|
||||
spreadsheet-parsexlsx_page-Setup.xlsx
|
||||
spreadsheet-parsexlsx_tab-color.xlsx
|
||||
spreadsheet-parsexlsx_target-abspath.xlsx
|
||||
sushi.xlsx
|
||||
text_and_numbers.xlsx
|
||||
write.xlsx
|
||||
xlrd_apachepoi_49609.xlsx
|
||||
xlrd_apachepoi_52348.xlsx
|
||||
xlrd_err_cell_empty.xlsx
|
||||
xlrd_issue150.xlsx
|
||||
xlrd_merged_cells.xlsx
|
||||
xlrd_reveng1.xlsx
|
||||
xlrd_self_evaluation_report_2014-05-19.xlsx
|
||||
xlrd_test_comments_excel.xlsx
|
||||
xlrd_test_comments_excel_sheet2.xlsx
|
||||
xlrd_test_comments_gdocs.xlsx
|
||||
xlrd_text_bar.xlsx
|
||||
xlsx-stream-d-date-cell.xlsx
|
||||
@ -336,14 +459,49 @@ NumberFormatCondition.xlsm
|
||||
apachepoi_45431.xlsm
|
||||
apachepoi_47026.xlsm
|
||||
apachepoi_47089.xlsm
|
||||
apachepoi_57181.xlsm
|
||||
apachepoi_60512.xlsm
|
||||
apachepoi_ExcelWithAttachments.xlsm
|
||||
apachepoi_SimpleMacro.xlsm
|
||||
apachepoi_mv-calculator-final-2-20-2013.xlsm
|
||||
apachepoi_testNames.xlsm
|
||||
hyperlink_no_rels.xlsm
|
||||
number_format.xlsm
|
||||
number_format_russian.xlsm
|
||||
numfmt_1_russian.xlsm
|
||||
openpyxl_r_vba+comments.xlsm
|
||||
openpyxl_r_vba-comments-saved.xlsm
|
||||
openpyxl_r_vba-test.xlsm
|
||||
pivot_table_test.xlsm
|
||||
roo_1900_base.xlsm
|
||||
roo_1904_base.xlsm
|
||||
roo_Bibelbund.xlsm
|
||||
roo_Pfand_from_windows_phone.xlsm
|
||||
roo_bbu.xlsm
|
||||
roo_boolean.xlsm
|
||||
roo_borders.xlsm
|
||||
roo_bug-numbered-sheet-names.xlsm
|
||||
roo_comments.xlsm
|
||||
roo_datetime.xlsm
|
||||
roo_emptysheets.xlsm
|
||||
roo_file_item_error.xlsm
|
||||
roo_formula.xlsm
|
||||
roo_formula_string_error.xlsm
|
||||
roo_link.xlsm
|
||||
roo_named_cells.xlsm
|
||||
roo_numbers1.xlsm
|
||||
roo_numeric-link.xlsm
|
||||
roo_only_one_sheet.xlsm
|
||||
roo_paragraph.xlsm
|
||||
roo_simple_spreadsheet.xlsm
|
||||
roo_style.xlsm
|
||||
roo_time-test.xlsm
|
||||
roo_type_excel.xlsm
|
||||
roo_type_openoffice.xlsm
|
||||
roo_whitespace.xlsm
|
||||
AutoFilter.ods
|
||||
BlankSheetTypes.ods
|
||||
apachepoi_SampleSS.ods
|
||||
cell_style_simple.ods
|
||||
formula_stress_test.ods
|
||||
merge_cells.ods
|
||||
@ -351,6 +509,7 @@ number_format.ods
|
||||
rich_text_stress.ods
|
||||
roo_Bibelbund.ods
|
||||
roo_Bibelbund1.ods
|
||||
roo_advanced_header.ods
|
||||
roo_bbu.ods
|
||||
roo_boolean.ods
|
||||
roo_borders.ods
|
||||
@ -358,7 +517,9 @@ roo_comments.ods
|
||||
roo_datetime.ods
|
||||
roo_dreimalvier.ods
|
||||
roo_emptysheets.ods
|
||||
roo_encrypted-letmein.ods
|
||||
roo_formula.ods
|
||||
roo_hidden_sheets.ods
|
||||
roo_html-escape.ods
|
||||
roo_matrix.ods
|
||||
roo_named_cells.ods
|
||||
@ -370,7 +531,7 @@ roo_simple_spreadsheet.ods
|
||||
roo_simple_spreadsheet_from_italo.ods
|
||||
roo_style.ods
|
||||
roo_time-test.ods
|
||||
roo_type_excel.ods.pending
|
||||
roo_type_excel.ods
|
||||
roo_type_excelx.ods
|
||||
roo_whitespace.ods
|
||||
sushi.ods
|
||||
@ -956,8 +1117,8 @@ roo_simple_spreadsheet.xls
|
||||
roo_simple_spreadsheet_from_italo.xls
|
||||
roo_style.xls
|
||||
roo_time-test.xls
|
||||
roo_type_excelx.xls.pending
|
||||
roo_type_openoffice.xls.pending
|
||||
roo_type_excelx.xls
|
||||
roo_type_openoffice.xls
|
||||
roo_whitespace.xls
|
||||
smart_tags_2007.xls
|
||||
sushi.xls
|
||||
|
629
xlsx.flow.js
629
xlsx.flow.js
@ -2,9 +2,10 @@
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true */
|
||||
/*exported XLSX */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.8.8';
|
||||
XLSX.version = '0.9.0';
|
||||
var current_codepage = 1200, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
|
||||
@ -1340,6 +1341,33 @@ function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
function cc2str(arr/*:Array<number>*/)/*:string*/ {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
@ -1385,6 +1413,7 @@ function getdatabin(data) {
|
||||
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
|
||||
|
||||
/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
|
||||
/* OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file/*:string*/) {
|
||||
var k = keys(zip.files);
|
||||
var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
|
||||
@ -1422,7 +1451,7 @@ if (typeof exports !== 'undefined') {
|
||||
_fs = require('fs');
|
||||
}
|
||||
}
|
||||
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var attregexg=/([^\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
|
||||
@ -1431,14 +1460,21 @@ function parsexmltag(tag/*:string*/, skip_root/*:?boolean*/)/*:any*/ {
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) z[q] = v;
|
||||
else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
|
||||
if(j===q.length) {
|
||||
//if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
//if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
@ -2682,6 +2718,63 @@ function write_rels(rels)/*:string*/ {
|
||||
if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest/*:Array<Array<string> >*/, opts)/*:string*/ {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file/*:string*/, res/*:string*/, tag/*:?string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base/*:string*/, file/*:string*/) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
/* ECMA-376 Part II 11.1 Core Properties Part */
|
||||
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
|
||||
var CORE_PROPS/*:Array<Array<string> >*/ = [
|
||||
@ -7875,6 +7968,17 @@ var XLSXFutureFunctions = {
|
||||
"_xlfn.Z.TEST": "Z.TEST"
|
||||
};
|
||||
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f/*:string*/)/*:string*/ {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var strs = {}; // shared strings
|
||||
var _ssfopts = {}; // spreadsheet formatting options
|
||||
|
||||
@ -8183,6 +8287,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
case 'n': p.v = parseFloat(p.v); break;
|
||||
case 's':
|
||||
sstr = strs[parseInt(p.v, 10)];
|
||||
if(typeof p.v == 'undefined') {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
}
|
||||
p.v = sstr.t;
|
||||
p.r = sstr.r;
|
||||
if(opts.cellHTML) p.h = sstr.h;
|
||||
@ -9456,6 +9564,7 @@ function process_style_xlml(styles, stag, opts) {
|
||||
function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o)/*:Workbook*/ {
|
||||
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
|
||||
var interiors = [];
|
||||
var i = 0;
|
||||
if(sid === undefined && row) sid = row.StyleID;
|
||||
if(sid === undefined && csty) sid = csty.StyleID;
|
||||
while(styles[sid] !== undefined) {
|
||||
@ -9521,13 +9630,15 @@ function xlml_clean_comment(comment/*:any*/) {
|
||||
}
|
||||
|
||||
function xlml_normalize(d)/*:string*/ {
|
||||
if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(has_buf &&/*::typeof Buffer !== "undefined" && d != null &&*/ Buffer.isBuffer(d)) return d.toString('utf8');
|
||||
if(typeof d === 'string') return d;
|
||||
throw new Error("Bad input format: expected Buffer or string");
|
||||
}
|
||||
|
||||
/* TODO: Everything */
|
||||
var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
/* UOS uses CJK in tags */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
||||
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
function parse_xlml_xml(d, opts)/*:Workbook*/ {
|
||||
var str = debom(xlml_normalize(d));
|
||||
if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts);
|
||||
@ -12189,6 +12300,443 @@ function parse_html(str/*:string*/, opts)/*:Workbook*/ {
|
||||
ws['!ref'] = encode_range(range);
|
||||
return o;
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
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"]
|
||||
};
|
||||
|
||||
return function pcx(d, _opts) {
|
||||
var opts = _opts || {};
|
||||
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>*/ = [], ws = {};
|
||||
var Rn, q/*:: = ({t:"", v:null, z:null, w:""}:any)*/;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag/*:: = {}*/;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
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);
|
||||
if(merges.length) ws['!merges'] = merges;
|
||||
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
|
||||
SheetNames.push(sheetag.name);
|
||||
Sheets[sheetag.name] = ws;
|
||||
}
|
||||
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 = {}; merges = [];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'table-row': case '行': // 9.1.3 <table:table-row>
|
||||
if(Rn[1] === '/') break;
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
|
||||
else ++C;
|
||||
}
|
||||
else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
rept = 1;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
if(R > range.e.r) range.e.r = R;
|
||||
if(C < range.s.c) range.s.c = C;
|
||||
if(R < range.s.r) range.s.r = R;
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null/*:: , z:null, w:""*/}/*:any*/);
|
||||
if(opts.cellFormula) {
|
||||
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']) rept = 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 = 'n'; q.v = datenum(new Date(ctag['date-value'])); 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 = ctag['string-value'];
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {/*:: t:"", v:null, z:null, w:""*/};
|
||||
textp = "";
|
||||
}
|
||||
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>
|
||||
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;
|
||||
|
||||
/* 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 'annotation': // 14.1 <office:annotation>
|
||||
case 'event-listeners': // 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;
|
||||
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 'master-styles': break; // TODO: <office:automatic-styles>
|
||||
|
||||
case 'default-style': // TODO: <style:default-style>
|
||||
case 'page-layout': break; // TODO: <style:page-layout>
|
||||
case 'style': break; // 16.2 <style:style>
|
||||
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 'text-content': break; // 16.27.27 <number:text-content>
|
||||
case 'text-properties': break; // 16.27.27 <style:text-properties>
|
||||
|
||||
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 '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 'named-range': break; // 9.4.12 <table:named-range>
|
||||
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 'span': break; // <text:span>
|
||||
case 'line-break': break; // 6.1.5 <text:line-break>
|
||||
case 'p': case '文本串':
|
||||
if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
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 'table-source': 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 'error-message': break; // 9.4.7 <table:
|
||||
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
|
||||
case 'database-range': break; // 9.4.15 <table:database-range>
|
||||
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': // TODO
|
||||
/* TODO: FODS Properties */
|
||||
case 'initial-creator':
|
||||
case 'creator':
|
||||
case 'creation-date':
|
||||
case 'generator':
|
||||
case 'document-statistic':
|
||||
case 'user-defined':
|
||||
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.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': break; // 6.1.8 hyperlink
|
||||
|
||||
/* non-standard */
|
||||
case 'table-protection': break;
|
||||
case 'data-pilot-grand-total': break; // <table:
|
||||
default:
|
||||
if(Rn[2] === 'dc:') break; // TODO: properties
|
||||
if(Rn[2] === 'draw:') break; // TODO: drawing
|
||||
if(Rn[2] === 'style:') break; // TODO: styles
|
||||
if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'loext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'uof:') break; // TODO: uof
|
||||
if(Rn[2] === '表:') break; // TODO: uof
|
||||
if(Rn[2] === '字:') break; // TODO: uof
|
||||
if(opts.WTF) throw Rn;
|
||||
}
|
||||
var out = {
|
||||
Sheets: Sheets,
|
||||
SheetNames: SheetNames
|
||||
};
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var write_ws = function(ws, wb, i/*:number*/, opts)/*:string*/ {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
|
||||
var R=0,C=0, range = decode_range(ws['!ref']);
|
||||
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 ref = encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
|
||||
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
case 's': case 'str': o.push(' <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
//case 'd': // TODO
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
o.push(' </table:table>\n');
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
return function wcx(wb, opts) {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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:table="urn:oasis:names:tc:opendocument:xmlns:table: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:config="urn:oasis:names:tc:opendocument:xmlns:config: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: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" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
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("");
|
||||
};
|
||||
})();
|
||||
/* actual implementation in utils, wrappers are for read/write */
|
||||
function write_csv_str(wb/*:Workbook*/, o/*:WriteOpts*/) {
|
||||
var idx = 0;
|
||||
@ -12196,26 +12744,49 @@ function write_csv_str(wb/*:Workbook*/, o/*:WriteOpts*/) {
|
||||
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
|
||||
return sheet_to_csv(wb.Sheets[wb.SheetNames[idx]], o);
|
||||
}
|
||||
/* Helper functions to call out to ODS */
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip/*:ZIPFile*/, opts/*:?ParseOpts*/) {
|
||||
opts = opts || ({}/*:any*/);
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data/*:string*/, opts/*:?ParseOpts*/) {
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
function get_ods() {
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./ods.js');
|
||||
return ODS;
|
||||
}
|
||||
function parse_ods(zip, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_ods(zip, opts);
|
||||
}
|
||||
function write_ods(wb, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.write_ods(wb, opts);
|
||||
}
|
||||
function parse_fods(data, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_fods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_fods(data, opts);
|
||||
function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
/*:: if(!jszip) throw new Error("JSZip is not available"); */
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest/*:Array<Array<string> >*/ = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
function fix_opts_func(defaults/*:Array<Array<any> >*/)/*:{(o:any):void}*/ {
|
||||
return function fix_opts(opts) {
|
||||
@ -12833,6 +13404,9 @@ var utils = {
|
||||
sheet_to_row_object_array: sheet_to_row_object_array
|
||||
};
|
||||
XLSX.parse_xlscfb = parse_xlscfb;
|
||||
XLSX.parse_ods = parse_ods;
|
||||
XLSX.parse_fods = parse_fods;
|
||||
XLSX.write_ods = write_ods;
|
||||
XLSX.parse_zip = parse_zip;
|
||||
XLSX.read = readSync; //xlsread
|
||||
XLSX.readFile = readFileSync; //readFile
|
||||
@ -12844,4 +13418,7 @@ XLSX.utils = utils;
|
||||
XLSX.CFB = CFB;
|
||||
XLSX.SSF = SSF;
|
||||
})(typeof exports !== 'undefined' ? exports : XLSX);
|
||||
/*exported XLS */
|
||||
var XLS = XLSX;
|
||||
/*exported ODS */
|
||||
var ODS = XLSX;
|
||||
|
622
xlsx.js
622
xlsx.js
@ -2,9 +2,10 @@
|
||||
/* vim: set ts=2: */
|
||||
/*jshint -W041 */
|
||||
/*jshint funcscope:true, eqnull:true */
|
||||
/*exported XLSX */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.8.8';
|
||||
XLSX.version = '0.9.0';
|
||||
var current_codepage = 1200, current_cptable;
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
if(typeof cptable === 'undefined') cptable = require('./dist/cpexcel.js');
|
||||
@ -1299,6 +1300,33 @@ function datenum(v, date1904) {
|
||||
return (epoch + 2209161600000) / (24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
/* ISO 8601 Duration */
|
||||
function parse_isodur(s) {
|
||||
var sec = 0, mt = 0, time = false;
|
||||
var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
|
||||
if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
|
||||
for(var i = 1; i != m.length; ++i) {
|
||||
if(!m[i]) continue;
|
||||
mt = 1;
|
||||
if(i > 3) time = true;
|
||||
switch(m[i].substr(m[i].length-1)) {
|
||||
case 'Y':
|
||||
throw new Error("Unsupported ISO Duration Field: " + m[i].substr(m[i].length-1));
|
||||
case 'D': mt *= 24;
|
||||
/* falls through */
|
||||
case 'H': mt *= 60;
|
||||
/* falls through */
|
||||
case 'M':
|
||||
if(!time) throw new Error("Unsupported ISO Duration Field: M");
|
||||
else mt *= 60;
|
||||
/* falls through */
|
||||
case 'S': break;
|
||||
}
|
||||
sec += mt * parseInt(m[i], 10);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
||||
function cc2str(arr) {
|
||||
var o = "";
|
||||
for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
|
||||
@ -1344,6 +1372,7 @@ function getdatabin(data) {
|
||||
function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
|
||||
|
||||
/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
|
||||
/* OASIS does not comment on filename case sensitivity */
|
||||
function safegetzipfile(zip, file) {
|
||||
var k = keys(zip.files);
|
||||
var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
|
||||
@ -1380,7 +1409,7 @@ if (typeof exports !== 'undefined') {
|
||||
_fs = require('fs');
|
||||
}
|
||||
}
|
||||
var attregexg=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var attregexg=/([^\s?>\/]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
|
||||
var tagregex=/<[^>]*>/g;
|
||||
var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
|
||||
function parsexmltag(tag, skip_root) {
|
||||
@ -1389,14 +1418,21 @@ function parsexmltag(tag, skip_root) {
|
||||
for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
|
||||
if(!skip_root) z[0] = tag.substr(0, eq);
|
||||
if(eq === tag.length) return z;
|
||||
var m = tag.match(attregexg), j=0, w="", v="", i=0, q="", cc="";
|
||||
var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="";
|
||||
if(m) for(i = 0; i != m.length; ++i) {
|
||||
cc = m[i];
|
||||
for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
|
||||
q = cc.substr(0,c); v = cc.substring(c+2, cc.length-1);
|
||||
for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
|
||||
if(j===q.length) z[q] = v;
|
||||
else z[(j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1)] = v;
|
||||
if(j===q.length) {
|
||||
//if(q.indexOf("_") > 0) q = q.substr(0, q.indexOf("_")); // from ods
|
||||
z[q] = v;
|
||||
}
|
||||
else {
|
||||
var k = (j===5 && q.substr(0,5)==="xmlns"?"xmlns":"")+q.substr(j+1);
|
||||
//if(z[k] && q.substr(j-3,3) == "ext") continue; // from ods
|
||||
z[k] = v;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
@ -2640,6 +2676,63 @@ function write_rels(rels) {
|
||||
if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
function parse_manifest(d, opts) {
|
||||
var str = xlml_normalize(d);
|
||||
var Rn;
|
||||
var FEtag;
|
||||
while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
|
||||
case 'manifest': break; // 4.2 <manifest:manifest>
|
||||
case 'file-entry': // 4.3 <manifest:file-entry>
|
||||
FEtag = parsexmltag(Rn[0], false);
|
||||
if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
|
||||
break;
|
||||
case 'encryption-data': // 4.4 <manifest:encryption-data>
|
||||
case 'algorithm': // 4.5 <manifest:algorithm>
|
||||
case 'start-key-generation': // 4.6 <manifest:start-key-generation>
|
||||
case 'key-derivation': // 4.7 <manifest:key-derivation>
|
||||
throw new Error("Unsupported ODS Encryption");
|
||||
default: if(opts && opts.WTF) throw Rn;
|
||||
}
|
||||
}
|
||||
|
||||
function write_manifest(manifest, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
|
||||
o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
|
||||
for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
|
||||
o.push('</manifest:manifest>');
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
function write_rdf_type(file, res, tag) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + file + '">\n',
|
||||
' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf_has(base, file) {
|
||||
return [
|
||||
' <rdf:Description rdf:about="' + base + '">\n',
|
||||
' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
|
||||
' </rdf:Description>\n'
|
||||
].join("");
|
||||
}
|
||||
function write_rdf(rdf, opts) {
|
||||
var o = [XML_HEADER];
|
||||
o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
|
||||
for(var i = 0; i != rdf.length; ++i) {
|
||||
o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
|
||||
o.push(write_rdf_has("",rdf[i][0]));
|
||||
}
|
||||
o.push(write_rdf_type("","Document", "pkg"));
|
||||
o.push('</rdf:RDF>');
|
||||
return o.join("");
|
||||
}
|
||||
/* ECMA-376 Part II 11.1 Core Properties Part */
|
||||
/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
|
||||
var CORE_PROPS = [
|
||||
@ -7833,6 +7926,17 @@ var XLSXFutureFunctions = {
|
||||
"_xlfn.Z.TEST": "Z.TEST"
|
||||
};
|
||||
|
||||
/* Part 3 TODO: actually parse formulae */
|
||||
function ods_to_csf_formula(f) {
|
||||
if(f.substr(0,3) == "of:") f = f.substr(3);
|
||||
/* 5.2 Basic Expressions */
|
||||
if(f.charCodeAt(0) == 61) {
|
||||
f = f.substr(1);
|
||||
if(f.charCodeAt(0) == 61) f = f.substr(1);
|
||||
}
|
||||
/* Part 3 Section 5.8 References */
|
||||
return f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, "$1").replace(/\./g, "");
|
||||
}
|
||||
var strs = {}; // shared strings
|
||||
var _ssfopts = {}; // spreadsheet formatting options
|
||||
|
||||
@ -8141,6 +8245,10 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
|
||||
case 'n': p.v = parseFloat(p.v); break;
|
||||
case 's':
|
||||
sstr = strs[parseInt(p.v, 10)];
|
||||
if(typeof p.v == 'undefined') {
|
||||
if(!opts.sheetStubs) continue;
|
||||
p.t = "stub";
|
||||
}
|
||||
p.v = sstr.t;
|
||||
p.r = sstr.r;
|
||||
if(opts.cellHTML) p.h = sstr.h;
|
||||
@ -9412,6 +9520,7 @@ function process_style_xlml(styles, stag, opts) {
|
||||
function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o) {
|
||||
var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
|
||||
var interiors = [];
|
||||
var i = 0;
|
||||
if(sid === undefined && row) sid = row.StyleID;
|
||||
if(sid === undefined && csty) sid = csty.StyleID;
|
||||
while(styles[sid] !== undefined) {
|
||||
@ -9483,7 +9592,9 @@ function xlml_normalize(d) {
|
||||
}
|
||||
|
||||
/* TODO: Everything */
|
||||
var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
/* UOS uses CJK in tags */
|
||||
var xlmlregex = /<(\/?)([^\s?>\/:]*:|)([^\s?>]*[^\s?>\/])[^>]*>/mg;
|
||||
//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
|
||||
function parse_xlml_xml(d, opts) {
|
||||
var str = debom(xlml_normalize(d));
|
||||
if(str.substr(0,1000).indexOf("<html") >= 0) return parse_html(str, opts);
|
||||
@ -12145,6 +12256,443 @@ function parse_html(str, opts) {
|
||||
ws['!ref'] = encode_range(range);
|
||||
return o;
|
||||
}
|
||||
var parse_content_xml = (function() {
|
||||
|
||||
var parse_text_p = function(text, tag) {
|
||||
return unescapexml(text.replace(/<text:s\/>/g," ").replace(/<[^>]*>/g,""));
|
||||
};
|
||||
|
||||
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"]
|
||||
};
|
||||
|
||||
return function pcx(d, _opts) {
|
||||
var opts = _opts || {};
|
||||
var str = xlml_normalize(d);
|
||||
var state = [], tmp;
|
||||
var tag;
|
||||
var NFtag = {name:""}, NF = "", pidx = 0;
|
||||
var sheetag;
|
||||
var rowtag;
|
||||
var Sheets = {}, SheetNames = [], ws = {};
|
||||
var Rn, q;
|
||||
var ctag = {value:""};
|
||||
var textp = "", textpidx = 0, textptag;
|
||||
var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
|
||||
var number_format_map = {};
|
||||
var merges = [], mrange = {}, mR = 0, mC = 0;
|
||||
var arrayf = [];
|
||||
var rept = 1, isstub = false;
|
||||
var i = 0;
|
||||
xlmlregex.lastIndex = 0;
|
||||
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);
|
||||
if(merges.length) ws['!merges'] = merges;
|
||||
sheetag.name = utf8read(sheetag['名称'] || sheetag.name);
|
||||
SheetNames.push(sheetag.name);
|
||||
Sheets[sheetag.name] = ws;
|
||||
}
|
||||
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 = {}; merges = [];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'table-row': case '行': // 9.1.3 <table:table-row>
|
||||
if(Rn[1] === '/') break;
|
||||
rowtag = parsexmltag(Rn[0], false);
|
||||
if(rowtag['行号']) R = rowtag['行号'] - 1; else ++R;
|
||||
C = -1; break;
|
||||
case 'covered-table-cell': // 9.1.5 table:covered-table-cell
|
||||
++C; break; /* stub */
|
||||
case 'table-cell': case '数据':
|
||||
if(Rn[0].charAt(Rn[0].length-2) === '/') {
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
if(ctag['number-columns-repeated']) C+= parseInt(ctag['number-columns-repeated'], 10);
|
||||
else ++C;
|
||||
}
|
||||
else if(Rn[1]!=='/') {
|
||||
++C;
|
||||
rept = 1;
|
||||
if(C > range.e.c) range.e.c = C;
|
||||
if(R > range.e.r) range.e.r = R;
|
||||
if(C < range.s.c) range.s.c = C;
|
||||
if(R < range.s.r) range.s.r = R;
|
||||
ctag = parsexmltag(Rn[0], false);
|
||||
q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
|
||||
if(opts.cellFormula) {
|
||||
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']) rept = 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 = 'n'; q.v = datenum(new Date(ctag['date-value'])); 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 = ctag['string-value'];
|
||||
} else throw new Error('Unsupported value type ' + q.t);
|
||||
}
|
||||
} else {
|
||||
isstub = false;
|
||||
if(q.t === 's') {
|
||||
q.v = textp || '';
|
||||
isstub = textpidx == 0;
|
||||
}
|
||||
if(textp) q.w = textp;
|
||||
if(!isstub || opts.cellStubs) {
|
||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||
ws[encode_cell({r:R,c:C})] = q;
|
||||
while(--rept > 0) ws[encode_cell({r:R,c:++C})] = dup(q);
|
||||
if(range.e.c <= C) range.e.c = C;
|
||||
}
|
||||
} else { C += rept; rept = 0; }
|
||||
q = {};
|
||||
textp = "";
|
||||
}
|
||||
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>
|
||||
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;
|
||||
|
||||
/* 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 'annotation': // 14.1 <office:annotation>
|
||||
case 'event-listeners': // 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;
|
||||
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 'master-styles': break; // TODO: <office:automatic-styles>
|
||||
|
||||
case 'default-style': // TODO: <style:default-style>
|
||||
case 'page-layout': break; // TODO: <style:page-layout>
|
||||
case 'style': break; // 16.2 <style:style>
|
||||
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 'text-content': break; // 16.27.27 <number:text-content>
|
||||
case 'text-properties': break; // 16.27.27 <style:text-properties>
|
||||
|
||||
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 '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 'named-range': break; // 9.4.12 <table:named-range>
|
||||
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 'span': break; // <text:span>
|
||||
case 'line-break': break; // 6.1.5 <text:line-break>
|
||||
case 'p': case '文本串':
|
||||
if(Rn[1]==='/') textp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
|
||||
else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
|
||||
break; // <text:p>
|
||||
case 's': break; // <text:s>
|
||||
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 'table-source': 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 'error-message': break; // 9.4.7 <table:
|
||||
case 'database-ranges': break; // 9.4.14 <table:database-ranges>
|
||||
case 'database-range': break; // 9.4.15 <table:database-range>
|
||||
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': // TODO
|
||||
/* TODO: FODS Properties */
|
||||
case 'initial-creator':
|
||||
case 'creator':
|
||||
case 'creation-date':
|
||||
case 'generator':
|
||||
case 'document-statistic':
|
||||
case 'user-defined':
|
||||
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.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': break; // 6.1.8 hyperlink
|
||||
|
||||
/* non-standard */
|
||||
case 'table-protection': break;
|
||||
case 'data-pilot-grand-total': break; // <table:
|
||||
default:
|
||||
if(Rn[2] === 'dc:') break; // TODO: properties
|
||||
if(Rn[2] === 'draw:') break; // TODO: drawing
|
||||
if(Rn[2] === 'style:') break; // TODO: styles
|
||||
if(Rn[2] === 'calcext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'loext:') break; // ignore undocumented extensions
|
||||
if(Rn[2] === 'uof:') break; // TODO: uof
|
||||
if(Rn[2] === '表:') break; // TODO: uof
|
||||
if(Rn[2] === '字:') break; // TODO: uof
|
||||
if(opts.WTF) throw Rn;
|
||||
}
|
||||
var out = {
|
||||
Sheets: Sheets,
|
||||
SheetNames: SheetNames
|
||||
};
|
||||
return out;
|
||||
};
|
||||
})();
|
||||
var write_content_xml = (function() {
|
||||
var null_cell_xml = ' <table:table-cell />\n';
|
||||
var write_ws = function(ws, wb, i, opts) {
|
||||
/* Section 9 Tables */
|
||||
var o = [];
|
||||
o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
|
||||
var R=0,C=0, range = decode_range(ws['!ref']);
|
||||
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 ref = encode_cell({r:R, c:C}), cell = ws[ref];
|
||||
if(cell) switch(cell.t) {
|
||||
case 'b': o.push(' <table:table-cell office:value-type="boolean" office:boolean-value="' + (cell.v ? 'true' : 'false') + '"><text:p>' + (cell.v ? 'TRUE' : 'FALSE') + '</text:p></table:table-cell>\n'); break;
|
||||
case 'n': o.push(' <table:table-cell office:value-type="float" office:value="' + cell.v + '"><text:p>' + (cell.w||cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
case 's': case 'str': o.push(' <table:table-cell office:value-type="string"><text:p>' + escapexml(cell.v) + '</text:p></table:table-cell>\n'); break;
|
||||
//case 'd': // TODO
|
||||
//case 'e':
|
||||
default: o.push(null_cell_xml);
|
||||
} else o.push(null_cell_xml);
|
||||
}
|
||||
o.push(' </table:table-row>\n');
|
||||
}
|
||||
o.push(' </table:table>\n');
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
return function wcx(wb, opts) {
|
||||
var o = [XML_HEADER];
|
||||
/* 3.1.3.2 */
|
||||
if(opts.bookType == "fods") o.push('<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office: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:table="urn:oasis:names:tc:opendocument:xmlns:table: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:config="urn:oasis:names:tc:opendocument:xmlns:config: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: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" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">');
|
||||
else o.push('<office:document-content office:version="1.2" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">\n'); // TODO
|
||||
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("");
|
||||
};
|
||||
})();
|
||||
/* actual implementation in utils, wrappers are for read/write */
|
||||
function write_csv_str(wb, o) {
|
||||
var idx = 0;
|
||||
@ -12152,26 +12700,48 @@ function write_csv_str(wb, o) {
|
||||
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
|
||||
return sheet_to_csv(wb.Sheets[wb.SheetNames[idx]], o);
|
||||
}
|
||||
/* Helper functions to call out to ODS */
|
||||
|
||||
function get_ods() {
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined' && typeof ODS === 'undefined') ODS = require('./ods.js');
|
||||
return ODS;
|
||||
}
|
||||
/* Part 3: Packages */
|
||||
function parse_ods(zip, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_ods(zip, opts);
|
||||
}
|
||||
function write_ods(wb, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.write_ods) throw new Error("Unsupported ODS");
|
||||
return ODS.write_ods(wb, opts);
|
||||
opts = opts || ({});
|
||||
var ods = !!safegetzipfile(zip, 'objectdata');
|
||||
if(ods) var manifest = parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
|
||||
var content = getzipdata(zip, 'content.xml');
|
||||
if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
|
||||
return parse_content_xml(ods ? content : utf8read(content), opts);
|
||||
}
|
||||
function parse_fods(data, opts) {
|
||||
get_ods();
|
||||
if(typeof ODS === 'undefined' || !ODS.parse_fods) throw new Error("Unsupported ODS");
|
||||
return ODS.parse_fods(data, opts);
|
||||
return parse_content_xml(data, opts);
|
||||
}
|
||||
|
||||
function write_ods(wb, opts) {
|
||||
if(opts.bookType == "fods") return write_content_xml(wb, opts);
|
||||
|
||||
var zip = new jszip();
|
||||
var f = "";
|
||||
|
||||
var manifest = [];
|
||||
var rdf = [];
|
||||
|
||||
/* 3:3.3 and 2:2.2.4 */
|
||||
f = "mimetype";
|
||||
zip.file(f, "application/vnd.oasis.opendocument.spreadsheet");
|
||||
|
||||
/* Part 1 Section 2.2 Documents */
|
||||
f = "content.xml";
|
||||
zip.file(f, write_content_xml(wb, opts));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "ContentFile"]);
|
||||
|
||||
/* Part 3 Section 6 Metadata Manifest File */
|
||||
f = "manifest.rdf";
|
||||
zip.file(f, write_rdf(rdf, opts));
|
||||
manifest.push([f, "application/rdf+xml"]);
|
||||
|
||||
/* Part 3 Section 4 Manifest File */
|
||||
f = "META-INF/manifest.xml";
|
||||
zip.file(f, write_manifest(manifest, opts));
|
||||
|
||||
return zip;
|
||||
}
|
||||
function fix_opts_func(defaults) {
|
||||
return function fix_opts(opts) {
|
||||
@ -12783,6 +13353,9 @@ var utils = {
|
||||
sheet_to_row_object_array: sheet_to_row_object_array
|
||||
};
|
||||
XLSX.parse_xlscfb = parse_xlscfb;
|
||||
XLSX.parse_ods = parse_ods;
|
||||
XLSX.parse_fods = parse_fods;
|
||||
XLSX.write_ods = write_ods;
|
||||
XLSX.parse_zip = parse_zip;
|
||||
XLSX.read = readSync; //xlsread
|
||||
XLSX.readFile = readFileSync; //readFile
|
||||
@ -12794,4 +13367,7 @@ XLSX.utils = utils;
|
||||
XLSX.CFB = CFB;
|
||||
XLSX.SSF = SSF;
|
||||
})(typeof exports !== 'undefined' ? exports : XLSX);
|
||||
/*exported XLS */
|
||||
var XLS = XLSX;
|
||||
/*exported ODS */
|
||||
var ODS = XLSX;
|
||||
|
@ -5,8 +5,6 @@
|
||||
importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
importScripts('xlsx.js');
|
||||
/* uncomment the next line for ODS support */
|
||||
importScripts('dist/ods.js');
|
||||
/*::self.*/postMessage({t:"ready"});
|
||||
|
||||
onmessage = function (oEvent) {
|
||||
|
@ -3,8 +3,6 @@
|
||||
importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
importScripts('xlsx.js');
|
||||
/* uncomment the next line for ODS support */
|
||||
importScripts('dist/ods.js');
|
||||
postMessage({t:"ready"});
|
||||
|
||||
onmessage = function (oEvent) {
|
||||
|
@ -5,8 +5,6 @@
|
||||
importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
importScripts('xlsx.js');
|
||||
/* uncomment the next line for ODS support */
|
||||
importScripts('dist/ods.js');
|
||||
/*::self.*/postMessage({t:"ready"});
|
||||
|
||||
function ab2str(data) {
|
||||
|
@ -3,8 +3,6 @@
|
||||
importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
importScripts('xlsx.js');
|
||||
/* uncomment the next line for ODS support */
|
||||
importScripts('dist/ods.js');
|
||||
postMessage({t:"ready"});
|
||||
|
||||
function ab2str(data) {
|
||||
|
@ -5,8 +5,6 @@
|
||||
importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
importScripts('xlsx.js');
|
||||
/* uncomment the next line for ODS support */
|
||||
importScripts('dist/ods.js');
|
||||
/*::self.*/postMessage({t:"ready"});
|
||||
|
||||
function ab2str(data) {
|
||||
|
@ -3,8 +3,6 @@
|
||||
importScripts('dist/cpexcel.js');
|
||||
importScripts('jszip.js');
|
||||
importScripts('xlsx.js');
|
||||
/* uncomment the next line for ODS support */
|
||||
importScripts('dist/ods.js');
|
||||
postMessage({t:"ready"});
|
||||
|
||||
function ab2str(data) {
|
||||
|
Loading…
Reference in New Issue
Block a user