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

PHP 匯出 CSV 完整解決方案:數字前導零保留與編碼轉換實戰

     編輯:PHP 相關知識

痛點與解決方案

PHP 匯出 CSV 時常遇到兩大問題:

  1. 數字科學計數法/前導零消失:Excel 自動將 00001 解析為 1
  2. 中文亂碼:UTF-8 產出的 CSV 在中文 Excel 開啟顯示亂碼

本文提供生產級解決方案,核心技巧:在欄位值前加入 \t (Tab) 字元強制 Excel 視為文字,搭配 mb_convert_encoding 轉 Big5/GB2312 編碼。

核心程式碼實作

<?php
/**
 * 產生 CSV 並輸出下載
 * @param array $lists  資料集合
 * @param string $filename 檔名稱
 */
function exportCsv(array $lists, string $filename = '') {
    // 1. 定義標題列
    $header = '規則111,規則222,審222,規222,服2222,規則1,規則2,規則3,匹配字符,設置時間,有效期';
    $exportData = $header . "\n";

    // 2. 組裝資料列(關鍵:每欄位以 "\t" 開頭強制文字格式)
    if (!empty($lists)) {
        foreach ($lists as $value) {
            $exportData .= '"' . "\t" . $value['Rule_id'] . '",'
                         . '"' . "\t" . $value['Rule_name'] . '",'
                         . '"' . "\t" . $value['Matching_level'] . '",'
                         . '"' . "\t" . $value['Rule_action'] . '",'
                         . '"' . "\t" . $value['Service_type'] . '",'
                         . '"' . "\t" . $value['Keyword1'] . '",'
                         . '"' . "\t" . $value['Keyword2'] . '",'
                         . '"' . "\t" . $value['Keyword3'] . '",'
                         . '"' . "\t" . $value['Matching_word'] . '",'
                         . '"' . "\t" . $value['Set_time'] . '",'
                         . '"' . "\t" . $value['Validation_time'] . '"' . "\n";
        }
    }

    // 3. 設定下載標頭
    $filename = $filename ?: "plcnetinfo_" . date("YmdHis") . ".csv";

    header("Content-Type: application/vnd.ms-excel; charset=gb2312");
    header("Content-Disposition: attachment; filename=\"{$filename}\"");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Pragma: public");

    // 4. 輸出前轉碼(UTF-8 -> GB2312/Big5 相容中文 Excel)
    echo mb_convert_encoding($exportData, "gb2312", "UTF-8");
}

// 使用範例
$sql = "SELECT * FROM rules WHERE status = 1";
$lists = $db->query($sql); // 假設 PDO 查詢結果
exportCsv($lists);
?>

關鍵技術細節解析

技巧作用說明
"\t" 前綴 保留前導零/長數字 Excel 偵測到 Tab 字元會將該欄位視為純文字,不進行數值轉換
雙引號包裹 處理逗號/換行 欄位內含逗號、雙引號、換行時不會破壞 CSV 結構
mb_convert_encoding 解決中文亂碼 中文版 Excel 預設開啟 CSV 使用系統編碼,UTF-8 會亂碼
header() 設定 觸發瀏覽器下載 Content-Disposition: attachment 強制下載而非瀏覽器開啟

進階擴展:通用 CSV 匯出類

<?php
class CsvExporter {
    private $data = [];
    private $headers = [];
    private $forceTextColumns = []; // 強制文字欄位索引

    public function setHeaders(array $headers) { $this->headers = $headers; }
    public function setData(array $data) { $this->data = $data; }
    public function setForceTextColumns(array $indices) { $this->forceTextColumns = $indices; }

    public function download(string $filename = '') {
        $output = fopen('php://temp', 'r+');
        
        // 寫入標題
        fputcsv($output, $this->headers);
        
        // 寫入資料
        foreach ($this->data as $row) {
            $formatted = [];
            foreach ($row as $idx => $val) {
                if (in_array($idx, $this->forceTextColumns)) {
                    $formatted[] = "\t" . $val; // 強制文字
                } else {
                    $formatted[] = $val;
                }
            }
            fputcsv($output, $formatted);
        }
        
        rewind($output);
        $csvContent = stream_get_contents($output);
        fclose($output);

        // 輸出下載(同前)
        header("Content-Type: application/vnd.ms-excel; charset=gb2312");
        header("Content-Disposition: attachment; filename=\"{$filename}\"");
        echo mb_convert_encoding($csvContent, "gb2312", "UTF-8");
    }
}

// 使用方式
$exporter = new CsvExporter();
$exporter->setHeaders(['ID', '姓名', '工號', '電話']);
$exporter->setData($userList);
$exporter->setForceTextColumns([2, 3]); // 工號、電話保留前導零
$exporter->download("users_" . date("Ymd") . ".csv");
?>

匯入端處理提醒

匯入時若欄位前有 "\t",請使用 trim() 清除:

$cleanValue = trim($rawValue, "\t\r\n\" ");

總結

  • \t 前綴法相容性最佳,支援 Excel、WPS、LibreOffice Calc
  • 大數據量建議改用 fputcsv() 串流寫入,避免記憶體耗盡
  • 編碼轉換務必在 header() 之後、echo 之前執行
  • 檔名含中文時需對應 RFC 5987 編碼:filename*=UTF-8''%E6%AA%94%E6%A1%88.csv
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved