Skip to content

Commit f5907e1

Browse files
authored
Merge pull request #676 from mindline-analytics/feat-axis-options
Support for axis options (Intersection Point & Reverse Axis) in PowerPoint2007 Writer
2 parents 47046dd + 6163037 commit f5907e1

File tree

6 files changed

+229
-8
lines changed

6 files changed

+229
-8
lines changed

docs/changes/1.1.0.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Features
44

5+
- Support for axis options - [@mindline](https://github.com/mindline-analytics) GH-676
6+
- Axis intersection point (axis crossing) through `setCrossesAt`/ `getCrossesAt`
7+
- Reverse axis order through `setIsReversedOrder`/ `isReversedOrder`
8+
- PowerPoint2007 Writer
59
- Support for Hyperlink Text Color - [@MartynasJanu](https://github.com/MartynasJanu) & [@Progi1984](https://github.com/Progi1984) GH-682
610
- PowerPoint2007 Reader
7-
- PowerPoint2007 Writer
11+
- PowerPoint2007 Writer

docs/usage/shapes/chart.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,62 @@ $shape->getPlotArea()->getAxisX()->setMinBounds(0);
9595
$shape->getPlotArea()->getAxisX()->setMaxBounds(200);
9696
```
9797

98+
#### Crossing
99+
100+
!!! warning
101+
Available only on the PowerPoint2007 Writer
102+
103+
For Axis, `setCrossesAt` can be used to define where it should be crossed by the perpendicular/ horizontal axis.
104+
The property can be defined by one of the three given constants or as an absolute value on the target axis.
105+
106+
``` php
107+
use PhpOffice\PhpPresentation\Shape\Axis;
108+
use PhpOffice\PhpPresentation\Shape\Chart\Type\Bar;
109+
110+
$bar = new Bar();
111+
112+
$shape = $slide->createChartShape();
113+
$shape->getPlotArea()->setType($bar);
114+
115+
// Usage of constant: Horizontal axis will cross the Y-Axis at `0`
116+
$shape->getPlotArea()->getAxisY()->setCrossesAt(Axis::CROSSES_AUTO);
117+
118+
// Usage of individual value: Horizontal axis will cross the Y-Axis at `3`
119+
$shape->getPlotArea()->getAxisY()->setCrossesAt('3');
120+
```
121+
122+
| Constant | Description |
123+
| -------------------- | ------------------------ |
124+
| `AXIS::CROSSES_AUTO` | Axis crosses at zero. |
125+
| `AXIS::CROSSES_MIN` | Axis crosses at minimum. |
126+
| `AXIS::CROSSES_MAX` | Axis crosses at maximum. |
127+
128+
#### Reversed Order
129+
130+
You can reverse the order of a categorial or value axis trought `setIsReversedOrder`.
131+
132+
Notice: If you reverse the order of a axis, this automatically changes the position of the other axis.
133+
To reset this effect, the axis intersection point on the other axis must be set to `Axis::CROSSES_MAX` using `setCrossesAt`.
134+
135+
``` php
136+
use PhpOffice\PhpPresentation\Shape\Axis;
137+
use PhpOffice\PhpPresentation\Shape\Chart\Type\Bar;
138+
139+
$bar = new Bar();
140+
141+
$shape = $slide->createChartShape();
142+
$shape->getPlotArea()->setType($bar);
143+
144+
// default value, will return false
145+
$shape->getPlotArea()->getAxisY()->isReversedOrder()
146+
147+
// reverse order
148+
$shape->getPlotArea()->getAxisY()->setIsReversedOrder(true);
149+
150+
// revert the automatic intersection switch on x axis
151+
$shape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MAX);
152+
```
153+
98154
#### Outline
99155

100156
You can define outline for each axis (X & Y).

src/PhpPresentation/Shape/Chart/Axis.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ class Axis implements ComparableInterface
3838
public const TICK_LABEL_POSITION_HIGH = 'high';
3939
public const TICK_LABEL_POSITION_LOW = 'low';
4040

41+
public const CROSSES_AUTO = 'autoZero';
42+
public const CROSSES_MIN = 'min';
43+
public const CROSSES_MAX = 'max';
44+
4145
/**
4246
* Title.
4347
*
@@ -84,6 +88,16 @@ class Axis implements ComparableInterface
8488
*/
8589
protected $maxBounds;
8690

91+
/**
92+
* @var string
93+
*/
94+
protected $crossesAt = self::CROSSES_AUTO;
95+
96+
/**
97+
* @var bool
98+
*/
99+
protected $isReversedOrder = false;
100+
87101
/**
88102
* @var string
89103
*/
@@ -243,6 +257,46 @@ public function setMaxBounds(int $maxBounds = null): self
243257
return $this;
244258
}
245259

260+
/**
261+
* @return string
262+
*/
263+
public function getCrossesAt(): string
264+
{
265+
return $this->crossesAt;
266+
}
267+
268+
/**
269+
* @param string $value
270+
*
271+
* @return self
272+
*/
273+
public function setCrossesAt(string $value = self::CROSSES_AUTO): self
274+
{
275+
$this->crossesAt = $value;
276+
277+
return $this;
278+
}
279+
280+
/**
281+
* @return bool
282+
*/
283+
public function isReversedOrder(): bool
284+
{
285+
return $this->isReversedOrder;
286+
}
287+
288+
/**
289+
* @param bool $value
290+
*
291+
* @return self
292+
*/
293+
public function setIsReversedOrder(bool $value = false): self
294+
{
295+
$this->isReversedOrder = $value;
296+
297+
return $this;
298+
}
299+
246300
public function getMajorGridlines(): ?Gridlines
247301
{
248302
return $this->majorGridlines;

src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,15 +2288,18 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty
22882288
return;
22892289
}
22902290

2291+
$crossesAt = $oAxis->getCrossesAt();
2292+
$orientation = $oAxis->isReversedOrder() ? 'maxMin' : 'minMax';
2293+
22912294
if (Chart\Axis::AXIS_X == $typeAxis) {
22922295
$mainElement = 'c:catAx';
22932296
$axIdVal = '52743552';
2294-
$axPosVal = 'b';
2297+
$axPosVal = $crossesAt === 'max' ? 't' : 'b';
22952298
$crossAxVal = '52749440';
22962299
} else {
22972300
$mainElement = 'c:valAx';
22982301
$axIdVal = '52749440';
2299-
$axPosVal = 'l';
2302+
$axPosVal = $crossesAt === 'max' ? 'r' : 'l';
23002303
$crossAxVal = '52743552';
23012304
}
23022305

@@ -2313,7 +2316,7 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty
23132316

23142317
// $mainElement > c:scaling > c:orientation
23152318
$objWriter->startElement('c:orientation');
2316-
$objWriter->writeAttribute('val', 'minMax');
2319+
$objWriter->writeAttribute('val', $orientation);
23172320
$objWriter->endElement();
23182321

23192322
if (null != $oAxis->getMaxBounds()) {
@@ -2476,10 +2479,16 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty
24762479
$objWriter->writeAttribute('val', $crossAxVal);
24772480
$objWriter->endElement();
24782481

2479-
// c:crosses
2480-
$objWriter->startElement('c:crosses');
2481-
$objWriter->writeAttribute('val', 'autoZero');
2482-
$objWriter->endElement();
2482+
// c:crosses "autoZero" | "min" | "max" | custom string value
2483+
if (in_array($crossesAt, ['autoZero', 'min', 'max'])) {
2484+
$objWriter->startElement('c:crosses');
2485+
$objWriter->writeAttribute('val', $crossesAt);
2486+
$objWriter->endElement();
2487+
} else {
2488+
$objWriter->startElement('c:crossesAt');
2489+
$objWriter->writeAttribute('val', $crossesAt);
2490+
$objWriter->endElement();
2491+
}
24832492

24842493
if (Chart\Axis::AXIS_X == $typeAxis) {
24852494
// c:lblAlgn

tests/PhpPresentation/Tests/Shape/Chart/AxisTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ public function testBounds(): void
6161
$this->assertNull($object->getMaxBounds());
6262
}
6363

64+
public function testCrossesAt(): void
65+
{
66+
$object = new Axis();
67+
68+
$this->assertEquals(Axis::CROSSES_AUTO, $object->getCrossesAt());
69+
$this->assertInstanceOf(Axis::class, $object->setCrossesAt(Axis::CROSSES_MAX));
70+
$this->assertEquals(Axis::CROSSES_MAX, $object->getCrossesAt());
71+
}
72+
73+
public function testIsReversedOrder(): void
74+
{
75+
$object = new Axis();
76+
$this->assertFalse($object->isReversedOrder());
77+
$this->assertInstanceOf(Axis::class, $object->setIsReversedOrder(true));
78+
$this->assertTrue($object->isReversedOrder());
79+
$this->assertInstanceOf(Axis::class, $object->setIsReversedOrder(false));
80+
$this->assertFalse($object->isReversedOrder());
81+
}
82+
6483
public function testFont(): void
6584
{
6685
$object = new Axis();

tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptChartsTest.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,85 @@ public function testAxisBounds(): void
276276
$this->assertIsSchemaECMA376Valid();
277277
}
278278

279+
public function testAxisCrosses(): void
280+
{
281+
$oSeries = new Series('Downloads', $this->seriesData);
282+
$oSeries->getFill()->setStartColor(new Color('FFAABBCC'));
283+
$oLine = new Line();
284+
$oLine->addSeries($oSeries);
285+
$oShape = $this->oPresentation->getActiveSlide()->createChartShape();
286+
$oShape->getPlotArea()->setType($oLine);
287+
288+
$elementCrosses = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crosses';
289+
$elementCrossesAt = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crossesAt';
290+
$elementAxPos = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:axPos';
291+
292+
// Default autoZero
293+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
294+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'autoZero');
295+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
296+
$this->assertIsSchemaECMA376Valid();
297+
298+
// Crosses max
299+
$oShape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MAX);
300+
$this->resetPresentationFile();
301+
302+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
303+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'max');
304+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 't');
305+
$this->assertIsSchemaECMA376Valid();
306+
307+
// Crosses min
308+
$oShape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MIN);
309+
$this->resetPresentationFile();
310+
311+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
312+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'min');
313+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
314+
$this->assertIsSchemaECMA376Valid();
315+
316+
// Crosses custom value
317+
$oShape->getPlotArea()->getAxisX()->setCrossesAt('10');
318+
$this->resetPresentationFile();
319+
320+
$this->assertZipXmlElementNotExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
321+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrossesAt);
322+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrossesAt, 'val', '10');
323+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
324+
$this->assertIsSchemaECMA376Valid();
325+
}
326+
327+
public function testIsReversedOrder(): void
328+
{
329+
$element = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:scaling/c:orientation';
330+
331+
$oSlide = $this->oPresentation->getActiveSlide();
332+
$oShape = $oSlide->createChartShape();
333+
$oLine = new Line();
334+
$oShape->getPlotArea()->setType($oLine);
335+
336+
// default
337+
$this->assertFalse($oShape->getPlotArea()->getAxisX()->isReversedOrder());
338+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', 'minMax');
339+
$this->assertIsSchemaECMA376Valid();
340+
341+
// reversed order
342+
$this->assertInstanceOf(Axis::class, $oShape->getPlotArea()->getAxisX()->setIsReversedOrder(true));
343+
$this->resetPresentationFile();
344+
345+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $element);
346+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', 'maxMin');
347+
$this->assertIsSchemaECMA376Valid();
348+
349+
// reset reversed order
350+
$this->assertInstanceOf(Axis::class, $oShape->getPlotArea()->getAxisX()->setIsReversedOrder(false));
351+
$this->resetPresentationFile();
352+
353+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $element);
354+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', 'minMax');
355+
$this->assertIsSchemaECMA376Valid();
356+
}
357+
279358
public function testAxisFont(): void
280359
{
281360
$oSlide = $this->oPresentation->getActiveSlide();

0 commit comments

Comments
 (0)