Export the transactions table to CSV

Angular · Angular · advanced · greenfield

Adds the CSV export service used by the transactions toolbar. Escaping covers the full RFC 4180 set — commas, quotes, and both line-break characters — with quote doubling; rows join with CRLF and the payload gets a BOM so Excel decodes UTF-8. The download path builds an object URL, clicks an attached anchor, and revokes the URL on a deferred tick per the documented pattern.

Requirements

Files touched

--- src/app/transactions/csv-export.service.ts
+import { Injectable } from '@angular/core';
+
+@Injectable({ providedIn: 'root' })
+export class CsvExportService {
+  buildCsv(header: string[], rows: string[][]): string {
+    const lines = [header, ...rows].map((row) =>
+      row.map((field) => this.escapeField(field)).join(','),
+    );
+    return '\ufeff' + lines.join('\r\n') + '\r\n';
+  }
+
+  download(filename: string, csv: string) {
+    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
+    const url = URL.createObjectURL(blob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.download = filename;
+    document.body.appendChild(link);
+    link.click();
+    link.remove();
+    setTimeout(() => URL.revokeObjectURL(url), 0);
+  }
+
+  private escapeField(field: string): string {
+    if (/[",\r\n]/.test(field)) {
+      return '"' + field.replaceAll('"', '""') + '"';
+    }
+    return field;
+  }

Review this PR

Angular practice