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

PHP 導出中文 Excel 文件完整方案:兩種實用類庫與代碼示例

     編輯:PHP 相關知識

PHP 導出 Excel(含中文)最佳實踐指南

在後台管理、數據報表、用戶導出等場景中,將數據導出為 Excel 是高頻需求。PHP 原生不支持直接生成 .xls/.xlsx,常見方案有:HTML 表格偽裝、PHPExcel/PhpSpreadsheet 庫、CSV 格式。本文提供兩種**零依賴、即插即用**的完整代碼方案,專門解決中文編碼亂碼、長數字科學計數法、大數據導出性能等痛點。

方案一:HTML 表格偽裝法(適合中小數據量,兼容性最好)

原理:輸出帶有 Office XML 命名空間的 HTML 表格,瀏覽器/Excel 識別為 .xls 文件。無需第三方庫,支持樣式、合併單元格、凍結窗格等基礎功能。

<?php
class ToExcel {
    /**
     * 導出 Excel
     * @param array $mapping  表頭映射 ['編號','姓名','郵箱','年齡']
     * @param array $dataList 數據二維數組 [[1,'張三','zhang@example.com',25], ...]
     * @param string $fileName 文件名(不含副檔名)
     */
    public function toExcel($mapping, $dataList, $fileName) {
        // 1. 設置響應頭:強制下載、指定文件名(中文需轉 GB2312 避免瀏覽器亂碼)
        header("Content-Type: application/vnd.ms-excel");
        header("Content-Disposition: attachment; filename=" . iconv('UTF-8', 'GB2312', $fileName) . ".xls");
        header("Pragma: no-cache");
        header("Expires: 0");

        // 2. 輸出 HTML + Office XML 命名空間
        echo '<html xmlns:o="urn:schemas-microsoft-com:office:office"
              xmlns:x="urn:schemas-microsoft-com:office:excel"
              xmlns="https://www.w3.org/TR/REC-html40">
            <head>
              <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
              <!--[if gte mso 9]><xml>
                <x:ExcelWorkbook>
                  <x:ExcelWorksheets>
                    <x:ExcelWorksheet>
                      <x:Name>Sheet1</x:Name>
                      <x:WorksheetOptions>
                        <x:DisplayGridlines/>
                        <x:Print>
                          <x:ValidPrinterInfo/>
                        </x:Print>
                      </x:WorksheetOptions>
                    </x:ExcelWorksheet>
                  </x:ExcelWorksheets>
                </x:ExcelWorkbook>
              </xml><![endif]-->
            </head>
            <body>';

        // 3. 表頭
        echo '<table border="1" cellspacing="0" cellpadding="3"><tr>';
        foreach ($mapping as $col) {
            echo '<th style="background:#0066CC;color:#fff;font-weight:bold;">' . htmlspecialchars($col) . '</th>';
        }
        echo '</tr>';

        // 4. 數據行
        foreach ($dataList as $row) {
            echo '<tr>';
            foreach ($row as $key => $val) {
                // 長數字(≥14位,如身份證、銀行卡)強制文本格式,防科學計數法
                if (is_numeric($val) && strlen($val) >= 14) {
                    echo '<td style="vnd.ms-excel.numberformat:@">' . htmlspecialchars($val) . '</td>';
                } else {
                    echo '<td>' . htmlspecialchars($val) . '</td>';
                }
            }
            echo '</tr>';
        }

        echo '</table></body></html>';
    }
}

// === 使用示例 ===
$map = ['編號', '姓名', '郵箱'];
$data = [
    [1, '管理員', 'admin@example.com'],
    [2, '會員', 'member@example.com'],
    [3, '測試用戶', 'test12345678901234@example.com'], // 長數字測試
];
$excel = new ToExcel();
$excel->toExcel($map, $data, '用戶列表_' . date('YmdHis'));
?>

關鍵點解析

  • 編碼轉換:iconv('UTF-8','GB2312',$fileName) 解決中文文件名在 IE/Edge 下載亂碼。
  • 長數字文本化:style="vnd.ms-excel.numberformat:@" 強制 Excel 以文本顯示,避免身份證號變科學計數法。
  • HTML 轉義:htmlspecialchars() 防止數據中含 < > & 破壞結構。
  • 內存佔用:一次性輸出,適合 < 5 萬行;超大數據建議分批輸出或用方案二。

方案二:Tab 分隔文本流(極簡、超高性能、適合百萬行)

原理:直接輸出 Tab (\t) 分隔、換行 (\n) 的純文本,Excel 打開自動識別列。無 HTML 開銷,內存佔用極低,速度最快。

<?php
header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=数据导出_" . date('YmdHis') . ".xls");
header("Pragma: no-cache");
header("Expires: 0");

// 模擬大數據流式輸出(不佔內存)
$handle = fopen('php://output', 'w');

// 表頭
$header = ['編號', '姓名', '郵箱', '註冊時間'];
// 寫入 BOM 防 UTF-8 無 BOM 導致 Excel 亂碼
fwrite($handle, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($handle, $header, "\t"); // 使用 Tab 分隔

// 模擬分批查詢輸出
for ($i = 1; $i <= 100000; $i++) {
    $row = [
        $i,
        "用戶{$i}",
        "user{$i}@example.com",
        date('Y-m-d H:i:s', strtotime("-$i days"))
    ];
    fputcsv($handle, $row, "\t");
    // 每 1000 行刷新一次,避免內存堆積
    if ($i % 1000 === 0) fflush($handle);
}

fclose($handle);
?>

優缺點對比

特性方案一 HTML 偽裝方案二 Tab 文本流
中文支持優(需 iconv 文件名)優(需 UTF-8 BOM)
樣式/合併儲存格支持不支持
長數字文本化支持需在 Excel 導入時指定列格式
性能/內存中等(<5萬行)極高(百萬行秒級)
依賴零依賴零依賴
適用場景後台導出、帶樣式報表大數據導出、日志導出、定時任務

進階建議:超大數據/複雜樣式 → PhpSpreadsheet

若需:多工作表、圖表、公式、條件格式、圖片嵌入、.xlsx 格式,請使用官方維護的 PhpSpreadsheet(原 PHPExcel 繼任者)。

composer require phpoffice/phpspreadsheet

但注意:PhpSpreadsheet 將所有數據載入內存,**百萬行級會 OOM**,需配合 CellCaching 或分塊寫入技巧。

總結

  • **常規後台導出(<5萬行、需樣式)** → 方案一 HTML 偽裝類,開箱即用。
  • **大數據導出(>10萬行、純數據)** → 方案二 Tab 文本流,極速低內存。
  • **複雜報表/多表/圖表** → PhpSpreadsheet,接受較高內存佔用。

根據業務場景選擇合適方案,即可輕鬆解決 PHP 導出中文 Excel 的所有痛點。

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