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 */
|
||||
private $hasSetBackgroundColor = false;
|
||||
|
||||
private $numberFormat;
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
@ -110,6 +112,25 @@ class Style
|
||||
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
|
||||
*/
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Box\Spout\Writer\Common\Manager\Style;
|
||||
|
||||
use Box\Spout\Common\Entity\Style\NumberFormat;
|
||||
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 */
|
||||
protected $serializedStyleToStyleIdMappingTable = [];
|
||||
protected $serializedNumberFormatToFormatIdMappingTable = [];
|
||||
|
||||
/** @var array [STYLE_ID] => [STYLE] mapping table, keeping track of the registered styles */
|
||||
protected $styleIdToStyleMappingTable = [];
|
||||
|
||||
protected $numberFormats = [];
|
||||
|
||||
/**
|
||||
* @param Style $defaultStyle
|
||||
*/
|
||||
@ -34,6 +38,11 @@ class StyleRegistry
|
||||
*/
|
||||
public function registerStyle(Style $style)
|
||||
{
|
||||
$format = $style->getNumberFormat();
|
||||
if (!empty($format)) {
|
||||
$registeredFormat = $this->registerNumberFormat($format);
|
||||
$style->setNumberFormat($registeredFormat);
|
||||
}
|
||||
$serializedStyle = $this->serialize($style);
|
||||
|
||||
if (!$this->hasStyleAlreadyBeenRegistered($style)) {
|
||||
@ -47,6 +56,19 @@ class StyleRegistry
|
||||
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.
|
||||
*
|
||||
@ -61,6 +83,20 @@ class StyleRegistry
|
||||
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.
|
||||
*
|
||||
@ -74,6 +110,19 @@ class StyleRegistry
|
||||
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
|
||||
*/
|
||||
@ -82,6 +131,14 @@ class StyleRegistry
|
||||
return array_values($this->styleIdToStyleMappingTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NumberFormat[] List of registered number formats
|
||||
*/
|
||||
public function getRegisteredNumberFormats()
|
||||
{
|
||||
return array_values($this->numberFormats);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $styleId
|
||||
* @return Style
|
||||
@ -111,4 +168,25 @@ class StyleRegistry
|
||||
|
||||
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"?>
|
||||
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
||||
EOD;
|
||||
|
||||
$content .= $this->getNumberFormatSectionContent();
|
||||
$content .= $this->getFontsSectionContent();
|
||||
$content .= $this->getFillsSectionContent();
|
||||
$content .= $this->getBordersSectionContent();
|
||||
@ -62,6 +62,22 @@ EOD;
|
||||
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.
|
||||
*
|
||||
@ -207,7 +223,7 @@ EOD;
|
||||
$fillId = $this->getFillIdForStyleId($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()) {
|
||||
$content .= ' applyFont="1"';
|
||||
|
Loading…
x
Reference in New Issue
Block a user