忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

PHP PhpSpreadsheet ワークシート上にチャート(グラフ)を作成する方法について(PhpSpreadsheet\Chart)


今回は PhpSpreadsheet で行う「チャート」の作成方法について説明したいと思います。




■簡単なチャートを作成する(1個の折れ線グラフ)

簡単なチャートを作成する例として、1個の商品の各年の売り上げの推移を折れ線グラフとして作成してみます。
(テストデータとしては以下の様なデータです)


PhpSpreadsheet\Chart を使ったチャートの作成手順は以下の様になります。

  • PhpSpreadsheet\Chart\DataSeries クラスでチャート・データシリーズの生成。
    (この前に PhpSpreadsheet\Chart\DataSeriesクラスで「描画データ」「X軸ラベル」等を生成し、指定する)
  • PhpSpreadsheet\Chart\PlotAreaクラスでプロットエリアにチャート・データシリーズを設定し、生成。
  • プロットエリアを指定し PhpSpreadsheet\Chartクラスでチャート生成。
  • ワークシートにチャート追加。
  • ワークブック登録クラス PhpSpreadsheet\Writer\IWritersetIncludeCharts() メソッドでチャートを含むことを設定。

この手順に従って、以下の様なソースになります。

<?php
// ライブラリ読込
require '../vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\IOFactory;

// Spreadsheetオブジェクト生成
$objSpreadsheet = new Spreadsheet();
// ワークシートオブジェクト取得
$objWorksheet = $objSpreadsheet->getActiveSheet();
//  チャート用テストデータ生成
$objWorksheet->fromArray(
	array(
		array('売上' , 2016, 2017, 2018, 2019, 2020),
		array('商品1',   12,   15,   21,   18,   20),
	)
);

//  X軸ラベルの指定
$arrCategorysDataSeries = array(
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1:$F$1', NULL, 5),	//	2016 to 2020
);
//  描画データの指定
$arrDataSeriesValues = array(
	new PhpSpreadsheet\Chart_DataSeriesValues('Number', 'Worksheet!$B$2:$F$2', NULL, 5),
);
//	チャート・データシリーズの生成
$objSeries = new PhpSpreadsheet\Chart_DataSeries(
	DataSeries::TYPE_LINECHART,                     // plotType
    NULL,                                           // plotGrouping(DataSeries::GROUPING_STANDARD)
	range(0, count($arrDataSeriesValues) - 1),      // plotOrder
	array(),                                           // plotLabel
	$arrCategorysDataSeries,                        // plotCategory
	$arrDataSeriesValues                            // plotValues
);

//	プロットエリアにチャート・データシリーズに設定
$objPlotArea = new PlotArea(NULL, array($objSeries));

//  チャート・タイトル生成
$objTitle = new Title('売上データ');
//	チャート生成
$objChart = new Chart(
	'chart1',       // name
	$objTitle,      // title
	NULL,           // legend
	$objPlotArea,   // plotArea
	TRUE,           // plotVisibleOnly
	0,              // displayBlanksAs
	NULL,           // xAxisLabel
	NULL		    // yAxisLabel
);
//	ワークシート内のチャート位置設定
$objChart->setTopLeftPosition('A6');        // 左上
$objChart->setBottomRightPosition('G18');   // 右下

//	ワークシートにチャート追加
$objWorksheet->addChart($objChart);

// [test-g-1.xlsx]:Excel2007形式で保存する
$objWriter = IOFactory::createWriter($objSpreadsheet, 'Xlsx');
$objWriter->setIncludeCharts(TRUE);
$objWriter->save('test-g-1.xlsx');
exit();
?>

このプログラムで必須のクラスの説明を以下に記します。

PhpSpreadsheet\Chart\DataSeries のクラス生成の引数は以下の様に定義されています。

