方案對比
| 方案 | 實現 | 優點 | 缺點 |
| CSV | fputcsv 逐行寫入,輸出 Content-Type: text/csv | 極簡、無依賴、流式大數據、跨平台 | 無樣式/公式/多 Sheet,Excel 打開可能編碼提示 |
| HTML 偽裝 | 直接輸出 Table HTML,Header Content-Type: application/vnd.ms-excel、Content-Disposition: attachment;filename=xx.xls | 保留 HTML 樣式/合併單元格、代碼極少 | Excel 彈出「文件格式不匹配」警告、不支持 .xlsx 特性 |
| OpenXML (PhpSpreadsheet) | composer require phpoffice/phpspreadsheet 程序化構建 Workbook/Worksheet/Style | 完整 .xlsx 標準、樣式/公式/圖表/數據驗證全支持 | 依賴較重、大數據需分塊寫入防 OOM |
代碼片段
// 1. CSV
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment;filename=data.csv');
$out = fopen('php://output', 'w');
fputcsv($out, ['ID','姓名','分數']);
foreach ($rows as $r) fputcsv($out, $r);
// 2. HTML 偽裝
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename=data.xls');
echo '| ID | 姓名 |
';
foreach ($rows as $r) echo "| {$r[0]} | {$r[1]} |
";
echo '
';
// 3. PhpSpreadsheet
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->fromArray(['ID','姓名','分數'], NULL, 'A1');
$sheet->fromArray($rows, NULL, 'A2');
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename=data.xlsx');
$writer->save('php://output');
選型建議
- 內部導出、無樣式需求 → CSV。
- 快速原型、兼容舊版 Excel → HTML 偽裝。
- 正式報表、樣式/公式/合規要求 → PhpSpreadsheet (OpenXML)。