Veda
Veda

Reputation: 607

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");

  }

}

Upvotes: 23

Views: 94591

Answers (9)

talhature
talhature

Reputation: 2165

It is a late reply but, you can use my mat-table-exporter package which utilizes xlsx sheetjs and provides paginated table export as excel, csv, json and txt formats.

Upvotes: 14

Rajkumar Dhariya
Rajkumar Dhariya

Reputation: 1

  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')
}

Upvotes: -1

Sadegh Maasoomi
Sadegh Maasoomi

Reputation: 300

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`);
}

Upvotes: 0

trungvose
trungvose

Reputation: 20034

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`);
}

Upvotes: 4

klaydze
klaydze

Reputation: 981

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`);
  }

Upvotes: 1

Jovo Skorupan
Jovo Skorupan

Reputation: 267

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>

Upvotes: 14

vinayofficial
vinayofficial

Reputation: 482

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.

Upvotes: 0

abhishek bhokare
abhishek bhokare

Reputation: 1

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>

Upvotes: -2

Vikas
Vikas

Reputation: 12036

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

Upvotes: 33

Related Questions