Click here to Skip to main content
15,891,033 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a primeng table where I am trying to export the filtered data to excel, I have create a table as component and using it where ever required. Here is the stackblitz code I am working on. I am using exceljs and file-saver npm packages to export the data. The only issue I had is to download only filtered data instead of all.

https://stackblitz.com/edit/primeng-card-demo-azewpe?file=src%2Fapp%2Fapp.module.ts

I have gone through this link but no luck https://medium.com/@sankarums/angular-primeng-table-export-only-filtered-data-to-excel-7fc97878099c

this.table.filteredValue this always gives me null

In the given example let us say I select client1 and click on export to excel it should download only the rows that belongs to client1

What I have tried:

Primeng Table Demo (forked) - StackBlitz[^]
Posted
Updated 21-Apr-24 22:25pm
v2

1 solution

I have been looking at the StackBlitz you put together, and it's giving you errors at runtime. For instance, you have a call to exportToExcel, but that's in the app.component.html and there's no corresponding exportToExcel function in app.component.ts. You declare this function in prime-table.component.ts.

If you want us to look at code, please put a working code sample in stackblitz. We will look at it then.

I forked your updated StackBlitz and combined everything into the app.component files to make life simple. In app.component.ts, I added the following lines:
ts
filteredvalues: any[] = [];
onFilter(event) {
  this.filteredvalues = event.filteredValue;
}
This event handler is going to take the filtered data and store it (note that I initially set filteredvalues to have all the data when I initialize them in ngOnInit). Then, I replace the references to this.data with this.filteredvalues in the exportToExcel method. That way, I know I am exporting the filtered data, and not the original dataset. The last part is to hook the filter capability of the table to the onFilter event handler. That is done by adding this to the table definition:
HTML
(onFilter)="onFilter($event)"
My fork of your repo can be found here[^].

To keep the answer in CodeProject, this is what my app.component.ts file now looks like:
TypeScript
import { Component, Input, TemplateRef } from '@angular/core';
import { PrimeNGConfig } from 'primeng/api';
import { Workbook } from 'exceljs';
import { saveAs } from 'file-saver';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  providers: [],
})
export class AppComponent {
  constructor(private primengConfig: PrimeNGConfig) {}

  columns: any[] = [];
  data: any[] = [];
  dropdownOptions: { [key: string]: any[] } = {};
  @Input()
  customBodyTemplate!: TemplateRef<any>;

  ngOnInit() {
    this.primengConfig.ripple = true;
    this.dropdownOptions = {
      billingStatus: ['Billable', 'Non-Billable'],
      client: ['Client1', 'Client2'],
    };
    this.columns = [
      { field: 'employeeId', header: 'Employee ID' },
      { field: 'employeeName', header: 'Full Name' },
      { field: 'emailId', header: 'Email' },
      { field: 'billingStatus', header: 'Billing Status', type: 'dropdown' },
      { field: 'designation', header: 'Designation' },
      { field: 'client', header: 'Client', type: 'dropdown' },
      { field: '', header: 'Action', type: 'button' },
    ];
    this.data = [
      {
        employeeId: '123',
        employeeName: 'xyz',
        emailId: 'xyz',
        billingStatus: 'Billable',
        designation: 'SSE',
        client: 'Client1',
      },
      {
        employeeId: '134',
        employeeName: 'pqr',
        emailId: 'xyz',
        billingStatus: 'Non-Billable',
        designation: 'SSE',
        client: 'Client2',
      },
      {
        employeeId: '123',
        employeeName: 'xyz',
        emailId: 'xyz',
        billingStatus: 'Billable',
        designation: 'SSE',
        client: 'Client1',
      },
      {
        employeeId: '134',
        employeeName: 'pqr',
        emailId: 'xyz1',
        billingStatus: 'Non-Billable',
        designation: 'SSE',
        client: 'Client2',
      },
      {
        employeeId: '123',
        employeeName: 'xyz2',
        emailId: 'xyz2',
        billingStatus: 'Billable',
        designation: 'SSE',
        client: 'Client1',
      },
      {
        employeeId: '134',
        employeeName: 'pqr',
        emailId: 'xyz',
        billingStatus: 'Non-Billable',
        designation: 'SSE',
        client: 'Client2',
      },
    ];
    this.filteredvalues = this.data;
  }

  filteredvalues: any[] = [];
  onFilter(event) {
    this.filteredvalues = event.filteredValue;
  }
  exportToExcel() {
    if (this.filteredvalues && Array.isArray(this.filteredvalues)) {
      let data: any[] = [];

      this.filteredvalues.forEach((employee: any) => {
        const rowData: any = {
          'Employee ID': employee.employeeId,
          'Full Name': employee.employeeName,
          Email: employee.emailId,
          'Billing Status': employee.billingStatus,
          Designation: employee.designation,
          Client: employee.client,
          'Billing Start Date': employee.billingStartDate,
        };

        if (!employee.isActive) {
          rowData['Exit Date'] = employee.exitDate;
        }
        data.push(rowData);
      });

      if (data.length > 0) {
        const header = Object.keys(data[0]);
        const headerArray: string[] = [];

        header.forEach((val) => {
          headerArray.push(val.charAt(0).toUpperCase() + val.slice(1));
        });

        let workbook = new Workbook();
        const worksheet = workbook.addWorksheet();
        worksheet.addRow([]);

        const headerRow = worksheet.addRow(headerArray);
        headerRow.eachCell((cell, number) => {
          cell.border = {
            top: { style: 'thin' },
            left: { style: 'thin' },
            bottom: { style: 'thin' },
            right: { style: 'thin' },
          };
        });

        data.forEach((d) => {
          const rowData: any[] = [];
          header.forEach((h) => {
            rowData.push(d[h] || '');
          });

          const dataRow = worksheet.addRow(rowData);

          dataRow.eachCell((cell, number) => {
            cell.border = {
              top: { style: 'thin' },
              left: { style: 'thin' },
              bottom: { style: 'thin' },
              right: { style: 'thin' },
            };

            // Apply border to empty cells
            if (!cell.value) {
              cell.border = {
                top: { style: 'thin' },
                left: { style: 'thin' },
                bottom: { style: 'thin' },
                right: { style: 'thin' },
              };
            }
          });
        });

        worksheet.columns.forEach((column) => {
          if (column) {
            (column as any).eachCell({ includeEmpty: true }, (cell: any) => {
              const maxLength = cell.value ? cell.value.toString().length : 0;
              column.width = Math.max(column.width || 10, maxLength + 2);
            });
          }
        });

        workbook.xlsx.writeBuffer().then((buffer: ArrayBuffer) => {
          const blob = new Blob([buffer], {
            type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
          });
          saveAs(blob, `${'EmployeeData'}.xlsx`);
        });
      }
    }
  }
}
and this is the app.component.html file.
HTML
<p-toolbar styleClass="mb-2">
  <ng-template pTemplate="left"> </ng-template>
  <ng-template pTemplate="center"> </ng-template>
  <ng-template pTemplate="right">
    <button
      type="button"
      pButton
      pRipple
      icon="pi pi-file-excel"
      class="p-button-success mr-2"
      (click)="exportToExcel()"
      pTooltip="XLS"
      tooltipPosition="bottom"
    ></button> </ng-template
></p-toolbar>
<p-table
  [showCurrentPageReport]="true"
  #dt1
  [columns]="columns"
  [value]="data"
  [paginator]="true"
  [rows]="15"
  (onFilter)="onFilter($event)"
  scrollHeight="410px"
  [resizableColumns]="true"
  [globalFilterFields]="columns"
  responsiveLayout="scroll"
  [showCurrentPageReport]="true"
  [scrollable]="true"
  [rowsPerPageOptions]="[5, 10, 15, 20, data.length]"
  currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
>
  <ng-template pTemplate="caption" *ngIf="showInput">
    <div class="flex">
      <span class="p-input-icon-left ml-auto">
        <i class="pi pi-search"></i>
        <input
          pInputText
          type="text"
          (input)="dt1.filterGlobal($any($event.target).value, 'contains')"
          placeholder="Search"
        />
      </span>
    </div>
  </ng-template>
  <ng-template pTemplate="header" let-columns>
    <tr>
      <th *ngFor="let col of columns">
        <ng-container *ngIf="col.type !== 'button'">
          <p pSortableColumn="{{ col.field }}">
            {{ col.header }}
            <p-sortIcon field="{{ col.field }}"></p-sortIcon>
          </p>
        </ng-container>
        <ng-container *ngIf="col.type === 'button'">
          <!-- Column type is button, so do not render pSortableColumn -->
          {{ col.header }}
        </ng-container>
      </th>
    </tr>
    <tr>
      <th *ngFor="let col of columns">
        <input
          pInputText
          type="text"
          (input)="
            dt1.filter($event.target.value, col.field, col.filterMatchMode)
          "
        />
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-rowData let-columns="columns">
    <ng-template #defaultTemplate>
      <tr>
        <td *ngFor="let col of columns">
          {{ rowData[col.field] }}
        </td>
      </tr>
    </ng-template>
    <ng-container
      *ngTemplateOutlet="
        customBodyTemplate ? customBodyTemplate : defaultTemplate;
        context: { $implicit: rowData }
      "
    >
    </ng-container>
  </ng-template>
</p-table>
<ng-template #customBodyTemplate let-rowData>
  <tr>
    <td *ngFor="let col of columns">
      <div *ngIf="!col.type">
        {{ rowData[col.field] }}
      </div>
      <div *ngIf="col.type == 'dropdown'">{{ rowData[col.field] }}</div>
      <div *ngIf="col.type == 'date'">{{ formatDate(rowData[col.field]) }}</div>
    </td>
  </tr>
</ng-template>
 
Share this answer
 
v2
Comments
demouser743 22-Apr-24 4:24am    
Hi Pete I have the working code to download to excel, but what I need is I want to filter the data and send it to that method
Pete O'Hanlon 22-Apr-24 4:26am    
I got that, but the code sample you have in Stackblitz doesn't work so we can't correct it for you.
demouser743 22-Apr-24 4:40am    
I added the code what I had but some how in stack blitz it is not working
Pete O'Hanlon 22-Apr-24 6:12am    
I have forked your repo and corrected it. You can find the details in my answer.
demouser743 22-Apr-24 6:14am    
Can I get the forked one?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900