JavaScript - 将CSV转换为XLSX(最好不使用库)

12

如标题所述,我当前有一个从SharePoint列表数据创建的CSV文件,为了将此信息显示为电子表格,我想将其转换为Excel XLSX文件。 我更喜欢不依赖第三方库来实现这个目标。 起初,我开始使用ActiveX对象尝试重新创建和/或保存CSV为XLSX,但由于除IE之外的其他浏览器无法使用它,因此存在限制。 我在考虑使用Blob来进行转换? 这就是我卡住的地方。

function createCsv(data) {
    var result = "";

    if (data == null || data.length == 0) {
        return;
    }

    var columnDelimiter = ',';
    var lineDelimiter = '\n';

    var keys = Object.keys(data[0]);

    // spreadsheet header

    result += keys.join(columnDelimiter);
    result += lineDelimiter;

    // spreadsheet data

    data.forEach(function (obj) {
        var count = 0;

        keys.forEach(function (key) {
            if (count > 0) {
                result += columnDelimiter;
            }

            result += obj[key];
            count++;               
        });

        result += lineDelimiter;
    });

    return result;
}

function downloadCsv(csv) {
    if (csv == null) {
        return;
    }

    var filename = "test.csv";

    csv = "data:text/csv;charset=utf-8," + csv;

    var data = encodeURI(csv);

    console.log(data);

    var link = document.getElementById('csv');
    link.setAttribute('href', data);
    link.setAttribute('download', filename);

    console.log(link);

    //displayCsv(csv);
}

function displayCsv() {
    // using test csv here
    var message = "data:text/csv;charset=utf-8, yo, hey, lol";
    //var fileType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    var fileType = "application/msexcel";

    var csvFile = new Blob([message], {type: fileType});
    var csvUrl = URL.createObjectURL(csvFile);

    console.log(csvFile);
    console.log(csvUrl);

}

CSV文件可以通过电子表格(下载并在Excel中打开)使用,但我需要一种在网页上将其作为电子表格而不是文本显示的方法,这就是我要转换它的原因。由于我正在SharePoint中使用它,因此可以使用Excel Web部件来显示XLSX文件-但不能像这样打开CSV文件。提前致谢。


我尝试使用 iframes,但问题是浏览器会自动下载我设置为 iframesrc 的链接,而不是显示它。只有当类型设置为 text/plain 时,它才会按预期显示 CSV。 - LaLaLottie
我也在寻找相同的解决方案。你解决了吗? - Valay
很遗憾,我没有。我只是用CSV文件勉强凑合着用。XLSX文件格式带有许多特殊编码,这使得转换不值得。但可能有第三方应用程序可以做到这一点。 - LaLaLottie
4个回答

4
我不确定这样做是否能解决您的问题,但如果xls文件可以满足您的需求,您可以通过在csv的第一行添加分隔符标签并将其重命名为xls来创建一个xls文件。 值周围的引号也很重要。
例如:
"sep=,"
"Service","Reported","Total","%"
"a service","23","70","32.86%"
"yet_a_service","27","70","38.57%"
"more_services","20","70","28.57%"

尝试在Mac上使用Excel 365,出现以下提示:“‘Book1.xls’的文件格式和扩展名不匹配。该文件可能已损坏或不安全。除非您信任其来源,否则不要打开它。您仍要打开它吗?” - Brian Burns
CSV != XLS。仅仅更改文件扩展名并不会改变文件格式,这只会导致混淆。XLS是一种二进制格式,与基于文本的CSV完全不同。 - ADyson

3

如果没有使用库进行操作,手动尝试执行此操作将是相当大的任务。虽然OpenXML文件在其核心上基于XML,但它们也被打包/压缩。

我建议您查看SheetJS。https://sheetjs.com/

您可以将CSV作为输入,立即将其写回为XSLX。


1
如果您愿意使用第三方库(考虑到转换过程的复杂性,我强烈建议这样做),这个解决方案将适合您的需求,如果需要在nodejs中完成转换。
如果您想在浏览器中使用它,convertCsvToExcel函数需要修改以将缓冲区转换为Blob对象,然后将该Blob对象转换为XLS文件。
// Convert a CSV string to XLSX buffer 
// change from xlsx/xls and other formats by going through sheetsjs documentation.
import * as XLSX from 'xlsx';

export const convertCsvToExcelBuffer = (csvString: string) => {
  const arrayOfArrayCsv = csvString.split("\n").map((row: string) => {
    return row.split(",")
  });
  const wb = XLSX.utils.book_new();
  const newWs = XLSX.utils.aoa_to_sheet(arrayOfArrayCsv);
  XLSX.utils.book_append_sheet(wb, newWs);
  const rawExcel = XLSX.write(wb, { type: 'base64' })
  return rawExcel
}

// Express request handler for sending the excel buffer to response.

export const convertCsvToExcel = async (req: express.Request, res: express.Response) => {
    const csvFileTxt = fileBuffer.toString()
    const excelBuffer = convertCsvToExcelBuffer(csvFileTxt)
    res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    res.status(200).send(Buffer.from(excelBuffer, 'base64'))
}

1
一个非常简单的解决方案是使用https://github.com/netas-ch/csv2xlsx库。
示例:
async function downloadAsExcel() {
    const cvrt = await import('src/Csv2Xlsx.js');

    // Meta-Data of the xlsx
    const metaData = {
        title: 'My Demo Spreadsheet',
        subject: 'A Demo for CSV to XLSX',
        creator: 'John Doe',
        company: 'Super Doe Ltd.',
        lastModifiedBy: 'John Doe',
        created: new Date(2020, 0, 1, 11, 21),
        modified: null // now
    };

    // download the csv and convert it to a excel file
    const aTag = await cvrt.Csv2Xlsx.convertCsv('my/demo/data.csv', 'mynewfilename.xlsx', metaData);

    // return value is a <a> element, add it to the DOM to start the download
    document.body.appendChild(aTag);

    // start the download automatically
    aTag.click();
}

在每个现代浏览器中运行(Chrome,Firefox,Safari)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接