Preview:
//Installations
npm install xlsx file-saver
npm install xlsx file-saver

//payment component
//ts
import { Component } from '@angular/core';
import { PaymentService } from '../Services/payment.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import * as XLSX from 'xlsx';
import * as FileSaver from 'file-saver';
declare var $: any;

@Component({
  selector: 'app-payment',
  standalone: true,
  imports: [CommonModule, FormsModule, ReactiveFormsModule],
  templateUrl: './payment.component.html',
  styleUrl: './payment.component.css'
})
export class PaymentComponent {
  payments: any[] = [];
  selectedPayment: any | null = null;
  filterPayment: any[] = [];
  searchTerm: string = '';

  constructor(private paymentService: PaymentService, private router: Router, private location: Location, private snackBar: MatSnackBar) {}

  ngOnInit(): void {
    this.loadPayments();
  }

  loadPayments(): void {
    this.paymentService.getPayments().subscribe({
      next: (data) => {
        this.payments = data;
        this.filterPayment = data;
        console.log(data)
      },
      error: (err) => {
        console.error('Error fetching payments:', err);
      }
    });
  }  

  filteredPayments(): void {
    if (!this.searchTerm) {
      this.filterPayment = this.payments;
    } else {
      const term = this.searchTerm.toLowerCase();
      this.filterPayment = this.payments.filter(payment =>
        payment.payment_ID.toString().includes(term) ||
        payment.memberName.toLowerCase().includes(term) ||
        payment.amount.toString().includes(term) ||
        payment.payment_Date.toString().includes(term) ||
        payment.paymentTypeName.toLowerCase().includes(term)
      );
    }
  }
 
  openModal(payment: any): void {
    this.selectedPayment = payment;
    $('#userModal').modal('show');
  }
 
  closeModal(): void {
    $('#userModal').modal('hide');
  }
 
  goBack(): void {
    this.location.back();
  }

  exportToExcel(): void {
    const customHeaders = [
      { header: 'Payment ID', key: 'payment_ID' },
      { header: 'Member Name', key: 'memberName' },
      { header: 'Amount', key: 'amount' },
      { header: 'Payment Date', key: 'payment_Date' },
      { header: 'Payment Type', key: 'paymentTypeName' }
    ];

    const worksheetData = this.filterPayment.map(payment => ({
      payment_ID: payment.payment_ID,
      memberName: payment.memberName,
      amount: payment.amount,
      payment_Date: this.formatDate(payment.payment_Date), // Format the date
      paymentTypeName: payment.paymentTypeName
    }));

    const worksheet = XLSX.utils.json_to_sheet(worksheetData, { header: customHeaders.map(h => h.key) });
    const workbook = { Sheets: { 'Payments': worksheet }, SheetNames: ['Payments'] };

    // Modify column headers
    customHeaders.forEach((header, index) => {
      const col = XLSX.utils.encode_col(index); // Convert 0 -> 'A', 1 -> 'B', etc.
      worksheet[`${col}1`] = { t: 's', v: header.header };
    });

    const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
    this.saveAsExcelFile(excelBuffer, 'payments');
  }

  private formatDate(date: string): string {
    return new Date(date).toISOString().split('T')[0];
  }

  private saveAsExcelFile(buffer: any, fileName: string): void {
    const data: Blob = new Blob([buffer], { type: EXCEL_TYPE });
    FileSaver.saveAs(data, `${fileName}_${new Date().getTime()}.xlsx`);
  }
}

const EXCEL_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';

//html
<br>
<div class="header-search-container">
    <i class="bi bi-arrow-left-circle header-icon" (click)="goBack()"></i>
    <h2 class="header-title">Payment Manager</h2>
    <div class="search-bar-container">
        <input type="text" class="form-control search-bar" placeholder="Search payments" [(ngModel)]="searchTerm" (input)="filteredPayments()">
    </div>
</div>
<br>
<br>
<div class="container">
    <div *ngIf="payments.length === 0">
        <p>No payments have been made.</p>
    </div>
    <div *ngIf="payments.length > 0" class="row">
        <table class="table">
            <thead class="table-dark">
                <tr>
                <th>Payment ID</th>
                <th>Member Name</th>
                <th>Amount</th>
                <th>Payment Date</th>
                <th>Payment Type</th>
                <th>Action</th>
                </tr>
            </thead>
            <tbody class>
                <tr *ngFor="let payment of filterPayment">
                <td>{{ payment.payment_ID }}</td>
                <td>{{ payment.memberName }}</td>
                <td>{{ payment.amount | currency: 'R ' }}</td>
                <td>{{ payment.payment_Date | date: 'short' }}</td>
                <td>{{ payment.paymentTypeName }}</td>
                <td>
                    <button class="btn btn-primary" (click)="openModal(payment)">View</button>
                </td>
                </tr>
            </tbody>
    </table>
    
    <button class="btn btn-success" (click)="exportToExcel()">Export to Excel</button>
    
    <div class="modal fade" id="userModal" tabindex="-1" aria-labelledby="userModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg">
          <div class="modal-content" style="text-align: center;">
            <div class="modal-header">
              <h5 class="modal-title" id="userModalLabel"><strong>Payment Details</strong></h5>
            </div>
            <div class="modal-body">
              <p><strong>Payment ID:</strong> {{ selectedPayment?.payment_ID }}</p>
              <p><strong>Member Name:</strong> {{ selectedPayment?.memberName }}</p>
              <p><strong>Amount:</strong> {{ selectedPayment?.amount | currency: 'R ' }}</p>
              <p><strong>Payment Date:</strong> {{ selectedPayment?.payment_Date | date: 'short' }}</p>
              <p><strong>Payment Type:</strong> {{ selectedPayment?.paymentTypeName }}</p>
            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-secondary" (click)="closeModal()">Close</button>
            </div>
          </div>
        </div>
      </div>
</div> 

//shared
//file-saver.d.ts
declare module 'file-saver';
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter