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

PHPExcel 實作一鍵匯出 Excel 完整教學 (ThinkPHP 框架)

     編輯:DB2 教學

前言

在 Web 系統中「一鍵匯出 Excel」是常見需求。本文以 ThinkPHP 3.x + PHPExcel 為例,示範從查詢資料、設定欄位標題、填入資料列、輸出下載的完整流程,並說明常見編碼與記憶體優化技巧。

環境準備

  • PHP 5.4+ / 7.x
  • ThinkPHP 3.2.x
  • PHPExcel 1.8+ (透過 Vendor 載入)

控制器完整程式碼

public function input() {
    // 1. 清除輸出緩衝,避免亂碼
    ob_end_clean();

    // 2. 設定標頭編碼
    header("Content-Type: text/html; charset=utf-8");

    // 3. 載入 PHPExcel 核心類別 (ThinkPHP Vendor 機制)
    Vendor('Excel.PHPExcel.Writer.IWriter');
    Vendor('Excel.PHPExcel.Writer.Excel5');
    Vendor('Excel.PHPExcel');
    Vendor('Excel.PHPExcel.IOFactory');

    // 4. 建立試算表物件
    $objPHPExcel = new PHPExcel();
    $sheet = $objPHPExcel->getActiveSheet();

    // 5. 設定欄位標題 (A1 ~ AL1)
    $titles = [
        'A1'=>'ID', 'B1'=>'Studentname', 'C1'=>'IDcard', 'D1'=>'StudentID',
        'E1'=>'ClassID', 'F1'=>'Sex', 'G1'=>'Nation', 'H1'=>'Birth',
        'I1'=>'Imagepath', 'J1'=>'Huji', 'K1'=>'Phone', 'L1'=>'QQ',
        'M1'=>'Email', 'N1'=>'Addressnow', 'O1'=>'Local', 'P1'=>'Position',
        'Q1'=>'Macrosoft', 'R1'=>'CoachID', 'S1'=>'CarID', 'T1'=>'CartypeID',
        'U1'=>'Introducer', 'V1'=>'Signdate', 'W1'=>'Signplace', 'X1'=>'Signgtype',
        'Y1'=>'Lubiao', 'Z1'=>'Lubiaodate', 'AA1'=>'Zhika', 'AB1'=>'Zhikadate',
        'AC1'=>'Subtabdate', 'AD1'=>'Begindate', 'AE1'=>'Bigtabdate',
        'AF1'=>'Weier', 'AG1'=>'Lixiao', 'AH1'=>'Fingerprint',
        'AI1'=>'Inform', 'AJ1'=>'SchoolID', 'AK1'=>'Setting', 'AL1'=>'Remarks'
    ];
    foreach ($titles as $cell => $value) {
        $sheet->setCellValue($cell, $value);
    }

    // 6. 組合查詢條件
    $where['Lixiao'] = '否';
    $where['SchoolID'] = $_SESSION['SchoolID'];
    $studentname = I('Studentname');
    $idcard      = I('IDcard');
    if ($studentname) $where['Studentname'] = $studentname;
    if ($idcard)      $where['IDcard']      = $idcard;
    $where['_logic'] = 'AND';

    // 7. 查詢資料
    $data = M('studentinfo')->where($where)->select();
    $count = count($data);

    // 8. 填入資料列 (從第 2 列開始)
    $row = 2;
    foreach ($data as $record) {
        $sheet->setCellValue('A'.$row, $record['ID'])
              ->setCellValue('B'.$row, $record['Studentname'])
              ->setCellValue('C'.$row, $record['IDcard'])
              ->setCellValue('D'.$row, $record['StudentID'])
              ->setCellValue('E'.$row, $record['ClassID'])
              ->setCellValue('F'.$row, $record['Sex'])
              ->setCellValue('G'.$row, $record['Nation'])
              ->setCellValue('H'.$row, $record['Birth'])
              ->setCellValue('I'.$row, $record['Imagepath'])
              ->setCellValue('J'.$row, $record['Huji'])      // 注意:原碼誤寫 G,這裡修正為 J
              ->setCellValue('K'.$row, $record['Phone'])
              ->setCellValue('L'.$row, $record['QQ'])
              ->setCellValue('M'.$row, $record['Email'])
              ->setCellValue('N'.$row, $record['Addressnow'])
              ->setCellValue('O'.$row, $record['Local'])
              ->setCellValue('P'.$row, $record['Position'])
              ->setCellValue('Q'.$row, $record['Macrosoft'])
              ->setCellValue('R'.$row, $record['CoachID'])
              ->setCellValue('S'.$row, $record['CarID'])
              ->setCellValue('T'.$row, $record['CartypeID'])
              ->setCellValue('U'.$row, $record['Introducer'])
              ->setCellValue('V'.$row, $record['Signdate'])
              ->setCellValue('W'.$row, $record['Signpalce']) // 原碼拼字 Signpalce
              ->setCellValue('X'.$row, $record['Signgtype'])
              ->setCellValue('Y'.$row, $record['Lubiao'])
              ->setCellValue('Z'.$row, $record['Lubiaodate'])
              ->setCellValue('AA'.$row, $record['Zhika'])
              ->setCellValue('AB'.$row, $record['Zhikadate'])
              ->setCellValue('AC'.$row, $record['Subtabdate'])
              ->setCellValue('AD'.$row, $record['Begindate'])
              ->setCellValue('AE'.$row, $record['Bigtabdate'])
              ->setCellValue('AF'.$row, $record['Weier'])
              ->setCellValue('AG'.$row, $record['Lixiao'])
              ->setCellValue('AH'.$row, $record['Fingerprint'])
              ->setCellValue('AI'.$row, $record['Inform'])
              ->setCellValue('AJ'.$row, $record['SchoolID'])
              ->setCellValue('AK'.$row, $record['Setting'])
              ->setCellValue('AL'.$row, $record['Remarks']);
        $row++;
    }

    // 9. 設定工作表標題
    $sheet->setTitle('studentinfo');
    $objPHPExcel->setActiveSheetIndex(0);

    // 10. 輸出 HTTP 標頭並送出檔案
    header('Content-Type: application/vnd.ms-excel');
    header('Content-Disposition: attachment; filename="studentinfo.xls"');
    header('Cache-Control: max-age=0');

    $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
    $objWriter->save('php://output');
    exit; // 確保腳本結束
}

