Skip to content
This repository was archived by the owner on May 26, 2022. It is now read-only.

Commit 887d6ef

Browse files
committed
Add setCellVerticalAlignment() & allow setShouldWrapText() to be explicitly set as false
- add Common\Entity\Style\CellVerticalAlignment - duplicate get/set/hasSet/shouldApply methods for CellAlignment in Common\Entity\Style\Style for CellVerticalAlignment instead, plus corresponding properties - add setCellVerticalAlignment method to Common\Creator\Style\StyleBuilder - add vertical alignment to StyleMerger:: mergeCellProperties() - adjust wrapText logic in mergeCellProperties() to fix issue #829 - apply vertical cell styling for both XLSX and ODS, via corresponding StyleManager classes - transform vertical alignment ‘center’ to ‘middle’ for ODS - fix logic around wrapText such that the choice whether to include wrapping styles depends on hasSetWrapText() being true, and then use shouldWrapText() thereafter to either set wrapping or no wrapping (for XLSX, wrapText=“1” or wrapText=“0”, for ODS, wrap-option=wrap or wrap-option=no-wrap). previously there was no way to set wrapping to be OFF, only to set it to be ON. - add new tests to ensure shouldWrapText(false) results in the correct negated wrapText (XLSX) / wrap-option (ODS) styles - add new tests to StyleBuilderTest for vertical alignment - add vertical alignment to documentation.md
1 parent cc42c1d commit 887d6ef

File tree

11 files changed

+229
-24
lines changed

11 files changed

+229
-24
lines changed

docs/_pages/documentation.md

+15-13
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,20 @@ $reader->setShouldPreserveEmptyRows(true);
116116

117117
For fonts and alignments, {{ site.spout_html }} does not support all the possible formatting options yet. But you can find the most important ones:
118118

119-
| Category | Property | API
120-
|:---------------------|:---------------|:--------------------------------------
121-
| Font | Bold | `StyleBuilder::setFontBold()`
122-
| | Italic | `StyleBuilder::setFontItalic()`
123-
| | Underline | `StyleBuilder::setFontUnderline()`
124-
| | Strikethrough | `StyleBuilder::setFontStrikethrough()`
125-
| | Font name | `StyleBuilder::setFontName('Arial')`
126-
| | Font size | `StyleBuilder::setFontSize(14)`
127-
| | Font color | `StyleBuilder::setFontColor(Color::BLUE)`<br>`StyleBuilder::setFontColor(Color::rgb(0, 128, 255))`
128-
| Alignment | Cell alignment | `StyleBuilder::setCellAlignment(CellAlignment::CENTER)`
129-
| | Wrap text | `StyleBuilder::setShouldWrapText(true)`
130-
| Format _(XLSX only)_ | Number format | `StyleBuilder::setFormat('0.000')`
131-
| | Date format | `StyleBuilder::setFormat('m/d/yy h:mm')`
119+
| Category | Property | API
120+
|:---------------------|:------------------------|:--------------------------------------
121+
| Font | Bold | `StyleBuilder::setFontBold()`
122+
| | Italic | `StyleBuilder::setFontItalic()`
123+
| | Underline | `StyleBuilder::setFontUnderline()`
124+
| | Strikethrough | `StyleBuilder::setFontStrikethrough()`
125+
| | Font name | `StyleBuilder::setFontName('Arial')`
126+
| | Font size | `StyleBuilder::setFontSize(14)`
127+
| | Font color | `StyleBuilder::setFontColor(Color::BLUE)`<br>`StyleBuilder::setFontColor(Color::rgb(0, 128, 255))`
128+
| Alignment | Cell alignment | `StyleBuilder::setCellAlignment(CellAlignment::CENTER)`
129+
| | Cell vertical alignment | `StyleBuilder::setCellVerticalAlignment(CellVerticalAlignment::CENTER)`
130+
| | Wrap text | `StyleBuilder::setShouldWrapText(true)`
131+
| Format _(XLSX only)_ | Number format | `StyleBuilder::setFormat('0.000')`
132+
| | Date format | `StyleBuilder::setFormat('m/d/yy h:mm')`
132133

133134
### Styling rows
134135

@@ -150,6 +151,7 @@ $style = (new StyleBuilder())
150151
->setFontColor(Color::BLUE)
151152
->setShouldWrapText()
152153
->setCellAlignment(CellAlignment::RIGHT)
154+
->setCellVerticalAlignment(CellVerticalAlignment::BOTTOM)
153155
->setBackgroundColor(Color::YELLOW)
154156
->build();
155157

