diff --git a/bin/xlsx.njs b/bin/xlsx.njs index e467337..13c8a18 100755 --- a/bin/xlsx.njs +++ b/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 ', 'CSV field separator', ",") .option('-R, --row-sep ', 'CSV row separator', "\n") .option('-n, --sheet-rows ', 'Number of rows to process (0=all rows)') + .option('--date-format ', 'output date format, for example yyyy-mm-dd') .option('--codepage ', 'default to specified codepage when ambiguous') - .option('--req ', '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 = []*/, 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]]]); } } } diff --git a/bits/24_hoppers.js b/bits/24_hoppers.js index ac7793c..fc075b8 100644 --- a/bits/24_hoppers.js +++ b/bits/24_hoppers.js @@ -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*/ = [], 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*/); diff --git a/bits/67_wsxml.js b/bits/67_wsxml.js index 7c78e98..d66e90c 100644 --- a/bits/67_wsxml.js +++ b/bits/67_wsxml.js @@ -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; diff --git a/bits/79_html.js b/bits/79_html.js index 5143a68..e3b943d 100644 --- a/bits/79_html.js +++ b/bits/79_html.js @@ -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*/ = 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*/ = 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*/ = [], midx = 0; var rowinfo/*:Array*/ = 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) { diff --git a/bits/90_utils.js b/bits/90_utils.js index a02370a..fb47773 100644 --- a/bits/90_utils.js +++ b/bits/90_utils.js @@ -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;