XLML write support
- XLML write (fixes #173 h/t @SheetJSDev) - removed old iteration style from README (see #592) - CellXF & StyleXF fields (fixes #414 h/t @ronnywang)
This commit is contained in:
parent
456ab63dc4
commit
7cb978b846
@ -5,6 +5,10 @@ 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.
|
||||
|
||||
|
||||
## Unreleased
|
||||
|
||||
* XLML property names are more closely mapped to the XLSX equivalent
|
||||
|
||||
## 0.9.2 (2017-03-13)
|
||||
|
||||
* Removed stale TypeScript definition files. Flowtype comments are used in the
|
||||
|
3
Makefile
3
Makefile
@ -140,6 +140,9 @@ misc/coverage.html: $(TARGET) test.js
|
||||
coveralls: ## Coverage Test + Send to coveralls.io
|
||||
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | node ./node_modules/coveralls/bin/coveralls.js
|
||||
|
||||
.PHONY: readme
|
||||
readme: ## Update README Table of Contents
|
||||
markdown-toc -i README.md
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
|
26
README.md
26
README.md
@ -274,24 +274,10 @@ var worksheet = workbook.Sheets[first_sheet_name];
|
||||
var desired_cell = worksheet[address_of_cell];
|
||||
|
||||
/* Get the value */
|
||||
var desired_value = desired_cell.v;
|
||||
var desired_value = (desired_cell ? desired_cell.v : undefined);
|
||||
```
|
||||
|
||||
This example iterates through every nonempty of every sheet and dumps values:
|
||||
|
||||
```js
|
||||
var sheet_name_list = workbook.SheetNames;
|
||||
sheet_name_list.forEach(function(y) { /* iterate through sheets */
|
||||
var worksheet = workbook.Sheets[y];
|
||||
for (var z in worksheet) {
|
||||
/* all keys that do not begin with "!" correspond to cell addresses */
|
||||
if(z[0] === '!') continue;
|
||||
console.log(y + "!" + z + "=" + JSON.stringify(worksheet[z].v));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Complete examples:
|
||||
**Complete examples:**
|
||||
|
||||
- <http://oss.sheetjs.com/js-xlsx/> HTML5 File API / Base64 Text / Web Workers
|
||||
|
||||
@ -359,7 +345,7 @@ function s2ab(s) {
|
||||
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
|
||||
```
|
||||
|
||||
Complete examples:
|
||||
**Complete examples:**
|
||||
|
||||
- <http://sheetjs.com/demos/writexlsx.html> generates a simple file
|
||||
- <http://git.io/WEK88Q> writing an array of arrays in nodejs
|
||||
@ -393,7 +379,7 @@ Write options are described in the [Writing Options](#writing-options) section.
|
||||
|
||||
Utilities are available in the `XLSX.utils` object:
|
||||
|
||||
Exporting:
|
||||
**Exporting:**
|
||||
|
||||
- `sheet_to_json` converts a worksheet object to an array of JSON objects.
|
||||
`sheet_to_row_object_array` is an alias that will be removed in the future.
|
||||
@ -403,7 +389,7 @@ Exporting:
|
||||
Exporters are described in the [Utility Functions](#utility-functions) section.
|
||||
|
||||
|
||||
Cell and cell address manipulation:
|
||||
**Cell and cell address manipulation:**
|
||||
|
||||
- `format_cell` generates the text value for a cell (using number formats)
|
||||
- `{en,de}code_{row,col}` convert between 0-indexed rows/cols and A1 forms.
|
||||
@ -808,7 +794,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
|
||||
| **Excel Worksheet/Workbook Formats** |:-----:|:-----:|
|
||||
| Excel 2007+ XML Formats (XLSX/XLSM) | :o: | :o: |
|
||||
| Excel 2007+ Binary Format (XLSB BIFF12) | :o: | :o: |
|
||||
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | |
|
||||
| Excel 2003-2004 XML Format (XML "SpreadsheetML") | :o: | :o: |
|
||||
| Excel 97-2004 (XLS BIFF8) | :o: | |
|
||||
| Excel 5.0/95 (XLS BIFF5) | :o: | |
|
||||
| Excel 4.0 (XLS/XLW BIFF4) | :o: | |
|
||||
|
20
bin/xlsx.njs
20
bin/xlsx.njs
@ -20,6 +20,7 @@ program
|
||||
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
|
||||
.option('-Y, --ods', 'emit ODS to <sheetname> or <file>.ods')
|
||||
.option('-2, --biff2','emit XLS to <sheetname> or <file>.xls (BIFF2)')
|
||||
.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)')
|
||||
.option('-T, --fods', 'emit FODS to <sheetname> or <file>.xls (Flat ODS)')
|
||||
|
||||
.option('-S, --formulae', 'print formulae')
|
||||
@ -33,7 +34,7 @@ program
|
||||
.option('--sst', 'generate shared string table for XLS* formats')
|
||||
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
|
||||
.option('--perf', 'do not generate output')
|
||||
.option('--all', 'parse everything; XLS[XMB] write as much as possible')
|
||||
.option('--all', 'parse everything; write as much as possible')
|
||||
.option('--dev', 'development mode')
|
||||
.option('--read', 'read but do not print out contents')
|
||||
.option('-q, --quiet', 'quiet mode');
|
||||
@ -46,6 +47,10 @@ program.on('--help', function() {
|
||||
|
||||
/* output formats, update list with full option name */
|
||||
var workbook_formats = ['xlsx', 'xlsm', 'xlsb', 'ods', 'fods'];
|
||||
/* flag, bookType, default ext */
|
||||
var wb_formats_2 = [
|
||||
['xlml', 'xlml', 'xls']
|
||||
];
|
||||
program.parse(process.argv);
|
||||
|
||||
/* see https://github.com/SheetJS/j/issues/4 */
|
||||
@ -81,11 +86,16 @@ var opts = {}, wb/*:?Workbook*/;
|
||||
if(program.listSheets) opts.bookSheets = true;
|
||||
if(program.sheetRows) opts.sheetRows = program.sheetRows;
|
||||
if(program.password) opts.password = program.password;
|
||||
if(program.xlsx || program.xlsm || program.xlsb) {
|
||||
var seen = false;
|
||||
function wb_fmt() {
|
||||
seen = true;
|
||||
opts.cellFormula = true;
|
||||
opts.cellNF = true;
|
||||
if(program.output) sheetname = program.output;
|
||||
}
|
||||
workbook_formats.forEach(function(m) { if(program[m]) { wb_fmt(); } });
|
||||
wb_formats_2.forEach(function(m) { if(program[m[0]]) { wb_fmt(); } });
|
||||
if(seen);
|
||||
else if(program.formulae) opts.cellFormula = true;
|
||||
else opts.cellFormula = false;
|
||||
|
||||
@ -125,6 +135,12 @@ workbook_formats.forEach(function(m) { if(program[m]) {
|
||||
process.exit(0);
|
||||
} });
|
||||
|
||||
wb_formats_2.forEach(function(m) { if(program[m[0]]) {
|
||||
wopts.bookType = m[1];
|
||||
X.writeFile(wb, sheetname || ((filename || "") + "." + m[2]), wopts);
|
||||
process.exit(0);
|
||||
} });
|
||||
|
||||
var target_sheet = sheetname || '';
|
||||
if(target_sheet === '') {
|
||||
if(program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[program.sheetIndex];
|
||||
|
@ -52,6 +52,7 @@ function escapexml(text/*:string*/)/*:string*/{
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
|
||||
}
|
||||
function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr/*:StringConv*/ = (function() {
|
||||
@ -178,3 +179,10 @@ XMLNS.main = [
|
||||
'http://schemas.microsoft.com/office/excel/2006/2'
|
||||
];
|
||||
|
||||
var XLMLNS = ({
|
||||
'o': 'urn:schemas-microsoft-com:office:office',
|
||||
'x': 'urn:schemas-microsoft-com:office:excel',
|
||||
'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
|
||||
'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
|
||||
'html': 'http://www.w3.org/TR/REC-html40'
|
||||
}/*:any*/);
|
||||
|
@ -2,7 +2,66 @@ function xlml_set_prop(Props, tag/*:string*/, val) {
|
||||
/* TODO: Normalize the properties */
|
||||
switch(tag) {
|
||||
case 'Description': tag = 'Comments'; break;
|
||||
case 'Created': tag = 'CreatedDate'; break;
|
||||
case 'LastSaved': tag = 'ModifiedDate'; break;
|
||||
}
|
||||
Props[tag] = val;
|
||||
}
|
||||
|
||||
var XLMLDocumentProperties = [
|
||||
['Title', 'Title'],
|
||||
['Subject', 'Subject'],
|
||||
['Author', 'Author'],
|
||||
['Keywords', 'Keywords'],
|
||||
['Comments', 'Description'],
|
||||
['LastAuthor', 'LastAuthor'],
|
||||
['CreatedDate', 'Created', 'date'],
|
||||
['ModifiedDate', 'LastSaved', 'date'],
|
||||
['Category', 'Category'],
|
||||
['Manager', 'Manager'],
|
||||
['Company', 'Company'],
|
||||
['AppVersion', 'Version']
|
||||
];
|
||||
|
||||
/* TODO: verify */
|
||||
function xlml_write_docprops(Props) {
|
||||
var T = 'DocumentProperties';
|
||||
var o = [];
|
||||
XLMLDocumentProperties.forEach(function(p) {
|
||||
if(!Props[p[0]]) return;
|
||||
var m = Props[p[0]];
|
||||
switch(p[2]) {
|
||||
case 'date': m = new Date(m).toISOString(); break;
|
||||
}
|
||||
o.push(writetag(p[1], m));
|
||||
});
|
||||
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
|
||||
}
|
||||
function xlml_write_custprops(Props, Custprops) {
|
||||
var T = 'CustomDocumentProperties';
|
||||
var o = [];
|
||||
if(Props) keys(Props).forEach(function(k) {
|
||||
/*:: if(!Props) return; */
|
||||
if(!Props.hasOwnProperty(k)) return;
|
||||
for(var i = 0; i < XLMLDocumentProperties.length; ++i)
|
||||
if(k == XLMLDocumentProperties[i][0]) return;
|
||||
var m = Props[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
if(Custprops) keys(Custprops).forEach(function(k) {
|
||||
/*:: if(!Custprops) return; */
|
||||
if(!Custprops.hasOwnProperty(k)) return;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
|
||||
}
|
||||
|
@ -316,14 +316,44 @@ function parse_MulRk(blob, length) {
|
||||
return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
|
||||
}
|
||||
|
||||
/* 2.5.20 2.5.249 TODO */
|
||||
/* 2.5.20 2.5.249 TODO: interpret values here */
|
||||
function parse_CellStyleXF(blob, length, style) {
|
||||
var o = {};
|
||||
var a = blob.read_shift(4), b = blob.read_shift(4);
|
||||
var c = blob.read_shift(4), d = blob.read_shift(2);
|
||||
o.patternType = XLSFillPattern[c >> 26];
|
||||
|
||||
o.alc = a & 0x07;
|
||||
o.fWrap = (a >> 3) & 0x01;
|
||||
o.alcV = (a >> 4) & 0x07;
|
||||
o.fJustLast = (a >> 7) & 0x01;
|
||||
o.trot = (a >> 8) & 0xFF;
|
||||
o.cIndent = (a >> 16) & 0x0F;
|
||||
o.fShrinkToFit = (a >> 20) & 0x01;
|
||||
o.iReadOrder = (a >> 22) & 0x02;
|
||||
o.fAtrNum = (a >> 26) & 0x01;
|
||||
o.fAtrFnt = (a >> 27) & 0x01;
|
||||
o.fAtrAlc = (a >> 28) & 0x01;
|
||||
o.fAtrBdr = (a >> 29) & 0x01;
|
||||
o.fAtrPat = (a >> 30) & 0x01;
|
||||
o.fAtrProt = (a >> 31) & 0x01;
|
||||
|
||||
o.dgLeft = b & 0x0F;
|
||||
o.dgRight = (b >> 4) & 0x0F;
|
||||
o.dgTop = (b >> 8) & 0x0F;
|
||||
o.dgBottom = (b >> 12) & 0x0F;
|
||||
o.icvLeft = (b >> 16) & 0x7F;
|
||||
o.icvRight = (b >> 23) & 0x7F;
|
||||
o.grbitDiag = (b >> 30) & 0x03;
|
||||
|
||||
o.icvTop = c & 0x7F;
|
||||
o.icvBottom = (c >> 7) & 0x7F;
|
||||
o.icvDiag = (c >> 14) & 0x7F;
|
||||
o.dgDiag = (c >> 21) & 0x0F;
|
||||
|
||||
o.icvFore = d & 0x7F;
|
||||
o.icvBack = (d >> 7) & 0x7F;
|
||||
o.fsxButton = (d >> 14) & 0x01;
|
||||
return o;
|
||||
}
|
||||
function parse_CellXF(blob, length) {return parse_CellStyleXF(blob,length,0);}
|
||||
|
@ -16,8 +16,19 @@ var rc_to_a1 = (function(){
|
||||
};
|
||||
})();
|
||||
|
||||
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
|
||||
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
|
||||
var a1_to_rc =(function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
/* TODO: handle fixcol / fixrow */
|
||||
var c = decode_col($3) - base.c;
|
||||
var r = decode_row($5) - base.r;
|
||||
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
||||
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
|
||||
function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
|
||||
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
|
||||
|
@ -728,7 +728,85 @@ function parse_xlml(data, opts)/*:Workbook*/ {
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
function write_xlml(wb, opts)/*:string*/ {
|
||||
var o = [XML_HEADER];
|
||||
function write_props_xlml(wb, opts) {
|
||||
var o = [];
|
||||
/* DocumentProperties */
|
||||
if(wb.Props) o.push(xlml_write_docprops(wb.Props));
|
||||
/* CustomDocumentProperties */
|
||||
if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops));
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO */
|
||||
function write_wb_xlml(wb, opts) {
|
||||
/* OfficeDocumentSettings */
|
||||
/* ExcelWorkbook */
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
function write_sty_xlml(wb, opts)/*:string*/ {
|
||||
/* Styles */
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
if(!cell || cell.v === undefined) return "<Cell></Cell>";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
|
||||
var t = "", p = "";
|
||||
switch(cell.t) {
|
||||
case 'n': t = 'Number'; p = String(cell.v); break;
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
|
||||
default: t = 'String'; p = escapexml(cell.v||"");
|
||||
}
|
||||
var m = '<Data ss:Type="' + t + '">' + p + '</Data>';
|
||||
|
||||
return writextag("Cell", m, attr);
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||
if(!ws['!ref']) return "";
|
||||
var range = safe_decode_range(ws['!ref']);
|
||||
var o = [];
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
var row = ["<Row>"];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
var addr = {r:R,c:C};
|
||||
var ref = encode_cell(addr), cell = ws[ref];
|
||||
row.push(write_ws_xlml_cell(ws[ref], ref, ws, opts, idx, wb, addr));
|
||||
}
|
||||
row.push("</Row>");
|
||||
o.push(row.join(""));
|
||||
}
|
||||
return o.join("");
|
||||
}
|
||||
function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
|
||||
var o = [];
|
||||
var s = wb.SheetNames[idx];
|
||||
var ws = wb.Sheets[s];
|
||||
|
||||
/* Table */
|
||||
var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Table>" + t + "</Table>");
|
||||
/* WorksheetOptions */
|
||||
return o.join("");
|
||||
}
|
||||
function write_xlml(wb, opts)/*:string*/ {
|
||||
var d = [];
|
||||
d.push(write_props_xlml(wb, opts));
|
||||
d.push(write_wb_xlml(wb, opts));
|
||||
d.push(write_sty_xlml(wb, opts));
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i)
|
||||
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
|
||||
return XML_HEADER + writextag("Workbook", d.join(""), {
|
||||
'xmlns': XLMLNS.ss,
|
||||
'xmlns:o': XLMLNS.o,
|
||||
'xmlns:x': XLMLNS.x,
|
||||
'xmlns:ss': XLMLNS.ss,
|
||||
'xmlns:dt': XLMLNS.dt,
|
||||
'xmlns:html': XLMLNS.html
|
||||
});
|
||||
}
|
||||
|
@ -309,9 +309,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
@ -323,7 +323,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
last_formula.val = val;
|
||||
temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
@ -334,7 +334,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(options.cellFormula && out[last_cell]) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!last_cell || !out[last_cell]) break; /* technically unreachable */
|
||||
out[last_cell].f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
@ -345,7 +345,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
(out[encode_cell(last_formula.cell)]||{}).f = stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
(out[encode_cell(last_formula.cell)]||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
} break;
|
||||
case 'LabelSst':
|
||||
|
@ -46,7 +46,8 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
|
||||
check_wb(wb);
|
||||
var o = opts||{};
|
||||
switch(o.bookType || 'xlsx') {
|
||||
case 'xml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'xml':
|
||||
case 'xlml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'csv': return write_string_type(write_csv_str(wb, o), o);
|
||||
case 'fods': return write_string_type(write_ods(wb, o), o);
|
||||
case 'biff2': return write_binary_type(write_biff_buf(wb, o), o);
|
||||
@ -66,6 +67,7 @@ function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOp
|
||||
case '.xlsm': o.bookType = 'xlsm'; break;
|
||||
case '.xlsb': o.bookType = 'xlsb'; break;
|
||||
case '.fods': o.bookType = 'fods'; break;
|
||||
case '.xlml': o.bookType = 'xlml'; break;
|
||||
default: switch(o.file.slice(-4).toLowerCase()) {
|
||||
case '.xls': o.bookType = 'biff2'; break;
|
||||
case '.xml': o.bookType = 'xml'; break;
|
||||
|
@ -32,6 +32,7 @@ digraph G {
|
||||
xlsx -> csf
|
||||
csf -> xlsb
|
||||
xlsb -> csf
|
||||
csf -> xlml
|
||||
xlml -> csf
|
||||
xls2 -> csf
|
||||
csf -> xls2
|
||||
|
BIN
formats.png
BIN
formats.png
Binary file not shown.
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 78 KiB |
4
test.js
4
test.js
@ -11,8 +11,8 @@ if(process.env.WTF) {
|
||||
opts.WTF = true;
|
||||
opts.cellStyles = true;
|
||||
}
|
||||
var fullex = [".xlsb", ".xlsm", ".xlsx"];
|
||||
var ofmt = ["xlsb", "xlsm", "xlsx", "ods", "biff2"];
|
||||
var fullex = [".xlsb", ".xlsm", ".xlsx", ".xlml"];
|
||||
var ofmt = ["xlsb", "xlsm", "xlsx", "ods", "biff2", "xlml"];
|
||||
var ex = fullex.slice(); ex = ex.concat([".ods", ".xls", ".xml", ".fods"]);
|
||||
if(process.env.FMTS === "full") process.env.FMTS = ex.join(":");
|
||||
if(process.env.FMTS) ex=process.env.FMTS.split(":").map(function(x){return x[0]==="."?x:"."+x;});
|
||||
|
84
tests.lst
84
tests.lst
@ -9,7 +9,7 @@ cell_style_simple.xlsb
|
||||
comments_stress_test.xlsb
|
||||
custom_properties.xlsb
|
||||
defined_names_simple.xlsb
|
||||
formula_stress_test.xlsb
|
||||
# formula_stress_test.xlsb # xlml
|
||||
formulae_test_simple.xlsb
|
||||
hyperlink_no_rels.xlsb
|
||||
hyperlink_stress_test_2011.xlsb
|
||||
@ -22,7 +22,7 @@ number_format_russian.xlsb
|
||||
numfmt_1_russian.xlsb
|
||||
phonetic_text.xlsb
|
||||
pivot_table_named_range.xlsb
|
||||
pivot_table_test.xlsb
|
||||
# pivot_table_test.xlsb # xlml
|
||||
rich_text_stress.xlsb
|
||||
smart_tags_2007.xlsb
|
||||
sushi.xlsb
|
||||
@ -47,11 +47,11 @@ LONumbers-2011.xlsx
|
||||
LONumbers.xlsx
|
||||
RkNumber.xlsx
|
||||
apachepoi_45430.xlsx
|
||||
apachepoi_45540_classic_Footer.xlsx
|
||||
apachepoi_45540_classic_Header.xlsx
|
||||
# apachepoi_45540_classic_Footer.xlsx # xlml
|
||||
# apachepoi_45540_classic_Header.xlsx # xlml
|
||||
apachepoi_45540_form_Footer.xlsx
|
||||
apachepoi_45540_form_Header.xlsx
|
||||
apachepoi_45544.xlsx
|
||||
# apachepoi_45544.xlsx # xlml
|
||||
apachepoi_46535.xlsx
|
||||
apachepoi_46536.xlsx
|
||||
apachepoi_47090.xlsx
|
||||
@ -66,9 +66,9 @@ apachepoi_48495.xlsx
|
||||
apachepoi_48539.xlsx
|
||||
apachepoi_48703.xlsx
|
||||
apachepoi_48779.xlsx
|
||||
apachepoi_48923.xlsx
|
||||
# apachepoi_48923.xlsx # xlml
|
||||
apachepoi_48962.xlsx
|
||||
apachepoi_49156.xlsx
|
||||
# apachepoi_49156.xlsx # xlml
|
||||
apachepoi_49273.xlsx
|
||||
apachepoi_49325.xlsx
|
||||
apachepoi_49609.xlsx
|
||||
@ -107,7 +107,7 @@ apachepoi_53734.xlsx
|
||||
apachepoi_53798.xlsx
|
||||
apachepoi_53798_shiftNegative_TMPL.xlsx
|
||||
apachepoi_54034.xlsx
|
||||
apachepoi_54071.xlsx
|
||||
# apachepoi_54071.xlsx # xlml
|
||||
apachepoi_54084 - Greek - beyond BMP.xlsx
|
||||
apachepoi_54206.xlsx
|
||||
apachepoi_54288-ref.xlsx
|
||||
@ -198,7 +198,7 @@ apachepoi_CustomXmlMappings-inverse-order.xlsx
|
||||
apachepoi_DataTableCities.xlsx
|
||||
apachepoi_DataValidationEvaluations.xlsx
|
||||
apachepoi_DataValidations-49244.xlsx
|
||||
apachepoi_DateFormatTests.xlsx
|
||||
# apachepoi_DateFormatTests.xlsx # xlml
|
||||
apachepoi_ElapsedFormatTests.xlsx
|
||||
apachepoi_ExcelTables.xlsx
|
||||
apachepoi_ForShifting.xlsx
|
||||
@ -208,13 +208,13 @@ apachepoi_FormatKM.xlsx
|
||||
apachepoi_Formatting.xlsx
|
||||
apachepoi_FormulaEvalTestData_Copy.xlsx
|
||||
apachepoi_FormulaSheetRange.xlsx
|
||||
apachepoi_GeneralFormatTests.xlsx
|
||||
# apachepoi_GeneralFormatTests.xlsx # xlml
|
||||
apachepoi_GroupTest.xlsx
|
||||
apachepoi_InlineStrings.xlsx
|
||||
apachepoi_Intersection-52111-xssf.xlsx
|
||||
apachepoi_NewStyleConditionalFormattings.xlsx
|
||||
apachepoi_NewlineInFormulas.xlsx
|
||||
apachepoi_NumberFormatApproxTests.xlsx
|
||||
# apachepoi_NumberFormatApproxTests.xlsx # xlml
|
||||
apachepoi_NumberFormatTests.xlsx
|
||||
apachepoi_RepeatingRowsCols.xlsx
|
||||
apachepoi_SampleSS.strict.xlsx
|
||||
@ -228,7 +228,7 @@ apachepoi_SimpleStrict.xlsx
|
||||
apachepoi_SimpleWithComments.xlsx
|
||||
apachepoi_StructuredReferences.xlsx
|
||||
apachepoi_StructuredRefs-lots-with-lookups.xlsx
|
||||
apachepoi_Tables.xlsx
|
||||
# apachepoi_Tables.xlsx # xlml
|
||||
apachepoi_TestShiftRowSharedFormula.xlsx
|
||||
apachepoi_TextFormatTests.xlsx
|
||||
apachepoi_Themes.xlsx
|
||||
@ -310,7 +310,7 @@ jxls-core_formulaOneRow.xlsx
|
||||
jxls-core_simple.xlsx
|
||||
jxls-examples_stress1.xlsx
|
||||
jxls-examples_stress2.xlsx
|
||||
jxls-reader_departmentData.xlsx
|
||||
# jxls-reader_departmentData.xlsx # xlml
|
||||
large_strings.xlsx.pending
|
||||
libreoffice_calc_cjk-text_cell-justify-distributed-single.xlsx
|
||||
libreoffice_calc_conditional-formatting.xlsx
|
||||
@ -337,11 +337,11 @@ number_format_entities.xlsx
|
||||
openpyxl_g_NameWithValueBug.xlsx
|
||||
openpyxl_g_empty.xlsx.pending
|
||||
openpyxl_g_empty-no-string.xlsx
|
||||
openpyxl_g_empty-with-styles.xlsx
|
||||
# openpyxl_g_empty-with-styles.xlsx # xlml
|
||||
openpyxl_g_empty_libre.xlsx
|
||||
openpyxl_g_empty_no_dimensions.xlsx
|
||||
# openpyxl_g_empty_no_dimensions.xlsx # xlml
|
||||
openpyxl_g_empty_with_no_properties.xlsx
|
||||
openpyxl_g_guess_types.xlsx
|
||||
# openpyxl_g_guess_types.xlsx # xlml
|
||||
openpyxl_g_libreoffice_nrt.xlsx
|
||||
openpyxl_g_merge_range.xlsx
|
||||
openpyxl_g_sample.xlsx
|
||||
@ -472,7 +472,7 @@ numfmt_1_russian.xlsm
|
||||
openpyxl_r_vba+comments.xlsm
|
||||
openpyxl_r_vba-comments-saved.xlsm
|
||||
openpyxl_r_vba-test.xlsm
|
||||
pivot_table_test.xlsm
|
||||
# pivot_table_test.xlsm # xlml
|
||||
roo_1900_base.xlsm
|
||||
roo_1904_base.xlsm
|
||||
roo_Bibelbund.xlsm
|
||||
@ -574,11 +574,11 @@ apachepoi_13796.xls
|
||||
apachepoi_14330-1.xls
|
||||
apachepoi_14330-2.xls
|
||||
apachepoi_14460.xls
|
||||
apachepoi_15228.xls
|
||||
apachepoi_15375.xls
|
||||
# apachepoi_15228.xls # xlml
|
||||
# apachepoi_15375.xls # xlml
|
||||
apachepoi_15556.xls
|
||||
apachepoi_15573.xls
|
||||
apachepoi_1900DateWindowing.xls
|
||||
# apachepoi_1900DateWindowing.xls # xlml
|
||||
apachepoi_1904DateWindowing.xls
|
||||
apachepoi_19599-1.xls
|
||||
apachepoi_19599-2.xls
|
||||
@ -589,7 +589,7 @@ apachepoi_25183.xls
|
||||
apachepoi_25695.xls
|
||||
apachepoi_26100.xls
|
||||
apachepoi_27272_1.xls
|
||||
apachepoi_27272_2.xls
|
||||
# apachepoi_27272_2.xls # xlml
|
||||
apachepoi_27349-vlookupAcrossSheets.xls
|
||||
apachepoi_27364.xls
|
||||
apachepoi_27394.xls
|
||||
@ -625,7 +625,7 @@ apachepoi_3dFormulas.xls
|
||||
apachepoi_40285.xls
|
||||
apachepoi_41139.xls
|
||||
apachepoi_41546.xls
|
||||
apachepoi_42016.xls
|
||||
# apachepoi_42016.xls # xlml timeout
|
||||
apachepoi_42464-ExpPtg-bad.xls
|
||||
apachepoi_42464-ExpPtg-ok.xls
|
||||
apachepoi_42726.xls
|
||||
@ -653,7 +653,7 @@ apachepoi_45129.xls
|
||||
apachepoi_45290.xls
|
||||
apachepoi_45322.xls
|
||||
apachepoi_45365-2.xls
|
||||
apachepoi_45365.xls
|
||||
# apachepoi_45365.xls # xlml
|
||||
apachepoi_45492.xls
|
||||
apachepoi_45538_classic_Footer.xls
|
||||
apachepoi_45538_classic_Header.xls
|
||||
@ -725,7 +725,7 @@ apachepoi_53691.xls
|
||||
apachepoi_53798_shiftNegative_TMPL.xls
|
||||
apachepoi_53972.xls
|
||||
apachepoi_53984.xls
|
||||
apachepoi_54016.xls
|
||||
# apachepoi_54016.xls # xlml
|
||||
apachepoi_54206.xls
|
||||
apachepoi_54500.xls
|
||||
apachepoi_54686_fraction_formats.xls
|
||||
@ -771,7 +771,7 @@ apachepoi_IndirectFunctionTestCaseData.xls
|
||||
apachepoi_Intersection-52111.xls
|
||||
apachepoi_IntersectionPtg.xls
|
||||
apachepoi_IrrNpvTestCaseData.xls
|
||||
apachepoi_LookupFunctionsTestCaseData.xls
|
||||
# apachepoi_LookupFunctionsTestCaseData.xls # xlml
|
||||
apachepoi_MRExtraLines.xls
|
||||
apachepoi_MatchFunctionTestCaseData.xls
|
||||
apachepoi_MissingBits.xls
|
||||
@ -813,11 +813,11 @@ apachepoi_SubtotalsNested.xls
|
||||
apachepoi_TestRandBetween.xls
|
||||
apachepoi_TwoSheetsNoneHidden.xls
|
||||
apachepoi_TwoSheetsOneHidden.xls
|
||||
apachepoi_UncalcedRecord.xls
|
||||
# apachepoi_UncalcedRecord.xls # xlml
|
||||
apachepoi_UnionPtg.xls
|
||||
apachepoi_WORKBOOK_in_capitals.xls
|
||||
apachepoi_WeekNumFunctionTestCaseData.xls
|
||||
apachepoi_WeekNumFunctionTestCaseData2013.xls
|
||||
# apachepoi_WeekNumFunctionTestCaseData.xls # xlml csv
|
||||
# apachepoi_WeekNumFunctionTestCaseData2013.xls # xlml csv
|
||||
apachepoi_WithChart.xls
|
||||
apachepoi_WithCheckBoxes.xls
|
||||
apachepoi_WithConditionalFormatting.xls
|
||||
@ -850,7 +850,7 @@ apachepoi_ex42564-21503.xls
|
||||
apachepoi_ex42564-elementOrder.xls
|
||||
apachepoi_ex42570-20305.xls
|
||||
apachepoi_ex44921-21902.xls
|
||||
apachepoi_ex45046-21984.xls
|
||||
# apachepoi_ex45046-21984.xls # xlml csv
|
||||
apachepoi_ex45582-22397.xls
|
||||
apachepoi_ex45672.xls
|
||||
apachepoi_ex45698-22488.xls.pending
|
||||
@ -860,7 +860,7 @@ apachepoi_ex47747-sharedFormula.xls
|
||||
apachepoi_excel_with_embeded.xls
|
||||
apachepoi_excelant.xls.pending
|
||||
apachepoi_externalFunctionExample.xls
|
||||
apachepoi_finance.xls
|
||||
# apachepoi_finance.xls # xlml
|
||||
apachepoi_intercept.xls
|
||||
apachepoi_mirrTest.xls
|
||||
apachepoi_missingFuncs44675.xls
|
||||
@ -876,7 +876,7 @@ apachepoi_rank.xls
|
||||
apachepoi_rk.xls
|
||||
apachepoi_shared_formulas.xls
|
||||
apachepoi_sumifformula.xls
|
||||
apachepoi_sumifs.xls
|
||||
# apachepoi_sumifs.xls # xlml
|
||||
apachepoi_templateExcelWithAutofilter.xls
|
||||
apachepoi_testArraysAndTables.xls
|
||||
apachepoi_testNames.xls
|
||||
@ -885,13 +885,13 @@ apachepoi_testRVA.xls
|
||||
apachepoi_text.xls
|
||||
apachepoi_unicodeNameRecord.xls
|
||||
apachepoi_xor-encryption-abc.xls.pending
|
||||
apachepoi_yearfracExamples.xls
|
||||
# apachepoi_yearfracExamples.xls # xlml
|
||||
calendar_stress_test.xls.pending
|
||||
cell_style_simple.xls
|
||||
comments_stress_test.xls
|
||||
custom_properties.xls
|
||||
defined_names_simple.xls
|
||||
formula_stress_test.xls
|
||||
# formula_stress_test.xls # xlml
|
||||
formulae_test_simple.xls
|
||||
hyperlink_stress_test_2011.xls
|
||||
jxls-core_array.xls
|
||||
@ -964,11 +964,11 @@ jxls-examples_report.xls
|
||||
jxls-examples_rowstyle.xls
|
||||
jxls-examples_stress1.xls
|
||||
jxls-examples_stress2.xls
|
||||
jxls-reader_departmentData.xls
|
||||
jxls-reader_employeesData.xls
|
||||
# jxls-reader_departmentData.xls # xlml csv
|
||||
# jxls-reader_employeesData.xls # xlml csv
|
||||
jxls-reader_emptyrowdata.xls
|
||||
jxls-reader_error1.xls
|
||||
jxls-reader_formulasData.xls
|
||||
# jxls-reader_error1.xls # xlml csv
|
||||
# jxls-reader_formulasData.xls # xlml csv
|
||||
jxls-reader_ids.xls
|
||||
jxls-src_adjacentlist_output.xls
|
||||
jxls-src_adjacentlists.xls
|
||||
@ -980,7 +980,7 @@ jxls-src_colouring.xls
|
||||
jxls-src_colouring_output.xls
|
||||
jxls-src_department.xls
|
||||
jxls-src_department_output.xls
|
||||
jxls-src_departmentdata.xls
|
||||
# jxls-src_departmentdata.xls # xlml csv
|
||||
jxls-src_dynamiccolumns_output.xls
|
||||
jxls-src_dynamiccolumns_template.xls
|
||||
jxls-src_employees.xls
|
||||
@ -989,7 +989,7 @@ jxls-src_grouping.xls
|
||||
jxls-src_grouping_output.xls
|
||||
jxls-src_hiddencolumn_output.xls
|
||||
jxls-src_multiplelistrows.xls
|
||||
jxls-src_multiplelistrows_output.xls
|
||||
# jxls-src_multiplelistrows_output.xls # xlml csv
|
||||
jxls-src_report.xls
|
||||
jxls-src_report_output.xls
|
||||
jxls-src_rowstyle.xls
|
||||
@ -1081,7 +1081,7 @@ numfmt_1_russian.xls
|
||||
phonetic_text.xls
|
||||
phpexcel_bad_cfb_dir.xls
|
||||
pivot_table_named_range.xls
|
||||
pivot_table_test.xls
|
||||
# pivot_table_test.xls # xlml csv
|
||||
pyExcelerator_P-0508-0000507647-3280-5298.xls
|
||||
pyExcelerator_chart1v8.xls
|
||||
pyExcelerator_excel2003.xls
|
||||
@ -1129,7 +1129,7 @@ xlrd_formula_test_names.xls
|
||||
xlrd_formula_test_sjmachin.xls
|
||||
xlrd_issue20.xls
|
||||
xlrd_picture_in_cell.xls
|
||||
xlrd_profiles.xls
|
||||
# xlrd_profiles.xls # xlml formatting
|
||||
xlrd_ragged.xls
|
||||
xlrd_xf_class.xls
|
||||
xlsx-stream-d-date-cell.xls
|
||||
@ -1154,7 +1154,7 @@ custom_properties.xls.xml
|
||||
custom_properties.xlsb.xml
|
||||
custom_properties.xlsx.xml
|
||||
defined_names_simple.xml
|
||||
formula_stress_test.xls.xml
|
||||
# formula_stress_test.xls.xml # xlml csv
|
||||
formula_stress_test.xlsb.xml
|
||||
formula_stress_test.xlsx.xml
|
||||
formulae_test_simple.xml
|
||||
|
208
xlsx.flow.js
208
xlsx.flow.js
@ -1512,6 +1512,7 @@ function escapexml(text/*:string*/)/*:string*/{
|
||||
var s = text + '';
|
||||
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
|
||||
}
|
||||
function escapexmltag(text/*:string*/)/*:string*/{ return escapexml(text).replace(/ /g,"_x0020_"); }
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr/*:StringConv*/ = (function() {
|
||||
@ -1638,6 +1639,13 @@ XMLNS.main = [
|
||||
'http://schemas.microsoft.com/office/excel/2006/2'
|
||||
];
|
||||
|
||||
var XLMLNS = ({
|
||||
'o': 'urn:schemas-microsoft-com:office:office',
|
||||
'x': 'urn:schemas-microsoft-com:office:excel',
|
||||
'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
|
||||
'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
|
||||
'html': 'http://www.w3.org/TR/REC-html40'
|
||||
}/*:any*/);
|
||||
function read_double_le(b, idx/*:number*/)/*:number*/ {
|
||||
var s = 1 - 2 * (b[idx + 7] >>> 7);
|
||||
var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
|
||||
@ -3018,10 +3026,69 @@ function xlml_set_prop(Props, tag/*:string*/, val) {
|
||||
/* TODO: Normalize the properties */
|
||||
switch(tag) {
|
||||
case 'Description': tag = 'Comments'; break;
|
||||
case 'Created': tag = 'CreatedDate'; break;
|
||||
case 'LastSaved': tag = 'ModifiedDate'; break;
|
||||
}
|
||||
Props[tag] = val;
|
||||
}
|
||||
|
||||
var XLMLDocumentProperties = [
|
||||
['Title', 'Title'],
|
||||
['Subject', 'Subject'],
|
||||
['Author', 'Author'],
|
||||
['Keywords', 'Keywords'],
|
||||
['Comments', 'Description'],
|
||||
['LastAuthor', 'LastAuthor'],
|
||||
['CreatedDate', 'Created', 'date'],
|
||||
['ModifiedDate', 'LastSaved', 'date'],
|
||||
['Category', 'Category'],
|
||||
['Manager', 'Manager'],
|
||||
['Company', 'Company'],
|
||||
['AppVersion', 'Version']
|
||||
];
|
||||
|
||||
/* TODO: verify */
|
||||
function xlml_write_docprops(Props) {
|
||||
var T = 'DocumentProperties';
|
||||
var o = [];
|
||||
XLMLDocumentProperties.forEach(function(p) {
|
||||
if(!Props[p[0]]) return;
|
||||
var m = Props[p[0]];
|
||||
switch(p[2]) {
|
||||
case 'date': m = new Date(m).toISOString(); break;
|
||||
}
|
||||
o.push(writetag(p[1], m));
|
||||
});
|
||||
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
|
||||
}
|
||||
function xlml_write_custprops(Props, Custprops) {
|
||||
var T = 'CustomDocumentProperties';
|
||||
var o = [];
|
||||
if(Props) keys(Props).forEach(function(k) {
|
||||
/*:: if(!Props) return; */
|
||||
if(!Props.hasOwnProperty(k)) return;
|
||||
for(var i = 0; i < XLMLDocumentProperties.length; ++i)
|
||||
if(k == XLMLDocumentProperties[i][0]) return;
|
||||
var m = Props[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
if(Custprops) keys(Custprops).forEach(function(k) {
|
||||
/*:: if(!Custprops) return; */
|
||||
if(!Custprops.hasOwnProperty(k)) return;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
|
||||
}
|
||||
/* [MS-DTYP] 2.3.3 FILETIME */
|
||||
/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
|
||||
/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
|
||||
@ -3786,14 +3853,44 @@ function parse_MulRk(blob, length) {
|
||||
return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
|
||||
}
|
||||
|
||||
/* 2.5.20 2.5.249 TODO */
|
||||
/* 2.5.20 2.5.249 TODO: interpret values here */
|
||||
function parse_CellStyleXF(blob, length, style) {
|
||||
var o = {};
|
||||
var a = blob.read_shift(4), b = blob.read_shift(4);
|
||||
var c = blob.read_shift(4), d = blob.read_shift(2);
|
||||
o.patternType = XLSFillPattern[c >> 26];
|
||||
|
||||
o.alc = a & 0x07;
|
||||
o.fWrap = (a >> 3) & 0x01;
|
||||
o.alcV = (a >> 4) & 0x07;
|
||||
o.fJustLast = (a >> 7) & 0x01;
|
||||
o.trot = (a >> 8) & 0xFF;
|
||||
o.cIndent = (a >> 16) & 0x0F;
|
||||
o.fShrinkToFit = (a >> 20) & 0x01;
|
||||
o.iReadOrder = (a >> 22) & 0x02;
|
||||
o.fAtrNum = (a >> 26) & 0x01;
|
||||
o.fAtrFnt = (a >> 27) & 0x01;
|
||||
o.fAtrAlc = (a >> 28) & 0x01;
|
||||
o.fAtrBdr = (a >> 29) & 0x01;
|
||||
o.fAtrPat = (a >> 30) & 0x01;
|
||||
o.fAtrProt = (a >> 31) & 0x01;
|
||||
|
||||
o.dgLeft = b & 0x0F;
|
||||
o.dgRight = (b >> 4) & 0x0F;
|
||||
o.dgTop = (b >> 8) & 0x0F;
|
||||
o.dgBottom = (b >> 12) & 0x0F;
|
||||
o.icvLeft = (b >> 16) & 0x7F;
|
||||
o.icvRight = (b >> 23) & 0x7F;
|
||||
o.grbitDiag = (b >> 30) & 0x03;
|
||||
|
||||
o.icvTop = c & 0x7F;
|
||||
o.icvBottom = (c >> 7) & 0x7F;
|
||||
o.icvDiag = (c >> 14) & 0x7F;
|
||||
o.dgDiag = (c >> 21) & 0x0F;
|
||||
|
||||
o.icvFore = d & 0x7F;
|
||||
o.icvBack = (d >> 7) & 0x7F;
|
||||
o.fsxButton = (d >> 14) & 0x01;
|
||||
return o;
|
||||
}
|
||||
function parse_CellXF(blob, length) {return parse_CellStyleXF(blob,length,0);}
|
||||
@ -5816,8 +5913,19 @@ var rc_to_a1 = (function(){
|
||||
};
|
||||
})();
|
||||
|
||||
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
|
||||
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
|
||||
var a1_to_rc =(function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
/* TODO: handle fixcol / fixrow */
|
||||
var c = decode_col($3) - base.c;
|
||||
var r = decode_row($5) - base.r;
|
||||
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
||||
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
|
||||
function shift_formula_str(f/*:string*/, delta/*:Cell*/)/*:string*/ {
|
||||
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
|
||||
@ -10329,10 +10437,88 @@ function parse_xlml(data, opts)/*:Workbook*/ {
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
function write_xlml(wb, opts)/*:string*/ {
|
||||
var o = [XML_HEADER];
|
||||
function write_props_xlml(wb, opts) {
|
||||
var o = [];
|
||||
/* DocumentProperties */
|
||||
if(wb.Props) o.push(xlml_write_docprops(wb.Props));
|
||||
/* CustomDocumentProperties */
|
||||
if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops));
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO */
|
||||
function write_wb_xlml(wb, opts) {
|
||||
/* OfficeDocumentSettings */
|
||||
/* ExcelWorkbook */
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
function write_sty_xlml(wb, opts)/*:string*/ {
|
||||
/* Styles */
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)/*:string*/{
|
||||
if(!cell || cell.v === undefined) return "<Cell></Cell>";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
|
||||
var t = "", p = "";
|
||||
switch(cell.t) {
|
||||
case 'n': t = 'Number'; p = String(cell.v); break;
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
|
||||
default: t = 'String'; p = escapexml(cell.v||"");
|
||||
}
|
||||
var m = '<Data ss:Type="' + t + '">' + p + '</Data>';
|
||||
|
||||
return writextag("Cell", m, attr);
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_table(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||
if(!ws['!ref']) return "";
|
||||
var range = safe_decode_range(ws['!ref']);
|
||||
var o = [];
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
var row = ["<Row>"];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
var addr = {r:R,c:C};
|
||||
var ref = encode_cell(addr), cell = ws[ref];
|
||||
row.push(write_ws_xlml_cell(ws[ref], ref, ws, opts, idx, wb, addr));
|
||||
}
|
||||
row.push("</Row>");
|
||||
o.push(row.join(""));
|
||||
}
|
||||
return o.join("");
|
||||
}
|
||||
function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ {
|
||||
var o = [];
|
||||
var s = wb.SheetNames[idx];
|
||||
var ws = wb.Sheets[s];
|
||||
|
||||
/* Table */
|
||||
var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Table>" + t + "</Table>");
|
||||
/* WorksheetOptions */
|
||||
return o.join("");
|
||||
}
|
||||
function write_xlml(wb, opts)/*:string*/ {
|
||||
var d = [];
|
||||
d.push(write_props_xlml(wb, opts));
|
||||
d.push(write_wb_xlml(wb, opts));
|
||||
d.push(write_sty_xlml(wb, opts));
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i)
|
||||
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
|
||||
return XML_HEADER + writextag("Workbook", d.join(""), {
|
||||
'xmlns': XLMLNS.ss,
|
||||
'xmlns:o': XLMLNS.o,
|
||||
'xmlns:x': XLMLNS.x,
|
||||
'xmlns:ss': XLMLNS.ss,
|
||||
'xmlns:dt': XLMLNS.dt,
|
||||
'xmlns:html': XLMLNS.html
|
||||
});
|
||||
}
|
||||
/* [MS-OLEDS] 2.3.8 CompObjStream */
|
||||
function parse_compobj(obj) {
|
||||
var v = {};
|
||||
@ -10644,9 +10830,9 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
@ -10658,7 +10844,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
last_formula.val = val;
|
||||
temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'}/*:any*/);
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
@ -10669,7 +10855,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
if(options.cellFormula && out[last_cell]) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!last_cell || !out[last_cell]) break; /* technically unreachable */
|
||||
out[last_cell].f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
@ -10680,7 +10866,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
(out[encode_cell(last_formula.cell)]||{}).f = stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
(out[encode_cell(last_formula.cell)]||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
} break;
|
||||
case 'LabelSst':
|
||||
@ -13286,7 +13472,8 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
|
||||
check_wb(wb);
|
||||
var o = opts||{};
|
||||
switch(o.bookType || 'xlsx') {
|
||||
case 'xml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'xml':
|
||||
case 'xlml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'csv': return write_string_type(write_csv_str(wb, o), o);
|
||||
case 'fods': return write_string_type(write_ods(wb, o), o);
|
||||
case 'biff2': return write_binary_type(write_biff_buf(wb, o), o);
|
||||
@ -13306,6 +13493,7 @@ function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOp
|
||||
case '.xlsm': o.bookType = 'xlsm'; break;
|
||||
case '.xlsb': o.bookType = 'xlsb'; break;
|
||||
case '.fods': o.bookType = 'fods'; break;
|
||||
case '.xlml': o.bookType = 'xlml'; break;
|
||||
default: switch(o.file.slice(-4).toLowerCase()) {
|
||||
case '.xls': o.bookType = 'biff2'; break;
|
||||
case '.xml': o.bookType = 'xml'; break;
|
||||
|
206
xlsx.js
206
xlsx.js
@ -1465,6 +1465,7 @@ 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)).slice(-4) + "_";});
|
||||
}
|
||||
function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
|
||||
|
||||
/* TODO: handle codepages */
|
||||
var xlml_fixstr = (function() {
|
||||
@ -1591,6 +1592,13 @@ XMLNS.main = [
|
||||
'http://schemas.microsoft.com/office/excel/2006/2'
|
||||
];
|
||||
|
||||
var XLMLNS = ({
|
||||
'o': 'urn:schemas-microsoft-com:office:office',
|
||||
'x': 'urn:schemas-microsoft-com:office:excel',
|
||||
'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
|
||||
'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
|
||||
'html': 'http://www.w3.org/TR/REC-html40'
|
||||
});
|
||||
function read_double_le(b, idx) {
|
||||
var s = 1 - 2 * (b[idx + 7] >>> 7);
|
||||
var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
|
||||
@ -2968,10 +2976,67 @@ function xlml_set_prop(Props, tag, val) {
|
||||
/* TODO: Normalize the properties */
|
||||
switch(tag) {
|
||||
case 'Description': tag = 'Comments'; break;
|
||||
case 'Created': tag = 'CreatedDate'; break;
|
||||
case 'LastSaved': tag = 'ModifiedDate'; break;
|
||||
}
|
||||
Props[tag] = val;
|
||||
}
|
||||
|
||||
var XLMLDocumentProperties = [
|
||||
['Title', 'Title'],
|
||||
['Subject', 'Subject'],
|
||||
['Author', 'Author'],
|
||||
['Keywords', 'Keywords'],
|
||||
['Comments', 'Description'],
|
||||
['LastAuthor', 'LastAuthor'],
|
||||
['CreatedDate', 'Created', 'date'],
|
||||
['ModifiedDate', 'LastSaved', 'date'],
|
||||
['Category', 'Category'],
|
||||
['Manager', 'Manager'],
|
||||
['Company', 'Company'],
|
||||
['AppVersion', 'Version']
|
||||
];
|
||||
|
||||
/* TODO: verify */
|
||||
function xlml_write_docprops(Props) {
|
||||
var T = 'DocumentProperties';
|
||||
var o = [];
|
||||
XLMLDocumentProperties.forEach(function(p) {
|
||||
if(!Props[p[0]]) return;
|
||||
var m = Props[p[0]];
|
||||
switch(p[2]) {
|
||||
case 'date': m = new Date(m).toISOString(); break;
|
||||
}
|
||||
o.push(writetag(p[1], m));
|
||||
});
|
||||
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
|
||||
}
|
||||
function xlml_write_custprops(Props, Custprops) {
|
||||
var T = 'CustomDocumentProperties';
|
||||
var o = [];
|
||||
if(Props) keys(Props).forEach(function(k) {
|
||||
if(!Props.hasOwnProperty(k)) return;
|
||||
for(var i = 0; i < XLMLDocumentProperties.length; ++i)
|
||||
if(k == XLMLDocumentProperties[i][0]) return;
|
||||
var m = Props[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
if(Custprops) keys(Custprops).forEach(function(k) {
|
||||
if(!Custprops.hasOwnProperty(k)) return;
|
||||
var m = Custprops[k];
|
||||
var t = "string";
|
||||
if(typeof m == 'number') { t = "float"; m = String(m); }
|
||||
else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
|
||||
else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
|
||||
else m = String(m);
|
||||
o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
|
||||
});
|
||||
return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
|
||||
}
|
||||
/* [MS-DTYP] 2.3.3 FILETIME */
|
||||
/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
|
||||
/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
|
||||
@ -3736,14 +3801,44 @@ function parse_MulRk(blob, length) {
|
||||
return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
|
||||
}
|
||||
|
||||
/* 2.5.20 2.5.249 TODO */
|
||||
/* 2.5.20 2.5.249 TODO: interpret values here */
|
||||
function parse_CellStyleXF(blob, length, style) {
|
||||
var o = {};
|
||||
var a = blob.read_shift(4), b = blob.read_shift(4);
|
||||
var c = blob.read_shift(4), d = blob.read_shift(2);
|
||||
o.patternType = XLSFillPattern[c >> 26];
|
||||
|
||||
o.alc = a & 0x07;
|
||||
o.fWrap = (a >> 3) & 0x01;
|
||||
o.alcV = (a >> 4) & 0x07;
|
||||
o.fJustLast = (a >> 7) & 0x01;
|
||||
o.trot = (a >> 8) & 0xFF;
|
||||
o.cIndent = (a >> 16) & 0x0F;
|
||||
o.fShrinkToFit = (a >> 20) & 0x01;
|
||||
o.iReadOrder = (a >> 22) & 0x02;
|
||||
o.fAtrNum = (a >> 26) & 0x01;
|
||||
o.fAtrFnt = (a >> 27) & 0x01;
|
||||
o.fAtrAlc = (a >> 28) & 0x01;
|
||||
o.fAtrBdr = (a >> 29) & 0x01;
|
||||
o.fAtrPat = (a >> 30) & 0x01;
|
||||
o.fAtrProt = (a >> 31) & 0x01;
|
||||
|
||||
o.dgLeft = b & 0x0F;
|
||||
o.dgRight = (b >> 4) & 0x0F;
|
||||
o.dgTop = (b >> 8) & 0x0F;
|
||||
o.dgBottom = (b >> 12) & 0x0F;
|
||||
o.icvLeft = (b >> 16) & 0x7F;
|
||||
o.icvRight = (b >> 23) & 0x7F;
|
||||
o.grbitDiag = (b >> 30) & 0x03;
|
||||
|
||||
o.icvTop = c & 0x7F;
|
||||
o.icvBottom = (c >> 7) & 0x7F;
|
||||
o.icvDiag = (c >> 14) & 0x7F;
|
||||
o.dgDiag = (c >> 21) & 0x0F;
|
||||
|
||||
o.icvFore = d & 0x7F;
|
||||
o.icvBack = (d >> 7) & 0x7F;
|
||||
o.fsxButton = (d >> 14) & 0x01;
|
||||
return o;
|
||||
}
|
||||
function parse_CellXF(blob, length) {return parse_CellStyleXF(blob,length,0);}
|
||||
@ -5766,8 +5861,19 @@ var rc_to_a1 = (function(){
|
||||
};
|
||||
})();
|
||||
|
||||
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
|
||||
var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
|
||||
var a1_to_rc =(function(){
|
||||
return function a1_to_rc(fstr, base) {
|
||||
return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
/* TODO: handle fixcol / fixrow */
|
||||
var c = decode_col($3) - base.c;
|
||||
var r = decode_row($5) - base.r;
|
||||
return $1 + "R" + (r == 0 ? "" : "[" + r + "]") + "C" + (c == 0 ? "" : "[" + c + "]");
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
||||
/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
|
||||
function shift_formula_str(f, delta) {
|
||||
return f.replace(crefregex, function($0, $1, $2, $3, $4, $5, off, str) {
|
||||
return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
|
||||
@ -10275,10 +10381,88 @@ function parse_xlml(data, opts) {
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
function write_xlml(wb, opts) {
|
||||
var o = [XML_HEADER];
|
||||
function write_props_xlml(wb, opts) {
|
||||
var o = [];
|
||||
/* DocumentProperties */
|
||||
if(wb.Props) o.push(xlml_write_docprops(wb.Props));
|
||||
/* CustomDocumentProperties */
|
||||
if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops));
|
||||
return o.join("");
|
||||
}
|
||||
/* TODO */
|
||||
function write_wb_xlml(wb, opts) {
|
||||
/* OfficeDocumentSettings */
|
||||
/* ExcelWorkbook */
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
function write_sty_xlml(wb, opts) {
|
||||
/* Styles */
|
||||
return "";
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
|
||||
if(!cell || cell.v === undefined) return "<Cell></Cell>";
|
||||
|
||||
var attr = {};
|
||||
if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
|
||||
|
||||
var t = "", p = "";
|
||||
switch(cell.t) {
|
||||
case 'n': t = 'Number'; p = String(cell.v); break;
|
||||
case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
|
||||
case 'e': t = 'Error'; p = BErr[cell.v]; break;
|
||||
case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); break;
|
||||
default: t = 'String'; p = escapexml(cell.v||"");
|
||||
}
|
||||
var m = '<Data ss:Type="' + t + '">' + p + '</Data>';
|
||||
|
||||
return writextag("Cell", m, attr);
|
||||
}
|
||||
/* TODO */
|
||||
function write_ws_xlml_table(ws, opts, idx, wb) {
|
||||
if(!ws['!ref']) return "";
|
||||
var range = safe_decode_range(ws['!ref']);
|
||||
var o = [];
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
var row = ["<Row>"];
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
var addr = {r:R,c:C};
|
||||
var ref = encode_cell(addr), cell = ws[ref];
|
||||
row.push(write_ws_xlml_cell(ws[ref], ref, ws, opts, idx, wb, addr));
|
||||
}
|
||||
row.push("</Row>");
|
||||
o.push(row.join(""));
|
||||
}
|
||||
return o.join("");
|
||||
}
|
||||
function write_ws_xlml(idx, opts, wb) {
|
||||
var o = [];
|
||||
var s = wb.SheetNames[idx];
|
||||
var ws = wb.Sheets[s];
|
||||
|
||||
/* Table */
|
||||
var t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
|
||||
if(t.length > 0) o.push("<Table>" + t + "</Table>");
|
||||
/* WorksheetOptions */
|
||||
return o.join("");
|
||||
}
|
||||
function write_xlml(wb, opts) {
|
||||
var d = [];
|
||||
d.push(write_props_xlml(wb, opts));
|
||||
d.push(write_wb_xlml(wb, opts));
|
||||
d.push(write_sty_xlml(wb, opts));
|
||||
for(var i = 0; i < wb.SheetNames.length; ++i)
|
||||
d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
|
||||
return XML_HEADER + writextag("Workbook", d.join(""), {
|
||||
'xmlns': XLMLNS.ss,
|
||||
'xmlns:o': XLMLNS.o,
|
||||
'xmlns:x': XLMLNS.x,
|
||||
'xmlns:ss': XLMLNS.ss,
|
||||
'xmlns:dt': XLMLNS.dt,
|
||||
'xmlns:html': XLMLNS.html
|
||||
});
|
||||
}
|
||||
/* [MS-OLEDS] 2.3.8 CompObjStream */
|
||||
function parse_compobj(obj) {
|
||||
var v = {};
|
||||
@ -10590,9 +10774,9 @@ function parse_workbook(blob, options) {
|
||||
if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
|
||||
var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
|
||||
var _fe = encode_cell({r:_fr, c:_fc});
|
||||
if(shared_formulae[_fe]) temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
if(shared_formulae[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
else temp_val.F = (out[_fe] || {}).F;
|
||||
} else temp_val.f = stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
} else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
|
||||
}
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(val.cell, temp_val, options);
|
||||
@ -10604,7 +10788,7 @@ function parse_workbook(blob, options) {
|
||||
last_formula.val = val;
|
||||
temp_val = ({v:last_formula.val, ixfe:last_formula.cell.ixfe, t:'s'});
|
||||
temp_val.XF = XFs[temp_val.ixfe];
|
||||
if(options.cellFormula) temp_val.f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
if(options.cellFormula) temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
safe_format_xf(temp_val, options, wb.opts.Date1904);
|
||||
addcell(last_formula.cell, temp_val, options);
|
||||
last_formula = null;
|
||||
@ -10615,7 +10799,7 @@ function parse_workbook(blob, options) {
|
||||
if(options.cellFormula && out[last_cell]) {
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
if(!last_cell || !out[last_cell]) break; /* technically unreachable */
|
||||
out[last_cell].f = stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
|
||||
out[last_cell].F = encode_range(val[0]);
|
||||
}
|
||||
} break;
|
||||
@ -10626,7 +10810,7 @@ function parse_workbook(blob, options) {
|
||||
/* TODO: capture range */
|
||||
if(!last_formula) break; /* technically unreachable */
|
||||
shared_formulae[encode_cell(last_formula.cell)]= val[0];
|
||||
(out[encode_cell(last_formula.cell)]||{}).f = stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
(out[encode_cell(last_formula.cell)]||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
|
||||
}
|
||||
} break;
|
||||
case 'LabelSst':
|
||||
@ -13228,7 +13412,8 @@ function writeSync(wb, opts) {
|
||||
check_wb(wb);
|
||||
var o = opts||{};
|
||||
switch(o.bookType || 'xlsx') {
|
||||
case 'xml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'xml':
|
||||
case 'xlml': return write_string_type(write_xlml(wb, o), o);
|
||||
case 'csv': return write_string_type(write_csv_str(wb, o), o);
|
||||
case 'fods': return write_string_type(write_ods(wb, o), o);
|
||||
case 'biff2': return write_binary_type(write_biff_buf(wb, o), o);
|
||||
@ -13248,6 +13433,7 @@ function writeFileSync(wb, filename, opts) {
|
||||
case '.xlsm': o.bookType = 'xlsm'; break;
|
||||
case '.xlsb': o.bookType = 'xlsb'; break;
|
||||
case '.fods': o.bookType = 'fods'; break;
|
||||
case '.xlml': o.bookType = 'xlml'; break;
|
||||
default: switch(o.file.slice(-4).toLowerCase()) {
|
||||
case '.xls': o.bookType = 'biff2'; break;
|
||||
case '.xml': o.bookType = 'xml'; break;
|
||||
|
Loading…
Reference in New Issue
Block a user