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

PHPExcel (PhpSpreadsheet) 圖表繪製入門:從資料到專業圖表完整教學

     編輯:PHP 相關知識

重要提示:PHPExcel 已停止維護

PHPExcel 專案已於 2017 年歸檔,不再更新。 官方繼任者為 PhpSpreadsheet (同一作者團隊),支援 PHP 7.1+、嚴格型別、PSR-4、更豐富的圖表 API。本文以 **PhpSpreadsheet** 為基礎講解,代碼完全相容最新版。

composer require phpoffice/phpspreadsheet

核心架構:Worksheet → DataSeries → PlotArea → Chart

PhpSpreadsheet 圖表物件層級:

  1. Worksheet:儲存資料儲存格 (A1:B10)。
  2. DataSeriesValues:封裝資料範圍 (類別軸標籤、數值資料)。
  3. DataSeries:定義圖表類型 (線圖、長條圖、圓餅圖...)、資料系列集合、繪圖順序。
  4. PlotArea:包含一或多個 DataSeries、座標軸、圖例、標題等佈局設定。
  5. Chart:最上層容器,設定圖表標題、位置、大小、Legend,並掛載 PlotArea。

步驟 1:準備資料

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

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

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

// 寫入標題列
$sheet->fromArray([
    ['月份', '產品A', '產品B', '產品C'],
    ['1月', 1200, 950, 800],
    ['2月', 1350, 1020, 850],
    ['3月', 1480, 1100, 920],
    ['4月', 1550, 1180, 980],
    ['5月', 1620, 1250, 1050],
    ['6月', 1700, 1300, 1100],
], null, 'A1'); // null = 不覆蓋現有格式,從 A1 開始寫入
?>

步驟 2:建立 DataSeries (以群組長條圖為例)

<?php
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;

// 類別軸 (X軸) 標籤:A2:A7 (月份)
$categories = new DataSeriesValues(
    DataSeriesValues::DATASERIES_TYPE_STRING,
    '工作表1!$A$2:$A$7', // 絕對參考
    null, 6 // 資料點數量
);

// 系列 1:產品A (B2:B7)
$seriesA = new DataSeriesValues(
    DataSeriesValues::DATASERIES_TYPE_NUMBER,
    '工作表1!$B$2:$B$7',
    null, 6
);
// 系列 2:產品B (C2:C7)
$seriesB = new DataSeriesValues(
    DataSeriesValues::DATASERIES_TYPE_NUMBER,
    '工作表1!$C$2:$C$7',
    null, 6
);
// 系列 3:產品C (D2:D7)
$seriesC = new DataSeriesValues(
    DataSeriesValues::DATASERIES_TYPE_NUMBER,
    '工作表1!$D$2:$D$7',
    null, 6
);

// 建立 DataSeries:群組長條圖 (BAR_CLUSTERED)
$dataSeries = new DataSeries(
    DataSeries::TYPE_BARCHART,        // 圖表類型常數
    DataSeries::GROUPING_CLUSTERED,   // 群組模式:簇狀/堆疊/百分比堆疊
    range(0, 2),                      // 系列索引 (0,1,2 對應下方三個系列)
    [],                               // 系列標籤 (可選,留空自動取標題列)
    [$categories],                    // 類別軸標籤陣列
    [$seriesA, $seriesB, $seriesC]    // 數值系列陣列
);

// 設定系列標題 (對應 B1, C1, D1)
$dataSeries->setPlotDirection(DataSeries::DIRECTION_COL); // 垂直長條 (預設水平)
$dataSeries->setPlotLabel(['工作表1!$B$1', '工作表1!$C$1', '工作表1!$D$1']);
?>

步驟 3:建立 PlotArea 與 Chart

<?php
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Chart\Layout;

// PlotArea:包含座標軸、圖例、標題、DataSeries
$plotArea = new PlotArea(
    null, // Layout (佈局,null 使用預設)
    [$dataSeries] // DataSeries 陣列
);

// 圖表標題
$title = new Title('2024 上半年產品銷售趨勢');

// 圖例位置
$legend = new Legend(Legend::POSITION_RIGHT, null, false);

// 建立 Chart 物件
$chart = new Chart(
    'chart1',           // 內部名稱
    $title,             // Title 物件
    $legend,            // Legend 物件
    $plotArea,          // PlotArea 物件
    true,               // plotVisibleOnly (只繪製可見儲存格)
    0,                  // displayBlanksAs (0=gap, 1=zero, 2=span)
    null,               // xAxisLabel
    null,               // yAxisLabel
    new Layout()        // 整體佈局
);

// 設定圖表位置與大小 (儲存格座標)
$chart->setTopLeftPosition('F2');   // 左上角錨點
$chart->setBottomRightPosition('N18'); // 右下角錨點 (寬約 9 欄 x 16 列)

