forked from sheetjs/sheetjs
more format parity
- XLS/XLSX/XLSB/XML/ODS cellFormula option + test - XLS/XLSX/XLSB/XML/ODS cellText option + test - XML document property order - XML write margins + protection - removed gitbook search
This commit is contained in:
parent
83ec60688f
commit
95a377c0e4
@ -12,6 +12,8 @@ enhancements and additional features by request.
|
|||||||
|
|
||||||
[**Commercial Support**](http://sheetjs.com/support)
|
[**Commercial Support**](http://sheetjs.com/support)
|
||||||
|
|
||||||
|
[**Rendered Documentation**](https://sheetjs.gitbooks.io/docs/)
|
||||||
|
|
||||||
[**In-Browser Demos**](http://sheetjs.com/demos)
|
[**In-Browser Demos**](http://sheetjs.com/demos)
|
||||||
|
|
||||||
[**Source Code**](http://git.io/xlsx)
|
[**Source Code**](http://git.io/xlsx)
|
||||||
@ -634,8 +636,9 @@ In addition to the base sheet keys, worksheets also add:
|
|||||||
the first cell (upper-left) in the range is set.
|
the first cell (upper-left) in the range is set.
|
||||||
|
|
||||||
- `ws['protect']`: object of write sheet protection properties. The `password`
|
- `ws['protect']`: object of write sheet protection properties. The `password`
|
||||||
key specifies the password. The writer uses the XOR obfuscation method. The
|
key specifies the password for formats that support password-protected sheets
|
||||||
following keys control the sheet protection (same as ECMA-376 18.3.1.85):
|
(XLSX/XLSB/XLS). The writer uses the XOR obfuscation method. The following
|
||||||
|
keys control the sheet protection (same as ECMA-376 18.3.1.85):
|
||||||
|
|
||||||
| key | functionality disabled if value is true |
|
| key | functionality disabled if value is true |
|
||||||
|:----------------------|:-----------------------------------------------------|
|
|:----------------------|:-----------------------------------------------------|
|
||||||
@ -659,7 +662,7 @@ In addition to the base sheet keys, worksheets also add:
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
type AutoFilter = {
|
type AutoFilter = {
|
||||||
ref:string; // A-1 based range representing the AutoFilter table range
|
ref:string; // A-1 based range representing the AutoFilter table range
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,25 +1,35 @@
|
|||||||
/* Common Name -> XLML Name */
|
/* Common Name -> XLML Name */
|
||||||
var XLMLDocPropsMap = {
|
var XLMLDocPropsMap = {
|
||||||
Category: 'Category',
|
|
||||||
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
|
|
||||||
Keywords: 'Keywords',
|
|
||||||
LastAuthor: 'LastAuthor',
|
|
||||||
LastPrinted: 'LastPrinted',
|
|
||||||
RevNumber: 'Revision',
|
|
||||||
Author: 'Author',
|
|
||||||
Comments: 'Description',
|
|
||||||
Identifier: 'Identifier', /* NOTE: missing from schema */
|
|
||||||
Language: 'Language', /* NOTE: missing from schema */
|
|
||||||
Subject: 'Subject',
|
|
||||||
Title: 'Title',
|
Title: 'Title',
|
||||||
|
Subject: 'Subject',
|
||||||
|
Author: 'Author',
|
||||||
|
Keywords: 'Keywords',
|
||||||
|
Comments: 'Description',
|
||||||
|
LastAuthor: 'LastAuthor',
|
||||||
|
RevNumber: 'Revision',
|
||||||
|
Application: 'AppName',
|
||||||
|
/* TotalTime: 'TotalTime', */
|
||||||
|
LastPrinted: 'LastPrinted',
|
||||||
CreatedDate: 'Created',
|
CreatedDate: 'Created',
|
||||||
ModifiedDate: 'LastSaved',
|
ModifiedDate: 'LastSaved',
|
||||||
|
/* Pages */
|
||||||
Application: 'AppName',
|
/* Words */
|
||||||
AppVersion: 'Version',
|
/* Characters */
|
||||||
TotalTime: 'TotalTime',
|
Category: 'Category',
|
||||||
|
/* PresentationFormat */
|
||||||
Manager: 'Manager',
|
Manager: 'Manager',
|
||||||
Company: 'Company'
|
Company: 'Company',
|
||||||
|
/* Guid */
|
||||||
|
/* HyperlinkBase */
|
||||||
|
/* Bytes */
|
||||||
|
/* Lines */
|
||||||
|
/* Paragraphs */
|
||||||
|
/* CharactersWithSpaces */
|
||||||
|
AppVersion: 'Version',
|
||||||
|
|
||||||
|
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
|
||||||
|
Identifier: 'Identifier', /* NOTE: missing from schema */
|
||||||
|
Language: 'Language' /* NOTE: missing from schema */
|
||||||
};
|
};
|
||||||
var evert_XLMLDPM = evert(XLMLDocPropsMap);
|
var evert_XLMLDPM = evert(XLMLDocPropsMap);
|
||||||
|
|
||||||
@ -28,19 +38,21 @@ function xlml_set_prop(Props, tag/*:string*/, val) {
|
|||||||
Props[tag] = val;
|
Props[tag] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: verify */
|
|
||||||
function xlml_write_docprops(Props, opts) {
|
function xlml_write_docprops(Props, opts) {
|
||||||
var o = [];
|
var o = [];
|
||||||
CORE_PROPS.concat(EXT_PROPS).forEach(function(p) {
|
keys(XLMLDocPropsMap).map(function(m) {
|
||||||
|
for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
|
||||||
|
for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
|
||||||
|
throw m;
|
||||||
|
}).forEach(function(p) {
|
||||||
if(Props[p[1]] == null) return;
|
if(Props[p[1]] == null) return;
|
||||||
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
|
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
|
||||||
switch(p[2]) {
|
switch(p[2]) {
|
||||||
case 'date': m = new Date(m).toISOString(); break;
|
case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
|
||||||
}
|
}
|
||||||
if(typeof m == 'number') m = String(m);
|
if(typeof m == 'number') m = String(m);
|
||||||
else if(m === true || m === false) { m = m ? "1" : "0"; }
|
else if(m === true || m === false) { m = m ? "1" : "0"; }
|
||||||
else if(m instanceof Date) m = new Date(m).toISOString();
|
else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
|
||||||
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
|
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
|
||||||
});
|
});
|
||||||
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
|
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
|
||||||
|
@ -244,8 +244,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
/* 18.3.1.73 row CT_Row */
|
/* 18.3.1.73 row CT_Row */
|
||||||
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
||||||
tag = parsexmltag(x.substr(0,ri), true);
|
tag = parsexmltag(x.substr(0,ri), true);
|
||||||
/* SpreadSheetGear uses implicit r/c */
|
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
|
||||||
tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
|
|
||||||
if(opts.sheetRows && opts.sheetRows < tagr) continue;
|
if(opts.sheetRows && opts.sheetRows < tagr) continue;
|
||||||
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
||||||
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
||||||
@ -297,7 +296,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
p.F = arrayf[i][1];
|
p.F = arrayf[i][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tag.t === undefined && p.v === undefined) {
|
if(tag.t == null && p.v === undefined) {
|
||||||
if(!opts.sheetStubs) continue;
|
if(!opts.sheetStubs) continue;
|
||||||
p.t = "z";
|
p.t = "z";
|
||||||
}
|
}
|
||||||
@ -335,7 +334,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
break;
|
break;
|
||||||
/* error string in .w, number in .v */
|
/* error string in .w, number in .v */
|
||||||
case 'e':
|
case 'e':
|
||||||
if(opts && opts.cellText === false) p.w = p.v;
|
if(!opts || opts.cellText !== false) p.w = p.v;
|
||||||
p.v = RBErr[p.v]; break;
|
p.v = RBErr[p.v]; break;
|
||||||
}
|
}
|
||||||
/* formatting */
|
/* formatting */
|
||||||
|
@ -400,7 +400,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
|
|||||||
case 'n': p.v = val[1]; break;
|
case 'n': p.v = val[1]; break;
|
||||||
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
|
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
|
||||||
case 'b': p.v = val[1] ? true : false; break;
|
case 'b': p.v = val[1] ? true : false; break;
|
||||||
case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
|
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
|
||||||
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
|
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
|
||||||
}
|
}
|
||||||
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
|
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
|
||||||
|
@ -121,11 +121,11 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
|
|||||||
if(cell.v === undefined) cell.v=+xml;
|
if(cell.v === undefined) cell.v=+xml;
|
||||||
if(!cell.t) cell.t = 'n';
|
if(!cell.t) cell.t = 'n';
|
||||||
break;
|
break;
|
||||||
case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break;
|
case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break;
|
||||||
default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
|
default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
|
||||||
}
|
}
|
||||||
safe_format_xlml(cell, nf, o);
|
safe_format_xlml(cell, nf, o);
|
||||||
if(o.cellFormula != null) {
|
if(o.cellFormula !== false) {
|
||||||
if(cell.Formula) {
|
if(cell.Formula) {
|
||||||
var fstr = unescapexml(cell.Formula);
|
var fstr = unescapexml(cell.Formula);
|
||||||
/* strictly speaking, the leading = is required but some writers omit */
|
/* strictly speaking, the leading = is required but some writers omit */
|
||||||
@ -837,17 +837,107 @@ function write_sty_xlml(wb, opts)/*:string*/ {
|
|||||||
}
|
}
|
||||||
/* WorksheetOptions */
|
/* WorksheetOptions */
|
||||||
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||||
|
if(!ws) return "";
|
||||||
var o = [];
|
var o = [];
|
||||||
|
/* NOTE: spec technically allows any order, but stick with implied order */
|
||||||
|
|
||||||
|
/* FitToPage */
|
||||||
|
/* DoNotDisplayColHeaders */
|
||||||
|
/* DoNotDisplayRowHeaders */
|
||||||
|
/* ViewableRange */
|
||||||
|
/* Selection */
|
||||||
|
/* GridlineColor */
|
||||||
|
/* Name */
|
||||||
|
/* ExcelWorksheetType */
|
||||||
|
/* IntlMacro */
|
||||||
|
/* Unsynced */
|
||||||
|
/* Selected */
|
||||||
|
/* CodeName */
|
||||||
|
|
||||||
|
if(ws['!margins']) {
|
||||||
|
o.push("<PageSetup>");
|
||||||
|
if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header}));
|
||||||
|
if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer}));
|
||||||
|
o.push(writextag("PageMargins", null, {
|
||||||
|
'x:Bottom': ws['!margins'].bottom || "0.75",
|
||||||
|
'x:Left': ws['!margins'].left || "0.7",
|
||||||
|
'x:Right': ws['!margins'].right || "0.7",
|
||||||
|
'x:Top': ws['!margins'].top || "0.75"
|
||||||
|
}));
|
||||||
|
o.push("</PageSetup>");
|
||||||
|
}
|
||||||
|
|
||||||
/* PageSetup */
|
/* PageSetup */
|
||||||
|
/* DisplayPageBreak */
|
||||||
|
/* TransitionExpressionEvaluation */
|
||||||
|
/* TransitionFormulaEntry */
|
||||||
|
/* Print */
|
||||||
|
/* Zoom */
|
||||||
|
/* PageLayoutZoom */
|
||||||
|
/* PageBreakZoom */
|
||||||
|
/* ShowPageBreakZoom */
|
||||||
|
/* DefaultRowHeight */
|
||||||
|
/* DefaultColumnWidth */
|
||||||
|
/* StandardWidth */
|
||||||
|
|
||||||
if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
|
if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
|
||||||
/* Visible */
|
/* Visible */
|
||||||
if(!!wb.Workbook.Sheets[idx].Hidden) o.push("<Visible>" + (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden") + "</Visible>");
|
if(!!wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {}));
|
||||||
else {
|
else {
|
||||||
/* Selected */
|
/* Selected */
|
||||||
for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
|
for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
|
||||||
if(i == idx) o.push("<Selected/>");
|
if(i == idx) o.push("<Selected/>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* LeftColumnVisible */
|
||||||
|
/* DisplayRightToLeft */
|
||||||
|
/* GridlineColorIndex */
|
||||||
|
/* DisplayFormulas */
|
||||||
|
/* DoNotDisplayGridlines */
|
||||||
|
/* DoNotDisplayHeadings */
|
||||||
|
/* DoNotDisplayOutline */
|
||||||
|
/* ApplyAutomaticOutlineStyles */
|
||||||
|
/* NoSummaryRowsBelowDetail */
|
||||||
|
/* NoSummaryColumnsRightDetail */
|
||||||
|
/* DoNotDisplayZeros */
|
||||||
|
/* ActiveRow */
|
||||||
|
/* ActiveColumn */
|
||||||
|
/* FilterOn */
|
||||||
|
/* RangeSelection */
|
||||||
|
/* TopRowVisible */
|
||||||
|
/* TopRowBottomPane */
|
||||||
|
/* LeftColumnRightPane */
|
||||||
|
/* ActivePane */
|
||||||
|
/* SplitHorizontal */
|
||||||
|
/* SplitVertical */
|
||||||
|
/* FreezePanes */
|
||||||
|
/* FrozenNoSplit */
|
||||||
|
/* TabColorIndex */
|
||||||
|
/* Panes */
|
||||||
|
|
||||||
|
/* NOTE: Password not supported in XLML Format */
|
||||||
|
if(ws['!protect']) {
|
||||||
|
o.push(writetag("ProtectContents", "True"));
|
||||||
|
if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True"));
|
||||||
|
if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True"));
|
||||||
|
if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection"));
|
||||||
|
else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells"));
|
||||||
|
[
|
||||||
|
[ "formatColumns", "AllowFormatCells" ],
|
||||||
|
[ "formatRows", "AllowSizeCols" ],
|
||||||
|
[ "formatCells", "AllowSizeRows" ],
|
||||||
|
[ "insertColumns", "AllowInsertCols" ],
|
||||||
|
[ "insertRows", "AllowInsertRows" ],
|
||||||
|
[ "insertHyperlinks", "AllowInsertHyperlinks" ],
|
||||||
|
[ "deleteColumns", "AllowDeleteCols" ],
|
||||||
|
[ "deleteRows", "AllowDeleteRows" ],
|
||||||
|
[ "sort", "AllowSort" ],
|
||||||
|
[ "autoFilter", "AllowFilter" ],
|
||||||
|
[ "pivotTables", "AllowUsePivotTables" ]
|
||||||
|
].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); });
|
||||||
|
}
|
||||||
|
|
||||||
if(o.length == 0) return "";
|
if(o.length == 0) return "";
|
||||||
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
|
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
|
||||||
}
|
}
|
||||||
|
@ -54,12 +54,13 @@ function slurp(R, blob, length/*:number*/, opts) {
|
|||||||
|
|
||||||
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
||||||
if(p.t === 'z') return;
|
if(p.t === 'z') return;
|
||||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
|
||||||
if(!p.XF) return;
|
if(!p.XF) return;
|
||||||
try {
|
try {
|
||||||
var fmtid = p.XF.ifmt||0;
|
var fmtid = p.XF.ifmt||0;
|
||||||
if(opts.cellNF) p.z = SSF._table[fmtid];
|
if(opts.cellNF) p.z = SSF._table[fmtid];
|
||||||
if(p.t === 'e'){}
|
} catch(e) { if(opts.WTF) throw e; }
|
||||||
|
if(!opts || opts.cellText !== false) try {
|
||||||
|
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||||
else if(fmtid === 0) {
|
else if(fmtid === 0) {
|
||||||
if(p.t === 'n') {
|
if(p.t === 'n') {
|
||||||
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
|
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
|
||||||
|
@ -135,7 +135,7 @@ var parse_content_xml = (function() {
|
|||||||
isstub = textpidx == 0;
|
isstub = textpidx == 0;
|
||||||
}
|
}
|
||||||
if(comments.length > 0) { q.c = comments; comments = []; }
|
if(comments.length > 0) { q.c = comments; comments = []; }
|
||||||
if(textp) q.w = textp;
|
if(textp && opts.cellText !== false) q.w = textp;
|
||||||
if(!isstub || opts.sheetStubs) {
|
if(!isstub || opts.sheetStubs) {
|
||||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||||
if(opts.dense) {
|
if(opts.dense) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"title": "SheetJS js-xlsx",
|
"title": "SheetJS js-xlsx",
|
||||||
"author": "sheetjs",
|
"author": "sheetjs",
|
||||||
"gitbook": "3.2.2",
|
"gitbook": "3.2.2",
|
||||||
"plugins": ["anchorjs", "ga", "sidebar-ad", "-sharing", "advanced-emoji"],
|
"plugins": ["anchorjs", "ga", "sidebar-ad", "-sharing", "-search", "advanced-emoji"],
|
||||||
"pluginsConfig": {
|
"pluginsConfig": {
|
||||||
"anchorjs": {
|
"anchorjs": {
|
||||||
"icon": "#",
|
"icon": "#",
|
||||||
|
@ -12,6 +12,8 @@ enhancements and additional features by request.
|
|||||||
|
|
||||||
[**Commercial Support**](http://sheetjs.com/support)
|
[**Commercial Support**](http://sheetjs.com/support)
|
||||||
|
|
||||||
|
[**Rendered Documentation**](https://sheetjs.gitbooks.io/docs/)
|
||||||
|
|
||||||
[**In-Browser Demos**](http://sheetjs.com/demos)
|
[**In-Browser Demos**](http://sheetjs.com/demos)
|
||||||
|
|
||||||
[**Source Code**](http://git.io/xlsx)
|
[**Source Code**](http://git.io/xlsx)
|
||||||
|
@ -14,8 +14,9 @@ In addition to the base sheet keys, worksheets also add:
|
|||||||
the first cell (upper-left) in the range is set.
|
the first cell (upper-left) in the range is set.
|
||||||
|
|
||||||
- `ws['protect']`: object of write sheet protection properties. The `password`
|
- `ws['protect']`: object of write sheet protection properties. The `password`
|
||||||
key specifies the password. The writer uses the XOR obfuscation method. The
|
key specifies the password for formats that support password-protected sheets
|
||||||
following keys control the sheet protection (same as ECMA-376 18.3.1.85):
|
(XLSX/XLSB/XLS). The writer uses the XOR obfuscation method. The following
|
||||||
|
keys control the sheet protection (same as ECMA-376 18.3.1.85):
|
||||||
|
|
||||||
| key | functionality disabled if value is true |
|
| key | functionality disabled if value is true |
|
||||||
|:----------------------|:-----------------------------------------------------|
|
|:----------------------|:-----------------------------------------------------|
|
||||||
@ -39,7 +40,7 @@ In addition to the base sheet keys, worksheets also add:
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
type AutoFilter = {
|
type AutoFilter = {
|
||||||
ref:string; // A-1 based range representing the AutoFilter table range
|
ref:string; // A-1 based range representing the AutoFilter table range
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
33
test.js
33
test.js
@ -284,6 +284,7 @@ describe('parse options', function() {
|
|||||||
if(typeof before != 'undefined') before(bef);
|
if(typeof before != 'undefined') before(bef);
|
||||||
else it('before', bef);
|
else it('before', bef);
|
||||||
describe('cell', function() {
|
describe('cell', function() {
|
||||||
|
var FSTPaths = [paths.fstxls, paths.fstxml, paths.fstxlsx, paths.fstxlsb, paths.fstods];
|
||||||
it('XLSX should generate HTML by default', function() {
|
it('XLSX should generate HTML by default', function() {
|
||||||
var wb = X.readFile(paths.cstxlsx);
|
var wb = X.readFile(paths.cstxlsx);
|
||||||
var ws = wb.Sheets.Sheet1;
|
var ws = wb.Sheets.Sheet1;
|
||||||
@ -299,7 +300,7 @@ describe('parse options', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should generate formulae by default', function() {
|
it('should generate formulae by default', function() {
|
||||||
[paths.fstxls, paths.fstxlsb].forEach(function(p) {
|
FSTPaths.forEach(function(p) {
|
||||||
var wb = X.readFile(p);
|
var wb = X.readFile(p);
|
||||||
var found = false;
|
var found = false;
|
||||||
wb.SheetNames.forEach(function(s) {
|
wb.SheetNames.forEach(function(s) {
|
||||||
@ -312,7 +313,7 @@ describe('parse options', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should not generate formulae when requested', function() {
|
it('should not generate formulae when requested', function() {
|
||||||
[paths.fstxls, paths.fstxlsb].forEach(function(p) {
|
FSTPaths.forEach(function(p) {
|
||||||
var wb =X.readFile(p,{cellFormula:false});
|
var wb =X.readFile(p,{cellFormula:false});
|
||||||
wb.SheetNames.forEach(function(s) {
|
wb.SheetNames.forEach(function(s) {
|
||||||
var ws = wb.Sheets[s];
|
var ws = wb.Sheets[s];
|
||||||
@ -322,6 +323,30 @@ describe('parse options', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('should generate formatted text by default', function() {
|
||||||
|
FSTPaths.forEach(function(p) {
|
||||||
|
var wb = X.readFile(p);
|
||||||
|
var found = false;
|
||||||
|
wb.SheetNames.forEach(function(s) {
|
||||||
|
var ws = wb.Sheets[s];
|
||||||
|
each_cell(ws, function(cell) {
|
||||||
|
if(typeof cell.w !== 'undefined') return (found = true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
assert(found);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not generate formatted text when requested', function() {
|
||||||
|
FSTPaths.forEach(function(p) {
|
||||||
|
var wb =X.readFile(p,{cellText:false});
|
||||||
|
wb.SheetNames.forEach(function(s) {
|
||||||
|
var ws = wb.Sheets[s];
|
||||||
|
each_cell(ws, function(cell) {
|
||||||
|
assert(typeof cell.w === 'undefined');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
it('should not generate number formats by default', function() {
|
it('should not generate number formats by default', function() {
|
||||||
[paths.nfxls, paths.nfxlsx, paths.nfxlsb].forEach(function(p) {
|
[paths.nfxls, paths.nfxlsx, paths.nfxlsb].forEach(function(p) {
|
||||||
var wb = X.readFile(p);
|
var wb = X.readFile(p);
|
||||||
@ -1218,7 +1243,7 @@ describe('roundtrip features', function() {
|
|||||||
|
|
||||||
if(m[0].t === 'n' && m[1].t === 'n') assert.equal(m[0].v, m[1].v);
|
if(m[0].t === 'n' && m[1].t === 'n') assert.equal(m[0].v, m[1].v);
|
||||||
else if(m[0].t === 'd' && m[1].t === 'd') assert.equal(m[0].v.toString(), m[1].v.toString());
|
else if(m[0].t === 'd' && m[1].t === 'd') assert.equal(m[0].v.toString(), m[1].v.toString());
|
||||||
else if(m[1].t === 'n') assert(Math.abs(datenum(new Date(m[0].v)) - m[1].v) < 0.01); /* TODO: 1sec adjustment */
|
else if(m[1].t === 'n') assert(Math.abs(datenum(new Date(m[0].v)) - m[1].v) < 0.01);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1253,7 +1278,7 @@ describe('roundtrip features', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
(fs.existsSync(paths.pmxlsx) ? describe : describe.skip)('should preserve page margins', function() {[
|
(fs.existsSync(paths.pmxlsx) ? describe : describe.skip)('should preserve page margins', function() {[
|
||||||
//['xlml', paths.pmxml],
|
['xlml', paths.pmxml],
|
||||||
['xlsx', paths.pmxlsx],
|
['xlsx', paths.pmxlsx],
|
||||||
['xlsb', paths.pmxlsb]
|
['xlsb', paths.pmxlsb]
|
||||||
].forEach(function(w) { it(w[0], function() {
|
].forEach(function(w) { it(w[0], function() {
|
||||||
|
166
xlsx.flow.js
166
xlsx.flow.js
@ -3330,26 +3330,36 @@ function write_cust_props(cp, opts)/*:string*/ {
|
|||||||
}
|
}
|
||||||
/* Common Name -> XLML Name */
|
/* Common Name -> XLML Name */
|
||||||
var XLMLDocPropsMap = {
|
var XLMLDocPropsMap = {
|
||||||
Category: 'Category',
|
|
||||||
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
|
|
||||||
Keywords: 'Keywords',
|
|
||||||
LastAuthor: 'LastAuthor',
|
|
||||||
LastPrinted: 'LastPrinted',
|
|
||||||
RevNumber: 'Revision',
|
|
||||||
Author: 'Author',
|
|
||||||
Comments: 'Description',
|
|
||||||
Identifier: 'Identifier', /* NOTE: missing from schema */
|
|
||||||
Language: 'Language', /* NOTE: missing from schema */
|
|
||||||
Subject: 'Subject',
|
|
||||||
Title: 'Title',
|
Title: 'Title',
|
||||||
|
Subject: 'Subject',
|
||||||
|
Author: 'Author',
|
||||||
|
Keywords: 'Keywords',
|
||||||
|
Comments: 'Description',
|
||||||
|
LastAuthor: 'LastAuthor',
|
||||||
|
RevNumber: 'Revision',
|
||||||
|
Application: 'AppName',
|
||||||
|
/* TotalTime: 'TotalTime', */
|
||||||
|
LastPrinted: 'LastPrinted',
|
||||||
CreatedDate: 'Created',
|
CreatedDate: 'Created',
|
||||||
ModifiedDate: 'LastSaved',
|
ModifiedDate: 'LastSaved',
|
||||||
|
/* Pages */
|
||||||
Application: 'AppName',
|
/* Words */
|
||||||
AppVersion: 'Version',
|
/* Characters */
|
||||||
TotalTime: 'TotalTime',
|
Category: 'Category',
|
||||||
|
/* PresentationFormat */
|
||||||
Manager: 'Manager',
|
Manager: 'Manager',
|
||||||
Company: 'Company'
|
Company: 'Company',
|
||||||
|
/* Guid */
|
||||||
|
/* HyperlinkBase */
|
||||||
|
/* Bytes */
|
||||||
|
/* Lines */
|
||||||
|
/* Paragraphs */
|
||||||
|
/* CharactersWithSpaces */
|
||||||
|
AppVersion: 'Version',
|
||||||
|
|
||||||
|
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
|
||||||
|
Identifier: 'Identifier', /* NOTE: missing from schema */
|
||||||
|
Language: 'Language' /* NOTE: missing from schema */
|
||||||
};
|
};
|
||||||
var evert_XLMLDPM = evert(XLMLDocPropsMap);
|
var evert_XLMLDPM = evert(XLMLDocPropsMap);
|
||||||
|
|
||||||
@ -3358,19 +3368,21 @@ function xlml_set_prop(Props, tag/*:string*/, val) {
|
|||||||
Props[tag] = val;
|
Props[tag] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: verify */
|
|
||||||
function xlml_write_docprops(Props, opts) {
|
function xlml_write_docprops(Props, opts) {
|
||||||
var o = [];
|
var o = [];
|
||||||
CORE_PROPS.concat(EXT_PROPS).forEach(function(p) {
|
keys(XLMLDocPropsMap).map(function(m) {
|
||||||
|
for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
|
||||||
|
for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
|
||||||
|
throw m;
|
||||||
|
}).forEach(function(p) {
|
||||||
if(Props[p[1]] == null) return;
|
if(Props[p[1]] == null) return;
|
||||||
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
|
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
|
||||||
switch(p[2]) {
|
switch(p[2]) {
|
||||||
case 'date': m = new Date(m).toISOString(); break;
|
case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
|
||||||
}
|
}
|
||||||
if(typeof m == 'number') m = String(m);
|
if(typeof m == 'number') m = String(m);
|
||||||
else if(m === true || m === false) { m = m ? "1" : "0"; }
|
else if(m === true || m === false) { m = m ? "1" : "0"; }
|
||||||
else if(m instanceof Date) m = new Date(m).toISOString();
|
else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
|
||||||
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
|
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
|
||||||
});
|
});
|
||||||
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
|
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
|
||||||
@ -10228,8 +10240,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
/* 18.3.1.73 row CT_Row */
|
/* 18.3.1.73 row CT_Row */
|
||||||
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
||||||
tag = parsexmltag(x.substr(0,ri), true);
|
tag = parsexmltag(x.substr(0,ri), true);
|
||||||
/* SpreadSheetGear uses implicit r/c */
|
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
|
||||||
tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
|
|
||||||
if(opts.sheetRows && opts.sheetRows < tagr) continue;
|
if(opts.sheetRows && opts.sheetRows < tagr) continue;
|
||||||
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
||||||
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
||||||
@ -10281,7 +10292,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
p.F = arrayf[i][1];
|
p.F = arrayf[i][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tag.t === undefined && p.v === undefined) {
|
if(tag.t == null && p.v === undefined) {
|
||||||
if(!opts.sheetStubs) continue;
|
if(!opts.sheetStubs) continue;
|
||||||
p.t = "z";
|
p.t = "z";
|
||||||
}
|
}
|
||||||
@ -10319,7 +10330,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
break;
|
break;
|
||||||
/* error string in .w, number in .v */
|
/* error string in .w, number in .v */
|
||||||
case 'e':
|
case 'e':
|
||||||
if(opts && opts.cellText === false) p.w = p.v;
|
if(!opts || opts.cellText !== false) p.w = p.v;
|
||||||
p.v = RBErr[p.v]; break;
|
p.v = RBErr[p.v]; break;
|
||||||
}
|
}
|
||||||
/* formatting */
|
/* formatting */
|
||||||
@ -10881,7 +10892,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles)/*:Worksheet*/ {
|
|||||||
case 'n': p.v = val[1]; break;
|
case 'n': p.v = val[1]; break;
|
||||||
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
|
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
|
||||||
case 'b': p.v = val[1] ? true : false; break;
|
case 'b': p.v = val[1] ? true : false; break;
|
||||||
case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
|
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
|
||||||
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
|
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
|
||||||
}
|
}
|
||||||
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
|
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
|
||||||
@ -12145,11 +12156,11 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
|
|||||||
if(cell.v === undefined) cell.v=+xml;
|
if(cell.v === undefined) cell.v=+xml;
|
||||||
if(!cell.t) cell.t = 'n';
|
if(!cell.t) cell.t = 'n';
|
||||||
break;
|
break;
|
||||||
case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break;
|
case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break;
|
||||||
default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
|
default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
|
||||||
}
|
}
|
||||||
safe_format_xlml(cell, nf, o);
|
safe_format_xlml(cell, nf, o);
|
||||||
if(o.cellFormula != null) {
|
if(o.cellFormula !== false) {
|
||||||
if(cell.Formula) {
|
if(cell.Formula) {
|
||||||
var fstr = unescapexml(cell.Formula);
|
var fstr = unescapexml(cell.Formula);
|
||||||
/* strictly speaking, the leading = is required but some writers omit */
|
/* strictly speaking, the leading = is required but some writers omit */
|
||||||
@ -12861,17 +12872,107 @@ function write_sty_xlml(wb, opts)/*:string*/ {
|
|||||||
}
|
}
|
||||||
/* WorksheetOptions */
|
/* WorksheetOptions */
|
||||||
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook*/)/*:string*/ {
|
||||||
|
if(!ws) return "";
|
||||||
var o = [];
|
var o = [];
|
||||||
|
/* NOTE: spec technically allows any order, but stick with implied order */
|
||||||
|
|
||||||
|
/* FitToPage */
|
||||||
|
/* DoNotDisplayColHeaders */
|
||||||
|
/* DoNotDisplayRowHeaders */
|
||||||
|
/* ViewableRange */
|
||||||
|
/* Selection */
|
||||||
|
/* GridlineColor */
|
||||||
|
/* Name */
|
||||||
|
/* ExcelWorksheetType */
|
||||||
|
/* IntlMacro */
|
||||||
|
/* Unsynced */
|
||||||
|
/* Selected */
|
||||||
|
/* CodeName */
|
||||||
|
|
||||||
|
if(ws['!margins']) {
|
||||||
|
o.push("<PageSetup>");
|
||||||
|
if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header}));
|
||||||
|
if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer}));
|
||||||
|
o.push(writextag("PageMargins", null, {
|
||||||
|
'x:Bottom': ws['!margins'].bottom || "0.75",
|
||||||
|
'x:Left': ws['!margins'].left || "0.7",
|
||||||
|
'x:Right': ws['!margins'].right || "0.7",
|
||||||
|
'x:Top': ws['!margins'].top || "0.75"
|
||||||
|
}));
|
||||||
|
o.push("</PageSetup>");
|
||||||
|
}
|
||||||
|
|
||||||
/* PageSetup */
|
/* PageSetup */
|
||||||
|
/* DisplayPageBreak */
|
||||||
|
/* TransitionExpressionEvaluation */
|
||||||
|
/* TransitionFormulaEntry */
|
||||||
|
/* Print */
|
||||||
|
/* Zoom */
|
||||||
|
/* PageLayoutZoom */
|
||||||
|
/* PageBreakZoom */
|
||||||
|
/* ShowPageBreakZoom */
|
||||||
|
/* DefaultRowHeight */
|
||||||
|
/* DefaultColumnWidth */
|
||||||
|
/* StandardWidth */
|
||||||
|
|
||||||
if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
|
if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
|
||||||
/* Visible */
|
/* Visible */
|
||||||
if(!!wb.Workbook.Sheets[idx].Hidden) o.push("<Visible>" + (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden") + "</Visible>");
|
if(!!wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {}));
|
||||||
else {
|
else {
|
||||||
/* Selected */
|
/* Selected */
|
||||||
for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
|
for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
|
||||||
if(i == idx) o.push("<Selected/>");
|
if(i == idx) o.push("<Selected/>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* LeftColumnVisible */
|
||||||
|
/* DisplayRightToLeft */
|
||||||
|
/* GridlineColorIndex */
|
||||||
|
/* DisplayFormulas */
|
||||||
|
/* DoNotDisplayGridlines */
|
||||||
|
/* DoNotDisplayHeadings */
|
||||||
|
/* DoNotDisplayOutline */
|
||||||
|
/* ApplyAutomaticOutlineStyles */
|
||||||
|
/* NoSummaryRowsBelowDetail */
|
||||||
|
/* NoSummaryColumnsRightDetail */
|
||||||
|
/* DoNotDisplayZeros */
|
||||||
|
/* ActiveRow */
|
||||||
|
/* ActiveColumn */
|
||||||
|
/* FilterOn */
|
||||||
|
/* RangeSelection */
|
||||||
|
/* TopRowVisible */
|
||||||
|
/* TopRowBottomPane */
|
||||||
|
/* LeftColumnRightPane */
|
||||||
|
/* ActivePane */
|
||||||
|
/* SplitHorizontal */
|
||||||
|
/* SplitVertical */
|
||||||
|
/* FreezePanes */
|
||||||
|
/* FrozenNoSplit */
|
||||||
|
/* TabColorIndex */
|
||||||
|
/* Panes */
|
||||||
|
|
||||||
|
/* NOTE: Password not supported in XLML Format */
|
||||||
|
if(ws['!protect']) {
|
||||||
|
o.push(writetag("ProtectContents", "True"));
|
||||||
|
if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True"));
|
||||||
|
if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True"));
|
||||||
|
if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection"));
|
||||||
|
else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells"));
|
||||||
|
[
|
||||||
|
[ "formatColumns", "AllowFormatCells" ],
|
||||||
|
[ "formatRows", "AllowSizeCols" ],
|
||||||
|
[ "formatCells", "AllowSizeRows" ],
|
||||||
|
[ "insertColumns", "AllowInsertCols" ],
|
||||||
|
[ "insertRows", "AllowInsertRows" ],
|
||||||
|
[ "insertHyperlinks", "AllowInsertHyperlinks" ],
|
||||||
|
[ "deleteColumns", "AllowDeleteCols" ],
|
||||||
|
[ "deleteRows", "AllowDeleteRows" ],
|
||||||
|
[ "sort", "AllowSort" ],
|
||||||
|
[ "autoFilter", "AllowFilter" ],
|
||||||
|
[ "pivotTables", "AllowUsePivotTables" ]
|
||||||
|
].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); });
|
||||||
|
}
|
||||||
|
|
||||||
if(o.length == 0) return "";
|
if(o.length == 0) return "";
|
||||||
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
|
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
|
||||||
}
|
}
|
||||||
@ -13048,12 +13149,13 @@ function slurp(R, blob, length/*:number*/, opts) {
|
|||||||
|
|
||||||
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
|
||||||
if(p.t === 'z') return;
|
if(p.t === 'z') return;
|
||||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
|
||||||
if(!p.XF) return;
|
if(!p.XF) return;
|
||||||
try {
|
try {
|
||||||
var fmtid = p.XF.ifmt||0;
|
var fmtid = p.XF.ifmt||0;
|
||||||
if(opts.cellNF) p.z = SSF._table[fmtid];
|
if(opts.cellNF) p.z = SSF._table[fmtid];
|
||||||
if(p.t === 'e'){}
|
} catch(e) { if(opts.WTF) throw e; }
|
||||||
|
if(!opts || opts.cellText !== false) try {
|
||||||
|
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||||
else if(fmtid === 0) {
|
else if(fmtid === 0) {
|
||||||
if(p.t === 'n') {
|
if(p.t === 'n') {
|
||||||
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
|
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
|
||||||
@ -15436,7 +15538,7 @@ var parse_content_xml = (function() {
|
|||||||
isstub = textpidx == 0;
|
isstub = textpidx == 0;
|
||||||
}
|
}
|
||||||
if(comments.length > 0) { q.c = comments; comments = []; }
|
if(comments.length > 0) { q.c = comments; comments = []; }
|
||||||
if(textp) q.w = textp;
|
if(textp && opts.cellText !== false) q.w = textp;
|
||||||
if(!isstub || opts.sheetStubs) {
|
if(!isstub || opts.sheetStubs) {
|
||||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||||
if(opts.dense) {
|
if(opts.dense) {
|
||||||
|
166
xlsx.js
166
xlsx.js
@ -3271,26 +3271,36 @@ function write_cust_props(cp, opts) {
|
|||||||
}
|
}
|
||||||
/* Common Name -> XLML Name */
|
/* Common Name -> XLML Name */
|
||||||
var XLMLDocPropsMap = {
|
var XLMLDocPropsMap = {
|
||||||
Category: 'Category',
|
|
||||||
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
|
|
||||||
Keywords: 'Keywords',
|
|
||||||
LastAuthor: 'LastAuthor',
|
|
||||||
LastPrinted: 'LastPrinted',
|
|
||||||
RevNumber: 'Revision',
|
|
||||||
Author: 'Author',
|
|
||||||
Comments: 'Description',
|
|
||||||
Identifier: 'Identifier', /* NOTE: missing from schema */
|
|
||||||
Language: 'Language', /* NOTE: missing from schema */
|
|
||||||
Subject: 'Subject',
|
|
||||||
Title: 'Title',
|
Title: 'Title',
|
||||||
|
Subject: 'Subject',
|
||||||
|
Author: 'Author',
|
||||||
|
Keywords: 'Keywords',
|
||||||
|
Comments: 'Description',
|
||||||
|
LastAuthor: 'LastAuthor',
|
||||||
|
RevNumber: 'Revision',
|
||||||
|
Application: 'AppName',
|
||||||
|
/* TotalTime: 'TotalTime', */
|
||||||
|
LastPrinted: 'LastPrinted',
|
||||||
CreatedDate: 'Created',
|
CreatedDate: 'Created',
|
||||||
ModifiedDate: 'LastSaved',
|
ModifiedDate: 'LastSaved',
|
||||||
|
/* Pages */
|
||||||
Application: 'AppName',
|
/* Words */
|
||||||
AppVersion: 'Version',
|
/* Characters */
|
||||||
TotalTime: 'TotalTime',
|
Category: 'Category',
|
||||||
|
/* PresentationFormat */
|
||||||
Manager: 'Manager',
|
Manager: 'Manager',
|
||||||
Company: 'Company'
|
Company: 'Company',
|
||||||
|
/* Guid */
|
||||||
|
/* HyperlinkBase */
|
||||||
|
/* Bytes */
|
||||||
|
/* Lines */
|
||||||
|
/* Paragraphs */
|
||||||
|
/* CharactersWithSpaces */
|
||||||
|
AppVersion: 'Version',
|
||||||
|
|
||||||
|
ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
|
||||||
|
Identifier: 'Identifier', /* NOTE: missing from schema */
|
||||||
|
Language: 'Language' /* NOTE: missing from schema */
|
||||||
};
|
};
|
||||||
var evert_XLMLDPM = evert(XLMLDocPropsMap);
|
var evert_XLMLDPM = evert(XLMLDocPropsMap);
|
||||||
|
|
||||||
@ -3299,19 +3309,21 @@ function xlml_set_prop(Props, tag, val) {
|
|||||||
Props[tag] = val;
|
Props[tag] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: verify */
|
|
||||||
function xlml_write_docprops(Props, opts) {
|
function xlml_write_docprops(Props, opts) {
|
||||||
var o = [];
|
var o = [];
|
||||||
CORE_PROPS.concat(EXT_PROPS).forEach(function(p) {
|
keys(XLMLDocPropsMap).map(function(m) {
|
||||||
|
for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
|
||||||
|
for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
|
||||||
|
throw m;
|
||||||
|
}).forEach(function(p) {
|
||||||
if(Props[p[1]] == null) return;
|
if(Props[p[1]] == null) return;
|
||||||
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
|
var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
|
||||||
switch(p[2]) {
|
switch(p[2]) {
|
||||||
case 'date': m = new Date(m).toISOString(); break;
|
case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
|
||||||
}
|
}
|
||||||
if(typeof m == 'number') m = String(m);
|
if(typeof m == 'number') m = String(m);
|
||||||
else if(m === true || m === false) { m = m ? "1" : "0"; }
|
else if(m === true || m === false) { m = m ? "1" : "0"; }
|
||||||
else if(m instanceof Date) m = new Date(m).toISOString();
|
else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
|
||||||
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
|
o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
|
||||||
});
|
});
|
||||||
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
|
return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
|
||||||
@ -10166,8 +10178,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
/* 18.3.1.73 row CT_Row */
|
/* 18.3.1.73 row CT_Row */
|
||||||
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
|
||||||
tag = parsexmltag(x.substr(0,ri), true);
|
tag = parsexmltag(x.substr(0,ri), true);
|
||||||
/* SpreadSheetGear uses implicit r/c */
|
tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
|
||||||
tagr = typeof tag.r !== 'undefined' ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
|
|
||||||
if(opts.sheetRows && opts.sheetRows < tagr) continue;
|
if(opts.sheetRows && opts.sheetRows < tagr) continue;
|
||||||
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
|
||||||
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
|
||||||
@ -10219,7 +10230,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
p.F = arrayf[i][1];
|
p.F = arrayf[i][1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tag.t === undefined && p.v === undefined) {
|
if(tag.t == null && p.v === undefined) {
|
||||||
if(!opts.sheetStubs) continue;
|
if(!opts.sheetStubs) continue;
|
||||||
p.t = "z";
|
p.t = "z";
|
||||||
}
|
}
|
||||||
@ -10257,7 +10268,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
|
|||||||
break;
|
break;
|
||||||
/* error string in .w, number in .v */
|
/* error string in .w, number in .v */
|
||||||
case 'e':
|
case 'e':
|
||||||
if(opts && opts.cellText === false) p.w = p.v;
|
if(!opts || opts.cellText !== false) p.w = p.v;
|
||||||
p.v = RBErr[p.v]; break;
|
p.v = RBErr[p.v]; break;
|
||||||
}
|
}
|
||||||
/* formatting */
|
/* formatting */
|
||||||
@ -10819,7 +10830,7 @@ function parse_ws_bin(data, _opts, rels, wb, themes, styles) {
|
|||||||
case 'n': p.v = val[1]; break;
|
case 'n': p.v = val[1]; break;
|
||||||
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
|
case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
|
||||||
case 'b': p.v = val[1] ? true : false; break;
|
case 'b': p.v = val[1] ? true : false; break;
|
||||||
case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
|
case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
|
||||||
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
|
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
|
||||||
}
|
}
|
||||||
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
|
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
|
||||||
@ -12081,11 +12092,11 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o
|
|||||||
if(cell.v === undefined) cell.v=+xml;
|
if(cell.v === undefined) cell.v=+xml;
|
||||||
if(!cell.t) cell.t = 'n';
|
if(!cell.t) cell.t = 'n';
|
||||||
break;
|
break;
|
||||||
case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; cell.w = xml; break;
|
case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break;
|
||||||
default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
|
default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
|
||||||
}
|
}
|
||||||
safe_format_xlml(cell, nf, o);
|
safe_format_xlml(cell, nf, o);
|
||||||
if(o.cellFormula != null) {
|
if(o.cellFormula !== false) {
|
||||||
if(cell.Formula) {
|
if(cell.Formula) {
|
||||||
var fstr = unescapexml(cell.Formula);
|
var fstr = unescapexml(cell.Formula);
|
||||||
/* strictly speaking, the leading = is required but some writers omit */
|
/* strictly speaking, the leading = is required but some writers omit */
|
||||||
@ -12795,17 +12806,107 @@ function write_sty_xlml(wb, opts) {
|
|||||||
}
|
}
|
||||||
/* WorksheetOptions */
|
/* WorksheetOptions */
|
||||||
function write_ws_xlml_wsopts(ws, opts, idx, wb) {
|
function write_ws_xlml_wsopts(ws, opts, idx, wb) {
|
||||||
|
if(!ws) return "";
|
||||||
var o = [];
|
var o = [];
|
||||||
|
/* NOTE: spec technically allows any order, but stick with implied order */
|
||||||
|
|
||||||
|
/* FitToPage */
|
||||||
|
/* DoNotDisplayColHeaders */
|
||||||
|
/* DoNotDisplayRowHeaders */
|
||||||
|
/* ViewableRange */
|
||||||
|
/* Selection */
|
||||||
|
/* GridlineColor */
|
||||||
|
/* Name */
|
||||||
|
/* ExcelWorksheetType */
|
||||||
|
/* IntlMacro */
|
||||||
|
/* Unsynced */
|
||||||
|
/* Selected */
|
||||||
|
/* CodeName */
|
||||||
|
|
||||||
|
if(ws['!margins']) {
|
||||||
|
o.push("<PageSetup>");
|
||||||
|
if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header}));
|
||||||
|
if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer}));
|
||||||
|
o.push(writextag("PageMargins", null, {
|
||||||
|
'x:Bottom': ws['!margins'].bottom || "0.75",
|
||||||
|
'x:Left': ws['!margins'].left || "0.7",
|
||||||
|
'x:Right': ws['!margins'].right || "0.7",
|
||||||
|
'x:Top': ws['!margins'].top || "0.75"
|
||||||
|
}));
|
||||||
|
o.push("</PageSetup>");
|
||||||
|
}
|
||||||
|
|
||||||
/* PageSetup */
|
/* PageSetup */
|
||||||
|
/* DisplayPageBreak */
|
||||||
|
/* TransitionExpressionEvaluation */
|
||||||
|
/* TransitionFormulaEntry */
|
||||||
|
/* Print */
|
||||||
|
/* Zoom */
|
||||||
|
/* PageLayoutZoom */
|
||||||
|
/* PageBreakZoom */
|
||||||
|
/* ShowPageBreakZoom */
|
||||||
|
/* DefaultRowHeight */
|
||||||
|
/* DefaultColumnWidth */
|
||||||
|
/* StandardWidth */
|
||||||
|
|
||||||
if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
|
if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
|
||||||
/* Visible */
|
/* Visible */
|
||||||
if(!!wb.Workbook.Sheets[idx].Hidden) o.push("<Visible>" + (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden") + "</Visible>");
|
if(!!wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {}));
|
||||||
else {
|
else {
|
||||||
/* Selected */
|
/* Selected */
|
||||||
for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
|
for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
|
||||||
if(i == idx) o.push("<Selected/>");
|
if(i == idx) o.push("<Selected/>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* LeftColumnVisible */
|
||||||
|
/* DisplayRightToLeft */
|
||||||
|
/* GridlineColorIndex */
|
||||||
|
/* DisplayFormulas */
|
||||||
|
/* DoNotDisplayGridlines */
|
||||||
|
/* DoNotDisplayHeadings */
|
||||||
|
/* DoNotDisplayOutline */
|
||||||
|
/* ApplyAutomaticOutlineStyles */
|
||||||
|
/* NoSummaryRowsBelowDetail */
|
||||||
|
/* NoSummaryColumnsRightDetail */
|
||||||
|
/* DoNotDisplayZeros */
|
||||||
|
/* ActiveRow */
|
||||||
|
/* ActiveColumn */
|
||||||
|
/* FilterOn */
|
||||||
|
/* RangeSelection */
|
||||||
|
/* TopRowVisible */
|
||||||
|
/* TopRowBottomPane */
|
||||||
|
/* LeftColumnRightPane */
|
||||||
|
/* ActivePane */
|
||||||
|
/* SplitHorizontal */
|
||||||
|
/* SplitVertical */
|
||||||
|
/* FreezePanes */
|
||||||
|
/* FrozenNoSplit */
|
||||||
|
/* TabColorIndex */
|
||||||
|
/* Panes */
|
||||||
|
|
||||||
|
/* NOTE: Password not supported in XLML Format */
|
||||||
|
if(ws['!protect']) {
|
||||||
|
o.push(writetag("ProtectContents", "True"));
|
||||||
|
if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True"));
|
||||||
|
if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True"));
|
||||||
|
if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection"));
|
||||||
|
else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells"));
|
||||||
|
[
|
||||||
|
[ "formatColumns", "AllowFormatCells" ],
|
||||||
|
[ "formatRows", "AllowSizeCols" ],
|
||||||
|
[ "formatCells", "AllowSizeRows" ],
|
||||||
|
[ "insertColumns", "AllowInsertCols" ],
|
||||||
|
[ "insertRows", "AllowInsertRows" ],
|
||||||
|
[ "insertHyperlinks", "AllowInsertHyperlinks" ],
|
||||||
|
[ "deleteColumns", "AllowDeleteCols" ],
|
||||||
|
[ "deleteRows", "AllowDeleteRows" ],
|
||||||
|
[ "sort", "AllowSort" ],
|
||||||
|
[ "autoFilter", "AllowFilter" ],
|
||||||
|
[ "pivotTables", "AllowUsePivotTables" ]
|
||||||
|
].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); });
|
||||||
|
}
|
||||||
|
|
||||||
if(o.length == 0) return "";
|
if(o.length == 0) return "";
|
||||||
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
|
return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
|
||||||
}
|
}
|
||||||
@ -12982,12 +13083,13 @@ function slurp(R, blob, length, opts) {
|
|||||||
|
|
||||||
function safe_format_xf(p, opts, date1904) {
|
function safe_format_xf(p, opts, date1904) {
|
||||||
if(p.t === 'z') return;
|
if(p.t === 'z') return;
|
||||||
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
|
||||||
if(!p.XF) return;
|
if(!p.XF) return;
|
||||||
try {
|
try {
|
||||||
var fmtid = p.XF.ifmt||0;
|
var fmtid = p.XF.ifmt||0;
|
||||||
if(opts.cellNF) p.z = SSF._table[fmtid];
|
if(opts.cellNF) p.z = SSF._table[fmtid];
|
||||||
if(p.t === 'e'){}
|
} catch(e) { if(opts.WTF) throw e; }
|
||||||
|
if(!opts || opts.cellText !== false) try {
|
||||||
|
if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
|
||||||
else if(fmtid === 0) {
|
else if(fmtid === 0) {
|
||||||
if(p.t === 'n') {
|
if(p.t === 'n') {
|
||||||
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
|
if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
|
||||||
@ -15370,7 +15472,7 @@ var parse_content_xml = (function() {
|
|||||||
isstub = textpidx == 0;
|
isstub = textpidx == 0;
|
||||||
}
|
}
|
||||||
if(comments.length > 0) { q.c = comments; comments = []; }
|
if(comments.length > 0) { q.c = comments; comments = []; }
|
||||||
if(textp) q.w = textp;
|
if(textp && opts.cellText !== false) q.w = textp;
|
||||||
if(!isstub || opts.sheetStubs) {
|
if(!isstub || opts.sheetStubs) {
|
||||||
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
if(!(opts.sheetRows && opts.sheetRows < R)) {
|
||||||
if(opts.dense) {
|
if(opts.dense) {
|
||||||
|
Loading…
Reference in New Issue
Block a user