PhpSpreadsheet\Chart_DataSeries __construct(
    [ $plotType = null        ],    // チャートタイプの定数
    [ $plotGrouping = null    ],    // グルーピング定数
    [ $plotOrder = array()	  ],   // 描画データの指標の配列 array(0, 1, 2 ...)
    [ $plotLabel = array()	  ],   // ラベル用配列     (DataSeriesValues クラスの配列)
    [ $plotCategory = array() ],   // X軸ラベル用配列  (DataSeriesValues クラスの配列)
    [ $plotValues = array()	  ],   // 描画データ用配列 (DataSeriesValues クラスの配列)
    [ $plotDirection = null   ],    // 描画方向定数 (内部的デフォルト:DIRECTION_COL)
    [ $smoothLine = null      ],    // スムージング指定(折れ線グラフまたは散布図)
    [ $plotStyle = null       ]     // 描画スタイル定数
)

//  各定数の定義は以下の通り

//	チャートタイプ定数の定義
const TYPE_BARCHART        = 'barChart';
const TYPE_BARCHART_3D     = 'bar3DChart';
const TYPE_LINECHART       = 'lineChart';
const TYPE_LINECHART_3D    = 'line3DChart';
const TYPE_AREACHART       = 'areaChart';
const TYPE_AREACHART_3D    = 'area3DChart';
const TYPE_PIECHART        = 'pieChart';
const TYPE_PIECHART_3D     = 'pie3DChart';
const TYPE_DOUGHTNUTCHART  = 'doughnutChart';
const TYPE_DONUTCHART      = 'doughnutChart';
const TYPE_SCATTERCHART    = 'scatterChart';
const TYPE_SURFACECHART    = 'surfaceChart';
const TYPE_SURFACECHART_3D = 'surface3DChart';
const TYPE_RADARCHART      = 'radarChart';
const TYPE_BUBBLECHART     = 'bubbleChart';
const TYPE_STOCKCHART      = 'stockChart';
const TYPE_CANDLECHART     = 'stockChart';

//	グルーピング定数の定義
const GROUPING_CLUSTERED       = 'clustered';
const GROUPING_STACKED         = 'stacked';
const GROUPING_PERCENT_STACKED = 'percentStacked';
const GROUPING_STANDARD        = 'standard';

//	描画方向定数の定義
const DIRECTION_BAR        = 'bar';
const DIRECTION_HORIZONTAL = 'bar';
const DIRECTION_COL        = 'col';
const DIRECTION_COLUMN     = 'col';
const DIRECTION_VERTICAL   = 'col';

//	描画スタイル定数の定義
const STYLE_LINEMARKER   = 'lineMarker';
const STYLE_SMOOTHMARKER = 'smoothMarker';
const STYLE_MARKER       = 'marker';
const STYLE_FILLED       = 'filled';


PhpSpreadsheet\Chart\DataSeries のクラス生成の引数の中で重要な 「ラベル」「X軸ラベル」「描画データ」の配列の要素のクラスである PhpSpreadsheet\Chart\DataSeriesValues のクラス生成の引数は以下の様に定義されています。

PhpSpreadsheet\DataSeriesValues __construct(
	$dataType = self::DATASERIES_TYPE_NUMBER, 	// データ型の定数
	$dataSource = null, 	// シリーズ(系列)データの位置指定
	$formatCode = null, 	// フォーマットコード
	$pointCount = 0, 		// シリーズ(系列)データの個数
	$dataValues = array(), // シリーズ(系列)データを直接指定
	$marker = null,			// ポイントマーカーの指定(文字列)
	$fillColor = null		// 
)

//	データ型定数の定義
const DATASERIES_TYPE_STRING    = 'String';
const DATASERIES_TYPE_NUMBER    = 'Number';

シリーズ(系列)データの位置指定はエクセルでのセル範囲(絶対位置:列と行の指定の前に「$」を指定)で指定します。

ポイントマーカーの指定はマーカーの種類を文字列で指定します。以下はマーカーを指定した例を示します。

