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

PHP 生成 Excel 文件到指定目錄:PHPExcel/PhpSpreadsheet 實戰指南

     編輯:PHP 相關知識

現狀說明

`header("Content-Disposition: attachment")` 只能觸發瀏覽器下載,**無法直接保存到服務器指定目錄**。需先生成文件對象,再調用保存方法寫入磁盤。

推薦庫:PhpSpreadsheet (PHPExcel 繼任者)

composer require phpoffice/phpspreadsheet

PHPExcel 已停止維護 (2017),PhpSpreadsheet 支援 PHP 7.1+、更快、功能更全、命名空間規範。

核心代碼:生成並保存到指定路徑

<?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;

function generateExcelReport(array $data, string $savePath, string $title = '報表'): bool {
    try {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle($title);
        
        // 1. 設置表頭
        $headers = ['ID', '姓名', '部門', '薪資', '入職日期'];
        $sheet->fromArray($headers, null, 'A1');
        
        // 表頭樣式
        $headerStyle = [
            'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF'], 'size' => 12],
            'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '4472C4']],
            'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
            'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => '000000']]],
        ];
        $sheet->getStyle('A1:E1')->applyFromArray($headerStyle);
        
        // 2. 填充數據 (從第 2 行開始)
        $sheet->fromArray($data, null, 'A2');
        
        // 數據行樣式
        $lastRow = count($data) + 1;
        $dataStyle = [
            'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
            'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'CCCCCC']]],
        ];
        $sheet->getStyle("A2:E{$lastRow}")->applyFromArray($dataStyle);
        
        // 3. 自動列寬
        foreach (range('A', 'E') as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }
        
        // 4. 凍結首行
        $sheet->freezePane('A2');
        
        // 5. 保存到指定路徑
        $writer = new Xlsx($spreadsheet);
        $writer->save($savePath);
        
        // 釋放內存
        $spreadsheet->disconnectWorksheets();
        unset($spreadsheet);
        
        return true;
    } catch (Exception $e) {
        error_log("Excel 生成失敗: " . $e->getMessage());
        return false;
    }
}

// 使用示例
$data = [
    [1, '張三', '技術部', 15000, '2020-01-15'],
    [2, '李四', '市場部', 12000, '2021-03-22'],
    [3, '王五', '技術部', 18000, '2019-07-01'],
];

$saveDir = __DIR__ . '/exports/';
if (!is_dir($saveDir)) mkdir($saveDir, 0755, true);
$fileName = 'employee_report_' . date('Ymd_His') . '.xlsx';
$fullPath = $saveDir . $fileName;

if (generateExcelReport($data, $fullPath, '員工薪資表')) {
    echo "生成成功: {$fullPath}";
    // 可選:記錄數據庫、發送郵件、推送通知...
} else {
    echo "生成失敗";
}
?>

插入圖片

<?php
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

$drawing = new Drawing();
$drawing->setName('公司Logo');
$drawing->setDescription('Logo');
$drawing->setPath(__DIR__ . '/assets/logo.png'); // 本地圖片路徑
$drawing->setHeight(60); // 高度 (寬度自動按比例)
$drawing->setCoordinates('A1'); // 插入位置
$drawing->setOffsetX(10); // 微調
$drawing->setWorksheet($sheet);

// 也可插入 URL 圖片 (需開啟 allow_url_fopen)
// $drawing->setPath('https://example.com/logo.png');
?>

導出大數據量優化 (分塊寫入)

<?php
function exportLargeDataset(Generator $dataGen, string $savePath, int $chunkSize = 1000): bool {
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    
    // 寫入表頭
    $sheet->fromArray(['ID', '數據'], null, 'A1');
    $row = 2;
    
    foreach ($dataGen as $record) {
        $sheet->fromArray([$record], null, "A{$row}");
        $row++;
        
        // 定期刷新到磁盤 (需自定義 Writer 或分多個文件)
        if ($row % 5000 === 0) {
            // PhpSpreadsheet 無原生流式寫入,大數據建議:
            // 1. 分多個文件 (employee_part_1.xlsx, part_2.xlsx...)
            // 2. 改用 CSV (fputcsv) 內存極低
            // 3. 使用 Box/Spout 流式庫
        }
    }
    
    $writer = new Xlsx($spreadsheet);
    $writer->save($savePath);
    return true;
}

// CSV 大數據導出示例 (推薦)
function exportCsv(Generator $dataGen, string $savePath): bool {
    $fp = fopen($savePath, 'w');
    fputcsv($fp, ['ID', '數據']); // 表頭
    foreach ($dataGen as $record) {
        fputcsv($fp, $record);
    }
    fclose($fp);
    return true;
}
?>

常見格式對比

格式Writer 類適用場景最大行數
XLSX (OOXML)Xlsx現代標準、樣式豐富、公式支援1,048,576
XLS (BIFF)Xls舊系統兼容65,536
CSVCsv大數據、純文本、跨語言、無樣式無限制 (受限於文件系統)
ODSOdsOpenDocument、LibreOffice1,048,576
HTMLHtml網頁預覽、郵件內嵌-
PDFMpdf / Dompdf (需額外庫)打印、歸檔-

內存優化關鍵點

  1. 生成後立即 `$spreadsheet->disconnectWorksheets(); unset($spreadsheet);`
  2. 避免在循環中重複創建 Style 對象,預先定義陣列復用
  3. 超大數據 (>5萬行) 必須用 CSV 或流式庫 (Box/Spout)
  4. 設置 `ini_set('memory_limit', '512M')` 甚至更高
  5. 使用 Generator 逐行讀取數據源,避免一次性載入數組

總結

使用 PhpSpreadsheet 可輕鬆實現 Excel 生成、樣式、圖片插入、保存到指定目錄。關鍵步驟:創建 Spreadsheet → 填充數據/樣式 → 實例化 Writer → `save($path)`。大數據場景請改用 CSV 或流式庫。舊代碼中的 `PHPExcel` 類名需更新為對應的 PhpSpreadsheet 命名空間類。

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