39 lines
1.5 KiB
TypeScript
39 lines
1.5 KiB
TypeScript
|
#!/usr/bin/env -S deno run --allow-net
|
||
|
// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts"
|
||
|
import { read, stream, Sheet2CSVOpts, WorkSheet } from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
|
||
|
|
||
|
interface Resumable { resume:()=>void; };
|
||
|
/* Generate row strings from a worksheet */
|
||
|
function sheet_to_csv_cb(ws: WorkSheet, cb:(d:string|null)=>void, opts: Sheet2CSVOpts = {}, batch = 1000): Resumable {
|
||
|
stream.set_readable(() => ({
|
||
|
__done: false,
|
||
|
// this function will be assigned by the SheetJS stream methods
|
||
|
_read: function() { this.__done = true; },
|
||
|
// this function is called by the stream methods
|
||
|
push: function(d: string|null) {
|
||
|
if(!this.__done) cb(d);
|
||
|
if(d == null) this.__done = true;
|
||
|
},
|
||
|
resume: function pump() {
|
||
|
for(var i = 0; i < batch && !this.__done; ++i) this._read();
|
||
|
if(!this.__done) setTimeout(pump.bind(this), 0);
|
||
|
}
|
||
|
}));
|
||
|
return stream.to_csv(ws, opts) as Resumable;
|
||
|
}
|
||
|
|
||
|
/* Callback invoked on each row (string) and at the end (null) */
|
||
|
const csv_cb = (d:string|null) => {
|
||
|
if(d == null) return;
|
||
|
/* The strings include line endings, so raw write ops should be used */
|
||
|
Deno.stdout.write(new TextEncoder().encode(d));
|
||
|
};
|
||
|
|
||
|
/* Fetch https://sheetjs.com/pres.numbers, parse, and get first worksheet */
|
||
|
const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer();
|
||
|
const wb = read(ab, { dense: true });
|
||
|
const ws = wb.Sheets[wb.SheetNames[0]];
|
||
|
|
||
|
/* Create and start CSV stream */
|
||
|
sheet_to_csv_cb(ws, csv_cb).resume();
|