Xuất File Excel Hiệu Năng Cao với FastExcelWriter trong PHP
Package: avadim/fast-excel-writer
Phiên bản hiện tại: v6.12.0 (phát hành 15/02/2026)
License: MIT | PHP: >= 7.4
Giới thiệu
FastExcelWriter là thư viện PHP thuần túy (pure PHP) cho phép tạo file Excel định dạng XLSX với tốc độ cực nhanh và tiêu thụ bộ nhớ tối thiểu. Thư viện được thiết kế để xử lý các tập dữ liệu lớn mà các giải pháp thông thường như PhpSpreadsheet thường gặp khó khăn.
So sánh nhanh với PhpSpreadsheet – thư viện Excel phổ biến nhất trong hệ sinh thái PHP:
- Nhanh hơn 7–9 lần
- Tiêu tốn ít bộ nhớ hơn 8–10 lần
- Hỗ trợ xuất file với hơn 100.000 dòng mà không bị timeout hay out-of-memory
FastExcelWriter là một phần của FastExcelPhp Project, bao gồm:
| Package | Mục đích |
|---|---|
avadim/fast-excel-writer |
Tạo file Excel XLSX |
avadim/fast-excel-reader |
Đọc file Excel XLSX |
avadim/fast-excel-templator |
Sinh file từ template XLSX có sẵn |
avadim/fast-excel-laravel |
Phiên bản tích hợp sẵn cho Laravel |
Cài đặt
composer require avadim/fast-excel-writer
Cơ bản: Tạo file Excel đầu tiên
Chỉ cần vài dòng code để tạo một file Excel hoàn chỉnh:
use \avadim\FastExcelWriter\Excel;
$data = [
['2003-12-31', 'Nguyễn Văn A', 220],
['2003-08-23', 'Trần Thị B', 153.5],
['2003-06-01', 'Lê Văn C', 34.12],
];
$excel = Excel::create(['Sheet1']);
$sheet = $excel->sheet();
// Ghi dòng tiêu đề
$sheet->writeRow(['Ngày', 'Tên', 'Doanh thu']);
// Ghi dữ liệu
foreach ($data as $row) {
$sheet->writeRow($row);
}
// Lưu file
$excel->save('bao_cao.xlsx');
// Hoặc gửi thẳng xuống trình duyệt để tải
$excel->download('bao_cao.xlsx');
Giải thích các method chính:
| Method | Mô tả |
|---|---|
Excel::create(['Sheet1']) |
Tạo workbook với một hoặc nhiều sheet |
$excel->sheet() |
Lấy sheet hiện tại đang làm việc |
$sheet->writeRow($data) |
Ghi một hàng dữ liệu và tự động xuống dòng tiếp theo |
$sheet->writeCell($value) |
Ghi vào một ô và di chuyển con trỏ sang ô kế tiếp |
$sheet->writeTo('B2', $value) |
Ghi trực tiếp vào ô theo địa chỉ |
$excel->save($path) |
Lưu file vào đường dẫn trên server |
$excel->download($name) |
Gửi file xuống trình duyệt (trigger download) |
Ví dụ thực tế: Xuất báo cáo đơn hàng có định dạng
Đây là ví dụ hoàn chỉnh xuất báo cáo doanh thu với header được định dạng, định dạng số/ngày tháng, và màu nền xen kẽ cho từng dòng:
use \avadim\FastExcelWriter\Excel;
use \avadim\FastExcelWriter\Style;
class OrderExportController extends Controller
{
public function exportOrders()
{
// Tạo workbook với tên sheet tùy ý
$excel = Excel::create(['Báo cáo đơn hàng']);
$sheet = $excel->sheet();
// --- Cấu hình cột ---
$sheet->setColDataStyle([
'A' => ['format' => '@date', 'width' => 14], // Cột ngày
'B' => ['format' => '@text', 'width' => 28], // Cột tên khách
'C' => ['format' => '#,##0.00 ₫', 'width' => 18], // Cột tiền
'D' => ['format' => '@text', 'width' => 16], // Cột trạng thái
]);
// --- Ghi header với style ---
$headerStyle = [
'font' => ['style' => 'bold', 'size' => 11],
'text-align' => 'center',
'vertical-align' => 'center',
'fill-color' => '#2563EB', // Nền xanh
'color' => '#FFFFFF', // Chữ trắng
'border' => 'thin',
'height' => 28,
];
$sheet->writeHeader(
['Ngày đặt', 'Khách hàng', 'Tổng tiền', 'Trạng thái'],
$headerStyle
);
// --- Ghi dữ liệu theo từng chunk ---
$rowNum = 0;
Order::with('customer')
->orderBy('created_at', 'desc')
->chunk(500, function ($orders) use ($sheet, &$rowNum) {
foreach ($orders as $order) {
$rowNum++;
$rowStyle = [
'height' => 20,
// Màu xen kẽ cho dễ đọc
'fill-color' => ($rowNum % 2 === 0) ? '#EFF6FF' : '#FFFFFF',
];
$sheet->writeRow([
$order->created_at->format('Y-m-d'),
$order->customer->name,
$order->total,
$order->status,
], $rowStyle);
}
});
// Bật autofilter trên header
$sheet->setAutoFilter('A1:D1');
// Cố định dòng tiêu đề khi cuộn
$sheet->setFreeze('A2');
return response()->streamDownload(
fn() => $excel->download('don_hang.xlsx'),
'don_hang.xlsx',
['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
);
}
}
Phân tích kỹ thuật:
1. Định dạng cột với setColDataStyle()
Thay vì định dạng từng ô riêng lẻ, bạn khai báo định dạng cho cả cột một lần duy nhất. FastExcelWriter áp dụng format khi ghi dữ liệu, không cần xử lý thêm.
2. Fluent Interface cho Style
Cách viết style dạng chuỗi liên tiếp giúp code ngắn gọn và dễ đọc:
$sheet->writeHeader($headers)
->applyFontStyleBold()
->applyTextAlign('center', 'center')
->applyBorder(Style::BORDER_STYLE_THIN)
->applyFillColor('#2563EB')
->applyRowHeight(28);
3. Chunk từ Eloquent
Kết hợp ->chunk() của Laravel với FastExcelWriter giúp xử lý hàng triệu bản ghi mà bộ nhớ RAM luôn ở mức thấp, ổn định.
Các tính năng nổi bật
Nhiều Sheet trong một Workbook
$excel = Excel::create(['Tháng 1', 'Tháng 2', 'Tháng 3']);
// Chuyển qua lại giữa các sheet
$sheet1 = $excel->sheet('Tháng 1');
$sheet2 = $excel->sheet('Tháng 2');
$sheet1->writeRow(['Ngày', 'Doanh thu']);
$sheet2->writeRow(['Ngày', 'Chi phí']);
Công thức Excel (Formulas)
$sheet->writeRow([100, 200, 300]);
$sheet->writeRow([150, 250, 350]);
// Viết công thức SUM vào ô
$sheet->writeTo('A3', '=SUM(A1:A2)');
$sheet->writeTo('D1', '=SUM(A1:C1)');
// Công thức phức tạp hơn
$sheet->writeTo('E1', '=IF(D1>500,"Cao","Thấp")');
Thêm Ghi chú (Notes) vào Ô
$sheet->writeCell('Doanh thu Q1');
$sheet->addNote('A1', "Tổng hợp từ 3 kênh:\n- Online\n- Offline\n- Đại lý");
// Tùy chỉnh style của note
$sheet->addNote('B2', 'Lưu ý quan trọng', [
'width' => '200pt',
'height' => '80pt',
'fill_color' => '#FFF3CD', // Nền vàng nhạt
'show' => true, // Hiển thị mặc định
]);
Chèn Ảnh
// Từ đường dẫn local
$sheet->addImage('A1', '/path/to/logo.png', ['width' => 150]);
// Từ URL
$sheet->addImage('B2', 'https://example.com/chart.jpg', ['height' => 100]);
// Từ chuỗi base64
$sheet->addImage('C3', 'data:image/png;base64,iVBORw0K...', ['width' => 200]);
// Kèm hyperlink
$sheet->addImage('D4', '/path/to/banner.jpg', [
'width' => 300,
'height' => 100,
'hyperlink' => 'https://example.com',
]);
Biểu đồ (Charts)
use \avadim\FastExcelWriter\Charts\Chart;
// Viết dữ liệu nguồn
$sheet->writeRow(['Tháng', 'Doanh thu', 'Chi phí']);
$sheet->writeRow(['T1', 1200, 800]);
$sheet->writeRow(['T2', 1500, 900]);
$sheet->writeRow(['T3', 1800, 1000]);
// Tạo biểu đồ cột
$chart = Chart::make(Chart::TYPE_BAR, 'Biểu đồ Doanh thu')
->setDataRange('Sheet1!$B$1:$C$4')
->setCategoriesRange('Sheet1!$A$2:$A$4')
->setPosition('F1', 'L15');
$sheet->addChart($chart);
Bảo vệ File và Sheet
// Đặt mật khẩu cho workbook
$excel->protect('matkhau123');
// Bảo vệ sheet (không cho chỉnh sửa)
$sheet->protect('matkhau456');
// Khóa/mở khóa một số ô cụ thể
$sheet->setColDataStyle('A', ['locked' => true]); // Khóa cả cột A
$sheet->setColDataStyle('B', ['locked' => false]); // Cho phép chỉnh sửa cột B
Định dạng có điều kiện (Conditional Formatting)
use \avadim\FastExcelWriter\Conditional\Conditional;
// Tô đỏ các ô có giá trị < 0
$conditional = Conditional::make()
->setCondition(Conditional::CONDITION_LESS_THAN, 0)
->setStyle(['fill-color' => '#FFCCCC', 'color' => '#CC0000']);
$sheet->addConditional('C2:C1000', $conditional);
// Thang màu gradient theo giá trị
$colorScale = Conditional::makeColorScale('#FF0000', '#FFFF00', '#00FF00');
$sheet->addConditional('C2:C1000', $colorScale);
Validation dữ liệu
use \avadim\FastExcelWriter\DataValidation\DataValidation;
// Dropdown list
$validation = DataValidation::make()
->setType(DataValidation::TYPE_LIST)
->setValueList(['Đang xử lý', 'Hoàn thành', 'Hủy']);
$sheet->addDataValidation('D2:D1000', $validation);
// Chỉ cho phép nhập số từ 1 đến 100
$numValidation = DataValidation::make()
->setType(DataValidation::TYPE_WHOLE)
->setOperator(DataValidation::OPERATOR_BETWEEN)
->setValues(1, 100);
$sheet->addDataValidation('E2:E1000', $numValidation);
So sánh hiệu năng: FastExcelWriter vs PhpSpreadsheet
Benchmark thực tế khi xuất file (không áp dụng style):
| Số dòng × cột | PhpSpreadsheet – Thời gian | PhpSpreadsheet – RAM | FastExcelWriter – Thời gian | FastExcelWriter – RAM |
|---|---|---|---|---|
| 1.000 × 5 | 0.98 giây | 2,048 KB | 0.19 giây | 2,048 KB |
| 1.000 × 25 | 4.68 giây | 14,336 KB | 1.36 giây | 2,048 KB |
| 5.000 × 25 | 23.19 giây | 77,824 KB | 3.61 giây | 2,048 KB |
| 10.000 × 50 | 105.8 giây | 256,000 KB | 13.02 giây | 2,048 KB |
Nhận xét đáng chú ý: Bộ nhớ của FastExcelWriter luôn giữ ở mức 2MB bất kể kích thước dữ liệu, trong khi PhpSpreadsheet tăng tuyến tính đến 250MB+ với 10.000 dòng.
So sánh tổng quan: Nên dùng gì?
| Tiêu chí | PhpSpreadsheet | FastExcelWriter |
|---|---|---|
| Đọc file Excel | ||
| Hỗ trợ nhiều định dạng (XLS, ODS…) | ||
| Tốc độ ghi | Chậm | Rất nhanh |
| Tiêu thụ RAM | Cao | Rất thấp |
| Xuất 100K+ dòng | Dễ bị timeout | Hoàn toàn ổn định |
| Charts, Styles, Formulas | ||
| Phù hợp nhất | Thao tác đa định dạng, đọc file | Xuất file lớn, báo cáo |
Tích hợp với Laravel
Nếu bạn đang dùng Laravel, có thể dùng gói chuyên biệt:
composer require avadim/fast-excel-laravel
Sau đó sử dụng qua Facade:
use \avadim\FastExcelLaravel\Excel;
// Xuất trực tiếp từ Eloquent Collection
$users = User::all();
$excel = Excel::create();
$sheet = $excel->sheet();
$sheet->writeHeader(['ID', 'Tên', 'Email']);
foreach ($users as $user) {
$sheet->writeRow([$user->id, $user->name, $user->email]);
}
return $excel->download('users.xlsx');
Hoặc kết hợp với Streaming Response của Laravel để xuất file ngay lập tức mà không tốn RAM server:
public function exportLargeReport()
{
return response()->streamDownload(function () {
$excel = Excel::create(['Báo cáo']);
$sheet = $excel->sheet();
$sheet->writeHeader(['ID', 'Khách hàng', 'Tổng tiền']);
Order::chunk(1000, function ($orders) use ($sheet) {
foreach ($orders as $order) {
$sheet->writeRow([
$order->id,
$order->customer_name,
$order->total,
]);
}
});
$excel->download('bao_cao_lon.xlsx');
}, 'bao_cao_lon.xlsx');
}
Kết luận
FastExcelWriter là lựa chọn tối ưu khi bạn cần:
- Xuất file Excel từ tập dữ liệu lớn (10.000 – hàng triệu dòng)
- Tối ưu tài nguyên server (RAM luôn ổn định ở mức thấp)
- Tránh lỗi timeout hoặc memory limit khi xuất báo cáo
- Tạo file Excel chuyên nghiệp với đầy đủ style, chart, formula, validation
Điểm đánh đổi duy nhất là thư viện chỉ ghi, không đọc – nhưng với mục đích xuất báo cáo thì đây không phải hạn chế. Nếu cần đọc file Excel, hãy kết hợp với avadim/fast-excel-reader từ cùng tác giả.
Tài nguyên
- GitHub: GitHub - aVadim483/fast-excel-writer: Lightweight and very fast XLSX Excel Spreadsheet Writer in PHP. Supports full XLSX-file functionality - cell formatting, formulas, styles, charts, etc. · GitHub
- Tài liệu đầy đủ: https://fast-excel-writer.readthedocs.io
- Packagist: avadim/fast-excel-writer - Packagist.org
- Ví dụ demo: thư mục
/demotrong repository