mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-12 19:16:45 +00:00
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataTable;
|
||||
//use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Theme as SpreadsheetTheme;
|
||||
|
||||
require __DIR__ . '/../Header.php';
|
||||
/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
|
||||
$spreadsheet = new Spreadsheet();
|
||||
// same as 33_Chart_create_area, but with 2013+ schemes
|
||||
$spreadsheet->getTheme()->setThemeColorName(SpreadsheetTheme::COLOR_SCHEME_2013_2022_NAME);
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
$sheet2 = $spreadsheet->createSheet();
|
||||
$sheet2->setTitle('Sheet2');
|
||||
$worksheet->fromArray(
|
||||
[
|
||||
['', 2010, 2011, 2012],
|
||||
['Q1', 12, 15, 21],
|
||||
['Q2', 56, 73, 86],
|
||||
['Q3', 52, 61, 69],
|
||||
['Q4', 30, 32, 0],
|
||||
]
|
||||
);
|
||||
|
||||
// Set the Labels for each data series we want to plot
|
||||
// Datatype
|
||||
// Cell reference for data
|
||||
// Format Code
|
||||
// Number of datapoints in series
|
||||
// Data values
|
||||
// Data Marker
|
||||
$dataSeriesLabels = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
|
||||
];
|
||||
// Set the X-Axis Labels
|
||||
// Datatype
|
||||
// Cell reference for data
|
||||
// Format Code
|
||||
// Number of datapoints in series
|
||||
// Data values
|
||||
// Data Marker
|
||||
$xAxisTickValues = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
|
||||
];
|
||||
// Set the Data values for each data series we want to plot
|
||||
// Datatype
|
||||
// Cell reference for data
|
||||
// Format Code
|
||||
// Number of datapoints in series
|
||||
// Data values
|
||||
// Data Marker
|
||||
$dataSeriesValues = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
|
||||
];
|
||||
|
||||
// Build the dataseries
|
||||
$series = new DataSeries(
|
||||
DataSeries::TYPE_AREACHART, // plotType
|
||||
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
|
||||
range(0, count($dataSeriesValues) - 1), // plotOrder
|
||||
$dataSeriesLabels, // plotLabel
|
||||
$xAxisTickValues, // plotCategory
|
||||
$dataSeriesValues // plotValues
|
||||
);
|
||||
|
||||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
$plotArea->setDataTable(new DataTable());
|
||||
// No need for Legend if using DataTable
|
||||
$legend = null; //new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
|
||||
|
||||
$title = new Title('Test %age-Stacked Area Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
||||
// Create the chart
|
||||
$chart = new Chart(
|
||||
'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('A1');
|
||||
$chart->setBottomRightPosition('H18');
|
||||
|
||||
// Add the chart to the worksheet
|
||||
$sheet2->addChart($chart);
|
||||
$spreadsheet->setActiveSheetIndex(1);
|
||||
|
||||
$helper->renderChart($chart, __FILE__);
|
||||
|
||||
// Save Excel 2007 file
|
||||
$helper->write($spreadsheet, __FILE__, ['Xlsx'], true, null, false);
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Chart;
|
||||
|
||||
class DataTable
|
||||
{
|
||||
private bool $showHorizontalBorder = true;
|
||||
|
||||
private bool $showVerticalBorder = true;
|
||||
|
||||
private bool $showOutline = true;
|
||||
|
||||
private bool $showKeys = true;
|
||||
|
||||
public function getShowHorizontalBorder(): bool
|
||||
{
|
||||
return $this->showHorizontalBorder;
|
||||
}
|
||||
|
||||
public function getShowVerticalBorder(): bool
|
||||
{
|
||||
return $this->showVerticalBorder;
|
||||
}
|
||||
|
||||
public function getShowOutline(): bool
|
||||
{
|
||||
return $this->showOutline;
|
||||
}
|
||||
|
||||
public function getShowKeys(): bool
|
||||
{
|
||||
return $this->showKeys;
|
||||
}
|
||||
|
||||
public function setShowHorizontalBorder(bool $showHorizontalBorder): self
|
||||
{
|
||||
$this->showHorizontalBorder = $showHorizontalBorder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setShowVerticalBorder(bool $showVerticalBorder): self
|
||||
{
|
||||
$this->showVerticalBorder = $showVerticalBorder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setShowOutline(bool $showOutline): self
|
||||
{
|
||||
$this->showOutline = $showOutline;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setShowKeys(bool $showKeys): self
|
||||
{
|
||||
$this->showKeys = $showKeys;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,8 @@ class PlotArea
|
||||
*/
|
||||
private array $plotSeries;
|
||||
|
||||
private ?DataTable $dataTable = null;
|
||||
|
||||
/**
|
||||
* Create a new PlotArea.
|
||||
*
|
||||
@@ -195,6 +197,18 @@ class PlotArea
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataTable(DataTable $dataTable): self
|
||||
{
|
||||
$this->dataTable = $dataTable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDataTable(): ?DataTable
|
||||
{
|
||||
return $this->dataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,7 @@ use PhpOffice\PhpSpreadsheet\Chart\AxisText;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataTable;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\GridLines;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
@@ -137,7 +138,7 @@ class Chart
|
||||
|
||||
break;
|
||||
case 'plotArea':
|
||||
$plotAreaLayout = $XaxisLabel = $YaxisLabel = null;
|
||||
$plotAreaLayout = $XaxisLabel = $YaxisLabel = $dataTable = null;
|
||||
$plotSeries = $plotAttributes = [];
|
||||
$catAxRead = false;
|
||||
$plotNoFill = false;
|
||||
@@ -358,6 +359,10 @@ class Chart
|
||||
}
|
||||
$plotAttributes = $this->readChartAttributes($chartDetail);
|
||||
|
||||
break;
|
||||
case 'dTable':
|
||||
$dataTable = $this->readDataTable($chartDetail);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -365,6 +370,11 @@ class Chart
|
||||
$plotAreaLayout = new Layout();
|
||||
}
|
||||
$plotArea = new PlotArea($plotAreaLayout, $plotSeries);
|
||||
if ($dataTable !== null) {
|
||||
$plotArea->setDataTable(
|
||||
$dataTable
|
||||
);
|
||||
}
|
||||
$this->setChartAttributes($plotAreaLayout, $plotAttributes);
|
||||
if ($plotNoFill) {
|
||||
$plotArea->setNoFill(true);
|
||||
@@ -1295,6 +1305,29 @@ class Chart
|
||||
return $plotAttributes;
|
||||
}
|
||||
|
||||
private function readDataTable(SimpleXMLElement $chartDetail): DataTable
|
||||
{
|
||||
$dataTable = new DataTable();
|
||||
$temp = self::getAttributeBoolean($chartDetail->showHorzBorder, 'val');
|
||||
if ($temp !== null) {
|
||||
$dataTable->setShowHorizontalBorder($temp);
|
||||
}
|
||||
$temp = self::getAttributeBoolean($chartDetail->showVertBorder, 'val');
|
||||
if ($temp !== null) {
|
||||
$dataTable->setShowVerticalBorder($temp);
|
||||
}
|
||||
$temp = self::getAttributeBoolean($chartDetail->showOutline, 'val');
|
||||
if ($temp !== null) {
|
||||
$dataTable->setShowOutline($temp);
|
||||
}
|
||||
$temp = self::getAttributeBoolean($chartDetail->showKeys, 'val');
|
||||
if ($temp !== null) {
|
||||
$dataTable->setShowKeys($temp);
|
||||
}
|
||||
|
||||
return $dataTable;
|
||||
}
|
||||
|
||||
/** @param array<mixed> $plotAttributes */
|
||||
private function setChartAttributes(Layout $plotArea, array $plotAttributes): void
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart as SpreadsheetChart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataTable;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
@@ -447,6 +448,10 @@ class Chart extends WriterPart
|
||||
$this->writeValueAxis($objWriter, $xAxisLabel, $chartType, $id2, $id1, $catIsMultiLevelSeries, $xAxis ?? new Axis());
|
||||
} else {
|
||||
$this->writeCategoryAxis($objWriter, $xAxisLabel, $id1, $id2, $catIsMultiLevelSeries, $xAxis ?? new Axis());
|
||||
$dataTable = $plotArea->getDataTable();
|
||||
if ($dataTable !== null) {
|
||||
$this->writeDataTable($objWriter, $dataTable);
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeValueAxis($objWriter, $yAxisLabel, $chartType, $id1, $id2, $valIsMultiLevelSeries, $yAxis ?? new Axis());
|
||||
@@ -485,6 +490,29 @@ class Chart extends WriterPart
|
||||
$objWriter->endElement(); // c:plotArea
|
||||
}
|
||||
|
||||
private function writeDataTable(XMLWriter $objWriter, DataTable $dataTable): void
|
||||
{
|
||||
$objWriter->startElement('c:dTable');
|
||||
|
||||
$objWriter->startElement('c:showHorzBorder');
|
||||
$objWriter->writeAttribute('val', $dataTable->getShowHorizontalBorder() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('c:showVertBorder');
|
||||
$objWriter->writeAttribute('val', $dataTable->getShowVerticalBorder() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('c:showOutline');
|
||||
$objWriter->writeAttribute('val', $dataTable->getShowOutline() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('c:showKeys');
|
||||
$objWriter->writeAttribute('val', $dataTable->getShowKeys() ? '1' : '0');
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement(); // c:dTable
|
||||
}
|
||||
|
||||
private function writeDataLabelsBool(XMLWriter $objWriter, string $name, ?bool $value): void
|
||||
{
|
||||
if ($value !== null) {
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataTable;
|
||||
//use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Theme as SpreadsheetTheme;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
|
||||
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||
|
||||
class DataTableTest extends AbstractFunctional
|
||||
{
|
||||
public function testSetDataTable(): void
|
||||
{
|
||||
$dataTable = new DataTable();
|
||||
self::assertTrue($dataTable->getShowHorizontalBorder());
|
||||
self::assertTrue($dataTable->getShowVerticalBorder());
|
||||
self::assertTrue($dataTable->getShowOutline());
|
||||
self::assertTrue($dataTable->getShowKeys());
|
||||
$dataTable->setShowHorizontalBorder(false)
|
||||
->setShowVerticalBorder(false)
|
||||
->setShowOutline(false)
|
||||
->setShowKeys(false);
|
||||
self::assertFalse($dataTable->getShowHorizontalBorder());
|
||||
self::assertFalse($dataTable->getShowVerticalBorder());
|
||||
self::assertFalse($dataTable->getShowOutline());
|
||||
self::assertFalse($dataTable->getShowKeys());
|
||||
}
|
||||
|
||||
private function readCharts(XlsxReader $reader): void
|
||||
{
|
||||
$reader->setIncludeCharts(true);
|
||||
}
|
||||
|
||||
private function writeCharts(XlsxWriter $writer): void
|
||||
{
|
||||
$writer->setIncludeCharts(true);
|
||||
}
|
||||
|
||||
public function testCopyDataTable(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
// based on 33_Chart_create_area3.
|
||||
$spreadsheet->getTheme()
|
||||
->setThemeColorName(
|
||||
SpreadsheetTheme::COLOR_SCHEME_2013_2022_NAME
|
||||
);
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
$sheet2 = $spreadsheet->createSheet();
|
||||
$sheet2->setTitle('Sheet2');
|
||||
$worksheet->fromArray(
|
||||
[
|
||||
['', 2010, 2011, 2012],
|
||||
['Q1', 12, 15, 21],
|
||||
['Q2', 56, 73, 86],
|
||||
['Q3', 52, 61, 69],
|
||||
['Q4', 30, 32, 0],
|
||||
]
|
||||
);
|
||||
|
||||
// Set the Labels for each data series we want to plot
|
||||
// Datatype
|
||||
// Cell reference for data
|
||||
// Format Code
|
||||
// Number of datapoints in series
|
||||
// Data values
|
||||
// Data Marker
|
||||
$dataSeriesLabels = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
|
||||
];
|
||||
// Set the X-Axis Labels
|
||||
// Datatype
|
||||
// Cell reference for data
|
||||
// Format Code
|
||||
// Number of datapoints in series
|
||||
// Data values
|
||||
// Data Marker
|
||||
$xAxisTickValues = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
|
||||
];
|
||||
// Set the Data values for each data series we want to plot
|
||||
// Datatype
|
||||
// Cell reference for data
|
||||
// Format Code
|
||||
// Number of datapoints in series
|
||||
// Data values
|
||||
// Data Marker
|
||||
$dataSeriesValues = [
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
|
||||
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
|
||||
];
|
||||
|
||||
// Build the dataseries
|
||||
$series = new DataSeries(
|
||||
DataSeries::TYPE_AREACHART, // plotType
|
||||
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
|
||||
range(0, count($dataSeriesValues) - 1), // plotOrder
|
||||
$dataSeriesLabels, // plotLabel
|
||||
$xAxisTickValues, // plotCategory
|
||||
$dataSeriesValues // plotValues
|
||||
);
|
||||
|
||||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
$plotArea->setDataTable(new DataTable());
|
||||
// No need for Legend if using DataTable
|
||||
$legend = null; //new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
|
||||
|
||||
$title = new Title('Test %age-Stacked Area Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
||||
// Create the chart
|
||||
$chart = new Chart(
|
||||
'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('A1');
|
||||
$chart->setBottomRightPosition('H18');
|
||||
|
||||
// Add the chart to the worksheet
|
||||
$sheet2->addChart($chart);
|
||||
$spreadsheet->setActiveSheetIndex(1);
|
||||
|
||||
// Save Excel 2007 file
|
||||
/** @var callable */
|
||||
$callableReader = [$this, 'readCharts'];
|
||||
/** @var callable */
|
||||
$callableWriter = [$this, 'writeCharts'];
|
||||
$reloadedSpreadsheet = $this->writeAndReload(
|
||||
$spreadsheet,
|
||||
'Xlsx',
|
||||
$this->readCharts(...),
|
||||
$this->writeCharts(...)
|
||||
);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
|
||||
$sheet = $reloadedSpreadsheet->getActiveSheet();
|
||||
$charts2 = $sheet->getChartCollection();
|
||||
self::assertCount(1, $charts2);
|
||||
$chart2 = $charts2[0];
|
||||
self::assertNotNull($chart2);
|
||||
$plotArea = $chart2->getPlotArea();
|
||||
self::assertNotNull($plotArea);
|
||||
$dtab = $plotArea->getDataTable();
|
||||
self::assertNotNull($dtab);
|
||||
self::assertTrue($dtab->getShowHorizontalBorder());
|
||||
self::assertTrue($dtab->getShowVerticalBorder());
|
||||
self::assertTrue($dtab->getShowOutline());
|
||||
self::assertTrue($dtab->getShowKeys());
|
||||
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user