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.
This commit is contained in:
oleibman 2022-08-27 22:59:35 -07:00 committed by GitHub
parent 24f1a2fbc1
commit 389ca80e00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 163 additions and 6 deletions

View File

@ -193,7 +193,7 @@ $dataSeriesValues = [
// 3- moving Avg (period=2) single-arrow trendline, w=1.5, same color as marker fill; no dispRSqr, no dispEq // 3- moving Avg (period=2) single-arrow trendline, w=1.5, same color as marker fill; no dispRSqr, no dispEq
$trendLines = [ $trendLines = [
new TrendLine(TrendLine::TRENDLINE_LINEAR, null, null, false, false), 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), new TrendLine(TrendLine::TRENDLINE_MOVING_AVG, null, 2, true),
]; ];
$dataSeriesValues[0]->setTrendLines($trendLines); $dataSeriesValues[0]->setTrendLines($trendLines);

View File

@ -73,6 +73,9 @@ foreach ($inputFileNames as $inputFileName) {
$helper->log(' ' . $chartName . ' - ' . $caption); $helper->log(' ' . $chartName . ' - ' . $caption);
$jpegFile = $helper->getFilename('35-' . $inputFileNameShort, 'png'); $jpegFile = $helper->getFilename('35-' . $inputFileNameShort, 'png');
if ($i !== 0) {
$jpegFile = substr($jpegFile, 0, -3) . "$i.png";
}
if (file_exists($jpegFile)) { if (file_exists($jpegFile)) {
unlink($jpegFile); unlink($jpegFile);
} }

View File

@ -34,13 +34,44 @@ class TrendLine extends Properties
/** @var bool */ /** @var bool */
private $dispEq = false; 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. * 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(); parent::__construct();
$this->setTrendLineProperties($trendLineType, $order, $period, $dispRSqr, $dispEq); $this->setTrendLineProperties(
$trendLineType,
$order,
$period,
$dispRSqr,
$dispEq,
$backward,
$forward,
$intercept,
$name
);
} }
public function getTrendLineType(): string public function getTrendLineType(): string
@ -103,8 +134,65 @@ class TrendLine extends Properties
return $this; 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)) { if (!empty($trendLineType)) {
$this->setTrendLineType($trendLineType); $this->setTrendLineType($trendLineType);
} }
@ -120,6 +208,18 @@ class TrendLine extends Properties
if ($dispEq !== null) { if ($dispEq !== null) {
$this->setDispEq($dispEq); $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; return $this;
} }

View File

@ -531,7 +531,25 @@ class Chart
$order = self::getAttribute($seriesDetail->order, 'val', 'integer'); $order = self::getAttribute($seriesDetail->order, 'val', 'integer');
/** @var ?int */ /** @var ?int */
$period = self::getAttribute($seriesDetail->period, 'val', 'integer'); $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; $trendLines[] = $trendLine;
break; break;

View File

@ -1158,10 +1158,19 @@ class Chart extends WriterPart
$period = $trendLine->getPeriod(); $period = $trendLine->getPeriod();
$dispRSqr = $trendLine->getDispRSqr(); $dispRSqr = $trendLine->getDispRSqr();
$dispEq = $trendLine->getDispEq(); $dispEq = $trendLine->getDispEq();
$forward = $trendLine->getForward();
$backward = $trendLine->getBackward();
$intercept = $trendLine->getIntercept();
$name = $trendLine->getName();
$trendLineColor = $trendLine->getLineColor(); // ChartColor $trendLineColor = $trendLine->getLineColor(); // ChartColor
$trendLineWidth = $trendLine->getLineStyleProperty('width'); $trendLineWidth = $trendLine->getLineStyleProperty('width');
$objWriter->startElement('c:trendline'); // N.B. lowercase 'ell' $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'); $objWriter->startElement('c:spPr');
if (!$trendLineColor->isUsable()) { if (!$trendLineColor->isUsable()) {
@ -1181,6 +1190,21 @@ class Chart extends WriterPart
$objWriter->startElement('c:trendlineType'); // N.B lowercase 'ell' $objWriter->startElement('c:trendlineType'); // N.B lowercase 'ell'
$objWriter->writeAttribute('val', $trendLineType); $objWriter->writeAttribute('val', $trendLineType);
$objWriter->endElement(); // 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) { if ($trendLineType == TrendLine::TRENDLINE_POLYNOMIAL) {
$objWriter->startElement('c:order'); $objWriter->startElement('c:order');
$objWriter->writeAttribute('val', $order); $objWriter->writeAttribute('val', $order);

View File

@ -73,6 +73,10 @@ class TrendLineTest extends AbstractFunctional
self::assertSame('accent4', $lineColor->getValue()); self::assertSame('accent4', $lineColor->getValue());
self::assertSame('stealth', $trendLine->getLineStyleProperty(['arrow', 'head', 'type'])); self::assertSame('stealth', $trendLine->getLineStyleProperty(['arrow', 'head', 'type']));
self::assertEquals(0.5, $trendLine->getLineStyleProperty('width')); 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]; $trendLine = $trendLines[1];
self::assertSame('poly', $trendLine->getTrendLineType()); self::assertSame('poly', $trendLine->getTrendLineType());
@ -82,6 +86,10 @@ class TrendLineTest extends AbstractFunctional
self::assertSame('accent3', $lineColor->getValue()); self::assertSame('accent3', $lineColor->getValue());
self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type'])); self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type']));
self::assertEquals(1.25, $trendLine->getLineStyleProperty('width')); 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]; $trendLine = $trendLines[2];
self::assertSame('movingAvg', $trendLine->getTrendLineType()); self::assertSame('movingAvg', $trendLine->getTrendLineType());
@ -91,6 +99,10 @@ class TrendLineTest extends AbstractFunctional
self::assertSame('accent2', $lineColor->getValue()); self::assertSame('accent2', $lineColor->getValue());
self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type'])); self::assertNull($trendLine->getLineStyleProperty(['arrow', 'head', 'type']));
self::assertEquals(1.5, $trendLine->getLineStyleProperty('width')); 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(); $reloadedSpreadsheet->disconnectWorksheets();
} }