首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 產生 Excel 檔案三種方案:原生 Header、PHPExcel/PhpSpreadsheet、CSV 替代

     編輯:PHP 相關知識

前言

「產生 Excel」需求常見於報表匯出、資料備份、模板下載。方案選擇取決於:格式複雜度(單純表格 vs 樣式/圖表/公式)、資料量(百筆 vs 萬筆)、效能/記憶體限制。本文比較三大主流方案並提供選型指南。

方案一:原生 HTTP Header + Tab 分隔 (最輕量、零依賴)

利用瀏覽器將 Tab 分隔文字自動識別為 Excel 可開啟格式。適用於純資料表格、無樣式、中小資料量。

<?php
// 設定下載標頭
header('Content-Type: application/vnd.ms-excel; charset=utf-8');
header('Content-Disposition: attachment; filename="report_' . date('YmdHis') . '.xls"');
header('Pragma: public');
header('Cache-Control: max-age=0');

// 輸出資料:欄位用 \t 分隔,列用 \n 換行
echo "ID\tName\tEmail\tAmount\n";
echo "1\t張三\tzhang@example.com\t100\n";
echo "2\t李四\tli@example.com\t200\n";
// ... 迴圈輸出資料庫查詢結果
?>

優缺點

優點缺點
零依賴、極快、記憶體極低 (可邊查詢邊輸出)無法設定欄寬、字型、顏色、凍結窗格、公式
相容所有 Excel 版本、LibreOffice、Google Sheets無法多工作表、圖表、圖片
可直接 echo 串流輸出,支援百萬列中文檔名需 rawurlencode 處理

進階:UTF-8 BOM 防止 Excel 開啟亂碼

<?php
header('Content-Type: application/vnd.ms-excel; charset=utf-8');
header('Content-Disposition: attachment; filename="report.xls"');
echo "\xEF\xBB\xBF"; // UTF-8 BOM,讓 Excel 自動識別編碼
echo "欄位1\t欄位2\n資料1\t資料2\n";
?>

方案二:PhpSpreadsheet (現代標準、功能完整)

PHPExcel 已停止維護 (2017),請改用其繼任者 PhpSpreadsheet。支援 .xlsx、.xls、.ods、.csv、PDF、HTML 等格式,完整樣式、公式、圖表、圖片、資料驗證。

安裝

composer require phpoffice/phpspreadsheet

基礎範例

<?php
require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Font;

$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle('銷售報表');

// 標題列
$headers = ['ID', '客戶', '金額', '日期'];
$sheet->fromArray($headers, null, 'A1');

// 樣式:粗體、背景色、置中、邊框
$style = [
    'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
    'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '4472C4']],
    'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
    'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
];
$sheet->getStyle('A1:D1')->applyFromArray($style);

// 資料列 (假設從資料庫查詢)
$data = [
    [1, '張三', 1000, '2024-01-15'],
    [2, '李四', 2500, '2024-01-16'],
];
$sheet->fromArray($data, null, 'A2');

// 金額欄位格式化為貨幣
$sheet->getStyle('C2:C' . (count($data)+1))
    ->getNumberFormat()->setFormatCode('#,##0.00');

// 自動欄寬
foreach (range('A', 'D') as $col) {
    $sheet->getColumnDimension($col)->setAutoSize(true);
}

// 輸出下載
$writer = new Xlsx($spreadsheet);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="report_' . date('YmdHis') . '.xlsx"');
$writer->save('php://output');
exit;
?>

大資料量優化 (Chunk Write)

<?php
// 使用 ChunkReadWriter 避免一次載入所有資料到記憶體
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->setPreCalculateFormulas(false);
$writer->setUseDiskCaching(true); // 使用磁碟快取
$writer->save('php://output');
?>

方案三:CSV 格式 (通用、極輕、支援串流)

CSV 非真正 Excel,但 Excel 可直接開啟。適合純資料、跨系統匯入、超大資料量、記憶體受限環境。

<?php
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="report_' . date('YmdHis') . '.csv"');
header('Pragma: no-cache');

// UTF-8 BOM 讓 Excel 正確識別中文
echo "\xEF\xBB\xBF";

$out = fopen('php://output', 'w');
fputcsv($out, ['ID', '客戶', '金額', '日期']); // 標題

// 分批查詢輸出 (PDO 範例)
$stmt = $pdo->query("SELECT id, name, amount, created_at FROM orders");
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
    fputcsv($out, $row);
}
fclose($out);
exit;
?>

方案選型決策樹

  1. 需要樣式、公式、圖表、多工作表、.xlsx 格式 → PhpSpreadsheet
  2. 純資料表格、無樣式、資料量 < 5 萬列、追求零依賴極速 → 原生 Header + Tab
  3. 資料量 > 10 萬列、記憶體 < 256MB、需串流輸出、跨系統相容 → CSV (fputcsv 串流)
  4. 舊專案相容 .xls (Excel 97-2003) → PhpSpreadsheet Writer\Xls 或原生 Header

常見坑點與解決

問題原因解決
Excel 開啟 CSV 中文亂碼Excel 預設用系統編碼 (Big5/GBK) 開啟 UTF-8 CSV加 UTF-8 BOM (\xEF\xBB\xBF) 或用「資料 → 從文字/CSV」匯入指定 UTF-8
PhpSpreadsheet 記憶體耗盡大資料集一次載入所有 Cell 物件啟用 setUseDiskCaching(true)、分批寫入、避免過度樣式化
原生 Header 輸出中文檔名亂碼HTTP 標頭編碼問題filename*=UTF-8'' . rawurlencode($filename) (RFC 5987)
數字被科學記號顯示 (1.23E+10)Excel 自動偵測格式PhpSpreadsheet 設定 setFormatCode('@') 文字格式;CSV 在欄位加 =\\"12345678901\\"
長數字 (身分證、手機) 截斷Excel 數值精度 15 位設為文字格式或前加單引號 '123456789012345

總結

三大方案各有甜點:原生 Header 適合快速原型與簡單匯出;PhpSpreadsheet 是功能完整的專業選擇;CSV 串流 是大資料量、低記憶體、跨平台的最佳拍檔。根據專案「格式需求 × 資料量 × 基礎設施」三維度選型,並善用上述坑點對策,即能輕鬆實作穩健的 Excel 匯出功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved