如何将JSON导出为CSV或Excel - Angular 2

36

假设我的JSON长这样:

var readyToExport = [
   {id: 1, name: 'a'},
   {id: 2, name: 'b'},
   {id: 3, name: 'c'}
];

如何在 Angular2 中将此 JSON 导出为 CSV 或 Excel 文件?

我使用的浏览器是 Chrome。

也许 Angular2 不相关,但是否有任何第三方插件可以注入到 Angular2 中并执行此任务?


有几种方法可以导出到CSV或Excel;你使用Angular可能并不重要。更重要的是你使用的浏览器,因为在客户端创建文件在各个浏览器上并不是非常统一。 - S McCrohan
我正在使用Chrome浏览器,你知道有什么第三方插件可以用来完成这个任务吗? - Vicheanak
您可以使用插件ngCsv - 使用AngularJS导出CSV。链接在这里:http://ngmodules.org/modules/ng-csv - Tai Nguyen
@TaiNguyen ng-csv需要ngSanitize,但在angular2中不可用。 - Vicheanak
@Vicheanak,您可以使用Node.js将JSON转换为CSV格式。然后,AngularJS2可以调用HTTP POST JSON并获取CSV文件。我认为是这样的。 - Tai Nguyen
8个回答

59

我使用这两个库实现了Excel导出:file-saverxlsx

您可以通过以下方式将其添加到您的现有项目中:

npm install file-saver --save
npm install xlsx --save

ExcelService 示例:

import { Injectable } from '@angular/core';
import * as FileSaver from 'file-saver';
import * as XLSX from 'xlsx';

const EXCEL_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
const EXCEL_EXTENSION = '.xlsx';

@Injectable()
export class ExcelService {

  constructor() { }

  public exportAsExcelFile(json: any[], excelFileName: string): void {
    const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
    const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
    const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' });
    this.saveAsExcelFile(excelBuffer, excelFileName);
  }

  private saveAsExcelFile(buffer: any, fileName: string): void {
    const data: Blob = new Blob([buffer], {
      type: EXCEL_TYPE
    });
    FileSaver.saveAs(data, fileName + '_export_' + new Date().getTime() + EXCEL_EXTENSION);
  }

}

你可以在我的Github上找到一个工作示例:https://github.com/luwojtaszek/ngx-excel-export

[样式化单元格]

如果你想为单元格添加样式(例如添加文本换行、居中单元格内容等),你可以使用xlsx和xlsx-style库来实现。

1)添加所需的依赖项

npm install file-saver --save
npm install xlsx --save
npm install xlsx-style --save

2) 在xlsx-style dist目录中替换cpexcel.js文件。

由于这个bug:https://github.com/protobi/js-xlsx/issues/78,需要在node_modules目录中用 xlsx/dist/cpexcel.js 替换 xlsx-style/dist/cpexcel.js

3) 实现ExcelService。

import { Injectable } from '@angular/core';
import * as FileSaver from 'file-saver';
import * as XLSX from 'xlsx';
import * as XLSXStyle from 'xlsx-style';

const EXCEL_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
const EXCEL_EXTENSION = '.xlsx';

@Injectable()
export class ExcelService {

  constructor() { }

  public exportAsExcelFile(json: any[], excelFileName: string): void {
    const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
    this.wrapAndCenterCell(worksheet.B2);
    const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
    // Use XLSXStyle instead of XLSX write function which property writes cell styles.
    const excelBuffer: any = XLSXStyle.write(workbook, { bookType: 'xlsx', type: 'buffer' });
    this.saveAsExcelFile(excelBuffer, excelFileName);
  }

  private wrapAndCenterCell(cell: XLSX.CellObject) {
    const wrapAndCenterCellStyle = { alignment: { wrapText: true, vertical: 'center', horizontal: 'center' } };
    this.setCellStyle(cell, wrapAndCenterCellStyle);
  }

  private setCellStyle(cell: XLSX.CellObject, style: {}) {
    cell.s = style;
  }

  private saveAsExcelFile(buffer: any, fileName: string): void {
    const data: Blob = new Blob([buffer], {
      type: EXCEL_TYPE
    });
    FileSaver.saveAs(data, fileName + '_export_' + new Date().getTime() + EXCEL_EXTENSION);
  }

}

工作示例:https://github.com/luwojtaszek/ngx-excel-export/tree/xlsx-style

[更新 - 2018年8月23日]

这在最新的Angular 6中可以正常工作。

yarn install xlsx --save

ExcelService 示例:

import {Injectable} from '@angular/core';
import * as XLSX from 'xlsx';

@Injectable()
export class ExcelService {

  constructor() {
  }

  static toExportFileName(excelFileName: string): string {
    return `${excelFileName}_export_${new Date().getTime()}.xlsx`;
  }

