Reputation: 23
I want to export filtered/sorted data(or whatever other actions applied to the table, ie: hide specific column) instead of exporting all the data. Is there a way to do it? I am fairly new to angular, if you could use simple language to explain that'll be great!
Below are my codes
excel.service.ts:
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({
providedIn: 'root'
})
export class ExcelService {
constructor() { }
public exportAsExcelFile(json: any[], excelFileName: string): void {
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
delete (worksheet[1])
const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
this.saveAsExcelFile(excelBuffer, excelFileName);
}
private saveAsExcelFile(buffer: any, fileName: string): void {
const data: Blob = new Blob([buffer], {type: EXCEL_TYPE});
FileSaver.saveAs(data, fileName + '_' + new Date().toLocaleDateString() + EXCEL_EXTENSION);
}
}
table.component.ts:
showTCExportMenu=false
showTEExportMenu=false
exportAsXLSX(data, name, reimport=false):void {
let table = data
reimport? null: table.forEach(
table => { table.justification? table.justification = table.justification.replace(/<\/?(?!a)\w*\b[^>]*>/ig, ''): null,
table.evidence? table.evidence = table.evidence.replace(/<\/?(?!a)\w*\b[^>]*>/ig, ''): null,
delete table.id, delete table.log
})
// execu ? this.getTestExecu(this.uuid): this.getTestCat(this.uuid)
this.excelService.exportAsExcelFile(table, name);
this.showTCExportMenu=false
this.showTEExportMenu=false
}
table.component.html:
<div>
<clr-datagrid [(clrDgSelected)]="selected">
<clr-dg-column
*ngFor="let column of columns"
[clrDgField]="getStringKey(column.key)">
<ng-container *clrDgHideableColumn="{hidden: false}">
{{column.title}}
</ng-container>
<clr-dg-filter
*ngIf="column?.filter"
[clrDgFilter]="getFilter(column)">
<ng-container filterHost></ng-container>
</clr-dg-filter>
</clr-dg-column>
<clr-dg-row
*clrDgItems="let item of records"
[clrDgItem]="item">
<clr-dg-cell
*ngFor="let column of columns"
[innerHTML]="renderValue(column, item)">
</clr-dg-cell>
<clr-dg-row-detail
[innerHTML]="expandRowRender && expandRowRender(item)"
*clrIfExpanded>
</clr-dg-row-detail>
</clr-dg-row>
<clr-dg-footer>
<button class="btn" (click)="exportAsXLSX(tableData, 'example', true)">Export to excel</button>
<clr-dg-pagination #pagination >
<clr-dg-page-size [clrPageSizeOptions]="[5,10,20,30, 50, 100]">Users per page</clr-dg-page-size>
{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}}
of {{pagination.totalItems}} records
</clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid>
</div>
here is where I get my data from api, catone.component.ts:
import { Component, OnInit } from '@angular/core';
import {TableColumns, TableData} from "../tableone/tableone.types";
import { faker } from '@faker-js/faker';
import {Observable, Subject} from "rxjs";
import {HttpClient} from "@angular/common/http";
import {ClrDatagridFilterInterface} from "@clr/angular";
import {AgefilterComponent} from "../agefilter/agefilter.component";
import {DatefilterComponent} from "../datefilter/datefilter.component";
interface InventoryData {
test_name: any;
description: any;
status: string;
test_level: string;
test_category: string;
test_type: string;
test_approach: string;
test_applicability: string;
requirement_accountability: string;
test_plan_accountability: string;
trigger_type: string;
applicable_metadata_statuses: string;
assessment_level_targeted: string;
comp_control_flag: string;
testing_platform: string;
effective_date: Date;
test_retired_date: Date;
metric_inclusion: string;
policy_requirement: string
}
export class AgeFilter implements ClrDatagridFilterInterface<InventoryData> {
changes = new Subject<any>();
public minAge!: number;
public maxAge!: number;
accepts(person: InventoryData): boolean {
return true
}
isActive(): boolean {
return false
}
}
export class BirthdayFilter implements ClrDatagridFilterInterface<InventoryData> {
changes = new Subject<any>;
value = '';
accepts(item: InventoryData): boolean {
return true
}
isActive(): boolean {
return false
}
}
@Component({
selector: 'catone',
templateUrl: './catone.component.html',
styleUrls: ['./catone.component.scss']
})
export class CatoneComponent implements OnInit {
columns: TableColumns<InventoryData> = [
{
title: 'Test_name',
key: 'test_name'
},
{
title: 'Description',
key: 'description'
},
{
title: 'Status',
key: 'status'
},
{
title: 'Test_level',
key: 'test_level'
},
{
title: 'Test_category',
key: 'test_category'
},
{
title: 'Test_type',
key: 'test_type',
},
{
title: 'Test_approach',
key: 'test_approach',
},
{
title: 'Test_applicability',
key: 'test_applicability',
},
{
title: 'Requirement_accountability',
key: 'requirement_accountability',
},
{
title: 'Test_plan_accountability',
key: 'test_plan_accountability',
},
{
title: 'Trigger_type',
key: 'trigger_type',
},
{
title: 'Applicable_metadata_statuses',
key: 'applicable_metadata_statuses',
},
{
title: 'Assessment_level_targeted',
key: 'assessment_level_targeted',
},
{
title: 'Comp_control_flag',
key: 'comp_control_flag',
},
{
title: 'Testing_platform',
key: 'testing_platform',
},
{
title: 'Effective_date',
key: 'effective_date',
},
{
title: 'Test_retired_date',
key: 'test_retired_date',
},
{
title: 'Metric_inclusion',
key: 'metric_inclusion',
},
{
title: 'Policy_requirement',
key: 'policy_requirement',
},
];
tableData: TableData<InventoryData> | Observable<TableData<InventoryData>> = [];
page = 1;
pageSize = 10;
total = 1000;
constructor(private httpClient: HttpClient) { }
renderExpand(p: InventoryData) {
return `
<pre>${'test name: ' + p.test_name}</pre>
`
}
handlePageChange(page: number) {
this.page = page;
this.requestApi();
}
requestApi() {
this.httpClient.get<InventoryData[]>(`myapi`)
.subscribe(data => {
this.tableData = data
})
}
ngOnInit(): void {
this.requestApi();
}
}
Upvotes: 0
Views: 242
Reputation: 655
without any exernal library you can use this function note that rows (in the class CSVargs) is the data to download so if you pass sorted rows or/and specific length's row should work
export interface CSVargs<T> { // you can make change T by any
rows: T[];
keys: string[];
titles: string[];
filename?: string;
columnDelimiter?: string;
lineDelimiter?: string;
}
export function downloadCSV(args: CSVargs) {
args.filename = args.filename || 'export.csv';
args.columnDelimiter = args.columnDelimiter || ';';
args.lineDelimiter = args.lineDelimiter || '\n';
let csv = convertArrayOfObjectsToCSV(args);
if (csv == null) { return; }
if (!csv.match(/^data:text\/csv/i)) {
const bom = '\uFEFF';
csv = 'data:text/csv;charset=utf-8,' + bom + csv;
}
const data = encodeURI(csv);
const link = document.createElement('a');
link.setAttribute('href', data);
link.setAttribute('download', args.filename);
link.click();
}
function convertArrayOfObjectsToCSV(args: CSVargs) {
if (!args.rows || !args.rows.length) {
return;
}
if (!args.keys || !args.keys.length) {
args.keys = Object.keys(args.rows[0]);
}
if (!args.titles || !args.titles.length) {
args.titles = args.keys;
}
let result = '';
result += '"' + args.titles.join('"' + args.columnDelimiter + '"') + '"';
result += args.lineDelimiter;
args.rows.forEach(item => {
let ctr = 0;
args.keys.forEach(key => {
if (ctr > 0) {
result += args.columnDelimiter;
}
const value = (item && !item[key]) ? item[key] : ''; // is better to check item not undefined not null not empty (create a function to check is not blanc)
result += '"' + value + '"';
ctr++;
});
result += args.lineDelimiter;
});
return result;
}
Upvotes: 0