$arrDataSeriesValues = array(
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"triangle"),//三角形
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"circle"),  //円形
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"diamond"), //ひし形
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"square"),  //四角形
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"star"),    //アスタリスク
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"plus"),    //十字
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"none"),    //マーカ無
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"dash"),    //長い横棒
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"dot"),     //短い横棒
 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER,'Worksheet!$B$2:$F$2',NULL,5,array(),"x"),       //×印
);


出力されたエクセルファイルを見てみると以下の様になります。




■複数の折れ線グラフをチャートに表示

複数の折れ線グラフをチャートに表示するには上のデータに「商品2」「商品3」を追加します。
追加されたデータを描画データの指定で PhpSpreadsheet\Chart\DataSeriesValues クラス生成を追加します。

<?php
// ライブラリ読込
require '../vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\IOFactory;

// Spreadsheetオブジェクト生成
$objSpreadsheet = new Spreadsheet();
// ワークシートオブジェクト取得
$objWorksheet = $objSpreadsheet->getActiveSheet();
//  チャート用テストデータ生成
$objWorksheet->fromArray(
	array(
		array('売上' , 2016, 2017, 2018, 2019, 2020),
		array('商品1',   12,   15,   21,   18,   20),
		array('商品2',   18,   19,   23,   14,   21),   //追加
		array('商品3',   15,   10,   20,   12,   23),   //追加
	)
);

//  X軸ラベルの指定
$arrCategorysDataSeries = array(
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1:$F$1', NULL, 5),	//	2016 to 2020
);
//  描画データの指定
$arrDataSeriesValues = array(
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$F$2', NULL, 5),  //商品1
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$3:$F$3', NULL, 5),  //商品2 追加
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$4:$F$4', NULL, 5),  //商品3 追加
);
//	チャート・データシリーズの生成
$objSeries = new DataSeries(
	DataSeries::TYPE_LINECHART,                     // plotType
    NULL,                                           // plotGrouping(DataSeries::GROUPING_STANDARD)
	range(0, count($arrDataSeriesValues) - 1),      // plotOrder
	array(),                                        // plotLabel
	$arrCategorysDataSeries,                        // plotCategory
	$arrDataSeriesValues                            // plotValues
);

//	プロットエリアにチャート・データシリーズに設定
$objPlotArea = new PlotArea(NULL, array($objSeries));

//  チャート・タイトル生成
$objTitle = new Title('売上データ');
//	チャート生成
$objChart = new Chart(
	'chart1',       // name
	$objTitle,      // title
	NULL,           // legend
	$objPlotArea,   // plotArea
	TRUE,           // plotVisibleOnly
	0,              // displayBlanksAs
	NULL,           // xAxisLabel
	NULL		    // yAxisLabel
);
//	ワークシート内のチャート位置設定
$objChart->setTopLeftPosition('A6');        // 左上
$objChart->setBottomRightPosition('G18');   // 右下

//	ワークシートにチャート追加
$objWorksheet->addChart($objChart);

// [test-g-1-2.xlsx]:Excel2007形式で保存する
$objWriter = IOFactory::createWriter($objSpreadsheet, 'Xlsx');
$objWriter->setIncludeCharts(TRUE);
$objWriter->save('test-g-1-2.xlsx');
exit();
?>

出力されたエクセルファイルを見てみると以下の様になります。




■複数の折れ線グラフをチャートに表示2(描画データの縦横の入替)

上記の例のデータの縦横を入れ替えた場合、つまり売り上げの時間軸が縦方向となり、商品毎の年度ごとの売り上げを1個の列に並べます。
チャート用テストデータ生成の fromArray() では縦横を入れ替えたデータに変更します。

X軸ラベルの指定は、年度の数値なので A列2行目6行目PhpSpreadsheet\Chart\DataSeriesValues への範囲設定は Worksheet!$A$2:$A$6 となります。

