How to export data to CSV in Angular
Exporting data to CSV is a common feature in dashboards and admin panels, letting users take data out of the application for analysis in spreadsheet tools. As the creator of CoreUI with 25 years of experience building data-heavy Angular applications, I implement CSV export without third-party libraries because the browser’s built-in Blob API handles it natively and keeps the bundle lean. The approach is to convert your array of objects into a CSV string, create a Blob, and trigger a download via an anchor element. This works for any tabular data and requires no dependencies.
Create a service that converts data to CSV and downloads it.
// csv-export.service.ts
import { Injectable } from '@angular/core'
@Injectable({ providedIn: 'root' })
export class CsvExportService {
exportToCsv<T extends Record<string, unknown>>(
data: T[],
filename = 'export.csv',
columns?: (keyof T)[]
): void {
if (!data.length) return
const keys = columns ?? (Object.keys(data[0]) as (keyof T)[])
const header = keys.join(',')
const rows = data.map(row =>
keys.map(key => this.escapeCsvValue(row[key])).join(',')
)
const csv = [header, ...rows].join('\n')
this.downloadCsv(csv, filename)
}
private escapeCsvValue(value: unknown): string {
const str = value == null ? '' : String(value)
// Wrap in quotes if contains comma, quote, or newline
if (str.includes(',') || str.includes('"') || str.includes('\n')) {
return `"${str.replace(/"/g, '""')}"`
}
return str
}
private downloadCsv(content: string, filename: string): void {
// BOM for proper UTF-8 encoding in Excel
const bom = '\uFEFF'
const blob = new Blob([bom + content], { type: 'text/csv;charset=utf-8;' })
const url = URL.createObjectURL(blob)
const anchor = document.createElement('a')
anchor.href = url
anchor.download = filename
anchor.click()
URL.revokeObjectURL(url)
}
}
The \uFEFF BOM (Byte Order Mark) ensures Excel opens UTF-8 encoded CSV files with correct character encoding — without it, special characters like accented letters appear garbled. escapeCsvValue wraps values containing commas or quotes in double quotes and doubles any existing quote characters, following the RFC 4180 standard.
Using the Service in a Component
Export table data with a button click.
// users.component.ts
import { Component } from '@angular/core'
import { CsvExportService } from './csv-export.service'
interface User {
id: number
name: string
email: string
role: string
createdAt: string
}
@Component({
selector: 'app-users',
standalone: true,
template: `
<button (click)="exportAll()">Export All</button>
<button (click)="exportSelected()">Export Selected Columns</button>
`
})
export class UsersComponent {
users: User[] = [
{ id: 1, name: 'Alice Smith', email: '[email protected]', role: 'admin', createdAt: '2026-01-15' },
{ id: 2, name: 'Bob, Jr.', email: '[email protected]', role: 'user', createdAt: '2026-02-03' }
]
constructor(private csvExport: CsvExportService) {}
exportAll(): void {
this.csvExport.exportToCsv(this.users, 'users.csv')
}
exportSelected(): void {
// Export only specific columns
this.csvExport.exportToCsv(this.users, 'users-summary.csv', ['name', 'email', 'role'])
}
}
The columns parameter controls which fields are exported and in what order. Omitting it exports all fields in insertion order. Note that “Bob, Jr.” is correctly wrapped in quotes in the CSV output because it contains a comma.
Best Practice Note
This is the same export utility pattern used in CoreUI Angular data table templates. For very large datasets (tens of thousands of rows), generate the CSV on the server and stream it as a file download to avoid blocking the browser’s main thread. The server approach is also better for applying server-side filters and transformations before export. For binary spreadsheet formats like .xlsx, a library like SheetJS is required since the browser cannot generate Excel’s binary format natively. See how to download files in Angular for server-generated file downloads.



