SheetJS / sheetjs

📗 SheetJS Spreadsheet Data Toolkit -- New home https://git.sheetjs.com/SheetJS/sheetjs
https://sheetjs.com/
Apache License 2.0
34.78k stars 7.99k forks source link

Is xlsx to csv conversion possible ? #2789

Closed jithinb68 closed 1 year ago

jithinb68 commented 1 year ago

Found this piece of code in the docs, but it doesn't seem to work. I have an input which is an s3 url of xlsx file input https://modulus.s3-****/Content.xlsx

var output_file_name = "out.csv";
var stream = XLSX.stream.to_csv(worksheet);
stream.pipe(fs.createWriteStream(output_file_name));

Is this the right way to do when input is an url also if its so how to generate worksheet from xlsx file

SheetJSDev commented 1 year ago

Assuming you are running in a newer version of NodeJS, use fetch to download the data and loop through the worksheets:

const XLSX = require("xlsx"), fs = require("fs");
const url = "...";

(async() => {
  const wb = XLSX.read(await (await fetch(url)).arrayBuffer());
  wb.SheetNames.forEach((name, idx) => {
    const ws = wb.Sheets[name];
    fs.writeFileSync(`out.${idx}.csv`, XLSX.utils.sheet_to_csv(ws));
  });
})();

If the file is not public, the AWS demo in the docs has an example using the official aws-sdk module to fetch an object, parse, and log the first worksheet

jithinb68 commented 1 year ago

Thanks @SheetJSDev . This works independently. But in my case I don't want to write into the file system. this Nodejs part which does the conversion need to send a response to the frontend and the frontend needs to download the file as csv. frontend send the url as request and backend needs to convert it and send back to UI to download. Can you please help me with that piece as well. Something similar to

SheetJSDev commented 1 year ago

XLSX.utils.sheet_to_csv(ws) is a string, you can just send that in the response.

jithinb68 commented 1 year ago

Thanks @SheetJSDev , Will this work with axios as well ? It's throwing an error response.data.arrayBuffer is not a function

jithinb68 commented 1 year ago

It's throws error in internal of XLSX.read ->TypeError: f.slice is not a function

`

app.get('/csv', async (req, res) => { try { const s3uri = req.query.s3uri const wb = XLSX.read(await axios(s3uri), {responseType:'arraybuffer'}); const sheetName = wb.SheetNames[0] const ws = wb.Sheets[sheetName]; const rawCsv = XLSX.utils.sheet_to_csv(ws); res.setHeader('Content-Type', 'text/csv'); res.send(rawCsv); } catch (error) { res.status(500).send("Server Error"); console.error(error); } })`

jithinb68 commented 1 year ago

@SheetJSDev Still the same issue after correcting the line -> TypeError: f.slice is not a function

Corrected it, we needed response.data to be passed. Thanks @SheetJSDev

Corrected code

app.get('/csv', async (req, res) => {
    try {
        const s3uri = req.query.s3uri
        const response = await axios(s3uri, {responseType:'arraybuffer'})
        const wb = XLSX.read(response.data);
        const sheetName = wb.SheetNames[0]
        const ws = wb.Sheets[sheetName];
        const rawCsv = XLSX.utils.sheet_to_csv(ws);
        res.setHeader('Content-Type', 'text/csv');
        res.send(rawCsv);
    } catch (error) {
        res.status(500).send("Server Error");
        console.error(error);
    }
})