Cell alignment

This PR adds support for cell alignment for XLSX and ODS files.
You can now align the content of the cells this way:
```
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Writer\Common\Creator\Style\StyleBuilder;

$style = (new StyleBuilder())
    ->setCellAlignment(CellAlignment::RIGHT)
    ->build();
...
```

Possible cell alignments are: LEFT, RIGHT, CENTER and JUSTIFY.
This commit is contained in:
Adrien Loison committed 2019-10-27 18:58:56 +01:00
1 parent 0a0b1f7196
commit 9f4c094fa0
12 files changed
+246 -46

No files matched your search

@@ -0,0 +1,32 @@
<?php
namespace Box\Spout\Common\Entity\Style;
/**
* Class Alignment
* This class provides constants to work with text alignment.
*/
abstract class CellAlignment
{
const LEFT = 'left';
const RIGHT = 'right';
const CENTER = 'center';
const JUSTIFY = 'justify';
private static $VALID_ALIGNMENTS = [
self::LEFT => 1,
self::RIGHT => 1,
self::CENTER => 1,
self::JUSTIFY => 1,
];
/**
* @param string $cellAlignment
*
* @return bool Whether the given cell alignment is valid
*/
public static function isValid($cellAlignment)
{
return isset(self::$VALID_ALIGNMENTS[$cellAlignment]);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ use Box\Spout\Common\Exception\InvalidColorException;
* Class Color
* This class provides constants and functions to work with colors
*/
class Color
abstract class Color
{
/** Standard colors - based on Office Online */
const BLACK = '000000';
+46 -1
View File
@@ -8,7 +8,7 @@ namespace Box\Spout\Common\Entity\Style;
*/
class Style
{
/** Default font values */
/** Default values */
const DEFAULT_FONT_SIZE = 11;
const DEFAULT_FONT_COLOR = Color::BLACK;
const DEFAULT_FONT_NAME = 'Arial';
@@ -54,6 +54,13 @@ class Style
/** @var bool Whether specific font properties should be applied */
private $shouldApplyFont = false;
/** @var bool Whether specific cell alignment should be applied */
private $shouldApplyCellAlignment = false;
/** @var string Cell alignment */
private $cellAlignment;
/** @var bool Whether the cell alignment property was set */
private $hasSetCellAlignment = false;
/** @var bool Whether the text should wrap in the cell (useful for long or multi-lines text) */
private $shouldWrapText = false;
/** @var bool Whether the wrap text property was set */
@@ -325,6 +332,44 @@ class Style
return $this->hasSetFontName;
}
/**
* @return string
*/
public function getCellAlignment()
{
return $this->cellAlignment;
}
/**
* @param string $cellAlignment The cell alignment
*
* @return Style
*/
public function setCellAlignment($cellAlignment)
{
$this->cellAlignment = $cellAlignment;
$this->hasSetCellAlignment = true;
$this->shouldApplyCellAlignment = true;
return $this;
}
/**
* @return bool
*/
public function hasSetCellAlignment()
{
return $this->hasSetCellAlignment;
}
/**
* @return bool Whether specific cell alignment should be applied
*/
public function shouldApplyCellAlignment()
{
return $this->shouldApplyCellAlignment;
}
/**
* @return bool
*/
@@ -3,7 +3,9 @@
namespace Box\Spout\Writer\Common\Creator\Style;
use Box\Spout\Common\Entity\Style\Border;
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Common\Entity\Style\Style;
use Box\Spout\Common\Exception\InvalidArgumentException;
/**
* Class StyleBuilder
@@ -122,6 +124,25 @@ class StyleBuilder
return $this;
}
/**
* Sets the cell alignment.
*
* @param string $cellAlignment The cell alignment
*
* @throws InvalidArgumentException If the given cell alignment is not valid
* @return StyleBuilder
*/
public function setCellAlignment($cellAlignment)
{
if (!CellAlignment::isValid($cellAlignment)) {
throw new InvalidArgumentException('Invalid cell alignment value');
}
$this->style->setCellAlignment($cellAlignment);
return $this;
}
/**
* Set a border
*
@@ -85,6 +85,9 @@ class StyleMerger
if (!$style->hasSetWrapText() && $baseStyle->shouldWrapText()) {
$styleToUpdate->setShouldWrapText();
}
if (!$style->hasSetCellAlignment() && $baseStyle->shouldApplyCellAlignment()) {
$styleToUpdate->setCellAlignment($baseStyle->getCellAlignment());
}
if (!$style->getBorder() && $baseStyle->shouldApplyBorder()) {
$styleToUpdate->setBorder($baseStyle->getBorder());
}
@@ -3,6 +3,7 @@
namespace Box\Spout\Writer\ODS\Manager\Style;
use Box\Spout\Common\Entity\Style\BorderPart;
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\ODS\Helper\BorderHelper;
@@ -199,6 +200,7 @@ EOD;
$content = '<style:style style:data-style-name="N0" style:family="table-cell" style:name="ce' . $styleIndex . '" style:parent-style-name="Default">';
$content .= $this->getTextPropertiesSectionContent($style);
$content .= $this->getParagraphPropertiesSectionContent($style);
$content .= $this->getTableCellPropertiesSectionContent($style);
$content .= '</style:style>';
@@ -214,26 +216,26 @@ EOD;
*/
private function getTextPropertiesSectionContent($style)
{
$content = '';
if ($style->shouldApplyFont()) {
$content .= $this->getFontSectionContent($style);
if (!$style->shouldApplyFont()) {
return '';
}
return $content;
return '<style:text-properties '
. $this->getFontSectionContent($style)
. '/>';
}
/**
* Returns the contents of the "<style:text-properties>" section, inside "<style:style>" section
* Returns the contents of the fonts definition section, inside "<style:text-properties>" section
*
* @param \Box\Spout\Common\Entity\Style\Style $style
*
* @return string
*/
private function getFontSectionContent($style)
{
$defaultStyle = $this->getDefaultStyle();
$content = '<style:text-properties';
$content = '';
$fontColor = $style->getFontColor();
if ($fontColor !== $defaultStyle->getFontColor()) {
@@ -263,11 +265,60 @@ EOD;
$content .= ' style:text-line-through-style="solid"';
}
$content .= '/>';
return $content;
}
/**
* Returns the contents of the "<style:paragraph-properties>" section, inside "<style:style>" section
*
* @param \Box\Spout\Common\Entity\Style\Style $style
*
* @return string
*/
private function getParagraphPropertiesSectionContent($style)
{
if (!$style->shouldApplyCellAlignment()) {
return '';
}
return '<style:paragraph-properties '
. $this->getCellAlignmentSectionContent($style)
. '/>';
}
/**
* Returns the contents of the cell alignment definition for the "<style:paragraph-properties>" section
*
* @param \Box\Spout\Common\Entity\Style\Style $style
*
* @return string
*/
private function getCellAlignmentSectionContent($style)
{
return sprintf(
' fo:text-align="%s" ',
$this->transformCellAlignment($style->getCellAlignment())
);
}
/**
* Even though "left" and "right" alignments are part of the spec, and interpreted
* respectively as "start" and "end", using the recommended values increase compatibility
* with software that will read the created ODS file.
*
* @param string $cellAlignment
*
* @return string
*/
private function transformCellAlignment($cellAlignment)
{
switch ($cellAlignment) {
case CellAlignment::LEFT: return 'start';
case CellAlignment::RIGHT: return 'end';
default: return $cellAlignment;
}
}
/**
* Returns the contents of the "<style:table-cell-properties>" section, inside "<style:style>" section
*
@@ -276,7 +327,7 @@ EOD;
*/
private function getTableCellPropertiesSectionContent($style)
{
$content = '';
$content = '<style:table-cell-properties ';
if ($style->shouldWrapText()) {
$content .= $this->getWrapTextXMLContent();
@@ -290,6 +341,8 @@ EOD;
$content .= $this->getBackgroundColorXMLContent($style);
}
$content .= '/>';
return $content;
}
@@ -300,7 +353,7 @@ EOD;
*/
private function getWrapTextXMLContent()
{
return '<style:table-cell-properties fo:wrap-option="wrap" style:vertical-align="automatic"/>';
return ' fo:wrap-option="wrap" style:vertical-align="automatic" ';
}
/**
@@ -311,13 +364,11 @@ EOD;
*/
private function getBorderXMLContent($style)
{
$borderProperty = '<style:table-cell-properties %s />';
$borders = array_map(function (BorderPart $borderPart) {
return BorderHelper::serializeBorderPart($borderPart);
}, $style->getBorder()->getParts());
return sprintf($borderProperty, implode(' ', $borders));
return sprintf(' %s ', implode(' ', $borders));
}
/**
@@ -328,9 +379,6 @@ EOD;
*/
private function getBackgroundColorXMLContent($style)
{
return sprintf(
'<style:table-cell-properties fo:background-color="#%s"/>',
$style->getBackgroundColor()
);
return sprintf(' fo:background-color="#%s" ', $style->getBackgroundColor());
}
}
@@ -249,9 +249,16 @@ EOD;
$content .= sprintf(' applyBorder="%d"', $style->shouldApplyBorder() ? 1 : 0);
if ($style->shouldWrapText()) {
if ($style->shouldApplyCellAlignment() || $style->shouldWrapText()) {
$content .= ' applyAlignment="1">';
$content .= '<alignment wrapText="1"/>';
$content .= '<alignment';
if ($style->shouldApplyCellAlignment()) {
$content .= sprintf(' horizontal="%s"', $style->getCellAlignment());
}
if ($style->shouldWrapText()) {
$content .= ' wrapText="1"';
}
$content .= '/>';
$content .= '</xf>';
} else {
$content .= '/>';