简体   繁体   中英

angular material data table export to excel

I am using angular material data.table to display data in a tabular format. I need to include a functionality which exports tabular data to excel. I am not able to find any documents which will help me to export the data. Can you please let me know how to export data to excel in angular which uses angular material data.table.

I tried using XLSX.utils and facing "Bad range (0): A1:A0 at check_ws" issue.

Location.component.html

<div class="example-container" #TABLE> 

  <mat-table #table [dataSource]="dataSource" matSort matSortActive="locationName" matSortDirection="asc" matSortDisableClear>
    <ng-container matColumnDef="locationName">
      <mat-header-cell *matHeaderCellDef mat-sort-header>Location Name </mat-header-cell>
      <mat-cell *matCellDef="let location"> {{location.locationName}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="address">
      <mat-header-cell *matHeaderCellDef>Address </mat-header-cell>
      <mat-cell *matCellDef="let location"> {{location.address}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="city">
      <mat-header-cell *matHeaderCellDef mat-sort-header> City </mat-header-cell>
      <mat-cell *matCellDef="let location"> {{location.city}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="country">
      <mat-header-cell *matHeaderCellDef mat-sort-header>Country </mat-header-cell>
      <mat-cell *matCellDef="let location"> {{location.country}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="zipcode">
      <mat-header-cell *matHeaderCellDef>ZipCode </mat-header-cell>
      <mat-cell *matCellDef="let location"> {{location.zipcode}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="phone">
      <mat-header-cell *matHeaderCellDef>Phone </mat-header-cell>
      <mat-cell *matCellDef="let location"> {{location.phone}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="timezone">
      <mat-header-cell *matHeaderCellDef> TimeZone </mat-header-cell>
      <mat-cell *matCellDef="let location"> {{location.timezone}} </mat-cell>
    </ng-container>
    <ng-container matColumnDef="action">
      <mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
      <!-- <mat-cell *matCellDef="let location"> {{location.timezone}} </mat-cell> -->
      <mat-cell *matCellDef="let location">
      <a href ="#" class="btn Action-Tab" >Edit</a>&nbsp;&nbsp;
          <a href ="#" class="btn Action-Tab" >Delete</a>
        </mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;">
    </mat-row>
  </mat-table>

  <mat-paginator [pageSizeOptions]="[10, 20, 50,100]"></mat-paginator>

</div>
<button mat-raised-button color="primary" (click)="ExportTOExcel()">Export as Excel</button>

Location.component.ts

import { Component, OnInit, OnDestroy , ViewChild,ElementRef} from '@angular/core';
import { ILocation } from '../../Ilocation';
import { LocationService } from '../../services/location.service';
import { DataTableResource } from 'angular5-data-table';
import { Subscription } from 'rxjs';
import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
import {DataSource} from '@angular/cdk/table';
import * as XLSX from 'xlsx';
// import { CdkTableModule } from '@angular/cdk/table';

@Component({
  selector: 'app-location',
  templateUrl: './location.component.html',
  styleUrls: ['./location.component.css']
})
export class LocationComponent implements OnInit , OnDestroy{
  errorMessage: string;
  filterBy : string;
  locations: ILocation[];
  items : ILocation[]=[];
  itemCount :number = 0;
  subscription:Subscription;
  limits = [5, 10, 20, 80];
  tableResource : DataTableResource<ILocation>;
  displayedColumns = ['locationName', 'address', 'city', 'country','zipcode', 'phone','timezone','action'];
  // dataSource: MatTableDataSource<ILocation>;
  dataSource;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort : MatSort;
  @ViewChild('TABLE',{ read: ElementRef }) table: ElementRef;

  constructor( private locationService: LocationService) {

   }

   applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
    this.dataSource.filter = filterValue;
  }

  ngOnInit() {
    this.subscription = this.locationService.getLocations()
    .subscribe(locations =>{
       this.locations = locations;
       this.dataSource = new MatTableDataSource(locations);
       this.dataSource.sort = this.sort;
       this.dataSource.paginator = this.paginator;
       this.dataSource.table = this.table;
      },
      error => this.errorMessage = <any>error);           
  }

  ngOnDestroy(){
    this.subscription.unsubscribe();

  }

  ExportTOExcel()
  {
    console.log("export");
    this.table.nativeElement.style.background = "red";
    const ws: XLSX.WorkSheet=XLSX.utils.table_to_sheet(this.table.nativeElement);
    const wb: XLSX.WorkBook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');

    /* save to file */
    XLSX.writeFile(wb,'SheetJS.xlsx');
    console.log("exported");

  }

}

You can use xlsx for exporting table as excel.
usage
Execute npm i xlsx

HTML:

<div class="example-container mat-elevation-z8 " #TABLE>
  <table mat-table #table [dataSource]="dataSource">

    <!--- Note that these columns can be defined in any order.
          The actual rendered columns are set as a property on the row definition" -->

    <!-- Position Column -->
    <ng-container matColumnDef="position">
      <th mat-header-cell *matHeaderCellDef> No. </th>
      <td mat-cell *matCellDef="let element"> {{element.position}} </td>
      //..................................rest of the html
    <button mat-raised-button color="primary" (click)="exportAsExcel()">Export as Excel</button></div>

In your Component

import {Component,ViewChild, ElementRef} from '@angular/core';
 import * as XLSX from 'xlsx';
//......
    export class AppComponent  {
      @ViewChild('TABLE') table: ElementRef;
    exportAsExcel()
    {
      const ws: XLSX.WorkSheet=XLSX.utils.table_to_sheet(this.table.nativeElement);//converts a DOM TABLE element to a worksheet
      const wb: XLSX.WorkBook = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');

      /* save to file */
      XLSX.writeFile(wb, 'SheetJS.xlsx');

    }
    }

DEMO

这是一个迟到的回复,但是您可以使用mat-table-exporter ,它利用 xlsx sheetjs 并提供分页表导出为 excel、csv、json 和 txt 格式。

Export to excel is easy to do with something like this:

exportExcel() {
    const workSheet = XLSX.utils.json_to_sheet(this.dataSource.data, {header:['dataprop1', 'dataprop2']});
    const workBook: XLSX.WorkBook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workBook, workSheet, 'SheetName');
    XLSX.writeFile(workBook, 'filename.xlsx');
}

Call it from button:

<button (click)="exportExcel()">Export</button>

If you are rendering the Material flex table by using <mat-table> , <mat-header-cell> , <mat-cell> . The XLSX.utils.table_to_book to table won't work.

You can view the complete guide and working example as:

Guide: https://trungk18.com/experience/angular-material-data-table-export-to-excel-file/

Stackblitz: https://stackblitz.com/edit/angular-material-table-export-excel-xlsx

<mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <ng-container matColumnDef="name">
    <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="symbol">
    <mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="matColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: matColumns;"></mat-row>
</mat-table>

You have to use XLSX.utils.json_to_sheet as to export the array to xlsx. It will be much more flexible and easy for you.

exportArrayToExcel(arr: any[], name?: string) {
    let { sheetName, fileName } = getFileName(name);
    var wb = XLSX.utils.book_new();
    var ws = XLSX.utils.json_to_sheet(arr);
    XLSX.utils.book_append_sheet(wb, ws, sheetName);
    XLSX.writeFile(wb, `${fileName}.xlsx`);
}

I was having the same issue and I found this solution, which worked for me...

(#1) Pay attention to div table wrapper, it MUST contain #TABLE

<div #TABLE> 
    <table mat-table>
       <!-- Your table code goes here -->
    </table>
</div>

(#2) Now, before the closing of your </table> or </mat-table> , make these changes...

<mat-header-row></mat-header-row> ==> <tr mat-header-row>...</tr>

<mat-row></mat-row> ==> <tr mat-row></tr>

At this point, If you lose some CSS style of your table, use below code to fix the style back...

tr.mat-header-row, tr.mat-row {
    display: flex;
}

Hope this can help you.

In my case, alternative to table_to_sheet is to use json_to_sheet . Since I don't know how to properly export the table (with pagination) and the filtered table, I leverage the json_to_sheet and in the dataSource instead of dataSource.data , I use the dataSource.filteredData .

So with this, it covers the ff:

  • Export table with pagination
  • Export table with filters
  exportToExcel() {
    let dataToExport = this.dataSource.filteredData
      .map(x => ({
        DisplayName: x.DisplayName,
        Name: x.Name,
        Type: x.Type == '0' ? 'Partial' : 'Full'
      }));

    let workSheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(dataToExport, <XLSX.Table2SheetOpts>{ sheet: 'Sheet 1' });
    let workBook: XLSX.WorkBook = XLSX.utils.book_new();

    // Adjust column width
    var wscols = [
      { wch: 50 },
      { wch: 50 },
      { wch: 30 }
    ];

    workSheet["!cols"] = wscols;

    XLSX.utils.book_append_sheet(workBook, workSheet, 'Sheet 1');
    XLSX.writeFile(workBook, `${this.exportToExcelFileName}.xlsx`);
  }

Do the following steps in order:

  1. First put your ID in the HTML table tag.
  2. Then inject the Excel service into the constructor and write the Excel function.
  3. Then write the Excel service.

HTML:

 <table id="ExampleTable">
  .
  .
  .
</table>

COMPONENT.TS:

 constructor(private excel: ExcelService) {}

AND

exportExcel(): void {
  this.excel.exportExcel('ExampleTable');
}

ExcelService:

public exportExcel(tableId: string, name?: string): void {
  const timeSpan = new Date().toISOString();
  const prefix = name || 'ExportResult';
  const fileName = `${prefix}-${timeSpan}`;
  const targetTableElm = document.getElementById(tableId);
  const wb = XLSX.utils.table_to_book(targetTableElm, { sheet: prefix } as 
  XLSX.Table2SheetOpts);
  XLSX.writeFile(wb, `${fileName}.xlsx`);
}

You can transform the data using this video ref

https://youtu.be/9Acf1-X9mzg

  exportTable() {
if (this.arrayname.length >= 1) { //here your array name which are display in table
    $('#exportable tr td').css('text-align', 'center'); //table formating
    const downloadLink = document.createElement('a');
    const table = document.getElementById('exportable');
    const tableHTML = table.outerHTML.replace(/ /g, '%20');
    var html = table.outerHTML;
    var url = 'data:application/vnd.ms-excel,' + escape(html); // Set your html table into url 
    downloadLink.href = 'data:' + url + ' ';
    downloadLink.download = 'tablename.xls'
    downloadLink.click();
} else {
    alert('table is empty')
}

you need to make changes in your HTML file. instead of :

<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;">

Do it like,

<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM