forked from sheetjs/sheetjs
Hyperlink cleanup [ci skip]
- XLS normalize URLs and use moniker (fixes #2385) - ODS row heights and column widths (fixes #2378) - DSV parse of files with leading <, deviating from Excel (fixes #1238) - read `ArrayBuffer` with no type (fixes #2316) - removed invalid test files that throw errors due to string length - AOA/JSON null optional map to #NULL! (fixes #1196)
This commit is contained in:
parent
8658054872
commit
e59de73f99
@ -135,7 +135,12 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
|
||||
if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
|
||||
else {
|
||||
if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
|
||||
if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.sheetStubs) continue; else cell.t = 'z'; }
|
||||
if(cell.v === null) {
|
||||
if(cell.f) cell.t = 'n';
|
||||
else if(o.nullError) { cell.t = 'e'; cell.v = 0; }
|
||||
else if(!o.sheetStubs) continue;
|
||||
else cell.t = 'z';
|
||||
}
|
||||
else if(typeof cell.v === 'number') cell.t = 'n';
|
||||
else if(typeof cell.v === 'boolean') cell.t = 'b';
|
||||
else if(cell.v instanceof Date) {
|
||||
|
@ -57,7 +57,7 @@ function write_rdf(rdf) {
|
||||
}
|
||||
/* TODO: pull properties */
|
||||
var write_meta_ods/*:{(wb:Workbook, opts:any):string}*/ = (function() {
|
||||
var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
var payload = '<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
|
||||
return function wmo(/*:: wb: Workbook, opts: any*/)/*:string*/ {
|
||||
return payload;
|
||||
};
|
||||
|
@ -523,16 +523,17 @@ function parse_URLMoniker(blob/*::, length, opts*/) {
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
|
||||
function parse_FileMoniker(blob/*::, length*/) {
|
||||
blob.l += 2; //var cAnti = blob.read_shift(2);
|
||||
var cAnti = blob.read_shift(2);
|
||||
var preamble = ""; while(cAnti-- > 0) preamble += "../";
|
||||
var ansiPath = blob.read_shift(0, 'lpstr-ansi');
|
||||
blob.l += 2; //var endServer = blob.read_shift(2);
|
||||
if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker");
|
||||
var sz = blob.read_shift(4);
|
||||
if(sz === 0) return ansiPath.replace(/\\/g,"/");
|
||||
if(sz === 0) return preamble + ansiPath.replace(/\\/g,"/");
|
||||
var bytes = blob.read_shift(4);
|
||||
if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker");
|
||||
var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,"");
|
||||
return unicodePath;
|
||||
return preamble + unicodePath;
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
|
||||
@ -551,6 +552,13 @@ function parse_HyperlinkString(blob/*::, length*/) {
|
||||
var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : "";
|
||||
return o;
|
||||
}
|
||||
function write_HyperlinkString(str/*:string*/, o) {
|
||||
if(!o) o = new_buf(6 + str.length * 2);
|
||||
o.write_shift(4, 1 + str.length);
|
||||
for(var i = 0; i < str.length; ++i) o.write_shift(2, str.charCodeAt(i));
|
||||
o.write_shift(2, 0);
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
|
||||
function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
|
||||
@ -571,6 +579,7 @@ function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
|
||||
var target = targetFrameName||moniker||oleMoniker||"";
|
||||
if(target && Loc) target+="#"+Loc;
|
||||
if(!target) target = "#" + Loc;
|
||||
if((flags & 0x0002) && target.charAt(0) == "/" && target.charAt(1) != "/") target = "file://" + target;
|
||||
var out = ({Target:target}/*:any*/);
|
||||
if(guid) out.guid = guid;
|
||||
if(fileTime) out.time = fileTime;
|
||||
@ -580,29 +589,31 @@ function parse_Hyperlink(blob, length)/*:Hyperlink*/ {
|
||||
function write_Hyperlink(hl) {
|
||||
var out = new_buf(512), i = 0;
|
||||
var Target = hl.Target;
|
||||
var F = Target.indexOf("#") > -1 ? 0x1f : 0x17;
|
||||
if(Target.slice(0,7) == "file://") Target = Target.slice(7);
|
||||
var hashidx = Target.indexOf("#");
|
||||
var F = hashidx > -1 ? 0x1f : 0x17;
|
||||
switch(Target.charAt(0)) { case "#": F=0x1c; break; case ".": F&=~2; break; }
|
||||
out.write_shift(4,2); out.write_shift(4, F);
|
||||
var data = [8,6815827,6619237,4849780,83]; for(i = 0; i < data.length; ++i) out.write_shift(4, data[i]);
|
||||
if(F == 0x1C) {
|
||||
Target = Target.slice(1);
|
||||
out.write_shift(4, Target.length + 1);
|
||||
for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i));
|
||||
out.write_shift(2, 0);
|
||||
write_HyperlinkString(Target, out);
|
||||
} else if(F & 0x02) {
|
||||
data = "e0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
|
||||
for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
|
||||
out.write_shift(4, 2*(Target.length + 1));
|
||||
for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i));
|
||||
var Pretarget = hashidx > -1 ? Target.slice(0, hashidx) : Target;
|
||||
out.write_shift(4, 2*(Pretarget.length + 1));
|
||||
for(i = 0; i < Pretarget.length; ++i) out.write_shift(2, Pretarget.charCodeAt(i));
|
||||
out.write_shift(2, 0);
|
||||
if(F & 0x08) write_HyperlinkString(hashidx > -1 ? Target.slice(hashidx+1): "", out);
|
||||
} else {
|
||||
data = "03 03 00 00 00 00 00 00 c0 00 00 00 00 00 00 46".split(" ");
|
||||
for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
|
||||
var P = 0;
|
||||
while(Target.slice(P*3,P*3+3)=="../"||Target.slice(P*3,P*3+3)=="..\\") ++P;
|
||||
out.write_shift(2, P);
|
||||
out.write_shift(4, Target.length + 1);
|
||||
for(i = 0; i < Target.length; ++i) out.write_shift(1, Target.charCodeAt(i) & 0xFF);
|
||||
out.write_shift(4, Target.length - 3 * P + 1);
|
||||
for(i = 0; i < Target.length - 3 * P; ++i) out.write_shift(1, Target.charCodeAt(i + 3 * P) & 0xFF);
|
||||
out.write_shift(1, 0);
|
||||
out.write_shift(2, 0xFFFF);
|
||||
out.write_shift(2, 0xDEAD);
|
||||
|
@ -352,7 +352,7 @@ var SYLK = (function() {
|
||||
Au:'ù', Bu:'ú', Cu:'û', Hu:'ü',
|
||||
KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
|
||||
DN:209, Dn:241, Hy:255,
|
||||
S:169, c:170, R:174, B:180,
|
||||
S:169, c:170, R:174, "B ":180,
|
||||
/*::[*/0/*::]*/:176, /*::[*/1/*::]*/:177, /*::[*/2/*::]*/:178,
|
||||
/*::[*/3/*::]*/:179, /*::[*/5/*::]*/:181, /*::[*/6/*::]*/:182,
|
||||
/*::[*/7/*::]*/:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
|
||||
|
@ -156,9 +156,9 @@ function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
||||
var rel = ((rels || {})['!id']||[])[val.id];
|
||||
if(rel) {
|
||||
val.Target = rel.Target;
|
||||
if(val.location) val.Target += "#"+val.location;
|
||||
if(val.location) val.Target += "#"+unescapexml(val.location);
|
||||
} else {
|
||||
val.Target = "#" + val.location;
|
||||
val.Target = "#" + unescapexml(val.location);
|
||||
rel = {Target: val.Target, TargetMode: 'Internal'};
|
||||
}
|
||||
val.Rel = rel;
|
||||
|
@ -183,6 +183,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
else str = utf8read(str);
|
||||
}
|
||||
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
|
||||
if((opening.indexOf(">") & 1023) > Math.min((opening.indexOf(",") & 1023), (opening.indexOf(";")&1023))) { var _o = dup(opts); _o.type = "string"; return PRN.to_workbook(str, _o); }
|
||||
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
|
||||
if(ishtml) return HTML_.to_workbook(str, opts);
|
||||
var Rn;
|
||||
@ -226,7 +227,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
|
||||
} else cursheet[encode_col(c) + encode_row(r)] = cell;
|
||||
}
|
||||
if(cell.HRef) {
|
||||
cell.l = ({Target:cell.HRef}/*:any*/);
|
||||
cell.l = ({Target:unescapexml(cell.HRef)}/*:any*/);
|
||||
if(cell.HRefScreenTip) cell.l.Tooltip = cell.HRefScreenTip;
|
||||
delete cell.HRef; delete cell.HRefScreenTip;
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ var parse_content_xml = (function() {
|
||||
case 'scripts': // 3.12 <office:scripts>
|
||||
case 'styles': // TODO <office:styles>
|
||||
case 'font-face-decls': // 3.14 <office:font-face-decls>
|
||||
case 'master-styles': //3.15.4 <office:master-styles> -- relevant for FODS
|
||||
case 'master-styles': // 3.15.4 <office:master-styles> -- relevant for FODS
|
||||
if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
|
||||
else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
|
||||
break;
|
||||
@ -515,11 +515,11 @@ var parse_content_xml = (function() {
|
||||
if(Rn[1]!== '/') {
|
||||
atag = parsexmltag(Rn[0], false);
|
||||
if(!atag.href) break;
|
||||
atag.Target = atag.href; delete atag.href;
|
||||
atag.Target = unescapexml(atag.href); delete atag.href;
|
||||
if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) {
|
||||
_Ref = ods_to_csf_3D(atag.Target.slice(1));
|
||||
atag.Target = "#" + _Ref[0] + "!" + _Ref[1];
|
||||
}
|
||||
} else if(atag.Target.match(/^\.\.[\\\/]/)) atag.Target = atag.Target.slice(3);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -37,9 +37,17 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
var R=0,C=0, range = decode_range(ws['!ref']||"A1");
|
||||
var marr/*:Array<Range>*/ = ws['!merges'] || [], mi = 0;
|
||||
var dense = Array.isArray(ws);
|
||||
for(R = 0; R < range.s.r; ++R) o.push(' <table:table-row></table:table-row>\n');
|
||||
if(ws["!cols"]) {
|
||||
for(C = 0; C <= range.e.c; ++C) o.push(' <table:table-column' + (ws["!cols"][C] ? ' table:style-name="co' + ws["!cols"][C].ods + '"' : '') + '></table:table-column>\n');
|
||||
}
|
||||
var H = "", ROWS = ws["!rows"]||[];
|
||||
for(R = 0; R < range.s.r; ++R) {
|
||||
H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
|
||||
o.push(' <table:table-row' + H + '></table:table-row>\n');
|
||||
}
|
||||
for(; R <= range.e.r; ++R) {
|
||||
o.push(' <table:table-row>\n');
|
||||
H = ROWS[R] ? ' table:style-name="ro' + ROWS[R].ods + '"' : "";
|
||||
o.push(' <table:table-row' + H + '>\n');
|
||||
for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
|
||||
for(; C <= range.e.c; ++C) {
|
||||
var skip = false, ct = {}, textp = "";
|
||||
@ -92,8 +100,11 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
}
|
||||
var text_p = write_text_p(textp);
|
||||
if(cell.l && cell.l.Target) {
|
||||
var _tgt = cell.l.Target; _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
|
||||
text_p = writextag('text:a', text_p, {'xlink:href': _tgt});
|
||||
var _tgt = cell.l.Target;
|
||||
_tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
|
||||
// TODO: choose correct parent path format based on link delimiters
|
||||
if(_tgt.charAt(0) != "#" && !_tgt.match(/^\w+:/)) _tgt = '../' + _tgt;
|
||||
text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&")});
|
||||
}
|
||||
o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
|
||||
}
|
||||
@ -103,7 +114,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
return o.join("");
|
||||
};
|
||||
|
||||
var write_automatic_styles_ods = function(o/*:Array<string>*/) {
|
||||
var write_automatic_styles_ods = function(o/*:Array<string>*/, wb) {
|
||||
o.push(' <office:automatic-styles>\n');
|
||||
|
||||
o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
|
||||
@ -114,6 +125,41 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
o.push(' <number:year/>\n');
|
||||
o.push(' </number:date-style>\n');
|
||||
|
||||
/* column styles */
|
||||
var cidx = 0;
|
||||
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
|
||||
if(!ws) return;
|
||||
if(ws["!cols"]) {
|
||||
for(var C = 0; C < ws["!cols"].length; ++C) if(ws["!cols"][C]) {
|
||||
var colobj = ws["!cols"][C];
|
||||
if(colobj.width == null && colobj.wpx == null && colobj.wch == null) continue;
|
||||
process_col(colobj);
|
||||
colobj.ods = cidx;
|
||||
var w = ws["!cols"][C].wpx + "px";
|
||||
o.push(' <style:style style:name="co' + cidx + '" style:family="table-column">\n');
|
||||
o.push(' <style:table-column-properties fo:break-before="auto" style:column-width="' + w + '"/>\n');
|
||||
o.push(' </style:style>\n');
|
||||
++cidx;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* row styles */
|
||||
var ridx = 0;
|
||||
wb.SheetNames.map(function(n) { return wb.Sheets[n]; }).forEach(function(ws) {
|
||||
if(!ws) return;
|
||||
if(ws["!rows"]) {
|
||||
for(var R = 0; R < ws["!rows"].length; ++R) if(ws["!rows"][R]) {
|
||||
ws["!rows"][R].ods = ridx;
|
||||
var h = ws["!rows"][R].hpx + "px";
|
||||
o.push(' <style:style style:name="ro' + ridx + '" style:family="table-row">\n');
|
||||
o.push(' <style:table-row-properties fo:break-before="auto" style:row-height="' + h + '"/>\n');
|
||||
o.push(' </style:style>\n');
|
||||
++ridx;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* table */
|
||||
o.push(' <style:style style:name="ta1" style:family="table">\n'); // style:master-page-name="mp1">\n');
|
||||
o.push(' <style:table-properties table:display="true" style:writing-mode="lr-tb"/>\n');
|
||||
@ -175,9 +221,13 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = (function() {
|
||||
'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
|
||||
});
|
||||
|
||||
if(opts.bookType == "fods") o.push('<office:document' + attr + fods + '>\n');
|
||||
else o.push('<office:document-content' + attr + '>\n');
|
||||
write_automatic_styles_ods(o);
|
||||
if(opts.bookType == "fods") {
|
||||
o.push('<office:document' + attr + fods + '>\n');
|
||||
o.push(write_meta_ods().replace(/office:document-meta/g, "office:meta"));
|
||||
// TODO: settings (equiv of settings.xml for ODS)
|
||||
} else o.push('<office:document-content' + attr + '>\n');
|
||||
// o.push(' <office:scripts/>\n');
|
||||
write_automatic_styles_ods(o, wb);
|
||||
o.push(' <office:body>\n');
|
||||
o.push(' <office:spreadsheet>\n');
|
||||
for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
|
||||
@ -217,7 +267,7 @@ function write_ods(wb/*:any*/, opts/*:any*/) {
|
||||
|
||||
/* TODO: this is hard-coded to satiate excel */
|
||||
f = "meta.xml";
|
||||
zip_add_file(zip, f, write_meta_ods(/*::wb, opts*/));
|
||||
zip_add_file(zip, f, XML_HEADER + write_meta_ods(/*::wb, opts*/));
|
||||
manifest.push([f, "text/xml"]);
|
||||
rdf.push([f, "MetadataFile"]);
|
||||
|
||||
|
@ -66,9 +66,9 @@ function read_prn(data, d, o, str) {
|
||||
|
||||
function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
reset_cp();
|
||||
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), opts);
|
||||
var d = data, n = [0,0,0,0], str = false;
|
||||
var o = opts||{};
|
||||
if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), (o = dup(o), o.type = "array", o));
|
||||
var d = data, n = [0,0,0,0], str = false;
|
||||
if(o.cellStyles) { o.cellNF = true; o.sheetStubs = true; }
|
||||
_ssfopts = {};
|
||||
if(o.dateNF) _ssfopts.dateNF = o.dateNF;
|
||||
|
@ -23,13 +23,14 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
||||
var v = val.v;
|
||||
switch(val.t){
|
||||
case 'z': if(v == null) break; continue;
|
||||
case 'e': v = void 0; break;
|
||||
case 'e': v = (v == 0 ? null : void 0); break;
|
||||
case 's': case 'd': case 'b': case 'n': break;
|
||||
default: throw new Error('unrecognized type ' + val.t);
|
||||
}
|
||||
if(hdr[C] != null) {
|
||||
if(v == null) {
|
||||
if(defval !== undefined) row[hdr[C]] = defval;
|
||||
if(val.t == "e" && v === null) row[hdr[C]] = null;
|
||||
else if(defval !== undefined) row[hdr[C]] = defval;
|
||||
else if(raw && v === null) row[hdr[C]] = null;
|
||||
else continue;
|
||||
} else {
|
||||
@ -221,6 +222,7 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
|
||||
if(!o.cellDates) { t = 'n'; v = datenum(v); }
|
||||
z = (o.dateNF || SSF._table[14]);
|
||||
}
|
||||
else if(v === null && o.nullError) { t = 'e'; v = 0; }
|
||||
if(!cell) ws[ref] = cell = ({t:t, v:v}/*:any*/);
|
||||
else {
|
||||
cell.t = t; cell.v = v;
|
||||
|
@ -1,5 +1,14 @@
|
||||
#### Hyperlinks
|
||||
|
||||
<details>
|
||||
<summary><b>Format Support</b> (click to show)</summary>
|
||||
|
||||
**Cell Hyperlinks**: XLSX/M, XLSB, BIFF8 XLS, XLML, ODS
|
||||
|
||||
**Tooltips**: XLSX/M, XLSB, BIFF8 XLS, XLML
|
||||
|
||||
</details>
|
||||
|
||||
Hyperlinks are stored in the `l` key of cell objects. The `Target` field of the
|
||||
hyperlink object is the target of the link, including the URI fragment. Tooltips
|
||||
are stored in the `Tooltip` field and are displayed when you move your mouse
|
||||
@ -9,16 +18,55 @@ For example, the following snippet creates a link from cell `A3` to
|
||||
<https://sheetjs.com> with the tip `"Find us @ SheetJS.com!"`:
|
||||
|
||||
```js
|
||||
ws['A3'].l = { Target:"https://sheetjs.com", Tooltip:"Find us @ SheetJS.com!" };
|
||||
ws['A1'].l = { Target:"https://sheetjs.com", Tooltip:"Find us @ SheetJS.com!" };
|
||||
```
|
||||
|
||||
Note that Excel does not automatically style hyperlinks -- they will generally
|
||||
be displayed as normal text.
|
||||
|
||||
_Remote Links_
|
||||
|
||||
HTTP / HTTPS links can be used directly:
|
||||
|
||||
```js
|
||||
ws['A2'].l = { Target:"https://docs.sheetjs.com/#hyperlinks" };
|
||||
ws['A3'].l = { Target:"http://localhost:7262/yes_localhost_works" };
|
||||
```
|
||||
|
||||
Excel also supports `mailto` email links with subject line:
|
||||
|
||||
```js
|
||||
ws['A4'].l = { Target:"mailto:ignored@dev.null" };
|
||||
ws['A5'].l = { Target:"mailto:ignored@dev.null?subject=Test Subject" };
|
||||
```
|
||||
|
||||
_Local Links_
|
||||
|
||||
Links to absolute paths should use the `file://` URI scheme:
|
||||
|
||||
```js
|
||||
ws['B1'].l = { Target:"file:///SheetJS/t.xlsx" }; /* Link to /SheetJS/t.xlsx */
|
||||
ws['B2'].l = { Target:"file:///c:/SheetJS.xlsx" }; /* Link to c:\SheetJS.xlsx */
|
||||
```
|
||||
|
||||
Links to relative paths can be specified without a scheme:
|
||||
|
||||
```js
|
||||
ws['B3'].l = { Target:"SheetJS.xlsb" }; /* Link to SheetJS.xlsb */
|
||||
ws['B4'].l = { Target:"../SheetJS.xlsm" }; /* Link to ../SheetJS.xlsm */
|
||||
```
|
||||
|
||||
Relative Paths have undefined behavior in the SpreadsheetML 2003 format. Excel
|
||||
2019 will treat a `..\` parent mark as two levels up.
|
||||
|
||||
_Internal Links_
|
||||
|
||||
Links where the target is a cell or range or defined name in the same workbook
|
||||
("Internal Links") are marked with a leading hash character:
|
||||
|
||||
```js
|
||||
ws['A2'].l = { Target:"#E2" }; /* link to cell E2 */
|
||||
ws['C1'].l = { Target:"#E2" }; /* Link to cell E2 */
|
||||
ws['C2'].l = { Target:"#Sheet2!E2" }; /* Link to cell E2 in sheet Sheet2 */
|
||||
ws['C3'].l = { Target:"#SomeDefinedName" }; /* Link to Defined Name */
|
||||
```
|
||||
|
||||
|
@ -22,11 +22,12 @@ as the corresponding styles. Dates are stored as date or numbers. Array holes
|
||||
and explicit `undefined` values are skipped. `null` values may be stubbed. All
|
||||
other values are stored as strings. The function takes an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :-----: | :--------------------------------------------------- |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|
||||
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
@ -46,12 +47,13 @@ var ws = XLSX.utils.aoa_to_sheet([
|
||||
existing worksheet object. It follows the same process as `aoa_to_sheet` and
|
||||
accepts an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :-----: | :--------------------------------------------------- |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`sheetStubs` | false | Create cell objects of type `z` for `null` values |
|
||||
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
@ -110,11 +112,14 @@ default column order is determined by the first appearance of the field using
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|
||||
|
||||
- All fields from each row will be written. If `header` is an array and it does
|
||||
not contain a particular field, the key will be appended to the array.
|
||||
- Cell types are deduced from the type of each value. For example, a `Date`
|
||||
object will generate a Date cell, while a string will generate a Text cell.
|
||||
- Null values will be skipped by default. If `nullError` is true, an error cell
|
||||
corresponding to `#NULL!` will be written to the worksheet.
|
||||
|
||||
<details>
|
||||
<summary><b>Examples</b> (click to show)</summary>
|
||||
@ -145,13 +150,14 @@ var ws = XLSX.utils.json_to_sheet([
|
||||
worksheet object. It follows the same process as `json_to_sheet` and accepts
|
||||
an options argument:
|
||||
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :------: | :-------------------------------------------------- |
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
| Option Name | Default | Description |
|
||||
| :---------- | :-----: | :--------------------------------------------------- |
|
||||
|`header` | | Use specified column order (default `Object.keys`) |
|
||||
|`dateNF` | FMT 14 | Use specified date format in string output |
|
||||
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|
||||
|`skipHeader` | false | If true, do not include header row in output |
|
||||
|`nullError` | false | If true, emit `#NULL!` error cells for `null` values |
|
||||
|`origin` | | Use specified cell as starting point (see below) |
|
||||
|
||||
`origin` is expected to be one of:
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
"fflate": "^0.3.8",
|
||||
"ssf": "~0.11.2",
|
||||
"wmf": "~1.0.1",
|
||||
"word": "~0.4.0"
|
||||
"word": "~0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sheetjs/uglify-js": "~2.7.3",
|
||||
|
@ -277,9 +277,9 @@ apachepoi_evaluate_formula_with_structured_table_references.xlsx
|
||||
apachepoi_headerFooterTest.xlsx
|
||||
apachepoi_noSharedStringTable.xlsx
|
||||
apachepoi_picture.xlsx
|
||||
apachepoi_poc-shared-strings.xlsx
|
||||
apachepoi_poc-xmlbomb-empty.xlsx
|
||||
apachepoi_poc-xmlbomb.xlsx
|
||||
# apachepoi_poc-shared-strings.xlsx # string length exceeds 32767 chars
|
||||
# apachepoi_poc-xmlbomb-empty.xlsx # string length exceeds 32767 chars
|
||||
# apachepoi_poc-xmlbomb.xlsx # string length exceeds 32767 chars
|
||||
# apachepoi_protected_passtika.xlsx # password
|
||||
apachepoi_ref-56737.xlsx
|
||||
apachepoi_ref2-56737.xlsx
|
||||
@ -777,7 +777,7 @@ apachepoi_46136-NoWarnings.xls
|
||||
apachepoi_46136-WithWarnings.xls
|
||||
apachepoi_46137.xls
|
||||
apachepoi_46250.xls
|
||||
apachepoi_46368.xls
|
||||
# apachepoi_46368.xls # string length exceeds 32767 chars
|
||||
apachepoi_46445.xls
|
||||
apachepoi_46515.xls
|
||||
apachepoi_46670_http.xls
|
||||
|
Loading…
Reference in New Issue
Block a user