add support for number formats
This commit is contained in:
parent
39d16b5bbf
commit
a8b3568719
114
src/Spout/Common/Entity/Style/NumberFormat.php
Normal file
114
src/Spout/Common/Entity/Style/NumberFormat.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Box\Spout\Common\Entity\Style;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Style
|
||||||
|
* Represents a style to be applied to a cell
|
||||||
|
*/
|
||||||
|
class NumberFormat
|
||||||
|
{
|
||||||
|
const TYPE_CURRENCY = 1;
|
||||||
|
const TYPE_PERCENTAGE = 2;
|
||||||
|
const TYPE_NUMERIC = 3;
|
||||||
|
|
||||||
|
const TYPES = [
|
||||||
|
self::TYPE_CURRENCY,
|
||||||
|
self::TYPE_PERCENTAGE,
|
||||||
|
self::TYPE_NUMERIC,
|
||||||
|
];
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
private $minDecimalPlaces;
|
||||||
|
private $maxDecimalPlaces;
|
||||||
|
|
||||||
|
private $currencySymbol;
|
||||||
|
|
||||||
|
private $commas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @return NumberFormat
|
||||||
|
*/
|
||||||
|
public function setId($id)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int|null
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $type
|
||||||
|
* @return NumberFormat
|
||||||
|
*/
|
||||||
|
public function setType($type)
|
||||||
|
{
|
||||||
|
if (!in_array($type,self::TYPES)) {
|
||||||
|
return $this;
|
||||||
|
//todo throw some excpection or something
|
||||||
|
}
|
||||||
|
$this->type = $type;
|
||||||
|
if ($type == self::TYPE_CURRENCY) {
|
||||||
|
if (($this->minDecimalPlaces === null) && ($this->maxDecimalPlaces === null)) {
|
||||||
|
$this->setDecimalPlaces(2,2);
|
||||||
|
}
|
||||||
|
if ($this->currencySymbol === null) {
|
||||||
|
$this->setCurrencySymbol('$');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $minDecimalPlaces
|
||||||
|
* @param int $maxDecimalPlaces
|
||||||
|
* @return NumberFormat
|
||||||
|
*/
|
||||||
|
public function setDecimalPlaces(int $minDecimalPlaces = null, int $maxDecimalPlaces = null)
|
||||||
|
{
|
||||||
|
$this->minDecimalPlaces = $minDecimalPlaces;
|
||||||
|
$this->maxDecimalPlaces = $maxDecimalPlaces;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $currencySymbol
|
||||||
|
* @return NumberFormat
|
||||||
|
*/
|
||||||
|
public function setCurrencySymbol(string $currencySymbol)
|
||||||
|
{
|
||||||
|
$this->currencySymbol = $currencySymbol;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFormatCode()
|
||||||
|
{
|
||||||
|
//todo spit out xml tag
|
||||||
|
$formatString = $this->type == self::TYPE_CURRENCY ? '$_' : '';
|
||||||
|
$formatString .= ($this->commas ? '#,##0' : '#0');
|
||||||
|
$formatString .= '.';
|
||||||
|
for ($i = 0; $i < $this->minDecimalPlaces; $i++) {
|
||||||
|
$formatString .= '0';
|
||||||
|
}
|
||||||
|
for ($i = $this->minDecimalPlaces; $i < $this->maxDecimalPlaces; $i++) {
|
||||||
|
$formatString .= '#';
|
||||||
|
}
|
||||||
|
if ($this->type == self::TYPE_PERCENTAGE) {
|
||||||
|
$formatString .= '%';
|
||||||
|
}
|
||||||
|
return $formatString;
|
||||||
|
}
|
||||||
|
}
|
@ -71,6 +71,8 @@ class Style
|
|||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $hasSetBackgroundColor = false;
|
private $hasSetBackgroundColor = false;
|
||||||
|
|
||||||
|
private $numberFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int|null
|
* @return int|null
|
||||||
*/
|
*/
|
||||||
@ -110,6 +112,25 @@ class Style
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return NumberFormat
|
||||||
|
*/
|
||||||
|
public function getNumberFormat()
|
||||||
|
{
|
||||||
|
return $this->numberFormat ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param NumberFormat $format
|
||||||
|
* @return Style
|
||||||
|
*/
|
||||||
|
public function setNumberFormat(NumberFormat $format)
|
||||||
|
{
|
||||||
|
$this->numberFormat = $format;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Box\Spout\Writer\Common\Manager\Style;
|
namespace Box\Spout\Writer\Common\Manager\Style;
|
||||||
|
|
||||||
|
use Box\Spout\Common\Entity\Style\NumberFormat;
|
||||||
use Box\Spout\Common\Entity\Style\Style;
|
use Box\Spout\Common\Entity\Style\Style;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,10 +13,13 @@ class StyleRegistry
|
|||||||
{
|
{
|
||||||
/** @var array [SERIALIZED_STYLE] => [STYLE_ID] mapping table, keeping track of the registered styles */
|
/** @var array [SERIALIZED_STYLE] => [STYLE_ID] mapping table, keeping track of the registered styles */
|
||||||
protected $serializedStyleToStyleIdMappingTable = [];
|
protected $serializedStyleToStyleIdMappingTable = [];
|
||||||
|
protected $serializedNumberFormatToFormatIdMappingTable = [];
|
||||||
|
|
||||||
/** @var array [STYLE_ID] => [STYLE] mapping table, keeping track of the registered styles */
|
/** @var array [STYLE_ID] => [STYLE] mapping table, keeping track of the registered styles */
|
||||||
protected $styleIdToStyleMappingTable = [];
|
protected $styleIdToStyleMappingTable = [];
|
||||||
|
|
||||||
|
protected $numberFormats = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Style $defaultStyle
|
* @param Style $defaultStyle
|
||||||
*/
|
*/
|
||||||
@ -34,6 +38,11 @@ class StyleRegistry
|
|||||||
*/
|
*/
|
||||||
public function registerStyle(Style $style)
|
public function registerStyle(Style $style)
|
||||||
{
|
{
|
||||||
|
$format = $style->getNumberFormat();
|
||||||
|
if (!empty($format)) {
|
||||||
|
$registeredFormat = $this->registerNumberFormat($format);
|
||||||
|
$style->setNumberFormat($registeredFormat);
|
||||||
|
}
|
||||||
$serializedStyle = $this->serialize($style);
|
$serializedStyle = $this->serialize($style);
|
||||||
|
|
||||||
if (!$this->hasStyleAlreadyBeenRegistered($style)) {
|
if (!$this->hasStyleAlreadyBeenRegistered($style)) {
|
||||||
@ -47,6 +56,19 @@ class StyleRegistry
|
|||||||
return $this->getStyleFromSerializedStyle($serializedStyle);
|
return $this->getStyleFromSerializedStyle($serializedStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function registerNumberFormat(NumberFormat $format)
|
||||||
|
{
|
||||||
|
$serializedFormat = $this->serializeFormat($format);
|
||||||
|
if (!$this->hasFormatAlreadyBeenRegistered($format)) {
|
||||||
|
$nextFormatId = count($this->serializedNumberFormatToFormatIdMappingTable);
|
||||||
|
$format->setId($nextFormatId);
|
||||||
|
|
||||||
|
$this->serializedNumberFormatToFormatIdMappingTable[$serializedFormat] = $nextFormatId;
|
||||||
|
$this->numberFormats[$nextFormatId] = $format;
|
||||||
|
}
|
||||||
|
return $this->getFormatFromSerializedFormat($serializedFormat);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given style has already been registered.
|
* Returns whether the given style has already been registered.
|
||||||
*
|
*
|
||||||
@ -61,6 +83,20 @@ class StyleRegistry
|
|||||||
return isset($this->serializedStyleToStyleIdMappingTable[$serializedStyle]);
|
return isset($this->serializedStyleToStyleIdMappingTable[$serializedStyle]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given number format has already been registered.
|
||||||
|
*
|
||||||
|
* @param NumberFormat $format
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function hasFormatAlreadyBeenRegistered(NumberFormat $format)
|
||||||
|
{
|
||||||
|
$serializedFormat = $this->serializeFormat($format);
|
||||||
|
|
||||||
|
// Using isset here because it is way faster than array_key_exists...
|
||||||
|
return isset($this->serializedNumberFormatToFormatIdMappingTable[$serializedFormat]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the registered style associated to the given serialization.
|
* Returns the registered style associated to the given serialization.
|
||||||
*
|
*
|
||||||
@ -74,6 +110,19 @@ class StyleRegistry
|
|||||||
return $this->styleIdToStyleMappingTable[$styleId];
|
return $this->styleIdToStyleMappingTable[$styleId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the registered number format associated to the given serialization.
|
||||||
|
*
|
||||||
|
* @param string $serializedFormat The serialized number format from which the actual format should be fetched from
|
||||||
|
* @return NumberFormat
|
||||||
|
*/
|
||||||
|
protected function getFormatFromSerializedFormat($serializedFormat)
|
||||||
|
{
|
||||||
|
$formatId = $this->serializedNumberFormatToFormatIdMappingTable[$serializedFormat];
|
||||||
|
|
||||||
|
return $this->numberFormats[$formatId];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Style[] List of registered styles
|
* @return Style[] List of registered styles
|
||||||
*/
|
*/
|
||||||
@ -82,6 +131,14 @@ class StyleRegistry
|
|||||||
return array_values($this->styleIdToStyleMappingTable);
|
return array_values($this->styleIdToStyleMappingTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return NumberFormat[] List of registered number formats
|
||||||
|
*/
|
||||||
|
public function getRegisteredNumberFormats()
|
||||||
|
{
|
||||||
|
return array_values($this->numberFormats);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $styleId
|
* @param int $styleId
|
||||||
* @return Style
|
* @return Style
|
||||||
@ -111,4 +168,25 @@ class StyleRegistry
|
|||||||
|
|
||||||
return $serializedStyle;
|
return $serializedStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the number format for future comparison with other formats.
|
||||||
|
* The ID is excluded from the comparison, as we only care about
|
||||||
|
* actual number format properties.
|
||||||
|
*
|
||||||
|
* @param Style $style
|
||||||
|
* @return string The serialized style
|
||||||
|
*/
|
||||||
|
public function serializeFormat(NumberFormat $format)
|
||||||
|
{
|
||||||
|
// In order to be able to properly compare style, set static ID value
|
||||||
|
$currentId = $format->getId();
|
||||||
|
$format->setId(0);
|
||||||
|
|
||||||
|
$serializedFormat = serialize($format);
|
||||||
|
|
||||||
|
$format->setId($currentId);
|
||||||
|
|
||||||
|
return $serializedFormat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class StyleManager extends \Box\Spout\Writer\Common\Manager\Style\StyleManager
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
||||||
EOD;
|
EOD;
|
||||||
|
$content .= $this->getNumberFormatSectionContent();
|
||||||
$content .= $this->getFontsSectionContent();
|
$content .= $this->getFontsSectionContent();
|
||||||
$content .= $this->getFillsSectionContent();
|
$content .= $this->getFillsSectionContent();
|
||||||
$content .= $this->getBordersSectionContent();
|
$content .= $this->getBordersSectionContent();
|
||||||
@ -62,6 +62,22 @@ EOD;
|
|||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getNumberFormatSectionContent()
|
||||||
|
{
|
||||||
|
$registeredFormats = $this->styleRegistry->getRegisteredNumberFormats();
|
||||||
|
if (empty($registeredFormats)) {
|
||||||
|
return '<numFmts count="0"/>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = '<numFmts count="'.count($registeredFormats).'">';
|
||||||
|
foreach ($registeredFormats as $format) {
|
||||||
|
|
||||||
|
$content .= '<numFmt numFmtId="'.$format->getId().'" formatCode="'.$format->getFormatCode().'"/>';
|
||||||
|
}
|
||||||
|
$content .= '</numFmts>';
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the content of the "<fonts>" section.
|
* Returns the content of the "<fonts>" section.
|
||||||
*
|
*
|
||||||
@ -207,7 +223,7 @@ EOD;
|
|||||||
$fillId = $this->getFillIdForStyleId($styleId);
|
$fillId = $this->getFillIdForStyleId($styleId);
|
||||||
$borderId = $this->getBorderIdForStyleId($styleId);
|
$borderId = $this->getBorderIdForStyleId($styleId);
|
||||||
|
|
||||||
$content .= '<xf numFmtId="0" fontId="' . $styleId . '" fillId="' . $fillId . '" borderId="' . $borderId . '" xfId="0"';
|
$content .= '<xf numFmtId="'.$style->getNumberFormat()->getId().'" fontId="' . $styleId . '" fillId="' . $fillId . '" borderId="' . $borderId . '" xfId="0"';
|
||||||
|
|
||||||
if ($style->shouldApplyFont()) {
|
if ($style->shouldApplyFont()) {
|
||||||
$content .= ' applyFont="1"';
|
$content .= ' applyFont="1"';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user