Reputation: 607
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>
<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
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
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
Reputation: 300
Do the following steps in order:
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
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
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:
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
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
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
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
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');
}
}
Upvotes: 33