  public exportAsExcelFile(json: any[], excelFileName: string): void {
    const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
    const workbook: XLSX.WorkBook = {Sheets: {'data': worksheet}, SheetNames: ['data']};
    XLSX.writeFile(workbook, ExcelService.toExportFileName(excelFileName));
  }
}

我更新了我的代码库:https://github.com/luwojtaszek/ngx-excel-export


你在你的项目中让它跑起来了吗? - Joshua Fabillar
你好,是否可以自动换行列。 - VSK
你可以使用xlsx和xlsx-style库来完成这个任务。我已经在我的帖子中更新了说明。你也可以在我的GitHub上找到一个可行的示例。 - luwojtaszek
4
@luwojtaszek,我尝试使用上述方法创建一个 Excel 文件,它创建了一个文件,但我无法打开它,显示文件已损坏。 - Piyush Kumar
5
将该行代码修改为const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });,保持原本的意思不变。 - Anuj
显示剩余18条评论

17

你使用Angular并不是很重要,但它能够为你打开一些更多的库。

基本上你有两个选择:

  1. 编写自己的json2csv转换器,这并不难。你已经有了JSON,可以将其转换为JS对象,然后只需迭代每个对象并获取当前列的正确字段。
  2. 你可以使用像https://github.com/zemirco/json2csv这���的库来帮你实现。

此外,这个SO问题可能会回答你的问题:如何将JSON转换为CSV格式并存储在变量中

CSV是类似Excel的程序的基本格式。除非你确实需要,否则不要去玩xls(x),这会让你头痛。


1
您可以通过后端生成XLS文件来进行导出。例如,对于PHP语言,可以使用PHPExcel库(相较于直接在浏览器中尝试完成而言,这种方式会更加简单)。 - johan

17

你可以使用 XLSX 库来处理 Angular2+。

按照提供的指南这里

public export() {
    const readyToExport = [
      {id: 1, name: 'a'},
      {id: 2, name: 'b'},
      {id: 3, name: 'c'}
    ];

    const workBook = XLSX.utils.book_new(); // create a new blank book
    const workSheet = XLSX.utils.json_to_sheet(readyToExport);

    XLSX.utils.book_append_sheet(workBook, workSheet, 'data'); // add the worksheet to the book
    XLSX.writeFile(workBook, 'temp.xlsx'); // initiate a file download in browser
  }

已使用Angular 5.2.0和XLSX 0.13.1进行测试


谢谢你,伙计,你救了我的命。 - Sahil Kashetwar
如何为单元格设置样式? - Muhammad Zeshan Ghafoor
1
@MohammadZeshan,基本上官方包描述中有关于格式化的参考资料。我建议您创建一个新问题,因为这超出了主题范围。 - debugger
使用XLSX时需要注意:它是一个庞大的库,无法进行树摇优化。因此,如果您想要包含它,您需要权衡一下是否值得承担20%或更多的最终捆绑包大小。 - jxn

4

我认为这是正确的方法...对我有用! 获取了一个JSON数组

downloadFile(data: any, filename:string) {
    const replacer = (key, value) => value === null ? '' : value;
    const header = Object.keys(data[0]);
    let csv = data.map(row => header.map(fieldName => JSON.stringify(row[fieldName],replacer)).join(','));
    csv.unshift(header.join(','));
    let csvArray = csv.join('\r\n');
    var blob = new Blob([csvArray], {type: 'text/csv' })
    saveAs(blob, filename + ".csv");
}

4
您可以使用这段简单的代码将JSON导出为CSV。该代码解决了许多基本问题,例如分隔符问题、自定义标题、跳过空列以及为特定列中的空数据添加“-”。请参考此GitHub链接,以解决有关在Angular中导出CSV的所有问题。

https://github.com/marvin-aroza/Angular-csv-export

将其视为您的JSON数据。
jsonData : any = [{
    name : 'Berlin',
    age : '45',
    country : 'Spain',
    phone : '896514326'
  },
  {
    name : 'Professor',
    age : '42',
    country : 'spain'
  },
  {
    name : 'Tokyo',
    age : '35',
    phone : '854668244'
  },
  {
    name : 'Helsinki',
    phone : '35863297'
  }];

你可以使用这些函数下载CSV。
exportCsv() {
    this.downloadFile(this.jsonData);
  }

  downloadFile(data, filename = 'data') {
    let arrHeader = ["name", "age", "country", "phone"];
    let csvData = this.ConvertToCSV(data, arrHeader);
    console.log(csvData)
    let blob = new Blob(['\ufeff' + csvData], { type: 'text/csv;charset=utf-8;' });
    let dwldLink = document.createElement("a");
    let url = URL.createObjectURL(blob);
    let isSafariBrowser = navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1;
    if (isSafariBrowser) {  //if Safari open in new window to save file with random filename.
      dwldLink.setAttribute("target", "_blank");
    }
    dwldLink.setAttribute("href", url);
    dwldLink.setAttribute("download", "sample.csv");
    dwldLink.style.visibility = "hidden";
    document.body.appendChild(dwldLink);
    dwldLink.click();
    document.body.removeChild(dwldLink);
  }