// 加入工作表
$sheet->addChart($chart);
?>

步驟 4:輸出 Excel 檔案

<?php
$writer = new Xlsx($spreadsheet);
$writer->setIncludeCharts(true); // 關鍵:必須啟用,否則圖表不會寫入
$writer->save('sales_chart.xlsx');
echo "檔案已產生:sales_chart.xlsx\n";
?>

常見圖表類型常數對照表

圖表類型DataSeries::TYPE_* 常數適用場景
群組長條圖TYPE_BARCHART + GROUPING_CLUSTERED多系列分類比較
堆疊長條圖TYPE_BARCHART + GROUPING_STACKED部分佔整體比例
百分比堆疊長條圖TYPE_BARCHART + GROUPING_PERCENT_STACKED各系列佔比隨時間變化
折線圖TYPE_LINECHART + GROUPING_STANDARD趨勢、時間序列
平滑折線圖TYPE_LINECHART + GROUPING_SMOOTH平滑趨勢曲線
圓餅圖TYPE_PIECHART單系列佔比
環狀圖TYPE_DOUGHNUTCHART多系列佔比 (環狀)
散佈圖TYPE_SCATTERCHART兩數值變數相關性
面積圖TYPE_AREACHART累積總量趨勢
雷達圖TYPE_RADARCHART多維度指標對比
混合圖表PlotArea 含多個不同 TYPE 的 DataSeries雙軸、長條+折線組合

進階:雙軸混合圖表 (長條圖 + 折線圖)

<?php
// 系列 1:長條圖 (銷售額) - 主軸
$barSeries = new DataSeries(
    DataSeries::TYPE_BARCHART,
    DataSeries::GROUPING_CLUSTERED,
    [0],
    [],
    [$categories],
    [$seriesSales]
);
$barSeries->setPlotLabel(['工作表1!$B$1']);

// 系列 2:折線圖 (成長率) - 次軸
$lineSeries = new DataSeries(
    DataSeries::TYPE_LINECHART,
    DataSeries::GROUPING_STANDARD,
    [1],
    [],
    [$categories],
    [$seriesGrowth]
);
$lineSeries->setPlotLabel(['工作表1!$C$1']);

// PlotArea 同時包含兩個 DataSeries
$plotArea = new PlotArea(null, [$barSeries, $lineSeries]);

// 次軸設定需在 Chart/PlotArea 層級處理 (PhpSpreadsheet 1.20+ 支援)
$chart = new Chart('combo1', $title, $legend, $plotArea, true, 0, null, null, new Layout());
// 註:雙軸完整支援需較新版本,若不支援可考慮輸出後用 Excel 手動調整或改用 Python openpyxl
?>

效能與記憶體優化

  • 大量資料:使用 Cell::setValueBinder(new AdvancedValueBinder()) 加速寫入;或分批寫入、關閉未需的快取。
  • 記憶體:預設儲存所有儲存格於記憶體。超過 10 萬列建議啟用 Cache\Serializer 或 Cache\Redis:
    Settings::setCacheStorage(new \PhpOffice\PhpSpreadsheet\Cache\Redis($redisClient));
  • 圖表渲染:PhpSpreadsheet 僅產生圖表 XML 定義,**不負責繪製圖像**。Excel/ LibreOffice 開啟時會即時渲染。若需伺服器端生成圖片 (PNG/JPG),需搭配 PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph (需安裝 JpGraph 庫) 或轉換為 PDF 後用 ImageMagick 截圖。

常見問題排除

現象原因與解決
輸出檔案無圖表未呼叫 $writer->setIncludeCharts(true);或圖表錨點位置超出工作表範圍
Excel 開啟提示「圖表資料遺失」DataSeries 參考範圍錯誤 (工作表名稱含空格需單引號、絕對參考 $)、系列索引不匹配
類別軸顯示數字而非標籤DataSeriesValues 類型應為 DATASERIES_TYPE_STRING,且範圍正確包含標題列
中文亂碼確保 PHP 檔案 UTF-8 編碼、資料庫連線 charset=utf8mb4、PhpSpreadsheet 內部自動處理 UTF-8
記憶體耗盡啟用快取存儲、分批處理、增加 memory_limit

結語

PhpSpreadsheet 提供完整、物件導向的圖表 API,涵蓋從簡單長條圖到複雜混合圖表的需求。掌握「資料範圍 → DataSeriesValues → DataSeries → PlotArea → Chart → Worksheet → Writer」這條建構鏈,並善用 setIncludeCharts(true)、正確的錨點定位、系列索引對應,即可在 PHP 中程式化產出專業級 Excel 圖表報表。建議搭配 官方文檔 Charts 章節 深入探索進階功能。

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