diff --git a/samples/Chart/33_Chart_create_scatter5_trendlines.php b/samples/Chart/33_Chart_create_scatter5_trendlines.php index a87f6ee13e..350046ad35 100644 --- a/samples/Chart/33_Chart_create_scatter5_trendlines.php +++ b/samples/Chart/33_Chart_create_scatter5_trendlines.php @@ -193,7 +193,7 @@ // 3- moving Avg (period=2) single-arrow trendline, w=1.5, same color as marker fill; no dispRSqr, no dispEq $trendLines = [ new TrendLine(TrendLine::TRENDLINE_LINEAR, null, null, false, false), - new TrendLine(TrendLine::TRENDLINE_POLYNOMIAL, 3, null, true, true), + new TrendLine(TrendLine::TRENDLINE_POLYNOMIAL, 3, null, true, true, 20.0, 28.0, 44104.5, 'metric3 polynomial fit'), new TrendLine(TrendLine::TRENDLINE_MOVING_AVG, null, 2, true), ]; $dataSeriesValues[0]->setTrendLines($trendLines); @@ -263,6 +263,7 @@ // Add the chart to the worksheet $chartSheet $chartSheet->addChart($chart); +$spreadsheet->setActiveSheetIndex(1); // Save Excel 2007 file $filename = $helper->getFilename(__FILE__); diff --git a/samples/Chart/35_Chart_render.php b/samples/Chart/35_Chart_render.php index 2376008c64..891cd27c7f 100644 --- a/samples/Chart/35_Chart_render.php +++ b/samples/Chart/35_Chart_render.php @@ -73,6 +73,9 @@ $helper->log(' ' . $chartName . ' - ' . $caption); $jpegFile = $helper->getFilename('35-' . $inputFileNameShort, 'png'); + if ($i !== 0) { + $jpegFile = substr($jpegFile, 0, -3) . "$i.png"; + } if (file_exists($jpegFile)) { unlink($jpegFile); } diff --git a/samples/templates/32readwriteScatterChartTrendlines1.xlsx b/samples/templates/32readwriteScatterChartTrendlines1.xlsx index f48366fe0a..c8411d4daf 100644 Binary files a/samples/templates/32readwriteScatterChartTrendlines1.xlsx and b/samples/templates/32readwriteScatterChartTrendlines1.xlsx differ diff --git a/src/PhpSpreadsheet/Chart/TrendLine.php b/src/PhpSpreadsheet/Chart/TrendLine.php index e177f8198a..75a5896c93 100644 --- a/src/PhpSpreadsheet/Chart/TrendLine.php +++ b/src/PhpSpreadsheet/Chart/TrendLine.php @@ -34,13 +34,44 @@ class TrendLine extends Properties /** @var bool */ private $dispEq = false; + /** @var string */ + private $name = ''; + + /** @var float */ + private $backward = 0.0; + + /** @var float */ + private $forward = 0.0; + + /** @var float */ + private $intercept = 0.0; + /** * Create a new TrendLine object. */ - public function __construct(string $trendLineType = '', ?int $order = null, ?int $period = null, bool $dispRSqr = false, bool $dispEq = false) - { + public function __construct( + string $trendLineType = '', + ?int $order = null, + ?int $period = null, + bool $dispRSqr = false, + bool $dispEq = false, + ?float $backward = null, + ?float $forward = null, + ?float $intercept = null, + ?string $name = null + ) { parent::__construct(); - $this->setTrendLineProperties($trendLineType, $order, $period, $dispRSqr, $dispEq); + $this->setTrendLineProperties( + $trendLineType, + $order, + $period, + $dispRSqr, + $dispEq, + $backward, + $forward, + $intercept, + $name + ); } public function getTrendLineType(): string @@ -103,8 +134,65 @@ public function setDispEq(bool $dispEq): self return $this; } - public function setTrendLineProperties(?string $trendLineType = null, ?int $order = 0, ?int $period = 0, ?bool $dispRSqr = false, ?bool $dispEq = false): self + public function getName(): string { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getBackward(): float + { + return $this->backward; + } + + public function setBackward(float $backward): self + { + $this->backward = $backward; + + return $this; + } + + public function getForward(): float + { + return $this->forward; + } + + public function setForward(float $forward): self + { + $this->forward = $forward; + + return $this; + } + + public function getIntercept(): float + { + return $this->intercept; + } + + public function setIntercept(float $intercept): self + { + $this->intercept = $intercept; + + return $this; + } + + public function setTrendLineProperties( + ?string $trendLineType = null, + ?int $order = 0, + ?int $period = 0, + ?bool $dispRSqr = false, + ?bool $dispEq = false, + ?float $backward = null, + ?float $forward = null, + ?float $intercept = null, + ?string $name = null + ): self { if (!empty($trendLineType)) { $this->setTrendLineType($trendLineType); } @@ -120,6 +208,18 @@ public function setTrendLineProperties(?string $trendLineType = null, ?int $orde if ($dispEq !== null) { $this->setDispEq($dispEq); } + if ($backward !== null) { + $this->setBackward($backward); + } + if ($forward !== null) { + $this->setForward($forward); + } + if ($intercept !== null) { + $this->setIntercept($intercept); + } + if ($name !== null) { + $this->setName($name); + } return $this; } diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index dab2b41089..6a6c3182bb 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -536,7 +536,25 @@ private function chartDataSeries(SimpleXMLElement $chartDetail, string $plotType $order = self::getAttribute($seriesDetail->order, 'val', 'integer'); /** @var ?int */ $period = self::getAttribute($seriesDetail->period, 'val', 'integer'); - $trendLine->setTrendLineProperties($trendLineType, $order, $period, $dispRSqr, $dispEq); + /** @var ?float */ + $forward = self::getAttribute($seriesDetail->forward, 'val', 'float'); + /** @var ?float */ + $backward = self::getAttribute($seriesDetail->backward, 'val', 'float'); + /** @var ?float */ + $intercept = self::getAttribute($seriesDetail->intercept, 'val', 'float'); + /** @var ?string */ + $name = (string) $seriesDetail->name; + $trendLine->setTrendLineProperties( + $trendLineType, + $order, + $period, + $dispRSqr, + $dispEq, + $backward, + $forward, + $intercept, + $name + ); $trendLines[] = $trendLine; break; diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index ad746a0a82..797d71dd77 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -1132,10 +1132,19 @@ private function writePlotGroup(?DataSeries $plotGroup, string $groupType, XMLWr $period = $trendLine->getPeriod(); $dispRSqr = $trendLine->getDispRSqr(); $dispEq = $trendLine->getDispEq(); + $forward = $trendLine->getForward(); + $backward = $trendLine->getBackward(); + $intercept = $trendLine->getIntercept(); + $name = $trendLine->getName(); $trendLineColor = $trendLine->getLineColor(); // ChartColor $trendLineWidth = $trendLine->getLineStyleProperty('width'); $objWriter->startElement('c:trendline'); // N.B. lowercase 'ell' + if ($name !== '') { + $objWriter->startElement('c:name'); + $objWriter->writeRawData($name); + $objWriter->endElement(); // c:name + } $objWriter->startElement('c:spPr'); if (!$trendLineColor->isUsable()) { @@ -1155,6 +1164,21 @@ private function writePlotGroup(?DataSeries $plotGroup, string $groupType, XMLWr $objWriter->startElement('c:trendlineType'); // N.B lowercase 'ell' $objWriter->writeAttribute('val', $trendLineType); $objWriter->endElement(); // trendlineType + if ($backward !== 0.0) { + $objWriter->startElement('c:backward'); + $objWriter->writeAttribute('val', "$backward"); + $objWriter->endElement(); // c:backward + } + if ($forward !== 0.0) { + $objWriter->startElement('c:forward'); + $objWriter->writeAttribute('val', "$forward"); + $objWriter->endElement(); // c:forward + } + if ($intercept !== 0.0) { + $objWriter->startElement('c:intercept'); + $objWriter->writeAttribute('val', "$intercept"); + $objWriter->endElement(); // c:intercept + } if ($trendLineType == TrendLine::TRENDLINE_POLYNOMIAL) { $objWriter->startElement('c:order'); $objWriter->writeAttribute('val', $order); diff --git a/tests/PhpSpreadsheetTests/Chart/TrendLineTest.php b/tests/PhpSpreadsheetTests/Chart/TrendLineTest.php index c8550d8319..954a733688 100644 --- a/tests/PhpSpreadsheetTests/Chart/TrendLineTest.php +++ b/tests/PhpSpreadsheetTests/Chart/TrendLineTest.php @@ -73,6 +73,10 @@ public function testTrendLine(): void self::assertSame('accent4', $lineColor->getValue()); self::assertSame('stealth', $trendLine->getLineStyleProperty(['arrow', 'head', 'type'])); self::assertEquals(0.5, $trendLine->getLineStyleProperty('width')); + self::assertSame('', $trendLine->getName()); + self::assertSame(0.0, $trendLine->getBackward()); + self::assertSame(0.0, $trendLine->getForward()); + self::assertSame(0.0, $trendLine->getIntercept()); $trendLine = $trendLines[1]; self::assertSame('poly', $trendLine->getTrendLineType()); @@ -82,6 +86,10 @@ public function testTrendLine(): void self::assertSame('accent3', $lineColor->getValue()); self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type'])); self::assertEquals(1.25, $trendLine->getLineStyleProperty('width')); + self::assertSame('metric3 polynomial', $trendLine->getName()); + self::assertSame(20.0, $trendLine->getBackward()); + self::assertSame(28.0, $trendLine->getForward()); + self::assertSame(14400.5, $trendLine->getIntercept()); $trendLine = $trendLines[2]; self::assertSame('movingAvg', $trendLine->getTrendLineType()); @@ -91,6 +99,10 @@ public function testTrendLine(): void self::assertSame('accent2', $lineColor->getValue()); self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type'])); self::assertEquals(1.5, $trendLine->getLineStyleProperty('width')); + self::assertSame('', $trendLine->getName()); + self::assertSame(0.0, $trendLine->getBackward()); + self::assertSame(0.0, $trendLine->getForward()); + self::assertSame(0.0, $trendLine->getIntercept()); $reloadedSpreadsheet->disconnectWorksheets(); }