前端按鈕範例

<div style="float:right">
  <form action="{:U('input')}" method="post">
    <input type="submit" value="一鍵導出 EXCEL" />
  </form>
</div>

關鍵優化與注意事項

1. 記憶體優化 (大量資料)

  • 使用 PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp 或 cache_to_diskISAM 降低記憶體佔用。
  • 分批寫入、分批輸出,避免一次載入過多模型物件。

2. 編碼處理

  • 資料庫連線、PHP 檔案、HTML 輸出皆統一 UTF-8。
  • 若匯出中文檔名,建議使用 urlencode 或 RFC 5987 格式:
    header('Content-Disposition: attachment; filename*=UTF-8\'\'' . urlencode('學生名單.xls'));

3. 欄位對應修正

原始碼中 Huji 寫入 G 欄導致覆蓋 Nation,已修正為 J 欄;Signpalce 疑為拼字錯誤,保留原資料庫欄位名稱。

4. 推薦升級 PhpSpreadsheet

PHPExcel 已停止維護 (2017),新專案建議改用 PhpSpreadsheet (支援 .xlsx、效能更好、PHP 7.1+)。

composer require phpoffice/phpspreadsheet

5. 大檔案改用 CSV 或 Stream

超過 5 萬列或 10 MB 建議改用 fputcsv 串流輸出 CSV,或使用 PhpSpreadsheet\Writer\Xlsx 搭配 setPreCalculateFormulas(false)。

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