export nits
- XLSX write dense mode null check (fixes #3261 h/t @mbornstein) - Use `subarray` for Uint8Array/Buffer ops (h/t @hardonthebeat)
This commit is contained in:
parent
9c3853ba25
commit
0e4eb976e1
64
bin/xlsx.njs
64
bin/xlsx.njs
@ -2,6 +2,7 @@
|
||||
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||
/* eslint-env node */
|
||||
/* vim: set ts=2 ft=javascript: */
|
||||
|
||||
var n = "xlsx";
|
||||
var X = require('../');
|
||||
try { X = require('../xlsx.flow'); } catch(e) {}
|
||||
@ -17,7 +18,7 @@ try { program = require('commander'); } catch(e) {
|
||||
"For older versions of node, explicitly install `xlsx-cli` globally:",
|
||||
" $ npm i -g xlsx-cli",
|
||||
" $ xlsx-cli --help"
|
||||
].forEach(function(m) { console.error(m); });
|
||||
].forEach(function (m) { console.error(m); });
|
||||
process.exit(1);
|
||||
}
|
||||
program
|
||||
@ -65,9 +66,10 @@ program
|
||||
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
|
||||
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
|
||||
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
|
||||
.option('--date-format <string>', 'output date format, for example yyyy-mm-dd')
|
||||
.option('--codepage <cp>', 'default to specified codepage when ambiguous')
|
||||
.option('--req <module>', 'require module before processing')
|
||||
.option('--sst', 'generate shared string table for XLS* formats')
|
||||
.option('-d, --no-dim', 'recalculate worksheet range')
|
||||
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
|
||||
.option('--read', 'read but do not generate output')
|
||||
.option('--book', 'for single-sheet formats, emit a file per worksheet')
|
||||
@ -102,18 +104,18 @@ var wb_formats_2 = [
|
||||
program.parse(process.argv);
|
||||
|
||||
var filename = '', sheetname = '';
|
||||
if(program.args[0]) {
|
||||
if (program.args[0]) {
|
||||
filename = program.args[0];
|
||||
if(program.args[1]) sheetname = program.args[1];
|
||||
if (program.args[1]) sheetname = program.args[1];
|
||||
}
|
||||
if(program.sheet) sheetname = program.sheet;
|
||||
if(program.file) filename = program.file;
|
||||
if (program.sheet) sheetname = program.sheet;
|
||||
if (program.file) filename = program.file;
|
||||
|
||||
if(!filename) {
|
||||
if (!filename) {
|
||||
console.error(n + ": must specify a filename");
|
||||
process.exit(1);
|
||||
}
|
||||
if(!fs.existsSync(filename)) {
|
||||
if (!fs.existsSync(filename)) {
|
||||
console.error(n + ": " + filename + ": No such file or directory");
|
||||
process.exit(2);
|
||||
}
|
||||
@ -209,15 +211,15 @@ wb_formats_2.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {
|
||||
} });
|
||||
|
||||
var target_sheet = sheetname || '';
|
||||
if(target_sheet === '') {
|
||||
if(+program.sheetIndex < (wb.SheetNames||[]).length) target_sheet = wb.SheetNames[+program.sheetIndex];
|
||||
else target_sheet = (wb.SheetNames||[""])[0];
|
||||
if (target_sheet === '') {
|
||||
if (+program.sheetIndex < (wb.SheetNames || []).length) target_sheet = wb.SheetNames[+program.sheetIndex];
|
||||
else target_sheet = (wb.SheetNames || [""])[0];
|
||||
}
|
||||
|
||||
var ws;
|
||||
try {
|
||||
ws = wb.Sheets[target_sheet];
|
||||
if(!ws) {
|
||||
if (!ws) {
|
||||
console.error("Sheet " + target_sheet + " cannot be found");
|
||||
process.exit(3);
|
||||
}
|
||||
@ -226,7 +228,7 @@ try {
|
||||
process.exit(4);
|
||||
}
|
||||
|
||||
if(!program.quiet && !program.book) console.error(target_sheet);
|
||||
if (!program.quiet && !program.book) console.error(target_sheet);
|
||||
|
||||
/* single worksheet file formats */
|
||||
[
|
||||
@ -254,21 +256,21 @@ if(!program.quiet && !program.book) console.error(target_sheet);
|
||||
process.exit(0);
|
||||
} });
|
||||
|
||||
function outit(o, fn) { if(fn) fs.writeFileSync(fn, o); else console.log(o); }
|
||||
function outit(o, fn) { if (fn) fs.writeFileSync(fn, o); else console.log(o); }
|
||||
|
||||
function doit(cb) {
|
||||
/*:: if(!wb) throw new Error("unreachable"); */
|
||||
if(program.book) wb.SheetNames.forEach(function(n, i) {
|
||||
/*:: if(!wb) throw new Error("unreachable"); */
|
||||
/*:: if (!wb) throw new Error("unreachable"); */
|
||||
if (program.book) wb.SheetNames.forEach(function (n, i) {
|
||||
/*:: if (!wb) throw new Error("unreachable"); */
|
||||
outit(cb(wb.Sheets[n]), (program.output || sheetname || filename) + "." + i);
|
||||
});
|
||||
else outit(cb(ws), program.output);
|
||||
}
|
||||
|
||||
var jso = {};
|
||||
switch(true) {
|
||||
switch (true) {
|
||||
case program.formulae:
|
||||
doit(function(ws) { return X.utils.sheet_to_formulae(ws).join("\n"); });
|
||||
doit(function (ws) { return X.utils.sheet_to_formulae(ws).join("\n"); });
|
||||
break;
|
||||
|
||||
case program.arrays: jso.header = 1;
|
||||
@ -276,33 +278,33 @@ switch(true) {
|
||||
case program.rawJs: jso.raw = true;
|
||||
/* falls through */
|
||||
case program.json:
|
||||
doit(function(ws) { return JSON.stringify(X.utils.sheet_to_json(ws,jso)); });
|
||||
doit(function (ws) { return JSON.stringify(X.utils.sheet_to_json(ws, jso)); });
|
||||
break;
|
||||
|
||||
default:
|
||||
if(!program.book) {
|
||||
var stream = X.stream.to_csv(ws, {FS:program.fieldSep||",", RS:program.rowSep||"\n"});
|
||||
if(program.output) stream.pipe(fs.createWriteStream(program.output));
|
||||
if (!program.book) {
|
||||
var stream = X.stream.to_csv(ws, { FS: program.fieldSep || ",", RS: program.rowSep || "\n" });
|
||||
if (program.output) stream.pipe(fs.createWriteStream(program.output));
|
||||
else stream.pipe(process.stdout);
|
||||
} else doit(function(ws) { return X.utils.sheet_to_csv(ws,{FS:program.fieldSep, RS:program.rowSep}); });
|
||||
} else doit(function (ws) { return X.utils.sheet_to_csv(ws, { FS: program.fieldSep, RS: program.rowSep }); });
|
||||
break;
|
||||
}
|
||||
|
||||
function dump_props(wb/*:Workbook*/) {
|
||||
var propaoa = [];
|
||||
if(Object.assign && Object.entries) propaoa = Object.entries(Object.assign({}, wb.Props, wb.Custprops));
|
||||
if (Object.assign && Object.entries) propaoa = Object.entries(Object.assign({}, wb.Props, wb.Custprops));
|
||||
else {
|
||||
var Keys/*:: :Array<string> = []*/, pi;
|
||||
if(wb.Props) {
|
||||
if (wb.Props) {
|
||||
Keys = Object.keys(wb.Props);
|
||||
for(pi = 0; pi < Keys.length; ++pi) {
|
||||
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
|
||||
for (pi = 0; pi < Keys.length; ++pi) {
|
||||
if (Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
|
||||
}
|
||||
}
|
||||
if(wb.Custprops) {
|
||||
if (wb.Custprops) {
|
||||
Keys = Object.keys(wb.Custprops);
|
||||
for(pi = 0; pi < Keys.length; ++pi) {
|
||||
if(Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
|
||||
for (pi = 0; pi < Keys.length; ++pi) {
|
||||
if (Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ function recordhopper(data, cb/*:RecordHopperCB*/, opts/*:?any*/) {
|
||||
/* control buffer usage for fixed-length buffers */
|
||||
function buf_array()/*:BufArray*/ {
|
||||
var bufs/*:Array<Block>*/ = [], blksz = has_buf ? 16384 : 2048;
|
||||
var has_buf_copy = has_buf && (typeof new_buf(blksz).copy == "function");
|
||||
var has_buf_subarray = has_buf && (typeof new_buf(blksz).subarray == "function");
|
||||
|
||||
var newblk = function ba_newblk(sz/*:number*/)/*:Block*/ {
|
||||
var o/*:Block*/ = (new_buf(sz)/*:any*/);
|
||||
prep_blob(o, 0);
|
||||
@ -55,7 +56,10 @@ function buf_array()/*:BufArray*/ {
|
||||
};
|
||||
|
||||
var push = function ba_push(buf) {
|
||||
endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz);
|
||||
if(curbuf.l > 0) bufs.push(curbuf.slice(0, curbuf.l));
|
||||
bufs.push(buf);
|
||||
curbuf = has_buf_subarray ? curbuf.subarray(curbuf.l || 0) : curbuf.slice(curbuf.l || 0);
|
||||
prep_blob(curbuf, 0);
|
||||
};
|
||||
|
||||
return ({ next:next, push:push, end:end, _bufs:bufs, end2:end2 }/*:any*/);
|
||||
|
@ -6,7 +6,7 @@ var mergecregex = /<(?:\w+:)?mergeCell ref=["'][A-Z0-9:]+['"]\s*[\/]?>/g;
|
||||
var hlinkregex = /<(?:\w+:)?hyperlink [^<>]*>/mg;
|
||||
var dimregex = /"(\w*:\w*)"/;
|
||||
var colregex = /<(?:\w+:)?col\b[^<>]*[\/]?>/g;
|
||||
var afregex = /<(?:\w+:)?autoFilter[^>]*/g;
|
||||
var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
|
||||
var marginregex= /<(?:\w+:)?pageMargins[^<>]*\/>/g;
|
||||
var sheetprregex = /<(?:\w+:)?sheetPr\b[^<>]*?\/>/;
|
||||
|
||||
@ -217,7 +217,7 @@ function write_ws_xml_cols(ws, cols)/*:string*/ {
|
||||
}
|
||||
|
||||
function parse_ws_xml_autofilter(data/*:string*/) {
|
||||
var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
|
||||
var o = { ref: (data.match(/ref=["']([^"']*)["']/)||[])[1]};
|
||||
return o;
|
||||
}
|
||||
function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ {
|
||||
@ -529,7 +529,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
|
||||
r = [];
|
||||
rr = encode_row(R);
|
||||
var data_R = dense ? data[R] : [];
|
||||
for(C = range.s.c; C <= range.e.c; ++C) {
|
||||
if(data_R) for(C = range.s.c; C <= range.e.c; ++C) {
|
||||
ref = cols[C] + rr;
|
||||
var _cell = dense ? data_R[C] : ws[ref];
|
||||
if(_cell === undefined) continue;
|
||||
|
@ -137,12 +137,6 @@ function sheet_to_html(ws/*:Worksheet*/, opts/*:?Sheet2HTMLOpts*//*, wb:?Workboo
|
||||
}
|
||||
|
||||
function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
|
||||
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.rows;
|
||||
if(!rows) {
|
||||
/* not an HTML TABLE */
|
||||
throw "Unsupported origin when " + table.tagName + " is not a TABLE";
|
||||
}
|
||||
|
||||
var opts = _opts || {};
|
||||
var dense = ws["!data"] != null;
|
||||
var or_R = 0, or_C = 0;
|
||||
@ -154,7 +148,6 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
}
|
||||
}
|
||||
|
||||
var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
|
||||
var range/*:Range*/ = {s:{r:0,c:0},e:{r:or_R,c:or_C}};
|
||||
if(ws["!ref"]) {
|
||||
var _range/*:Range*/ = decode_range(ws["!ref"]);
|
||||
@ -164,6 +157,15 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
range.e.c = Math.max(range.e.c, _range.e.c);
|
||||
if(or_R == -1) range.e.r = or_R = _range.e.r + 1;
|
||||
}
|
||||
|
||||
|
||||
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.rows;
|
||||
if(!rows) {
|
||||
/* not an HTML TABLE */
|
||||
throw "Unsupported origin when " + table.tagName + " is not a TABLE";
|
||||
}
|
||||
var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
|
||||
|
||||
var merges/*:Array<Range>*/ = [], midx = 0;
|
||||
var rowinfo/*:Array<RowInfo>*/ = ws["!rows"] || (ws["!rows"] = []);
|
||||
var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
|
||||
@ -187,7 +189,9 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
|
||||
}
|
||||
/* TODO: figure out how to extract nonstandard mso- style */
|
||||
CS = +elt.getAttribute("colspan") || 1;
|
||||
if( ((RS = (+elt.getAttribute("rowspan") || 1)))>1 || CS>1) merges.push({s:{r:R + or_R,c:C + or_C},e:{r:R + or_R + (RS||1) - 1, c:C + or_C + (CS||1) - 1}});
|
||||
if( ((RS = (+elt.getAttribute("rowspan") || 1)))>1 || CS>1) {
|
||||
merges.push({s:{r:R + or_R,c:C + or_C},e:{r:R + or_R + (RS||1) - 1, c:C + or_C + (CS||1) - 1}});
|
||||
}
|
||||
var o/*:Cell*/ = {t:'s', v:v};
|
||||
var _t/*:string*/ = elt.getAttribute("data-t") || elt.getAttribute("t") || "";
|
||||
if(v != null) {
|
||||
|
@ -24,7 +24,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
|
||||
switch(val.t){
|
||||
case 'z': if(v == null) break; continue;
|
||||
case 'e': v = (v == 0 ? null : void 0); break;
|
||||
case 's': case 'b':break;
|
||||
case 's': case 'b': break;
|
||||
case 'n': if(!val.z || !fmt_is_date(val.z)) break;
|
||||
v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
|
||||
if(typeof v == "number") break;
|
||||
|
Loading…
Reference in New Issue
Block a user