SheetJS/sheetjs

Deno support

Closed this issue · 8 comments

I've come across SheetJS via the Deno third-party modules. However there's no example or usage for deno. Is it possible to use with Deno? Apparently Deno prefers code imports that conform to ES modules. I've tried to use SheetJS via skypak.dev which can sometimes help convert node packages to modern ES modules, but I can't get the import to work, so sample code doesn't work. https://jspm.org/ might be another option. Unfortunately I'm learning server-side JS and Deno. Appreciate any tips to get it working on Deno. Thanks.

FYI found this trail (up to about 10 messages from that point) which has some diagnosis - looks like it's not possible currently

same problem..

we have SheetJS working with Deno v1.10.x here, in case it helps either of you:

https://github.com/githubocto/flat-postprocessing/blob/main/src/xlsx.ts

Assuming the next release will have actual ESM builds and a proper module reference in package.json, what else is needed for Deno support?

@thouger There are two ways to read a file and then use sheetjs for other operations:

  1. Use fetch: #1630 (comment)

    It is recommended to use binary parsing.

  2. Use Deno.read:
  // demo.js
  // Use: deno run --allow-all demo.js
  import XLSX from 'https://esm.sh/xlsx';
  
  const xlsxData /* Uint8Array */ = Deno.readFileSync(new URL('example.xlsx', import.meta.url).pathname);
  const workBook = XLSX.readFile(
      xlsxData.buffer,
      { type: "array" }
  );
  
  // console.log('sheets', workBook.Sheets);
  console.log('sheetNames', workBook.SheetNames);
  const json = XLSX.utils.sheet_to_json(workBook.Sheets[workBook.SheetNames[0]])
  
  console.log('jsonData-sheetNames[0]', json);

@thouger There are two ways to read a file and then use sheetjs for other operations:

  1. Use fetch: Read the excel file simple issue #1630 (comment)

    It is recommended to use binary parsing.

  2. Use Deno.read:
  // demo.js
  // Use: deno run --allow-all demo.js
  import XLSX from 'https://esm.sh/xlsx';
  
  const xlsxData = Deno.readFileSync(new URL('example.xlsx', import.meta.url).pathname);
  const workBook = XLSX.readFile(
      xlsxData.buffer /* Uint8Array */,
      { type: "array" }
  );
  
  // console.log('sheets', workBook.Sheets);
  console.log('sheetNames', workBook.SheetNames);
  const json = XLSX.utils.sheet_to_json(workBook.Sheets[workBook.SheetNames[0]])
  
  console.log('jsonData-sheetNames[0]', json);

谢谢你的回答哈哈哈哈,我后面放弃了deno了,很多库没有兼容比较麻烦。

Consider the following sample:

import * as XLSX from 'https://jspm.dev/npm:xlsx@0.18.0!cjs';

const rawdata = Deno.readFileSync("test.xlsb");
const wb = XLSX.read(rawdata, {type: "buffer"});
const buf = XLSX.write(wb, {type: "buffer", bookType: "fods"});
await Deno.writeFileSync("test.fods", new Uint8Array(buf));

This currently works with release 0.18.0 on deno 1.10.3 + typescript 4.2.2 with the following command:

$ deno run --allow-read --allow-write test.ts

It is also possible to reference the ESM build directly:

import * as XLSX from 'https://unpkg.com/xlsx/xlsx.mjs';

Issues:

  1. importing the full or any of the other commonjs bundles gives type errors due to confusion with the CFB module types. This is a typedef issue and should be revisited. (it's actually unclear why Deno does this, bug in the runtime?)

It is still not generally recommended to use the ESM build for a few reasons, including "missing codepage support" (the library will need a method to do it instead of proactively trying to require the support) and "functions not amenable to tree-shaking" (write and writeFile call different functions based on a bookType parameter or parsing the filename, so writing XLSX will currently end up pulling in write support for all supported formats)

  1. Deno does not present a global equivalent of the NodeJS Buffer, which results in the fallback array-of-bytes when writing with type "buffer". That needs to be revisited for each of the major export file types (there are a handful of areas that generate output stubs and they should be explicitly verified)

  2. Deno.readFileSync / Deno.writeFileSync should be baked into the library. The write call (guarded behind a typeof check for Deno and any other recommended tests for detecting a Deno runtime) should be put somewhere in write_dl while the read call should be put somewhere in read_binary

pushed a special tag v0.18.0+deno and added a new deno demo

// @deno-types="https://deno.land/x/sheetjs@v0.18.0+deno/types/index.d.ts"
import * as XLSX from 'https://deno.land/x/sheetjs@v0.18.0+deno/xlsx.mjs';
import * as cptable from 'https://deno.land/x/sheetjs/dist/cpexcel.full.mjs';
XLSX.set_cptable(cptable);

const ws = XLSX.utils.aoa_to_sheet([["a","b","c"],[1,2,3],[4,5,6]]);
const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "test.xlsx");
const workbook = XLSX.readFile("test.xlsx");
XLSX.utils.sheet_add_aoa(workbook.Sheets["Sheet1"], [[7, 8, 9]], { origin: -1 });
XLSX.writeFile(workbook, "test1.xlsx");

The other discussed issues will be raised separately