Skip to content

Commit 7e3485b

Browse files
committed
Null Values in Chart
Based on PR PHPOffice#2854 by @Tom-Magill.
1 parent 095baa9 commit 7e3485b

File tree

3 files changed

+132
-6
lines changed

3 files changed

+132
-6
lines changed

src/PhpWord/Style/Chart.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ class Chart extends AbstractStyle
149149
*/
150150
private $gridX = false;
151151

152+
/**
153+
* How to display blank values (nulls) in series data.
154+
* Options: 'gap' (break line), 'span' (connect line), 'zero' (plot as zero).
155+
*
156+
* @var string
157+
*/
158+
private $displayBlanksAs = 'gap'; // Default to gap
159+
152160
/**
153161
* Create a new instance.
154162
*
@@ -548,4 +556,31 @@ public function setShowGridX($value = true)
548556

549557
return $this;
550558
}
559+
560+
/**
561+
* Set display blanks as option.
562+
*
563+
* @param string $value 'gap', 'span', or 'zero'
564+
*
565+
* @return self
566+
*/
567+
public function setDisplayBlanksAs($value)
568+
{
569+
$validValues = ['gap', 'span', 'zero'];
570+
if (in_array($value, $validValues, true)) {
571+
$this->displayBlanksAs = $value;
572+
}
573+
574+
return $this;
575+
}
576+
577+
/**
578+
* Get display blanks as option.
579+
*
580+
* @return string
581+
*/
582+
public function getDisplayBlanksAs()
583+
{
584+
return $this->displayBlanksAs;
585+
}
551586
}

src/PhpWord/Writer/Word2007/Part/Chart.php

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@ private function writePlotArea(XMLWriter $xmlWriter): void
205205
}
206206

207207
$xmlWriter->endElement(); // c:plotArea
208+
209+
$xmlWriter->startElement('c:plotVisOnly');
210+
$xmlWriter->writeAttribute('val', '1');
211+
$xmlWriter->endElement();
212+
213+
$displayBlanksAs = method_exists($style, 'getDisplayBlanksAs') ? $style->getDisplayBlanksAs() : 'gap';
214+
215+
$xmlWriter->startElement('c:dispBlanksAs');
216+
$xmlWriter->writeAttribute('val', $displayBlanksAs);
217+
$xmlWriter->endElement();
208218
}
209219

210220
/**
@@ -314,13 +324,17 @@ private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values): void
314324
foreach ($values as $value) {
315325
$xmlWriter->startElement('c:pt');
316326
$xmlWriter->writeAttribute('idx', $index);
317-
if (\PhpOffice\PhpWord\Settings::isOutputEscapingEnabled()) {
318-
$xmlWriter->writeElement('c:v', $value);
319-
} else {
320-
$xmlWriter->startElement('c:v');
321-
$xmlWriter->writeRaw($value);
322-
$xmlWriter->endElement(); // c:v
327+
328+
if ($value !== null) {
329+
if (\PhpOffice\PhpWord\Settings::isOutputEscapingEnabled()) {
330+
$xmlWriter->writeElement('c:v', $value);
331+
} else {
332+
$xmlWriter->startElement('c:v');
333+
$xmlWriter->writeRaw($value);
334+
$xmlWriter->endElement(); // c:v
335+
}
323336
}
337+
324338
$xmlWriter->endElement(); // c:pt
325339
++$index;
326340
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpWord\Tests\Writer\Word2007\Part;
4+
5+
use PhpOffice\PhpWord\Element\Chart;
6+
use PhpOffice\PhpWord\Shared\XMLWriter;
7+
use PhpOffice\PhpWord\Writer\Word2007\Part\Chart as ChartWriter;
8+
use PHPUnit\Framework\TestCase;
9+
use ReflectionClass;
10+
11+
class ChartNullHandlingTest extends TestCase
12+
{
13+
/**
14+
* Test that the Style class correctly sets/gets the property.
15+
*/
16+
public function testSetGetDisplayBlanksAs(): void
17+
{
18+
// Note: Pass empty arrays for categories/values to avoid constructor errors
19+
$chart = new Chart('line', [], []);
20+
$style = $chart->getStyle();
21+
22+
// 1. Default should be 'gap'
23+
self::assertEquals('gap', $style->getDisplayBlanksAs());
24+
25+
// 2. Test setting 'span'
26+
$style->setDisplayBlanksAs('span');
27+
self::assertEquals('span', $style->getDisplayBlanksAs());
28+
29+
// 3. Test invalid value (should remain 'span')
30+
$style->setDisplayBlanksAs('invalid_option');
31+
self::assertEquals('span', $style->getDisplayBlanksAs());
32+
}
33+
34+
public function testWriteChartHandlesNullsAndGaps(): void
35+
{
36+
// 1. Setup Data
37+
$categories = ['Jan', 'Feb', 'Mar'];
38+
$values = [10, null, 20];
39+
$seriesNames = ['My Series']; // <--- ADD THIS
40+
41+
// 2. Create Chart with Series Name
42+
$chart = new Chart('line', $categories, $values, $seriesNames);
43+
$chart->getStyle()->setDisplayBlanksAs('gap');
44+
45+
// 3. Setup Writer
46+
$xmlWriter = new XMLWriter();
47+
$chartWriter = new ChartWriter();
48+
49+
// Mock the parent writer
50+
$chartWriter->setParentWriter($this->createMock(\PhpOffice\PhpWord\Writer\Word2007::class));
51+
52+
// 4. Inject Chart into Writer
53+
$reflectionWriter = new ReflectionClass(ChartWriter::class);
54+
$elementProperty = $reflectionWriter->getProperty('element');
55+
$elementProperty->setAccessible(true);
56+
$elementProperty->setValue($chartWriter, $chart);
57+
58+
// 5. Run
59+
$method = $reflectionWriter->getMethod('writeChart');
60+
$method->setAccessible(true);
61+
$method->invokeArgs($chartWriter, [$xmlWriter]);
62+
63+
$xml = $xmlWriter->getData();
64+
65+
// --- ASSERTIONS ---
66+
self::assertStringContainsString('<c:dispBlanksAs val="gap"/>', $xml);
67+
68+
// Check for the empty point (null value)
69+
self::assertMatchesRegularExpression('/<c:pt idx="1"\s*\/?>/', $xml);
70+
71+
// Ensure no zero value was written for index 1
72+
self::assertDoesNotMatchRegularExpression(
73+
'/<c:pt idx="1"[^>]*>.*?<c:v>0<\/c:v>.*?<\/c:pt>/s',
74+
$xml
75+
);
76+
}
77+
}

0 commit comments

Comments
 (0)