また、描画データの指定は、各商品毎の数値なので「商品1」であれば B列2行目6行目PhpSpreadsheet\Chart\DataSeriesValues への範囲設定は Worksheet!$B$2:$B$6 となります。

尚、各グラフの線が何を指しているのかを表示する為に、系列ラベルの指定を追加で行います。 描画データの指定と同様に、「商品1」「商品2」「商品3」の文字列をそれぞれ PhpSpreadsheet\Chart\DataSeriesValues クラスで生成し、配列に設定します。 この配列を PhpSpreadsheet\Chart\DataSeries クラスで生成時に plotLabel の引数として指定します。
この系列ラベルをチャート上に表示させるには、 レジェンドクラス PhpSpreadsheet\Chart\Legend で生成したオブジェクトを PhpSpreadsheet\Chart 生成時に指定する必要があります。
よってソースは以下の様になります。

<?php
// ライブラリ読込
require '../vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\IOFactory;

// Spreadsheetオブジェクト生成
$objSpreadsheet = new Spreadsheet();
// ワークシートオブジェクト取得
$objWorksheet = $objSpreadsheet->getActiveSheet();
//  チャート用テストデータ生成
$objWorksheet->fromArray(
	array(
		array('売上', '商品1', '商品2', '商品3'),
		array(  2016,      12,      18,      15),
		array(  2017,      15,      19,      10),
		array(  2018,      21,      23,      20),
		array(  2019,      18,      14,      12),
		array(  2020,      20,      21,      23),
	)
);

//  系列ラベルの指定
$arrDataSeriesLabels = array(
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', NULL, 1),       //商品1
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', NULL, 1),       //商品2
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', NULL, 1),       //商品3
);
//  X軸ラベルの指定
$arrCategorysDataSeries = array(
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$6', NULL, 5),	//2016 to 2020
);
//  描画データの指定
$arrDataSeriesValues = array(
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$6', NULL, 5),  //商品1
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$6', NULL, 5),  //商品2
	new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$6', NULL, 5),  //商品3
);
//	チャート・データシリーズの生成
$objSeries = new DataSeries(
	DataSeries::TYPE_LINECHART,                     // plotType
    NULL,                                           // plotGrouping(DataSeries::GROUPING_STANDARD)
	range(0, count($arrDataSeriesValues) - 1),      // plotOrder
	$arrDataSeriesLabels,                           // plotLabel
	$arrCategorysDataSeries,                        // plotCategory
	$arrDataSeriesValues                            // plotValues
);

//	プロットエリアにチャート・データシリーズに設定
$objPlotArea = new PlotArea(NULL, array($objSeries));
//	レジェンド生成(各折れ線の説明を行う)
$objLegend = new Legend(Legend::POSITION_TOPRIGHT, NULL, false);
//  チャート・タイトル生成
$objTitle = new Title('売上データ');
//	チャート生成
$objChart = new Chart(
	'chart1',       // name
	$objTitle,      // title
	$objLegend,     // legend
	$objPlotArea,   // plotArea
	TRUE,           // plotVisibleOnly
	0,              // displayBlanksAs
	NULL,           // xAxisLabel
	NULL		    // yAxisLabel
);
//	ワークシート内のチャート位置設定
$objChart->setTopLeftPosition('A8');        // 左上
$objChart->setBottomRightPosition('G20');   // 右下

//	ワークシートにチャート追加
$objWorksheet->addChart($objChart);

// [test-g-1-3.xlsx]:Excel2007形式で保存する
$objWriter = IOFactory::createWriter($objSpreadsheet, 'Xlsx');
$objWriter->setIncludeCharts(TRUE);
$objWriter->save('test-g-1-3.xlsx');
exit();
?>

出力されたエクセルファイルを見てみると以下の様になります。
データの並びは縦横が違いますが、作成されたチャートは、1個前のチャートと同じものが作成されます。












PR

コメント

コメントを書く