如果想编辑 CSV 的格式,可以添加以下函数

ConvertToCSV(objArray, headerList) {
    console.log(objArray);
    console.log(headerList);
    let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
    let str = '';
    let row = 'S.No,';

    let newHeaders = ["Name", "Age", "Country", "Phone"];

    for (let index in newHeaders) {
      row += newHeaders[index] + ',';
    }
    row = row.slice(0, -1);
    str += row + '\r\n';
    for (let i = 0; i < array.length; i++) {
      let line = (i + 1) + '';
      for (let index in headerList) {
        let head = headerList[index];

        line += ',' + this.strRep(array[i][head]);
      }
      str += line + '\r\n';
    }
    return str;
  }

如果数值中有逗号,您可以使用此函数删除逗号并将其视为单个数值。

strRep(data) {
    if(typeof data == "string") {
      let newData = data.replace(/,/g, " ");
       return newData;
    }
    else if(typeof data == "undefined") {
      return "-";
    }
    else if(typeof data == "number") {
      return  data.toString();
    }
    else {
      return data;
    }
  }

2
使用XLSX库将JSON转换为XLS文件并下载
操作 演示 源代码 链接 方法:
1. 包含库。
<script type="text/javascript" src="//unpkg.com/xlsx/dist/xlsx.full.min.js"></script>

JavaScript 代码
    var createXLSLFormatObj = [];

    /* XLS Head Columns */
    var xlsHeader = ["EmployeeID", "Full Name"];

    /* XLS Rows Data */
    var xlsRows = [{
            "EmployeeID": "EMP001",
            "FullName": "Jolly"
        },
        {
            "EmployeeID": "EMP002",
            "FullName": "Macias"
        },
        {
            "EmployeeID": "EMP003",
            "FullName": "Lucian"
        },
        {
            "EmployeeID": "EMP004",
            "FullName": "Blaze"
        },
        {
            "EmployeeID": "EMP005",
            "FullName": "Blossom"
        },
        {
            "EmployeeID": "EMP006",
            "FullName": "Kerry"
        },
        {
            "EmployeeID": "EMP007",
            "FullName": "Adele"
        },
        {
            "EmployeeID": "EMP008",
            "FullName": "Freaky"
        },
        {
            "EmployeeID": "EMP009",
            "FullName": "Brooke"
        },
        {
            "EmployeeID": "EMP010",
            "FullName": "FreakyJolly.Com"
        }
    ];


    createXLSLFormatObj.push(xlsHeader);
    $.each(xlsRows, function(index, value) {
        var innerRowData = [];
        $("tbody").append('<tr><td>' + value.EmployeeID + '</td><td>' + value.FullName + '</td></tr>');
        $.each(value, function(ind, val) {

            innerRowData.push(val);
        });
        createXLSLFormatObj.push(innerRowData);
    });


    /* File Name */
    var filename = "FreakyJSON_To_XLS.xlsx";

    /* Sheet Name */
    var ws_name = "FreakySheet";

    if (typeof console !== 'undefined') console.log(new Date());
    var wb = XLSX.utils.book_new(),
        ws = XLSX.utils.aoa_to_sheet(createXLSLFormatObj);

    /* Add worksheet to workbook */
    XLSX.utils.book_append_sheet(wb, ws, ws_name);

    /* Write workbook and Download */
    if (typeof console !== 'undefined') console.log(new Date());
    XLSX.writeFile(wb, filename);
    if (typeof console !== 'undefined') console.log(new Date());

您可以参考此代码在Angular 2组件中使用。

@RajRajeshwarSinghRathore,我已经检查过了,对我来说它运行良好,请再试一次并单击“下载XLS文件”按钮。 - Code Spy
1
是的,现在它正在工作。也许当时有一些问题。谢谢。 - Raj Rajeshwar Singh Rathore
如果您已经有正确格式的JSON,请使用json_to_sheet而不是aoa_to_sheet。 - Sérgio S. Filho
使用XLSX时需要注意:它是一个庞大的库,无法进行树摇。因此,如果您想要包含它,您需要权衡一下是否值得承担最终捆绑包大小的20%或更多的开销。 - jxn

0

Primeng DataTable导出不会导出模板列,这就是我正在寻找另一种解决方案的原因。同时也无法对模板列进行排序。 - Fab

0

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