Skip to content

Commit c1f5f04

Browse files
committed
xlsx-cli separate package [ci skip]
1 parent 3a26260 commit c1f5f04

File tree

7 files changed

+384
-5
lines changed

7 files changed

+384
-5
lines changed

bin/xlsx.njs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,20 @@ var n = "xlsx";
66
var X = require('../');
77
try { X = require('../xlsx.flow'); } catch(e) {}
88
require('exit-on-epipe');
9-
var fs = require('fs'), program = require('commander');
9+
var fs = require('fs'), program;
10+
try { program = require('commander'); } catch(e) {
11+
[
12+
"The `xlsx` command line tool is deprecated in favor of `xlsx-cli`.",
13+
"",
14+
"For new versions of node, we recommend using `npx`:",
15+
" $ npx xlsx-cli --help",
16+
"",
17+
"For older versions of node, explicitly install `xlsx-cli` globally:",
18+
" $ npm i -g xlsx-cli",
19+
" $ xlsx-cli --help"
20+
].forEach(function(m) { console.error(m); });
21+
process.exit(1);
22+
}
1023
program
1124
.version(X.version)
1225
.usage('[options] <file> [sheetname]')

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@
3535
"adler-32": "~1.2.0",
3636
"cfb": "^1.1.4",
3737
"codepage": "~1.15.0",
38-
"commander": "~2.17.1",
3938
"crc-32": "~1.2.0",
40-
"exit-on-epipe": "~1.0.1",
41-
"fflate": "^0.7.1",
4239
"ssf": "~0.11.2",
4340
"wmf": "~1.0.1",
4441
"word": "~0.3.0"
@@ -49,10 +46,13 @@
4946
"acorn": "7.4.1",
5047
"alex": "^9.1.0",
5148
"blanket": "~1.2.3",
49+
"commander": "~2.17.1",
5250
"dtslint": "^0.1.2",
5351
"eslint": "7.23.0",
5452
"eslint-plugin-html": "^6.1.2",
5553
"eslint-plugin-json": "^2.1.2",
54+
"exit-on-epipe": "~1.0.1",
55+
"fflate": "^0.7.1",
5656
"jsdom": "~11.1.0",
5757
"markdown-spellcheck": "^1.3.1",
5858
"mocha": "~2.5.3",
@@ -90,7 +90,7 @@
9090
},
9191
"homepage": "https://sheetjs.com/",
9292
"bugs": {
93-
"url": "https://github.com/SheetJS/js-xlsx/issues"
93+
"url": "https://github.com/SheetJS/sheetjs/issues"
9494
},
9595
"license": "Apache-2.0",
9696
"engines": {

packages/xlsx-cli/.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.tgz

packages/xlsx-cli/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# xlsx-cli
2+
3+
This is a standalone version of the CLI tool for [SheetJS](https://sheetjs.com).
4+
5+
For newer versions of node, the tool should be invoked with `npx`:
6+
7+
```bash
8+
$ npx xlsx-cli --help # help and usage info
9+
$ npx xlsx-cli --xlsx test.csv # generates test.csv.xlsx from test.csv
10+
```
11+
12+
For older versions of node, the tool should be installed globally:
13+
14+
```bash
15+
$ sudo npm install -g xlsx-cli # install globally (once)
16+
17+
$ xlsx-cli --help # help and usage info
18+
$ npx xlsx-cli --xlsx test.csv # generates test.csv.xlsx from test.csv
19+
```
20+

packages/xlsx-cli/bin/xlsx.njs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env node
2+
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
3+
/* eslint-env node */
4+
/* vim: set ts=2 ft=javascript: */
5+
var cli = require('../');
6+
7+
cli();

packages/xlsx-cli/index.js

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
#!/usr/bin/env node
2+
/* index.js (C) 2020-present SheetJS -- http://sheetjs.com */
3+
/* eslint-env node */
4+
/* vim: set ts=2 ft=javascript: */
5+
6+
var n = "xlsx-cli";
7+
var X = require('xlsx');
8+
require('exit-on-epipe');
9+
var fs = require('fs'), program = require('commander');
10+
function run() {
11+
program
12+
.version(X.version)
13+
.usage('[options] <file> [sheetname]')
14+
.option('-f, --file <file>', 'use specified workbook')
15+
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
16+
.option('-N, --sheet-index <idx>', 'use specified sheet index (0-based)')
17+
.option('-p, --password <pw>', 'if file is encrypted, try with specified pw')
18+
.option('-l, --list-sheets', 'list sheet names and exit')
19+
.option('-o, --output <file>', 'output to specified file')
20+
21+
.option('-B, --xlsb', 'emit XLSB to <sheetname> or <file>.xlsb')
22+
.option('-M, --xlsm', 'emit XLSM to <sheetname> or <file>.xlsm')
23+
.option('-X, --xlsx', 'emit XLSX to <sheetname> or <file>.xlsx')
24+
.option('-I, --xlam', 'emit XLAM to <sheetname> or <file>.xlam')
25+
.option('-Y, --ods', 'emit ODS to <sheetname> or <file>.ods')
26+
.option('-8, --xls', 'emit XLS to <sheetname> or <file>.xls (BIFF8)')
27+
.option('-5, --biff5', 'emit XLS to <sheetname> or <file>.xls (BIFF5)')
28+
//.option('-4, --biff4','emit XLS to <sheetname> or <file>.xls (BIFF4)')
29+
//.option('-3, --biff3','emit XLS to <sheetname> or <file>.xls (BIFF3)')
30+
.option('-2, --biff2', 'emit XLS to <sheetname> or <file>.xls (BIFF2)')
31+
.option('-i, --xla', 'emit XLA to <sheetname> or <file>.xla')
32+
.option('-6, --xlml', 'emit SSML to <sheetname> or <file>.xls (2003 XML)')
33+
.option('-T, --fods', 'emit FODS to <sheetname> or <file>.fods (Flat ODS)')
34+
35+
.option('-S, --formulae', 'emit list of values and formulae')
36+
.option('-j, --json', 'emit formatted JSON (all fields text)')
37+
.option('-J, --raw-js', 'emit raw JS object (raw numbers)')
38+
.option('-A, --arrays', 'emit rows as JS objects (raw numbers)')
39+
.option('-H, --html', 'emit HTML to <sheetname> or <file>.html')
40+
.option('-D, --dif', 'emit DIF to <sheetname> or <file>.dif (Lotus DIF)')
41+
.option('-U, --dbf', 'emit DBF to <sheetname> or <file>.dbf (MSVFP DBF)')
42+
.option('-K, --sylk', 'emit SYLK to <sheetname> or <file>.slk (Excel SYLK)')
43+
.option('-P, --prn', 'emit PRN to <sheetname> or <file>.prn (Lotus PRN)')
44+
.option('-E, --eth', 'emit ETH to <sheetname> or <file>.eth (Ethercalc)')
45+
.option('-t, --txt', 'emit TXT to <sheetname> or <file>.txt (UTF-8 TSV)')
46+
.option('-r, --rtf', 'emit RTF to <sheetname> or <file>.txt (Table RTF)')
47+
.option('-z, --dump', 'dump internal representation as JSON')
48+
.option('--props', 'dump workbook properties as CSV')
49+
50+
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
51+
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
52+
.option('-n, --sheet-rows <num>', 'Number of rows to process (0=all rows)')
53+
.option('--codepage <cp>', 'default to specified codepage when ambiguous')
54+
.option('--req <module>', 'require module before processing')
55+
.option('--sst', 'generate shared string table for XLS* formats')
56+
.option('--compress', 'use compression when writing XLSX/M/B and ODS')
57+
.option('--read', 'read but do not generate output')
58+
.option('--book', 'for single-sheet formats, emit a file per worksheet')
59+
.option('--all', 'parse everything; write as much as possible')
60+
.option('--dev', 'development mode')
61+
.option('--sparse', 'sparse mode')
62+
.option('-q, --quiet', 'quiet mode');
63+
64+
program.on('--help', function () {
65+
console.log(' Default output format is CSV');
66+
console.log(' Support email: [email protected]');
67+
console.log(' Web Demo: http://oss.sheetjs.com/js-' + n + '/');
68+
});
69+
70+
/* flag, bookType, default ext */
71+
var workbook_formats = [
72+
['xlsx', 'xlsx', 'xlsx'],
73+
['xlsm', 'xlsm', 'xlsm'],
74+
['xlam', 'xlam', 'xlam'],
75+
['xlsb', 'xlsb', 'xlsb'],
76+
['xls', 'xls', 'xls'],
77+
['xla', 'xla', 'xla'],
78+
['biff5', 'biff5', 'xls'],
79+
['ods', 'ods', 'ods'],
80+
['fods', 'fods', 'fods']
81+
];
82+
var wb_formats_2 = [
83+
['xlml', 'xlml', 'xls']
84+
];
85+
program.parse(process.argv);
86+
87+
var filename = '', sheetname = '';
88+
if (program.args[0]) {
89+
filename = program.args[0];
90+
if (program.args[1]) sheetname = program.args[1];
91+
}
92+
if (program.sheet) sheetname = program.sheet;
93+
if (program.file) filename = program.file;
94+
95+
if (!filename) {
96+
console.error(n + ": must specify a filename");
97+
process.exit(1);
98+
}
99+
if (!fs.existsSync(filename)) {
100+
console.error(n + ": " + filename + ": No such file or directory");
101+
process.exit(2);
102+
}
103+
104+
if (program.req) program.req.split(",").forEach(function (r) {
105+
require((fs.existsSync(r) || fs.existsSync(r + '.js')) ? require('path').resolve(r) : r);
106+
});
107+
108+
var opts = {}, wb/*:?Workbook*/;
109+
if (program.listSheets) opts.bookSheets = true;
110+
if (program.sheetRows) opts.sheetRows = program.sheetRows;
111+
if (program.password) opts.password = program.password;
112+
var seen = false;
113+
function wb_fmt() {
114+
seen = true;
115+
opts.cellFormula = true;
116+
opts.cellNF = true;
117+
if (program.output) sheetname = program.output;
118+
}
119+
function isfmt(m/*:string*/)/*:boolean*/ {
120+
if (!program.output) return false;
121+
var t = m.charAt(0) === "." ? m : "." + m;
122+
return program.output.slice(-t.length) === t;
123+
}
124+
workbook_formats.forEach(function (m) { if (program[m[0]] || isfmt(m[0])) { wb_fmt(); } });
125+
wb_formats_2.forEach(function (m) { if (program[m[0]] || isfmt(m[0])) { wb_fmt(); } });
126+
if (seen) {
127+
} else if (program.formulae) opts.cellFormula = true;
128+
else opts.cellFormula = false;
129+
130+
var wopts = ({ WTF: opts.WTF, bookSST: program.sst }/*:any*/);
131+
if (program.compress) wopts.compression = true;
132+
133+
if (program.all) {
134+
opts.cellFormula = true;
135+
opts.bookVBA = true;
136+
opts.cellNF = true;
137+
opts.cellHTML = true;
138+
opts.cellStyles = true;
139+
opts.sheetStubs = true;
140+
opts.cellDates = true;
141+
wopts.cellStyles = true;
142+
wopts.sheetStubs = true;
143+
wopts.bookVBA = true;
144+
}
145+
if (program.sparse) opts.dense = false; else opts.dense = true;
146+
if (program.codepage) opts.codepage = +program.codepage;
147+
148+
if (program.dev) {
149+
opts.WTF = true;
150+
wb = X.readFile(filename, opts);
151+
} else try {
152+
wb = X.readFile(filename, opts);
153+
} catch (e) {
154+
var msg = (program.quiet) ? "" : n + ": error parsing ";
155+
msg += filename + ": " + e;
156+
console.error(msg);
157+
process.exit(3);
158+
}
159+
if (program.read) process.exit(0);
160+
if (!wb) { console.error(n + ": error parsing " + filename + ": empty workbook"); process.exit(0); }
161+
/*:: if(!wb) throw new Error("unreachable"); */
162+
if (program.listSheets) {
163+
console.log((wb.SheetNames || []).join("\n"));
164+
process.exit(0);
165+
}
166+
if (program.dump) {
167+
console.log(JSON.stringify(wb));
168+
process.exit(0);
169+
}
170+
if (program.props) {
171+
if (wb) dump_props(wb);
172+
process.exit(0);
173+
}
174+
175+
/* full workbook formats */
176+
workbook_formats.forEach(function (m) {
177+
if (program[m[0]] || isfmt(m[0])) {
178+
wopts.bookType = m[1];
179+
if (wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
180+
process.exit(0);
181+
}
182+
});
183+
184+
wb_formats_2.forEach(function (m) {
185+
if (program[m[0]] || isfmt(m[0])) {
186+
wopts.bookType = m[1];
187+
if (wb) X.writeFile(wb, program.output || sheetname || ((filename || "") + "." + m[2]), wopts);
188+
process.exit(0);
189+
}
190+
});
191+
192+
var target_sheet = sheetname || '';
193+
if (target_sheet === '') {
194+
if (+program.sheetIndex < (wb.SheetNames || []).length) target_sheet = wb.SheetNames[+program.sheetIndex];
195+
else target_sheet = (wb.SheetNames || [""])[0];
196+
}
197+
198+
var ws;
199+
try {
200+
ws = wb.Sheets[target_sheet];
201+
if (!ws) {
202+
console.error("Sheet " + target_sheet + " cannot be found");
203+
process.exit(3);
204+
}
205+
} catch (e) {
206+
console.error(n + ": error parsing " + filename + " " + target_sheet + ": " + e);
207+
process.exit(4);
208+
}
209+
210+
if (!program.quiet && !program.book) console.error(target_sheet);
211+
212+
/* single worksheet file formats */
213+
[
214+
['biff2', '.xls'],
215+
['biff3', '.xls'],
216+
['biff4', '.xls'],
217+
['sylk', '.slk'],
218+
['html', '.html'],
219+
['prn', '.prn'],
220+
['eth', '.eth'],
221+
['rtf', '.rtf'],
222+
['txt', '.txt'],
223+
['dbf', '.dbf'],
224+
['dif', '.dif']
225+
].forEach(function (m) {
226+
if (program[m[0]] || isfmt(m[1])) {
227+
wopts.bookType = m[0];
228+
if (program.book) {
229+
/*:: if(wb == null) throw new Error("Unreachable"); */
230+
wb.SheetNames.forEach(function (n, i) {
231+
wopts.sheet = n;
232+
X.writeFile(wb, (program.output || sheetname || filename || "") + m[1] + "." + i, wopts);
233+
});
234+
} else X.writeFile(wb, program.output || sheetname || ((filename || "") + m[1]), wopts);
235+
process.exit(0);
236+
}
237+
});
238+
239+
function outit(o, fn) { if (fn) fs.writeFileSync(fn, o); else console.log(o); }
240+
241+
function doit(cb) {
242+
/*:: if(!wb) throw new Error("unreachable"); */
243+
if (program.book) wb.SheetNames.forEach(function (n, i) {
244+
/*:: if(!wb) throw new Error("unreachable"); */
245+
outit(cb(wb.Sheets[n]), (program.output || sheetname || filename) + "." + i);
246+
});
247+
else outit(cb(ws), program.output);
248+
}
249+
250+
var jso = {};
251+
switch (true) {
252+
case program.formulae:
253+
doit(function (ws) { return X.utils.sheet_to_formulae(ws).join("\n"); });
254+
break;
255+
256+
case program.arrays: jso.header = 1;
257+
/* falls through */
258+
case program.rawJs: jso.raw = true;
259+
/* falls through */
260+
case program.json:
261+
doit(function (ws) { return JSON.stringify(X.utils.sheet_to_json(ws, jso)); });
262+
break;
263+
264+
default:
265+
if (!program.book) {
266+
var stream = X.stream.to_csv(ws, { FS: program.fieldSep, RS: program.rowSep });
267+
if (program.output) stream.pipe(fs.createWriteStream(program.output));
268+
else stream.pipe(process.stdout);
269+
} else doit(function (ws) { return X.utils.sheet_to_csv(ws, { FS: program.fieldSep, RS: program.rowSep }); });
270+
break;
271+
}
272+
273+
function dump_props(wb/*:Workbook*/) {
274+
var propaoa = [];
275+
if (Object.assign && Object.entries) propaoa = Object.entries(Object.assign({}, wb.Props, wb.Custprops));
276+
else {
277+
var Keys/*:: :Array<string> = []*/, pi;
278+
if (wb.Props) {
279+
Keys = Object.keys(wb.Props);
280+
for (pi = 0; pi < Keys.length; ++pi) {
281+
if (Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
282+
}
283+
}
284+
if (wb.Custprops) {
285+
Keys = Object.keys(wb.Custprops);
286+
for (pi = 0; pi < Keys.length; ++pi) {
287+
if (Object.prototype.hasOwnProperty.call(Keys, Keys[pi])) propaoa.push([Keys[pi], Keys[/*::+*/Keys[pi]]]);
288+
}
289+
}
290+
}
291+
console.log(X.utils.sheet_to_csv(X.utils.aoa_to_sheet(propaoa)));
292+
}
293+
}
294+
295+
module.exports = run;

0 commit comments

Comments
 (0)