src/Spout/Common/Entity/Style/CellAlignment.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Box\Spout\Common\Entity\Style;
44

55
/**
6-
* Class Alignment
6+
* Class CellAlignment
77
* This class provides constants to work with text alignment.
88
*/
99
abstract class CellAlignment
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Box\Spout\Common\Entity\Style;
4+
5+
/**
6+
* Class CellVerticalAlignment
7+
* This class provides constants to work with text vertical alignment.
8+
*/
9+
abstract class CellVerticalAlignment
10+
{
11+
public const AUTO = 'auto';
12+
public const BASELINE = 'baseline';
13+
public const BOTTOM = 'bottom';
14+
public const CENTER = 'center';
15+
public const DISTRIBUTED = 'distributed';
16+
public const JUSTIFY = 'justify';
17+
public const TOP = 'top';
18+
19+
private static $VALID_ALIGNMENTS = [
20+
self::AUTO => 1,
21+
self::BASELINE => 1,
22+
self::BOTTOM => 1,
23+
self::CENTER => 1,
24+
self::DISTRIBUTED => 1,
25+
self::JUSTIFY => 1,
26+
self::TOP => 1,
27+
];
28+
29+
/**
30+
* @param string $cellVerticalAlignment
31+
*
32+
* @return bool Whether the given cell vertical alignment is valid
33+
*/
34+
public static function isValid($cellVerticalAlignment)
35+
{
36+
return isset(self::$VALID_ALIGNMENTS[$cellVerticalAlignment]);
37+
}
38+
}

src/Spout/Common/Entity/Style/Style.php

+46
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ class Style
6161
/** @var bool Whether the cell alignment property was set */
6262
private $hasSetCellAlignment = false;
6363

64+
/** @var bool Whether specific cell vertical alignment should be applied */
65+
private $shouldApplyCellVerticalAlignment = false;
66+
/** @var string Cell vertical alignment */
67+
private $cellVerticalAlignment;
68+
/** @var bool Whether the cell vertical alignment property was set */
69+
private $hasSetCellVerticalAlignment = false;
70+
6471
/** @var bool Whether the text should wrap in the cell (useful for long or multi-lines text) */
6572
private $shouldWrapText = false;
6673
/** @var bool Whether the wrap text property was set */
@@ -354,6 +361,14 @@ public function getCellAlignment()
354361
return $this->cellAlignment;
355362
}
356363

364+
/**
365+
* @return string
366+
*/
367+
public function getCellVerticalAlignment()
368+
{
369+
return $this->cellVerticalAlignment;
370+
}
371+
357372
/**
358373
* @param string $cellAlignment The cell alignment
359374
*
@@ -369,6 +384,21 @@ public function setCellAlignment($cellAlignment)
369384
return $this;
370385
}
371386

387+
/**
388+
* @param string $cellVerticalAlignment The cell vertical alignment
389+
*
390+
* @return Style
391+
*/
392+
public function setCellVerticalAlignment($cellVerticalAlignment)
393+
{
394+
$this->cellVerticalAlignment = $cellVerticalAlignment;
395+
$this->hasSetCellVerticalAlignment = true;
396+
$this->shouldApplyCellVerticalAlignment = true;
397+
$this->isEmpty = false;
398+
399+
return $this;
400+
}
401+
372402
/**
373403
* @return bool
374404
*/
@@ -377,6 +407,14 @@ public function hasSetCellAlignment()
377407
return $this->hasSetCellAlignment;
378408
}
379409

410+
/**
411+
* @return bool
412+
*/
413+
public function hasSetCellVerticalAlignment()
414+
{
415+
return $this->hasSetCellVerticalAlignment;
416+
}
417+
380418
/**
381419
* @return bool Whether specific cell alignment should be applied
382420
*/
@@ -385,6 +423,14 @@ public function shouldApplyCellAlignment()
385423
return $this->shouldApplyCellAlignment;
386424
}
387425

426+
/**
427+
* @return bool Whether specific cell alignment should be applied
428+
*/
429+
public function shouldApplyCellVerticalAlignment()
430+
{
431+
return $this->shouldApplyCellVerticalAlignment;
432+
}
433+
388434
/**
389435
* @return bool
390436
*/

src/Spout/Writer/Common/Creator/Style/StyleBuilder.php

