.csv spreadsheet using pure client-side JavaScript—without needing third-party libraries or extra server round-trips.
Exporting tabular data to CSV (Comma-Separated Values) is a frequent requirement in Salesforce business applications. Whether you are providing a quick report download on an Account page or letting users export custom dashboard metrics, handling CSV creation inside Lightning Web Components provides a seamless, high-speed user experience.
Why Handle CSV Export on the Client Side?
- Zero Server Load: Generates the entire file in the user's browser, eliminating CPU and heap limit strain on Apex controllers.
- Instant Downloads: Creates a downloadable file immediately with standard JavaScript
BlobandURL.createObjectURLAPIs. - Universal Format: CSV files seamlessly open in Excel, Google Sheets, or data analytics platforms.
1. Building the Component Template
The UI component contains a standard lightning-button to trigger the download workflow.
<!-- exportButton.html -->
<template>
<lightning-card title="Export Records" icon-name="custom:custom63">
<div class="slds-p-around_medium">
<p class="slds-m-bottom_small">Click the button below to download the latest account list.</p>
<lightning-button
variant="brand"
label="Export to CSV"
icon-name="utility:download"
onclick={handleExport}>
</lightning-button>
</div>
</lightning-card>
</template>
2. Implementing the JavaScript CSV Converter and Downloader
The JavaScript controller transforms record objects into comma-separated lines, escapes special characters, builds a Blob, and triggers the browser download action.
// exportButton.js
import { LightningElement } from 'lwc';
export default class ExportButton extends LightningElement {
// Sample data source (can also be populated via @wire or imperative Apex)
records = [
{ Id: '001', Name: 'Acme Corp', Industry: 'Manufacturing', AnnualRevenue: 5000000 },
{ Id: '002', Name: 'Global Media, Inc.', Industry: 'Media & Tech', AnnualRevenue: 12500000 },
{ Id: '003', Name: 'Summit Health', Industry: 'Healthcare', AnnualRevenue: 3400000 }
];
columnHeader = ['Id', 'Name', 'Industry', 'AnnualRevenue'];
handleExport() {
if (!this.records || !this.records.length) {
return;
}
const csvContent = this.convertToCSV(this.records, this.columnHeader);
this.downloadCSVFile(csvContent, 'Account_Export.csv');
}
convertToCSV(data, headers) {
const csvRows = [];
// Add header row
csvRows.push(headers.join(','));
// Format each record row
data.forEach(record => {
const values = headers.map(header => {
let val = record[header] !== undefined && record[header] !== null ? String(record[header]) : '';
// Escape quotes and wrap values containing commas or line breaks in double quotes
if (val.includes(',') || val.includes('"') || val.includes('\n')) {
val = `"${val.replace(/"/g, '""')}"`;
}
return val;
});
csvRows.push(values.join(','));
});
return csvRows.join('\r\n');
}
downloadCSVFile(csvData, fileName) {
// Prefix UTF-8 BOM to guarantee proper character encoding in Microsoft Excel
const blob = new Blob(['\uFEFF' + csvData], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = fileName;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
}
- Map Data: Extract values row-by-row based on your defined column headers.
- Escape Strings: Wrap strings with double quotes if they contain commas, newlines, or quotation marks to preserve CSV columns.
- Create Blob: Convert the raw string into a standard CSV Blob object.
- Trigger Virtual Link: Dynamically create and click an invisible
<a>element to prompt the browser's save dialog.
\uFEFF) to the beginning of your Blob prevents this formatting issue completely.
3. Exposing the Component in Lightning App Builder
To make the component available on Record Pages, App Pages, or Home Pages, configure your component XML configuration file.
<!-- exportButton.js-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>61.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
- Browser Performance: Best suited for small to medium datasets (up to a few thousand records). For massive bulk extractions (50,000+ rows), use Bulk API 2.0 or asynchronous batch jobs.
- Column Customization: Use dynamic column mapping to allow users to export only visible columns from a
lightning-datatable. - Memory Cleanup: Always invoke
URL.revokeObjectURL(url)to release browser memory immediately after the click event triggers.