forked from sheetjs/sheetjs
outline minutiae
- column levels (fixes #1655) - XLSX parse sheetPr with children (fixes #1798) - XLSX enforce 32768 string limit (fixes #1537)
This commit is contained in:
parent
4518cc8967
commit
a4ee0ef05a
@ -223,7 +223,7 @@ function write_WriteAccess(s/*:string*/, opts) {
|
||||
/* [MS-XLS] 2.4.351 */
|
||||
function parse_WsBool(blob, length, opts) {
|
||||
var flags = opts && opts.biff == 8 || length == 2 ? blob.read_shift(2) : (blob.l += length, 0);
|
||||
return { fDialog: flags & 0x10 };
|
||||
return { fDialog: flags & 0x10, fBelow: flags & 0x40, fRight: flags & 0x80 };
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.4.28 */
|
||||
|
@ -45,6 +45,7 @@ function col_obj_w(C/*:number*/, col) {
|
||||
if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
|
||||
else if(col.width != null) p.width = col.width;
|
||||
if(col.hidden) p.hidden = true;
|
||||
if(col.level != null) { p.outlineLevel = p.level = col.level; }
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
|
||||
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
|
||||
var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
|
||||
var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
|
||||
var sheetprregex2= /<(?:\w:)?sheetPr[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetPr)>/;
|
||||
var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
|
||||
|
||||
/* 18.3 Worksheets */
|
||||
@ -32,6 +33,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
|
||||
/* 18.3.1.82 sheetPr CT_SheetPr */
|
||||
var sheetPr = data1.match(sheetprregex);
|
||||
if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
|
||||
else if((sheetPr = data1.match(sheetprregex2))) parse_ws_xml_sheetpr2(sheetPr[0], sheetPr[1]||"", s, wb, idx, styles, themes);
|
||||
|
||||
/* 18.3.1.35 dimension CT_SheetDimension */
|
||||
var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
|
||||
@ -104,6 +106,9 @@ function parse_ws_xml_sheetpr(sheetPr/*:string*/, s, wb/*:WBWBProps*/, idx/*:num
|
||||
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
|
||||
if(data.codeName) wb.Sheets[idx].CodeName = unescapexml(utf8read(data.codeName));
|
||||
}
|
||||
function parse_ws_xml_sheetpr2(sheetPr/*:string*/, body/*:string*/, s, wb/*:WBWBProps*/, idx/*:number*/, styles, themes) {
|
||||
parse_ws_xml_sheetpr(sheetPr.slice(0, sheetPr.indexOf(">")), s, wb, idx);
|
||||
}
|
||||
function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
|
||||
var needed = false;
|
||||
var props = {}, payload = null;
|
||||
@ -191,6 +196,7 @@ function parse_ws_xml_cols(columns, cols) {
|
||||
var coll = parsexmltag(cols[coli], true);
|
||||
if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
|
||||
var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
|
||||
if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
|
||||
delete coll.min; delete coll.max; coll.width = +coll.width;
|
||||
if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
|
||||
process_col(coll);
|
||||
@ -280,6 +286,7 @@ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string
|
||||
case 'e': o.t = "e"; break;
|
||||
case 'z': break;
|
||||
default: if(cell.v == null) { delete cell.t; break; }
|
||||
if(cell.v.length > 32767) throw new Error("Text length must not exceed 32767 characters");
|
||||
if(opts && opts.bookSST) {
|
||||
v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
|
||||
o.t = "s"; break;
|
||||
|
@ -79,14 +79,23 @@ function parse_BrtWsFmtInfo(/*::data, length*/) {
|
||||
/* [MS-XLSB] 2.4.823 BrtWsProp */
|
||||
function parse_BrtWsProp(data, length) {
|
||||
var z = {};
|
||||
var f = data[data.l]; ++data.l;
|
||||
z.above = !(f & 0x40);
|
||||
z.left = !(f & 0x80);
|
||||
/* TODO: pull flags */
|
||||
data.l += 19;
|
||||
data.l += 18;
|
||||
z.name = parse_XLSBCodeName(data, length - 19);
|
||||
return z;
|
||||
}
|
||||
function write_BrtWsProp(str, o) {
|
||||
function write_BrtWsProp(str, outl, o) {
|
||||
if(o == null) o = new_buf(84+4*str.length);
|
||||
for(var i = 0; i < 3; ++i) o.write_shift(1,0);
|
||||
var f = 0xC0;
|
||||
if(outl) {
|
||||
if(outl.above) f &= ~0x40;
|
||||
if(outl.left) f &= ~0x80;
|
||||
}
|
||||
o.write_shift(1, f);
|
||||
for(var i = 1; i < 3; ++i) o.write_shift(1,0);
|
||||
write_BrtColor({auto:1}, o);
|
||||
o.write_shift(-4,-1);
|
||||
o.write_shift(-4,-1);
|
||||
@ -660,6 +669,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
|
||||
case 0x0093: /* 'BrtWsProp' */
|
||||
if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
|
||||
if(val.name) wb.Sheets[idx].CodeName = val.name;
|
||||
if(val.above || val.left) s['!outline'] = { above: val.above, left: val.left };
|
||||
break;
|
||||
|
||||
case 0x0089: /* 'BrtBeginWsView' */
|
||||
@ -956,7 +966,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
|
||||
/* passed back to write_zip and removed there */
|
||||
ws['!comments'] = [];
|
||||
write_record(ba, "BrtBeginSheet");
|
||||
if(wb.vbaraw) write_record(ba, "BrtWsProp", write_BrtWsProp(c));
|
||||
if(wb.vbaraw || ws['!outline']) write_record(ba, "BrtWsProp", write_BrtWsProp(c, ws['!outline']));
|
||||
write_record(ba, "BrtWsDim", write_BrtWsDim(r));
|
||||
write_WSVIEWS2(ba, ws, wb.Workbook);
|
||||
write_WSFMTINFO(ba, ws);
|
||||
|
@ -618,6 +618,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
|
||||
case 'unsynced' /*case 'Unsynced'*/: break;
|
||||
case 'print' /*case 'Print'*/: break;
|
||||
case 'printerrors' /*case 'PrintErrors'*/: break;
|
||||
case 'panes' /*case 'Panes'*/: break;
|
||||
case 'scale' /*case 'Scale'*/: break;
|
||||
case 'pane' /*case 'Pane'*/: break;
|
||||
@ -657,11 +658,17 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
case 'allowformatcells' /*case 'AllowFormatCells'*/: break;
|
||||
case 'allowsizecols' /*case 'AllowSizeCols'*/: break;
|
||||
case 'allowsizerows' /*case 'AllowSizeRows'*/: break;
|
||||
case 'nosummaryrowsbelowdetail' /*case 'NoSummaryRowsBelowDetail'*/: break;
|
||||
case 'nosummaryrowsbelowdetail' /*case 'NoSummaryRowsBelowDetail'*/:
|
||||
if(!cursheet["!outline"]) cursheet["!outline"] = {};
|
||||
cursheet["!outline"].above = true;
|
||||
break;
|
||||
case 'tabcolorindex' /*case 'TabColorIndex'*/: break;
|
||||
case 'donotdisplayheadings' /*case 'DoNotDisplayHeadings'*/: break;
|
||||
case 'showpagelayoutzoom' /*case 'ShowPageLayoutZoom'*/: break;
|
||||
case 'nosummarycolumnsrightdetail' /*case 'NoSummaryColumnsRightDetail'*/: break;
|
||||
case 'nosummarycolumnsrightdetail' /*case 'NoSummaryColumnsRightDetail'*/:
|
||||
if(!cursheet["!outline"]) cursheet["!outline"] = {};
|
||||
cursheet["!outline"].left = true;
|
||||
break;
|
||||
case 'blackandwhite' /*case 'BlackAndWhite'*/: break;
|
||||
case 'donotdisplayzeros' /*case 'DoNotDisplayZeros'*/: break;
|
||||
case 'displaypagebreak' /*case 'DisplayPageBreak'*/: break;
|
||||
|
@ -272,6 +272,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
|
||||
case 'WsBool':
|
||||
if(val.fDialog) out["!type"] = "dialog";
|
||||
if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
|
||||
if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
|
||||
break; // TODO
|
||||
case 'XF':
|
||||
XFs.push(val); break;
|
||||
|
@ -13,7 +13,7 @@ In the browser, just add a script tag:
|
||||
|-----------:|:-------------------------------------------|
|
||||
| `unpkg` | <https://unpkg.com/xlsx/> |
|
||||
| `jsDelivr` | <https://jsdelivr.com/package/npm/xlsx> |
|
||||
| `CDNjs` | <https://cdnjs.com/libraries/xlsx> |
|
||||
| `CDNjs` | <https://cdnjs.com/libraries/xlsx> |
|
||||
| `packd` | <https://bundle.run/xlsx@latest?name=XLSX> |
|
||||
|
||||
`unpkg` makes the latest version available at:
|
||||
|
@ -14,6 +14,7 @@ type ColInfo = {
|
||||
wch?: number; // width in characters
|
||||
|
||||
/* other fields for preserving features from files */
|
||||
level?: number; // 0-indexed outline / group level
|
||||
MDW?: number; // Excel's "Max Digit Width" unit, always integral
|
||||
};
|
||||
```
|
||||
|
3
types/index.d.ts
vendored
3
types/index.d.ts
vendored
@ -340,6 +340,9 @@ export interface ColInfo {
|
||||
/** width in "characters" */
|
||||
wch?: number;
|
||||
|
||||
/** outline / group level */
|
||||
level?: number;
|
||||
|
||||
/** Excel's "Max Digit Width" unit, always integral */
|
||||
MDW?: number;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user