+20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Box\Spout\Common\Entity\Style\Border;
66
use Box\Spout\Common\Entity\Style\CellAlignment;
7+
use Box\Spout\Common\Entity\Style\CellVerticalAlignment;
78
use Box\Spout\Common\Entity\Style\Style;
89
use Box\Spout\Common\Exception\InvalidArgumentException;
910

@@ -143,6 +144,25 @@ public function setCellAlignment($cellAlignment)
143144
return $this;
144145
}
145146

147+
/**
148+
* Sets the cell vertical alignment.
149+
*
150+
* @param string $cellVerticalAlignment The cell vertical alignment
151+
*
152+
* @throws InvalidArgumentException If the given cell vertical alignment is not valid
153+
* @return StyleBuilder
154+
*/
155+
public function setCellVerticalAlignment($cellVerticalAlignment)
156+
{
157+
if (!CellVerticalAlignment::isValid($cellVerticalAlignment)) {
158+
throw new InvalidArgumentException('Invalid cell vertical alignment value');
159+
}
160+
161+
$this->style->setCellVerticalAlignment($cellVerticalAlignment);
162+
163+
return $this;
164+
}
165+
146166
/**
147167
* Set a border
148168
*

src/Spout/Writer/Common/Manager/Style/StyleMerger.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,15 @@ private function mergeOtherFontProperties(Style $styleToUpdate, Style $style, St
8282
*/
8383
private function mergeCellProperties(Style $styleToUpdate, Style $style, Style $baseStyle)
8484
{
85-
if (!$style->hasSetWrapText() && $baseStyle->shouldWrapText()) {
86-
$styleToUpdate->setShouldWrapText();
85+
if (!$style->hasSetWrapText() && $baseStyle->hasSetWrapText()) {
86+
$styleToUpdate->setShouldWrapText($baseStyle->shouldWrapText());
8787
}
8888
if (!$style->hasSetCellAlignment() && $baseStyle->shouldApplyCellAlignment()) {
8989
$styleToUpdate->setCellAlignment($baseStyle->getCellAlignment());
9090
}
91+
if (!$style->hasSetCellVerticalAlignment() && $baseStyle->shouldApplyCellVerticalAlignment()) {
92+
$styleToUpdate->setCellVerticalAlignment($baseStyle->getCellVerticalAlignment());
93+
}
9194
if ($style->getBorder() === null && $baseStyle->shouldApplyBorder()) {
9295
$styleToUpdate->setBorder($baseStyle->getBorder());
9396
}

src/Spout/Writer/ODS/Manager/Style/StyleManager.php

+38-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Box\Spout\Common\Entity\Style\BorderPart;
66
use Box\Spout\Common\Entity\Style\CellAlignment;
7+
use Box\Spout\Common\Entity\Style\CellVerticalAlignment;
78
use Box\Spout\Writer\Common\Entity\Worksheet;
89
use Box\Spout\Writer\ODS\Helper\BorderHelper;
910

@@ -277,12 +278,13 @@ private function getFontSectionContent($style)
277278
*/
278279
private function getParagraphPropertiesSectionContent($style)
279280
{
280-
if (!$style->shouldApplyCellAlignment()) {
281+
if (!$style->shouldApplyCellAlignment() && !$style->shouldApplyCellVerticalAlignment()) {
281282
return '';
282283
}
283284

284285
return '<style:paragraph-properties '
285286
. $this->getCellAlignmentSectionContent($style)
287+
. $this->getCellVerticalAlignmentSectionContent($style)
286288
. '/>';
287289
}
288290

@@ -301,6 +303,21 @@ private function getCellAlignmentSectionContent($style)
301303
);
302304
}
303305

306+
/**
307+
* Returns the contents of the cell vertical alignment definition for the "<style:paragraph-properties>" section
308+
*
309+
* @param \Box\Spout\Common\Entity\Style\Style $style
310+
*
311+
* @return string
312+
*/
313+
private function getCellVerticalAlignmentSectionContent($style)
314+
{
315+
return \sprintf(
316+
' fo:vertical-align="%s" ',
317+
$this->transformCellVerticalAlignment($style->getCellVerticalAlignment())
318+
);
319+
}
320+
304321
/**
305322
* Even though "left" and "right" alignments are part of the spec, and interpreted
306323
* respectively as "start" and "end", using the recommended values increase compatibility
@@ -319,6 +336,21 @@ private function transformCellAlignment($cellAlignment)
319336
}
320337
}
321338

339+
/**
340+
* Spec uses 'middle' rather than 'center'
341+
* http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1420236_253892949
342+
*
343+
* @param string $cellAlignment
344+
*
345+
* @return string
346+
*/
347+
private function transformCellVerticalAlignment($cellVerticalAlignment)
348+
{
349+
return ($cellVerticalAlignment === CellVerticalAlignment::CENTER)
350+
? 'middle'
351+
: $cellVerticalAlignment;
352+
}
353+
322354
/**
323355
* Returns the contents of the "<style:table-cell-properties>" section, inside "<style:style>" section
324356
*
@@ -329,8 +361,8 @@ private function getTableCellPropertiesSectionContent($style)
329361
{
330362
$content = '<style:table-cell-properties ';
331363

332-
if ($style->shouldWrapText()) {
333-
$content .= $this->getWrapTextXMLContent();
364+
if ($style->hasSetWrapText()) {
365+
$content .= $this->getWrapTextXMLContent($style->shouldWrapText());
334366
}
335367

336368
if ($style->shouldApplyBorder()) {
@@ -349,11 +381,12 @@ private function getTableCellPropertiesSectionContent($style)
349381
/**
350382
* Returns the contents of the wrap text definition for the "<style:table-cell-properties>" section
351383
*
384+
* @param boolean $shouldWrapText
352385
* @return string
353386
*/
354-
private function getWrapTextXMLContent()
387+
private function getWrapTextXMLContent($shouldWrapText)
355388
{
356-
return ' fo:wrap-option="wrap" style:vertical-align="automatic" ';
389+
return ' fo:wrap-option="' . ($shouldWrapText ? '' : 'no-') . 'wrap" style:vertical-align="automatic" ';
357390
}
358391

359392
/**

src/Spout/Writer/XLSX/Manager/Style/StyleManager.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,17 @@ protected function getCellXfsSectionContent()
250250

251251
$content .= \sprintf(' applyBorder="%d"', $style->shouldApplyBorder() ? 1 : 0);
252252

253-
if ($style->shouldApplyCellAlignment() || $style->shouldWrapText()) {
253+
if ($style->shouldApplyCellAlignment() || $style->shouldApplyCellVerticalAlignment() || $style->hasSetWrapText()) {
254254
$content .= ' applyAlignment="1">';
255255
$content .= '<alignment';
256256
if ($style->shouldApplyCellAlignment()) {
257257
$content .= \sprintf(' horizontal="%s"', $style->getCellAlignment());
258258
}
259-
if ($style->shouldWrapText()) {
260-
$content .= ' wrapText="1"';
259+
if ($style->shouldApplyCellVerticalAlignment()) {
260+
$content .= \sprintf(' vertical="%s"', $style->getCellVerticalAlignment());
261+
}
262+
if ($style->hasSetWrapText()) {
263+
$content .= ' wrapText="' . ($style->shouldWrapText() ? '1' : '0') . '"';
261264
}
262265
$content .= '/>';
263266
$content .= '</xf>';

tests/Spout/Writer/Common/Creator/StyleBuilderTest.php

+19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Box\Spout\Common\Entity\Style\Border;
66
use Box\Spout\Common\Entity\Style\CellAlignment;
7+
use Box\Spout\Common\Entity\Style\CellVerticalAlignment;
78
use Box\Spout\Common\Entity\Style\Color;
89
use Box\Spout\Common\Exception\InvalidArgumentException;
910
use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
@@ -53,6 +54,15 @@ public function testStyleBuilderShouldApplyCellAlignment()
5354
$this->assertTrue($style->shouldApplyCellAlignment());
5455
}
5556

57+
/**
58+
* @return void
59+
*/
60+
public function testStyleBuilderShouldApplyCellVerticalAlignment()
61+
{
62+
$style = (new StyleBuilder())->setCellVerticalAlignment(CellVerticalAlignment::CENTER)->build();
63+
$this->assertTrue($style->shouldApplyCellVerticalAlignment());
64+
}
65+
5666
/**
5767
* @return void
5868
*/
@@ -61,4 +71,13 @@ public function testStyleBuilderShouldThrowOnInvalidCellAlignment()
6171
$this->expectException(InvalidArgumentException::class);
6272
(new StyleBuilder())->setCellAlignment('invalid_cell_alignment')->build();
6373
}
74+
75+
/**
76+
* @return void
77+
*/
78+
public function testStyleBuilderShouldThrowOnInvalidCellVerticalAlignment()
79+
{
80+
$this->expectException(InvalidArgumentException::class);
81+
(new StyleBuilder())->setCellVerticalAlignment('invalid_cell_alignment')->build();
82+
}
6483
}

0 commit comments

Comments
 (0)