PHP PhpSpreadsheet: Not able to put multiple sets of data series to the same chart plot area

42 Views Asked by At

Using PhpSpreadsheet I do not manage to combine multiple sets of data series inside the same chart. Here is my code:

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Layout;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\Chart as ExcelChart;

$spreadsheet = new Spreadsheet();
$layout = new Layout();
$layout->setShowVal(true);
$layout->setShowPercent(true);
$layout->setShowLegendKey(true);
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->setSelectedCell('A26');

// First bunch, it is being displayed in cells correctly:
$worksheet->fromArray(
   [
      ['', 2010, 2011, 2012],
      ['Q1', 12, 15, 21],
      ['Q2', 56, 73, 86],
      ['Q3', 52, 61, 69],
      ['Q4', 30, 32, 12],
   ],
   NULL,
   'A26'
);
// Second bunch, it is being displayed in cells correctly too:
$worksheet->fromArray(
   [
      ['', '2010', '2011', '2012'],
      ['Q1', 18, 154, 29],
      ['Q2', 76, 33, 16],
      ['Q3', 59, 89, 103],
      ['Q4', 51, 98, 45],
   ],
   NULL,
   'A35'
);  
$dataSeriesLabels = [
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$26', null, 1), // 2010
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$26', null, 1), // 2011
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$26', null, 1), // 2012
];

$xAxisTickValues = [
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$27:$A$30', null, 4), // Q1 to Q4
];

$dataSeriesValues = [
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$27:$B$30', null, 4),
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$27:$C$30', null, 4),
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$27:$D$30', null, 4),
];

$series = new DataSeries(
   DataSeries::TYPE_BARCHART, // plotType
   DataSeries::GROUPING_CLUSTERED, // plotGrouping
   range(0, count($dataSeriesValues) - 1), // plotOrder
   $dataSeriesLabels, // plotLabel
   $xAxisTickValues, // plotCategory
   $dataSeriesValues        // plotValues
);
$series->setPlotDirection(DataSeries::DIRECTION_COL);

// Second series values:
$dataSeriesValues2 = [
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$36:$B$39', null, 4),
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$36:$C$39', null, 4),
   new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$36:$D$39', null, 4),
];

$series2 = new DataSeries(
   DataSeries::TYPE_BARCHART,
   DataSeries::GROUPING_CLUSTERED,
   range(0, count($dataSeriesValues2) - 1),
   $dataSeriesLabels, // Using the same labels as the first series
   $xAxisTickValues,  // Using the same tick values as the first series
   $dataSeriesValues2
);
$series2->setPlotDirection(DataSeries::DIRECTION_COL);

// Combine $series and $series2 in same plot area:
$plotArea = new PlotArea($layout, [$series, $series2]);

$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
$title = new Title('Test Bar Chart');
$yAxisLabel = new Title('Value ($k)');

// Create the chart
$chart = new ExcelChart(
   'chart1', // name
   $title, // title
   $legend, // legend
   $plotArea, // plotArea
   true, // plotVisibleOnly
   DataSeries::EMPTY_AS_GAP, // displayBlanksAs
   null, // xAxisLabel
   $yAxisLabel  // yAxisLabel
);

// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A6');
$chart->setBottomRightPosition('K22');
// Add the chart to the worksheet
$worksheet->addChart($chart);

The results is Excel reports an error in the chart (drawing) and displays only the data.

If I remove one of the series from here:

$plotArea = new PlotArea($layout, [$series, $series2]);

..and pass only one like this:

$plotArea = new PlotArea($layout, [$series]);

Then chart is being created as expected. And if I pass only the second one then it creates a chart again:

$plotArea = new PlotArea($layout, [$series2]);

But the problem is I need to combine multiple sets of data series in a single chart dynamically.

1

There are 1 best solutions below

0
Vlado On

So far I resolved the issue by changing the type of the second DataSeries to line:

$series2 = new DataSeries(
    DataSeries::TYPE_LINECHART,  // Here          
    null,
    range(0, count($dataSeriesValues2) - 1),
    $dataSeriesLabels2,
    $xAxisTickValues2,
    $dataSeriesValues2
);

Now chart is drawn. Still would be good to find a way to keep same type.