Skip to content

Commit 389ca80

Browse files
authored
Additional Properties for Trendlines (#3028)
Fix #3011. Some properties for Trendlines were omitted in the original request for this feature. Also, the trendlines sample spreadsheet included two charts. The rendering script 35_Chart_render handles this, but overlays the first output file with the second. It is changed to produce files with different names.
1 parent 24f1a2f commit 389ca80

File tree

7 files changed

+163
-6
lines changed

7 files changed

+163
-6
lines changed

samples/Chart/33_Chart_create_scatter5_trendlines.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@
193193
// 3- moving Avg (period=2) single-arrow trendline, w=1.5, same color as marker fill; no dispRSqr, no dispEq
194194
$trendLines = [
195195
new TrendLine(TrendLine::TRENDLINE_LINEAR, null, null, false, false),
196-
new TrendLine(TrendLine::TRENDLINE_POLYNOMIAL, 3, null, true, true),
196+
new TrendLine(TrendLine::TRENDLINE_POLYNOMIAL, 3, null, true, true, 20.0, 28.0, 44104.5, 'metric3 polynomial fit'),
197197
new TrendLine(TrendLine::TRENDLINE_MOVING_AVG, null, 2, true),
198198
];
199199
$dataSeriesValues[0]->setTrendLines($trendLines);

samples/Chart/35_Chart_render.php

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@
7373
$helper->log(' ' . $chartName . ' - ' . $caption);
7474

7575
$jpegFile = $helper->getFilename('35-' . $inputFileNameShort, 'png');
76+
if ($i !== 0) {
77+
$jpegFile = substr($jpegFile, 0, -3) . "$i.png";
78+
}
7679
if (file_exists($jpegFile)) {
7780
unlink($jpegFile);
7881
}
Binary file not shown.

src/PhpSpreadsheet/Chart/TrendLine.php

+104-4
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,44 @@ class TrendLine extends Properties
3434
/** @var bool */
3535
private $dispEq = false;
3636

37+
/** @var string */
38+
private $name = '';
39+
40+
/** @var float */
41+
private $backward = 0.0;
42+
43+
/** @var float */
44+
private $forward = 0.0;
45+
46+
/** @var float */
47+
private $intercept = 0.0;
48+
3749
/**
3850
* Create a new TrendLine object.
3951
*/
40-
public function __construct(string $trendLineType = '', ?int $order = null, ?int $period = null, bool $dispRSqr = false, bool $dispEq = false)
41-
{
52+
public function __construct(
53+
string $trendLineType = '',
54+
?int $order = null,
55+
?int $period = null,
56+
bool $dispRSqr = false,
57+
bool $dispEq = false,
58+
?float $backward = null,
59+
?float $forward = null,
60+
?float $intercept = null,
61+
?string $name = null
62+
) {
4263
parent::__construct();
43-
$this->setTrendLineProperties($trendLineType, $order, $period, $dispRSqr, $dispEq);
64+
$this->setTrendLineProperties(
65+
$trendLineType,
66+
$order,
67+
$period,
68+
$dispRSqr,
69+
$dispEq,
70+
$backward,
71+
$forward,
72+
$intercept,
73+
$name
74+
);
4475
}
4576

4677
public function getTrendLineType(): string
@@ -103,8 +134,65 @@ public function setDispEq(bool $dispEq): self
103134
return $this;
104135
}
105136

106-
public function setTrendLineProperties(?string $trendLineType = null, ?int $order = 0, ?int $period = 0, ?bool $dispRSqr = false, ?bool $dispEq = false): self
137+
public function getName(): string
107138
{
139+
return $this->name;
140+
}
141+
142+
public function setName(string $name): self
143+
{
144+
$this->name = $name;
145+
146+
return $this;
147+
}
148+
149+
public function getBackward(): float
150+
{
151+
return $this->backward;
152+
}
153+
154+
public function setBackward(float $backward): self
155+
{
156+
$this->backward = $backward;
157+
158+
return $this;
159+
}
160+
161+
public function getForward(): float
162+
{
163+
return $this->forward;
164+
}
165+
166+
public function setForward(float $forward): self
167+
{
168+
$this->forward = $forward;
169+
170+
return $this;
171+
}
172+
173+
public function getIntercept(): float
174+
{
175+
return $this->intercept;
176+
}
177+
178+
public function setIntercept(float $intercept): self
179+
{
180+
$this->intercept = $intercept;
181+
182+
return $this;
183+
}
184+
185+
public function setTrendLineProperties(
186+
?string $trendLineType = null,
187+
?int $order = 0,
188+
?int $period = 0,
189+
?bool $dispRSqr = false,
190+
?bool $dispEq = false,
191+
?float $backward = null,
192+
?float $forward = null,
193+
?float $intercept = null,
194+
?string $name = null
195+
): self {
108196
if (!empty($trendLineType)) {
109197
$this->setTrendLineType($trendLineType);
110198
}
@@ -120,6 +208,18 @@ public function setTrendLineProperties(?string $trendLineType = null, ?int $orde
120208
if ($dispEq !== null) {
121209
$this->setDispEq($dispEq);
122210
}
211+
if ($backward !== null) {
212+
$this->setBackward($backward);
213+
}
214+
if ($forward !== null) {
215+
$this->setForward($forward);
216+
}
217+
if ($intercept !== null) {
218+
$this->setIntercept($intercept);
219+
}
220+
if ($name !== null) {
221+
$this->setName($name);
222+
}
123223

124224
return $this;
125225
}

src/PhpSpreadsheet/Reader/Xlsx/Chart.php

+19-1
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,25 @@ private function chartDataSeries(SimpleXMLElement $chartDetail, string $plotType
531531
$order = self::getAttribute($seriesDetail->order, 'val', 'integer');
532532
/** @var ?int */
533533
$period = self::getAttribute($seriesDetail->period, 'val', 'integer');
534-
$trendLine->setTrendLineProperties($trendLineType, $order, $period, $dispRSqr, $dispEq);
534+
/** @var ?float */
535+
$forward = self::getAttribute($seriesDetail->forward, 'val', 'float');
536+
/** @var ?float */
537+
$backward = self::getAttribute($seriesDetail->backward, 'val', 'float');
538+
/** @var ?float */
539+
$intercept = self::getAttribute($seriesDetail->intercept, 'val', 'float');
540+
/** @var ?string */
541+
$name = (string) $seriesDetail->name;
542+
$trendLine->setTrendLineProperties(
543+
$trendLineType,
544+
$order,
545+
$period,
546+
$dispRSqr,
547+
$dispEq,
548+
$backward,
549+
$forward,
550+
$intercept,
551+
$name
552+
);
535553
$trendLines[] = $trendLine;
536554

537555
break;

src/PhpSpreadsheet/Writer/Xlsx/Chart.php

+24
Original file line numberDiff line numberDiff line change
@@ -1158,10 +1158,19 @@ private function writePlotGroup(?DataSeries $plotGroup, string $groupType, XMLWr
11581158
$period = $trendLine->getPeriod();
11591159
$dispRSqr = $trendLine->getDispRSqr();
11601160
$dispEq = $trendLine->getDispEq();
1161+
$forward = $trendLine->getForward();
1162+
$backward = $trendLine->getBackward();
1163+
$intercept = $trendLine->getIntercept();
1164+
$name = $trendLine->getName();
11611165
$trendLineColor = $trendLine->getLineColor(); // ChartColor
11621166
$trendLineWidth = $trendLine->getLineStyleProperty('width');
11631167

11641168
$objWriter->startElement('c:trendline'); // N.B. lowercase 'ell'
1169+
if ($name !== '') {
1170+
$objWriter->startElement('c:name');
1171+
$objWriter->writeRawData($name);
1172+
$objWriter->endElement(); // c:name
1173+
}
11651174
$objWriter->startElement('c:spPr');
11661175

11671176
if (!$trendLineColor->isUsable()) {
@@ -1181,6 +1190,21 @@ private function writePlotGroup(?DataSeries $plotGroup, string $groupType, XMLWr
11811190
$objWriter->startElement('c:trendlineType'); // N.B lowercase 'ell'
11821191
$objWriter->writeAttribute('val', $trendLineType);
11831192
$objWriter->endElement(); // trendlineType
1193+
if ($backward !== 0.0) {
1194+
$objWriter->startElement('c:backward');
1195+
$objWriter->writeAttribute('val', "$backward");
1196+
$objWriter->endElement(); // c:backward
1197+
}
1198+
if ($forward !== 0.0) {
1199+
$objWriter->startElement('c:forward');
1200+
$objWriter->writeAttribute('val', "$forward");
1201+
$objWriter->endElement(); // c:forward
1202+
}
1203+
if ($intercept !== 0.0) {
1204+
$objWriter->startElement('c:intercept');
1205+
$objWriter->writeAttribute('val', "$intercept");
1206+
$objWriter->endElement(); // c:intercept
1207+
}
11841208
if ($trendLineType == TrendLine::TRENDLINE_POLYNOMIAL) {
11851209
$objWriter->startElement('c:order');
11861210
$objWriter->writeAttribute('val', $order);

tests/PhpSpreadsheetTests/Chart/TrendLineTest.php

+12
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ public function testTrendLine(): void
7373
self::assertSame('accent4', $lineColor->getValue());
7474
self::assertSame('stealth', $trendLine->getLineStyleProperty(['arrow', 'head', 'type']));
7575
self::assertEquals(0.5, $trendLine->getLineStyleProperty('width'));
76+
self::assertSame('', $trendLine->getName());
77+
self::assertSame(0.0, $trendLine->getBackward());
78+
self::assertSame(0.0, $trendLine->getForward());
79+
self::assertSame(0.0, $trendLine->getIntercept());
7680

7781
$trendLine = $trendLines[1];
7882
self::assertSame('poly', $trendLine->getTrendLineType());
@@ -82,6 +86,10 @@ public function testTrendLine(): void
8286
self::assertSame('accent3', $lineColor->getValue());
8387
self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type']));
8488
self::assertEquals(1.25, $trendLine->getLineStyleProperty('width'));
89+
self::assertSame('metric3 polynomial', $trendLine->getName());
90+
self::assertSame(20.0, $trendLine->getBackward());
91+
self::assertSame(28.0, $trendLine->getForward());
92+
self::assertSame(14400.5, $trendLine->getIntercept());
8593

8694
$trendLine = $trendLines[2];
8795
self::assertSame('movingAvg', $trendLine->getTrendLineType());
@@ -91,6 +99,10 @@ public function testTrendLine(): void
9199
self::assertSame('accent2', $lineColor->getValue());
92100
self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type']));
93101
self::assertEquals(1.5, $trendLine->getLineStyleProperty('width'));
102+
self::assertSame('', $trendLine->getName());
103+
self::assertSame(0.0, $trendLine->getBackward());
104+
self::assertSame(0.0, $trendLine->getForward());
105+
self::assertSame(0.0, $trendLine->getIntercept());
94106

95107
$reloadedSpreadsheet->disconnectWorksheets();
96108
}

0 commit comments

Comments
 (0)