diff --git a/samples/Chart/33_Chart_create_scatter2.php b/samples/Chart/33_Chart_create_scatter2.php index cbc3ec1ac6..700ee37d17 100644 --- a/samples/Chart/33_Chart_create_scatter2.php +++ b/samples/Chart/33_Chart_create_scatter2.php @@ -1,6 +1,7 @@ setAxisNumberProperties(Properties::FORMAT_CODE_DATE ); $xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601, true); -$xAxis->setAxisOption('textRotation', '45'); +//$xAxis->setAxisOption('textRotation', '45'); +$xAxisText = new AxisText(); +$xAxisText->setRotation(45)->getFillColorObject()->setValue('00FF00')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); +$xAxis->setAxisText($xAxisText); $yAxis = new ChartAxis(); $yAxis->setLineStyleProperties( @@ -135,6 +139,9 @@ Properties::LINE_STYLE_JOIN_BEVEL ); $yAxis->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB); +$yAxisText = new AxisText(); +$yAxisText->setGlowProperties(20.0, 'accent1', 20, ChartColor::EXCEL_COLOR_TYPE_SCHEME); +$yAxis->setAxisText($yAxisText); // Build the dataseries $series = new DataSeries( diff --git a/samples/Chart/33_Chart_create_stock.php b/samples/Chart/33_Chart_create_stock.php index 34fa3a6cd2..386e360485 100644 --- a/samples/Chart/33_Chart_create_stock.php +++ b/samples/Chart/33_Chart_create_stock.php @@ -1,6 +1,8 @@ getBorderColor()->setColorProperties('ffc000'); +$legend->getFillColor()->setColorProperties('cccccc'); +$legendText = new AxisText(); +$legendText->getFillColorObject()->setValue('008080')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); +$legendText->setShadowProperties(1); +$legend->setLegendText($legendText); $title = new Title('Test Stock Chart'); $xAxisLabel = new Title('Counts'); @@ -103,6 +111,7 @@ // Add the chart to the worksheet $worksheet->addChart($chart); +$worksheet->setSelectedCells('G2'); // Save Excel 2007 file $filename = $helper->getFilename(__FILE__); diff --git a/src/PhpSpreadsheet/Chart/Axis.php b/src/PhpSpreadsheet/Chart/Axis.php index ade7b99d8c..91ff032a87 100644 --- a/src/PhpSpreadsheet/Chart/Axis.php +++ b/src/PhpSpreadsheet/Chart/Axis.php @@ -52,6 +52,9 @@ public function __construct() /** @var string */ private $axisType = ''; + /** @var ?AxisText */ + private $axisText; + /** * Axis Options. * @@ -183,6 +186,14 @@ public function setAxisOptionsProperties( */ public function getAxisOptionsProperty($property) { + if ($property === 'textRotation') { + if ($this->axisText !== null) { + if ($this->axisText->getRotation() !== null) { + return (string) $this->axisText->getRotation(); + } + } + } + return $this->axisOptions[$property]; } @@ -295,4 +306,16 @@ public function setMinorGridlines(?GridLines $gridlines): self return $this; } + + public function getAxisText(): ?AxisText + { + return $this->axisText; + } + + public function setAxisText(?AxisText $axisText): self + { + $this->axisText = $axisText; + + return $this; + } } diff --git a/src/PhpSpreadsheet/Chart/AxisText.php b/src/PhpSpreadsheet/Chart/AxisText.php new file mode 100644 index 0000000000..db8191cc8a --- /dev/null +++ b/src/PhpSpreadsheet/Chart/AxisText.php @@ -0,0 +1,35 @@ +fillColor = new ChartColor(); + } + + public function setRotation(?int $rotation): self + { + $this->rotation = $rotation; + + return $this; + } + + public function getRotation(): ?int + { + return $this->rotation; + } + + public function getFillColorObject(): ChartColor + { + return $this->fillColor; + } +} diff --git a/src/PhpSpreadsheet/Chart/Legend.php b/src/PhpSpreadsheet/Chart/Legend.php index edd87015af..e1bc4dc9f7 100644 --- a/src/PhpSpreadsheet/Chart/Legend.php +++ b/src/PhpSpreadsheet/Chart/Legend.php @@ -48,6 +48,15 @@ class Legend */ private $layout; + /** @var ChartColor */ + private $borderColor; + + /** @var ChartColor */ + private $fillColor; + + /** @var ?AxisText */ + private $legendText; + /** * Create a new Legend. * @@ -60,6 +69,18 @@ public function __construct($position = self::POSITION_RIGHT, ?Layout $layout = $this->setPosition($position); $this->layout = $layout; $this->setOverlay($overlay); + $this->borderColor = new ChartColor(); + $this->fillColor = new ChartColor(); + } + + public function getBorderColor(): ChartColor + { + return $this->borderColor; + } + + public function getFillColor(): ChartColor + { + return $this->fillColor; } /** @@ -148,4 +169,16 @@ public function getLayout() { return $this->layout; } + + public function getLegendText(): ?AxisText + { + return $this->legendText; + } + + public function setLegendText(?AxisText $legendText): self + { + $this->legendText = $legendText; + + return $this; + } } diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index 5230cf0d76..b488c9569c 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -4,6 +4,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; use PhpOffice\PhpSpreadsheet\Chart\Axis; +use PhpOffice\PhpSpreadsheet\Chart\AxisText; use PhpOffice\PhpSpreadsheet\Chart\ChartColor; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; @@ -350,6 +351,10 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) $legendPos = 'r'; $legendLayout = null; $legendOverlay = false; + $legendBorderColor = null; + $legendFillColor = null; + $legendText = null; + $addLegendText = false; foreach ($chartDetails as $chartDetailKey => $chartDetail) { $chartDetail = Xlsx::testSimpleXml($chartDetail); switch ($chartDetailKey) { @@ -364,10 +369,44 @@ public function readChart(SimpleXMLElement $chartElements, $chartName) case 'layout': $legendLayout = $this->chartLayoutDetails($chartDetail); + break; + case 'spPr': + $children = $chartDetails->spPr->children($this->aNamespace); + if (isset($children->solidFill)) { + $legendFillColor = $this->readColor($children->solidFill); + } + if (isset($children->ln->solidFill)) { + $legendBorderColor = $this->readColor($children->ln->solidFill); + } + + break; + case 'txPr': + $children = $chartDetails->txPr->children($this->aNamespace); + $addLegendText = false; + $legendText = new AxisText(); + if (isset($children->p->pPr->defRPr->solidFill)) { + $colorArray = $this->readColor($children->p->pPr->defRPr->solidFill); + $legendText->getFillColorObject()->setColorPropertiesArray($colorArray); + $addLegendText = true; + } + if (isset($children->p->pPr->defRPr->effectLst)) { + $this->readEffects($children->p->pPr->defRPr, $legendText, false); + $addLegendText = true; + } + break; } } $legend = new Legend("$legendPos", $legendLayout, (bool) $legendOverlay); + if ($legendFillColor !== null) { + $legend->getFillColor()->setColorPropertiesArray($legendFillColor); + } + if ($legendBorderColor !== null) { + $legend->getBorderColor()->setColorPropertiesArray($legendBorderColor); + } + if ($addLegendText) { + $legend->setLegendText($legendText); + } break; } @@ -1176,13 +1215,19 @@ private function setChartAttributes(Layout $plotArea, $plotAttributes): void } } - private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void + private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject, bool $getSppr = true): void { - if (!isset($chartObject, $chartDetail->spPr)) { + if (!isset($chartObject)) { return; } - $sppr = $chartDetail->spPr->children($this->aNamespace); - + if ($getSppr) { + if (!isset($chartDetail->spPr)) { + return; + } + $sppr = $chartDetail->spPr->children($this->aNamespace); + } else { + $sppr = $chartDetail; + } if (isset($sppr->effectLst->glow)) { $axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / ChartProperties::POINTS_WIDTH_MULTIPLIER; if ($axisGlowSize != 0.0) { @@ -1412,13 +1457,28 @@ private function setAxisProperties(SimpleXMLElement $chartDetail, ?Axis $whichAx } if (isset($chartDetail->txPr)) { $children = $chartDetail->txPr->children($this->aNamespace); + $addAxisText = false; + $axisText = new AxisText(); if (isset($children->bodyPr)) { /** @var string */ $textRotation = self::getAttribute($children->bodyPr, 'rot', 'string'); if (is_numeric($textRotation)) { - $whichAxis->setAxisOption('textRotation', (string) ChartProperties::xmlToAngle($textRotation)); + $axisText->setRotation((int) ChartProperties::xmlToAngle($textRotation)); + $addAxisText = true; } } + if (isset($children->p->pPr->defRPr->solidFill)) { + $colorArray = $this->readColor($children->p->pPr->defRPr->solidFill); + $axisText->getFillColorObject()->setColorPropertiesArray($colorArray); + $addAxisText = true; + } + if (isset($children->p->pPr->defRPr->effectLst)) { + $this->readEffects($children->p->pPr->defRPr, $axisText, false); + $addAxisText = true; + } + if ($addAxisText) { + $whichAxis->setAxisText($axisText); + } } } } diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index 7306b4ceb3..a4fc68eacc 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -201,6 +201,22 @@ private function writeLegend(XMLWriter $objWriter, ?Legend $legend = null): void $objWriter->writeAttribute('val', ($legend->getOverlay()) ? '1' : '0'); $objWriter->endElement(); + $fillColor = $legend->getFillColor(); + $borderColor = $legend->getBorderColor(); + if ($fillColor->isUsable() || $borderColor->isUsable()) { + $objWriter->startElement('c:spPr'); + if ($fillColor->isUsable()) { + $this->writeColor($objWriter, $fillColor); + } + if ($borderColor->isUsable()) { + $objWriter->startElement('a:ln'); + $this->writeColor($objWriter, $borderColor); + $objWriter->endElement(); // a:ln + } + $objWriter->endElement(); // c:spPr + } + + $legendText = $legend->getLegendText(); $objWriter->startElement('c:txPr'); $objWriter->startElement('a:bodyPr'); $objWriter->endElement(); @@ -213,17 +229,21 @@ private function writeLegend(XMLWriter $objWriter, ?Legend $legend = null): void $objWriter->writeAttribute('rtl', '0'); $objWriter->startElement('a:defRPr'); - $objWriter->endElement(); - $objWriter->endElement(); + if ($legendText !== null) { + $this->writeColor($objWriter, $legendText->getFillColorObject()); + $this->writeEffects($objWriter, $legendText); + } + $objWriter->endElement(); // a:defRpr + $objWriter->endElement(); // a:pPr $objWriter->startElement('a:endParaRPr'); $objWriter->writeAttribute('lang', 'en-US'); - $objWriter->endElement(); + $objWriter->endElement(); // a:endParaRPr - $objWriter->endElement(); - $objWriter->endElement(); + $objWriter->endElement(); // a:p + $objWriter->endElement(); // c:txPr - $objWriter->endElement(); + $objWriter->endElement(); // c:legend } /** @@ -608,16 +628,24 @@ private function writeCategoryAxis(XMLWriter $objWriter, ?Title $xAxisLabel, $id } $textRotation = $yAxis->getAxisOptionsProperty('textRotation'); - if (is_numeric($textRotation)) { + $axisText = $yAxis->getAxisText(); + + if ($axisText !== null || is_numeric($textRotation)) { $objWriter->startElement('c:txPr'); $objWriter->startElement('a:bodyPr'); - $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); + if (is_numeric($textRotation)) { + $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); + } $objWriter->endElement(); // a:bodyPr $objWriter->startElement('a:lstStyle'); $objWriter->endElement(); // a:lstStyle $objWriter->startElement('a:p'); $objWriter->startElement('a:pPr'); $objWriter->startElement('a:defRPr'); + if ($axisText !== null) { + $this->writeColor($objWriter, $axisText->getFillColorObject()); + $this->writeEffects($objWriter, $axisText); + } $objWriter->endElement(); // a:defRPr $objWriter->endElement(); // a:pPr $objWriter->endElement(); // a:p @@ -826,16 +854,24 @@ private function writeValueAxis(XMLWriter $objWriter, ?Title $yAxisLabel, $group } $textRotation = $xAxis->getAxisOptionsProperty('textRotation'); - if (is_numeric($textRotation)) { + $axisText = $xAxis->getAxisText(); + + if ($axisText !== null || is_numeric($textRotation)) { $objWriter->startElement('c:txPr'); $objWriter->startElement('a:bodyPr'); - $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); + if (is_numeric($textRotation)) { + $objWriter->writeAttribute('rot', Properties::angleToXml((float) $textRotation)); + } $objWriter->endElement(); // a:bodyPr $objWriter->startElement('a:lstStyle'); $objWriter->endElement(); // a:lstStyle $objWriter->startElement('a:p'); $objWriter->startElement('a:pPr'); $objWriter->startElement('a:defRPr'); + if ($axisText !== null) { + $this->writeColor($objWriter, $axisText->getFillColorObject()); + $this->writeEffects($objWriter, $axisText); + } $objWriter->endElement(); // a:defRPr $objWriter->endElement(); // a:pPr $objWriter->endElement(); // a:p diff --git a/tests/PhpSpreadsheetTests/Chart/DataSeriesColorTest.php b/tests/PhpSpreadsheetTests/Chart/DataSeriesColorTest.php new file mode 100644 index 0000000000..c0b7069d87 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Chart/DataSeriesColorTest.php @@ -0,0 +1,232 @@ +setIncludeCharts(true); + } + + public function writeCharts(XlsxWriter $writer): void + { + $writer->setIncludeCharts(true); + } + + public function testDataSeriesValues(): void + { + $spreadsheet = new Spreadsheet(); + $worksheet = $spreadsheet->getActiveSheet(); + // changed data to simulate a trend chart - Xaxis are dates; Yaxis are 3 measurements from each date + $worksheet->fromArray( + [ + ['', 'metric1', 'metric2', 'metric3'], + ['=DATEVALUE("2021-01-01")', 12.1, 15.1, 21.1], + ['=DATEVALUE("2021-01-04")', 56.2, 73.2, 86.2], + ['=DATEVALUE("2021-01-07")', 52.2, 61.2, 69.2], + ['=DATEVALUE("2021-01-10")', 30.2, 32.2, 0.2], + ] + ); + $worksheet->getStyle('A2:A5')->getNumberFormat()->setFormatCode(Properties::FORMAT_CODE_DATE_ISO8601); + $worksheet->getColumnDimension('A')->setAutoSize(true); + $worksheet->setSelectedCells('A1'); + + // 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), // was 2010 + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // was 2011 + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // was 2012 + ]; + // Set the X-Axis Labels + // changed from STRING to NUMBER + // added 2 additional x-axis values associated with each of the 3 metrics + // added FORMATE_CODE_NUMBER + $xAxisTickValues = [ + //new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), + ]; + // 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 + // added FORMAT_CODE_NUMBER + $dataSeriesValues = [ + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', Properties::FORMAT_CODE_NUMBER, 4), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', Properties::FORMAT_CODE_NUMBER, 4), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', Properties::FORMAT_CODE_NUMBER, 4), + ]; + + // series 1 + // marker details + $dataSeriesValues[0] + ->setPointMarker('diamond') + ->setPointSize(5) + ->getMarkerFillColor() + ->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_RGB); + $dataSeriesValues[0] + ->getMarkerBorderColor() + ->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_RGB); + + // line details - smooth line, connected + $dataSeriesValues[0] + ->setScatterLines(true) + ->setSmoothLine(true) + ->setLineColorProperties('accent1', 40, ChartColor::EXCEL_COLOR_TYPE_SCHEME); // value, alpha, type + $dataSeriesValues[0]->setLineStyleProperties( + 2.5, // width in points + Properties::LINE_STYLE_COMPOUND_TRIPLE, // compound + Properties::LINE_STYLE_DASH_SQUARE_DOT, // dash + Properties::LINE_STYLE_CAP_SQUARE, // cap + Properties::LINE_STYLE_JOIN_MITER, // join + Properties::LINE_STYLE_ARROW_TYPE_OPEN, // head type + (string) Properties::LINE_STYLE_ARROW_SIZE_4, // head size preset index + Properties::LINE_STYLE_ARROW_TYPE_ARROW, // end type + (string) Properties::LINE_STYLE_ARROW_SIZE_6 // end size preset index + ); + + // series 2 - straight line - no special effects, connected, straight line + $dataSeriesValues[1] // square fill + ->setPointMarker('square') + ->setPointSize(6) + ->getMarkerBorderColor() + ->setColorProperties('accent6', 3, ChartColor::EXCEL_COLOR_TYPE_SCHEME); + $dataSeriesValues[1] // square border + ->getMarkerFillColor() + ->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); + $dataSeriesValues[1] + ->setScatterLines(true) + ->setSmoothLine(false) + ->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_RGB); + $dataSeriesValues[1]->setLineWidth(2.0); + + // series 3 - markers, no line + $dataSeriesValues[2] // triangle fill + //->setPointMarker('triangle') // let Excel choose shape + ->setPointSize(7) + ->getMarkerFillColor() + ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); + $dataSeriesValues[2] // triangle border + ->getMarkerBorderColor() + ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); + $dataSeriesValues[2]->setScatterLines(false); // points not connected + + // Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers + $xAxis = new ChartAxis(); + //$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE ); + $xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601, true); + //$xAxis->setAxisOption('textRotation', '45'); + $xAxisText = new AxisText(); + $xAxisText->setRotation(45)->getFillColorObject()->setValue('00FF00')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); + $xAxis->setAxisText($xAxisText); + + $yAxis = new ChartAxis(); + $yAxis->setLineStyleProperties( + 2.5, // width in points + Properties::LINE_STYLE_COMPOUND_SIMPLE, + Properties::LINE_STYLE_DASH_DASH_DOT, + Properties::LINE_STYLE_CAP_FLAT, + Properties::LINE_STYLE_JOIN_BEVEL + ); + $yAxis->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB); + $yAxisText = new AxisText(); + $yAxisText->setGlowProperties(20.0, 'accent1', 20, ChartColor::EXCEL_COLOR_TYPE_SCHEME); + $yAxis->setAxisText($yAxisText); + + // Build the dataseries + $series = new DataSeries( + DataSeries::TYPE_SCATTERCHART, // plotType + null, // plotGrouping (Scatter charts don't have any grouping) + range(0, count($dataSeriesValues) - 1), // plotOrder + $dataSeriesLabels, // plotLabel + $xAxisTickValues, // plotCategory + $dataSeriesValues, // plotValues + null, // plotDirection + false, // smooth line + DataSeries::STYLE_SMOOTHMARKER // plotStyle + ); + + // Set the series in the plot area + $plotArea = new PlotArea(null, [$series]); + // Set the chart legend + $legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); + + $title = new Title('Test Scatter Trend 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 + // added xAxis for correct date display + $xAxis, // xAxis + $yAxis, // yAxis + ); + + // Set the position where the chart should appear in the worksheet + $chart->setTopLeftPosition('A7'); + $chart->setBottomRightPosition('P20'); + + // Add the chart to the worksheet + $worksheet->addChart($chart); + + /** @var callable */ + $callableReader = [$this, 'readCharts']; + /** @var callable */ + $callableWriter = [$this, 'writeCharts']; + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter); + $spreadsheet->disconnectWorksheets(); + + $sheet = $reloadedSpreadsheet->getActiveSheet(); + $charts2 = $sheet->getChartCollection(); + self::assertCount(1, $charts2); + $chart2 = $charts2[0]; + self::assertNotNull($chart2); + $xAxisText = $chart2->getChartAxisX()->getAxisText(); + $yAxisText = $chart2->getChartAxisY()->getAxisText(); + if ($xAxisText === null || $yAxisText === null) { + self::fail('Unexpected null x-axis or y-axis'); + } else { + self::assertSame(45, $xAxisText->getRotation()); + self::assertSame('00FF00', $xAxisText->getFillColorObject()->getValue()); + self::assertSame(ChartColor::EXCEL_COLOR_TYPE_RGB, $xAxisText->getFillColorObject()->getType()); + self::assertSame(20.0, $yAxisText->getGlowProperty('size')); + self::assertSame(['value' => 'accent1', 'type' => 'schemeClr', 'alpha' => 20], $yAxisText->getGlowProperty('color')); + } + + $reloadedSpreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/PhpSpreadsheetTests/Chart/LegendColorTest.php b/tests/PhpSpreadsheetTests/Chart/LegendColorTest.php new file mode 100644 index 0000000000..4d4e86b731 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Chart/LegendColorTest.php @@ -0,0 +1,164 @@ +setIncludeCharts(true); + } + + public function writeCharts(XlsxWriter $writer): void + { + $writer->setIncludeCharts(true); + } + + public function testLegend(): void + { + $spreadsheet = new Spreadsheet(); + $worksheet = $spreadsheet->getActiveSheet(); + $worksheet->fromArray( + [ + ['Counts', 'Max', 'Min', 'Min Threshold', 'Max Threshold'], + [10, 10, 5, 0, 50], + [30, 20, 10, 0, 50], + [20, 30, 15, 0, 50], + [40, 10, 0, 0, 50], + [100, 40, 5, 0, 50], + ], + null, + 'A1', + true + ); + $worksheet->getStyle('B2:E6')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_NUMBER_00); + + // 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), //Max / Open + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), //Min / Close + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), //Min Threshold / Min + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$E$1', null, 1), //Max Threshold / Max + ]; + // 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$6', null, 5), // Counts + ]; + // 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$6', null, 5), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$6', null, 5), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$6', null, 5), + new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$E$2:$E$6', null, 5), + ]; + + // Build the dataseries + $series = new DataSeries( + DataSeries::TYPE_STOCKCHART, // plotType + null, // plotGrouping - if we set this to not null, then xlsx throws error + range(0, count($dataSeriesValues) - 1), // plotOrder + $dataSeriesLabels, // plotLabel + $xAxisTickValues, // plotCategory + $dataSeriesValues // plotValues + ); + + // Set the series in the plot area + $plotArea = new PlotArea(null, [$series]); + // Set the chart legend + $legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); + $legend->getBorderColor()->setColorProperties('ffc000'); + $legend->getFillColor()->setColorProperties('cccccc'); + $legendText = new AxisText(); + $legendText->getFillColorObject()->setValue('008080')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); + $legendText->setShadowProperties(1); + $legend->setLegendText($legendText); + + $title = new Title('Test Stock Chart'); + $xAxisLabel = new Title('Counts'); + $yAxisLabel = new Title('Values'); + + // Create the chart + $chart = new Chart( + 'stock-chart', // name + $title, // title + $legend, // legend + $plotArea, // plotArea + true, // plotVisibleOnly + DataSeries::EMPTY_AS_GAP, // displayBlanksAs + $xAxisLabel, // xAxisLabel + $yAxisLabel // yAxisLabel + ); + + // Set the position where the chart should appear in the worksheet + $chart->setTopLeftPosition('A7'); + $chart->setBottomRightPosition('H20'); + + // Add the chart to the worksheet + $worksheet->addChart($chart); + $worksheet->setSelectedCells('G2'); + + /** @var callable */ + $callableReader = [$this, 'readCharts']; + /** @var callable */ + $callableWriter = [$this, 'writeCharts']; + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter); + $spreadsheet->disconnectWorksheets(); + + $sheet = $reloadedSpreadsheet->getActiveSheet(); + $charts2 = $sheet->getChartCollection(); + self::assertCount(1, $charts2); + $chart2 = $charts2[0]; + self::assertNotNull($chart2); + $legend2 = $chart2->getLegend(); + if ($legend2 === null) { + self::fail('Unexpected null legend'); + } else { + self::assertSame('ffc000', $legend2->getBorderColor()->getValue()); + self::assertSame('cccccc', $legend2->getFillColor()->getValue()); + $legendText2 = $legend2->getLegendText(); + if ($legendText2 === null) { + self::fail('Unexpected null legendText'); + } else { + self::assertSame('008080', $legendText2->getFillColorObject()->getValue()); + self::assertSame('outerShdw', $legendText2->getShadowProperty('effect')); + self::assertSame(4.0, (float) $legendText2->getShadowProperty('blur')); + self::assertSame(45.0, (float) $legendText2->getShadowProperty('direction')); + } + } + + $reloadedSpreadsheet->disconnectWorksheets(); + } +}