Support DataBar of conditional formatting rule (#1754)

Implemented the databar of Conditional Type for XLSX Files.
- DataBar can be read, written, and added for basic use.
- Supports reading, writing and adding using "extLst".

About "extLst"
- https://docs.microsoft.com/en-us/openspecs/office_standards/ms-xlsx/07d607af-5618-4ca2-b683-6a78dc0d9627

The following setting items on the Excel setting screen can be read, written, and added.
- (minimum, maximum)type: Automatic, LowestValue, Number, Percent, Formula, Percentile
- Direction: context, leftToRight, rightToLeft (show data bar only)
- Fills Solid, Gradient
- FillColor: PositiveValues, NegativeValues
- Borders: Solid, None
- BorderColor: PositiveValues, NegativeValues
- Axis position: Automatic, Midpoint, None
- Axis color
This commit is contained in:
もりもと たかひろ 2021-01-30 00:57:40 +09:00 committed by GitHub
parent 97aa78fc9a
commit 8d2d78334f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1270 additions and 13 deletions

View File

@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Added ### Added
- Nothing. - Implemented DataBar for conditional formatting in Xlsx, providing read/write and creation of (type, value, direction, fills, border, axis position, color settings) as DataBar options in Excel. [#1754](https://github.com/PHPOffice/PhpSpreadsheet/pull/1754)
### Changed ### Changed

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@ -884,6 +884,44 @@ $spreadsheet->getActiveSheet()
); );
``` ```
### DataBar of Conditional formatting
The basics are the same as conditional formatting.
Additional DataBar object to conditional formatting.
For example, the following code will result in the conditional formatting shown in the image.
```php
$conditional = new Conditional();
$conditional->setConditionType(Conditional::CONDITION_DATABAR);
$conditional->setDataBar(new ConditionalDataBar());
$conditional->getDataBar()
->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('num', '2'))
->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('max'))
->setColor('FFFF555A');
$ext = $conditional
->getDataBar()
->setConditionalFormattingRuleExt(new ConditionalFormattingRuleExtension())
->getConditionalFormattingRuleExt();
$ext->setCfRule('dataBar');
$ext->setSqref('A1:A5'); // target CellCoordinates
$ext->setDataBarExt(new ConditionalDataBarExtension());
$ext->getDataBarExt()
->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('num', '2'))
->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('autoMax'))
->setMinLength(0)
->setMaxLength(100)
->setBorder(true)
->setDirection('rightToLeft')
->setNegativeBarBorderColorSameAsPositive(false)
->setBorderColor('FFFF555A')
->setNegativeFillColor('FFFF0000')
->setNegativeBorderColor('FFFF0000')
->setAxisColor('FF000000');
```
![10-databar-of-conditional-formatting.png](./images/10-databar-of-conditional-formatting.png)
## Add a comment to a cell ## Add a comment to a cell
To add a comment to a cell, use the following code. The example below To add a comment to a cell, use the following code. The example below

View File

@ -2,7 +2,11 @@
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx; namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Conditional; use PhpOffice\PhpSpreadsheet\Style\Conditional;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormattingRuleExtension;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormatValueObject;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use SimpleXMLElement; use SimpleXMLElement;
@ -25,7 +29,8 @@ class ConditionalStyles
{ {
$this->setConditionalStyles( $this->setConditionalStyles(
$this->worksheet, $this->worksheet,
$this->readConditionalStyles($this->worksheetXml) $this->readConditionalStyles($this->worksheetXml),
$this->worksheetXml->extLst
); );
} }
@ -36,14 +41,16 @@ class ConditionalStyles
foreach ($conditional->cfRule as $cfRule) { foreach ($conditional->cfRule as $cfRule) {
if ( if (
((string) $cfRule['type'] == Conditional::CONDITION_NONE ((string) $cfRule['type'] == Conditional::CONDITION_NONE
|| (string) $cfRule['type'] == Conditional::CONDITION_CELLIS || (string) $cfRule['type'] == Conditional::CONDITION_CELLIS
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS
|| (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS || (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS
|| (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION) || (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION)
&& isset($this->dxfs[(int) ($cfRule['dxfId'])]) && isset($this->dxfs[(int) ($cfRule['dxfId'])])
) { ) {
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule; $conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
} elseif ((string) $cfRule['type'] == Conditional::CONDITION_DATABAR) {
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
} }
} }
} }
@ -51,11 +58,11 @@ class ConditionalStyles
return $conditionals; return $conditionals;
} }
private function setConditionalStyles(Worksheet $worksheet, array $conditionals): void private function setConditionalStyles(Worksheet $worksheet, array $conditionals, $xmlExtLst): void
{ {
foreach ($conditionals as $ref => $cfRules) { foreach ($conditionals as $ref => $cfRules) {
ksort($cfRules); ksort($cfRules);
$conditionalStyles = $this->readStyleRules($cfRules); $conditionalStyles = $this->readStyleRules($cfRules, $xmlExtLst);
// Extract all cell references in $ref // Extract all cell references in $ref
$cellBlocks = explode(' ', str_replace('$', '', strtoupper($ref))); $cellBlocks = explode(' ', str_replace('$', '', strtoupper($ref)));
@ -65,8 +72,9 @@ class ConditionalStyles
} }
} }
private function readStyleRules($cfRules) private function readStyleRules($cfRules, $extLst)
{ {
$conditionalFormattingRuleExtensions = ConditionalFormattingRuleExtension::parseExtLstXml($extLst);
$conditionalStyles = []; $conditionalStyles = [];
foreach ($cfRules as $cfRule) { foreach ($cfRules as $cfRule) {
$objConditional = new Conditional(); $objConditional = new Conditional();
@ -88,10 +96,61 @@ class ConditionalStyles
} else { } else {
$objConditional->addCondition((string) $cfRule->formula); $objConditional->addCondition((string) $cfRule->formula);
} }
$objConditional->setStyle(clone $this->dxfs[(int) ($cfRule['dxfId'])]);
if (isset($cfRule->dataBar)) {
$objConditional->setDataBar($this->readDataBarOfConditionalRule($cfRule, $conditionalFormattingRuleExtensions));
} else {
$objConditional->setStyle(clone $this->dxfs[(int) ($cfRule['dxfId'])]);
}
$conditionalStyles[] = $objConditional; $conditionalStyles[] = $objConditional;
} }
return $conditionalStyles; return $conditionalStyles;
} }
private function readDataBarOfConditionalRule($cfRule, $conditionalFormattingRuleExtensions): ConditionalDataBar
{
$dataBar = new ConditionalDataBar();
//dataBar attribute
if (isset($cfRule->dataBar['showValue'])) {
$dataBar->setShowValue((bool) $cfRule->dataBar['showValue']);
}
//dataBar children
//conditionalFormatValueObjects
$cfvoXml = $cfRule->dataBar->cfvo;
$cfvoIndex = 0;
foreach ((count($cfvoXml) > 1 ? $cfvoXml : [$cfvoXml]) as $cfvo) {
if ($cfvoIndex === 0) {
$dataBar->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject((string) $cfvo['type'], (string) $cfvo['val']));
}
if ($cfvoIndex === 1) {
$dataBar->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject((string) $cfvo['type'], (string) $cfvo['val']));
}
++$cfvoIndex;
}
//color
if (isset($cfRule->dataBar->color)) {
$dataBar->setColor((string) $cfRule->dataBar->color['rgb']);
}
//extLst
$this->readDataBarExtLstOfConditionalRule($dataBar, $cfRule, $conditionalFormattingRuleExtensions);
return $dataBar;
}
private function readDataBarExtLstOfConditionalRule(ConditionalDataBar $dataBar, $cfRule, $conditionalFormattingRuleExtensions): void
{
if (isset($cfRule->extLst)) {
$ns = $cfRule->extLst->getNamespaces(true);
foreach ((count($cfRule->extLst) > 0 ? $cfRule->extLst->ext : [$cfRule->extLst->ext]) as $ext) {
$extId = (string) $ext->children($ns['x14'])->id;
if (isset($conditionalFormattingRuleExtensions[$extId]) && (string) $ext['uri'] === '{B025F937-C7B1-47D3-B67F-A62EFF666E3E}') {
$dataBar->setConditionalFormattingRuleExt($conditionalFormattingRuleExtensions[$extId]);
}
}
}
}
} }

View File

@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheet\Style; namespace PhpOffice\PhpSpreadsheet\Style;
use PhpOffice\PhpSpreadsheet\IComparable; use PhpOffice\PhpSpreadsheet\IComparable;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar;
class Conditional implements IComparable class Conditional implements IComparable
{ {
@ -13,6 +14,7 @@ class Conditional implements IComparable
const CONDITION_EXPRESSION = 'expression'; const CONDITION_EXPRESSION = 'expression';
const CONDITION_CONTAINSBLANKS = 'containsBlanks'; const CONDITION_CONTAINSBLANKS = 'containsBlanks';
const CONDITION_NOTCONTAINSBLANKS = 'notContainsBlanks'; const CONDITION_NOTCONTAINSBLANKS = 'notContainsBlanks';
const CONDITION_DATABAR = 'dataBar';
// Operator types // Operator types
const OPERATOR_NONE = ''; const OPERATOR_NONE = '';
@ -64,6 +66,11 @@ class Conditional implements IComparable
*/ */
private $condition = []; private $condition = [];
/**
* @var ConditionalDataBar
*/
private $dataBar;
/** /**
* Style. * Style.
* *
@ -241,6 +248,28 @@ class Conditional implements IComparable
return $this; return $this;
} }
/**
* get DataBar.
*
* @return ConditionalDataBar | null
*/
public function getDataBar()
{
return $this->dataBar;
}
/**
* set DataBar.
*
* @return $this
*/
public function setDataBar(ConditionalDataBar $dataBar)
{
$this->dataBar = $dataBar;
return $this;
}
/** /**
* Get hash code. * Get hash code.
* *

View File

@ -0,0 +1,102 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting;
class ConditionalDataBar
{
/** <dataBar> attribute */
/** @var null|bool */
private $showValue;
/** <dataBar> children */
/** @var ConditionalFormatValueObject */
private $minimumConditionalFormatValueObject;
/** @var ConditionalFormatValueObject */
private $maximumConditionalFormatValueObject;
/** @var string */
private $color;
/** <extLst> */
/** @var ConditionalFormattingRuleExtension */
private $conditionalFormattingRuleExt;
/**
* @return null|bool
*/
public function getShowValue()
{
return $this->showValue;
}
/**
* @param bool $showValue
*/
public function setShowValue($showValue)
{
$this->showValue = $showValue;
return $this;
}
/**
* @return ConditionalFormatValueObject
*/
public function getMinimumConditionalFormatValueObject()
{
return $this->minimumConditionalFormatValueObject;
}
public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject)
{
$this->minimumConditionalFormatValueObject = $minimumConditionalFormatValueObject;
return $this;
}
/**
* @return ConditionalFormatValueObject
*/
public function getMaximumConditionalFormatValueObject()
{
return $this->maximumConditionalFormatValueObject;
}
public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject)
{
$this->maximumConditionalFormatValueObject = $maximumConditionalFormatValueObject;
return $this;
}
public function getColor(): string
{
return $this->color;
}
public function setColor(string $color): self
{
$this->color = $color;
return $this;
}
/**
* @return ConditionalFormattingRuleExtension
*/
public function getConditionalFormattingRuleExt()
{
return $this->conditionalFormattingRuleExt;
}
public function setConditionalFormattingRuleExt(ConditionalFormattingRuleExtension $conditionalFormattingRuleExt)
{
$this->conditionalFormattingRuleExt = $conditionalFormattingRuleExt;
return $this;
}
}

View File

@ -0,0 +1,290 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting;
class ConditionalDataBarExtension
{
/** <dataBar> attributes */
/** @var int */
private $minLength;
/** @var int */
private $maxLength;
/** @var null|bool */
private $border;
/** @var null|bool */
private $gradient;
/** @var string */
private $direction;
/** @var null|bool */
private $negativeBarBorderColorSameAsPositive;
/** @var string */
private $axisPosition;
// <dataBar> children
/** @var ConditionalFormatValueObject */
private $maximumConditionalFormatValueObject;
/** @var ConditionalFormatValueObject */
private $minimumConditionalFormatValueObject;
/** @var string */
private $borderColor;
/** @var string */
private $negativeFillColor;
/** @var string */
private $negativeBorderColor;
/** @var array */
private $axisColor = [
'rgb' => null,
'theme' => null,
'tint' => null,
];
public function getXmlAttributes()
{
$ret = [];
foreach (['minLength', 'maxLength', 'direction', 'axisPosition'] as $attrKey) {
if (null !== $this->{$attrKey}) {
$ret[$attrKey] = $this->{$attrKey};
}
}
foreach (['border', 'gradient', 'negativeBarBorderColorSameAsPositive'] as $attrKey) {
if (null !== $this->{$attrKey}) {
$ret[$attrKey] = $this->{$attrKey} ? '1' : '0';
}
}
return $ret;
}
public function getXmlElements()
{
$ret = [];
$elms = ['borderColor', 'negativeFillColor', 'negativeBorderColor'];
foreach ($elms as $elmKey) {
if (null !== $this->{$elmKey}) {
$ret[$elmKey] = ['rgb' => $this->{$elmKey}];
}
}
foreach (array_filter($this->axisColor) as $attrKey => $axisColorAttr) {
if (!isset($ret['axisColor'])) {
$ret['axisColor'] = [];
}
$ret['axisColor'][$attrKey] = $axisColorAttr;
}
return $ret;
}
/**
* @return int
*/
public function getMinLength()
{
return $this->minLength;
}
public function setMinLength(int $minLength): self
{
$this->minLength = $minLength;
return $this;
}
/**
* @return int
*/
public function getMaxLength()
{
return $this->maxLength;
}
public function setMaxLength(int $maxLength): self
{
$this->maxLength = $maxLength;
return $this;
}
/**
* @return null|bool
*/
public function getBorder()
{
return $this->border;
}
public function setBorder(bool $border): self
{
$this->border = $border;
return $this;
}
/**
* @return null|bool
*/
public function getGradient()
{
return $this->gradient;
}
public function setGradient(bool $gradient): self
{
$this->gradient = $gradient;
return $this;
}
/**
* @return string
*/
public function getDirection()
{
return $this->direction;
}
public function setDirection(string $direction): self
{
$this->direction = $direction;
return $this;
}
/**
* @return null|bool
*/
public function getNegativeBarBorderColorSameAsPositive()
{
return $this->negativeBarBorderColorSameAsPositive;
}
public function setNegativeBarBorderColorSameAsPositive(bool $negativeBarBorderColorSameAsPositive): self
{
$this->negativeBarBorderColorSameAsPositive = $negativeBarBorderColorSameAsPositive;
return $this;
}
/**
* @return string
*/
public function getAxisPosition()
{
return $this->axisPosition;
}
public function setAxisPosition(string $axisPosition): self
{
$this->axisPosition = $axisPosition;
return $this;
}
/**
* @return ConditionalFormatValueObject
*/
public function getMaximumConditionalFormatValueObject()
{
return $this->maximumConditionalFormatValueObject;
}
public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject)
{
$this->maximumConditionalFormatValueObject = $maximumConditionalFormatValueObject;
return $this;
}
/**
* @return ConditionalFormatValueObject
*/
public function getMinimumConditionalFormatValueObject()
{
return $this->minimumConditionalFormatValueObject;
}
public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject)
{
$this->minimumConditionalFormatValueObject = $minimumConditionalFormatValueObject;
return $this;
}
/**
* @return string
*/
public function getBorderColor()
{
return $this->borderColor;
}
public function setBorderColor(string $borderColor): self
{
$this->borderColor = $borderColor;
return $this;
}
/**
* @return string
*/
public function getNegativeFillColor()
{
return $this->negativeFillColor;
}
public function setNegativeFillColor(string $negativeFillColor): self
{
$this->negativeFillColor = $negativeFillColor;
return $this;
}
/**
* @return string
*/
public function getNegativeBorderColor()
{
return $this->negativeBorderColor;
}
public function setNegativeBorderColor(string $negativeBorderColor): self
{
$this->negativeBorderColor = $negativeBorderColor;
return $this;
}
public function getAxisColor(): array
{
return $this->axisColor;
}
/**
* @param mixed $rgb
* @param null|mixed $theme
* @param null|mixed $tint
*/
public function setAxisColor($rgb, $theme = null, $tint = null): self
{
$this->axisColor = [
'rgb' => $rgb,
'theme' => $theme,
'tint' => $tint,
];
return $this;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting;
class ConditionalFormatValueObject
{
private $type;
private $value;
private $cellFormula;
/**
* ConditionalFormatValueObject constructor.
*
* @param $type
* @param $value
* @param null|mixed $cellFormula
*/
public function __construct($type, $value = null, $cellFormula = null)
{
$this->type = $type;
$this->value = $value;
$this->cellFormula = $cellFormula;
}
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @param mixed $type
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* @param mixed $value
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* @return mixed
*/
public function getCellFormula()
{
return $this->cellFormula;
}
/**
* @param mixed $cellFormula
*/
public function setCellFormula($cellFormula)
{
$this->cellFormula = $cellFormula;
return $this;
}
}

View File

@ -0,0 +1,197 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting;
use SimpleXMLElement;
class ConditionalFormattingRuleExtension
{
const CONDITION_EXTENSION_DATABAR = 'dataBar';
/** <conditionalFormatting> attributes */
private $id;
/** @var string Conditional Formatting Rule */
private $cfRule;
/** <conditionalFormatting> children */
/** @var ConditionalDataBarExtension */
private $dataBar;
/** @var string Sequence of References */
private $sqref;
/**
* ConditionalFormattingRuleExtension constructor.
*
* @param $id
*/
public function __construct($id = null, string $cfRule = self::CONDITION_EXTENSION_DATABAR)
{
if (null === $id) {
$this->id = '{' . $this->generateUuid() . '}';
} else {
$this->id = $id;
}
$this->cfRule = $cfRule;
}
private function generateUuid()
{
$chars = str_split('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');
foreach ($chars as $i => $char) {
if ($char === 'x') {
$chars[$i] = dechex(random_int(0, 15));
} elseif ($char === 'y') {
$chars[$i] = dechex(random_int(8, 11));
}
}
return implode('', $chars);
}
public static function parseExtLstXml($extLstXml)
{
$conditionalFormattingRuleExtensions = [];
$conditionalFormattingRuleExtensionXml = null;
if ($extLstXml instanceof SimpleXMLElement) {
foreach ((count($extLstXml) > 0 ? $extLstXml : [$extLstXml]) as $extLst) {
//this uri is conditionalFormattings
//https://docs.microsoft.com/en-us/openspecs/office_standards/ms-xlsx/07d607af-5618-4ca2-b683-6a78dc0d9627
if (isset($extLst->ext['uri']) && (string) $extLst->ext['uri'] === '{78C0D931-6437-407d-A8EE-F0AAD7539E65}') {
$conditionalFormattingRuleExtensionXml = $extLst->ext;
}
}
if ($conditionalFormattingRuleExtensionXml) {
$ns = $conditionalFormattingRuleExtensionXml->getNamespaces(true);
$extFormattingsXml = $conditionalFormattingRuleExtensionXml->children($ns['x14']);
foreach ($extFormattingsXml->children($ns['x14']) as $extFormattingXml) {
$extCfRuleXml = $extFormattingXml->cfRule;
$extFormattingRuleObj = new self((string) $extCfRuleXml->attributes()->id);
$extFormattingRuleObj->setSqref((string) $extFormattingXml->children($ns['xm'])->sqref);
$conditionalFormattingRuleExtensions[$extFormattingRuleObj->getId()] = $extFormattingRuleObj;
$extDataBarObj = new ConditionalDataBarExtension();
$extFormattingRuleObj->setDataBarExt($extDataBarObj);
$dataBarXml = $extCfRuleXml->dataBar;
self::parseExtDataBarAttributesFromXml($extDataBarObj, $dataBarXml);
self::parseExtDataBarElementChildrenFromXml($extDataBarObj, $dataBarXml, $ns);
}
}
}
return $conditionalFormattingRuleExtensions;
}
private static function parseExtDataBarAttributesFromXml(ConditionalDataBarExtension $extDataBarObj, SimpleXMLElement $dataBarXml): void
{
$dataBarAttribute = $dataBarXml->attributes();
if ($dataBarAttribute->minLength) {
$extDataBarObj->setMinLength((int) $dataBarAttribute->minLength);
}
if ($dataBarAttribute->maxLength) {
$extDataBarObj->setMaxLength((int) $dataBarAttribute->maxLength);
}
if ($dataBarAttribute->border) {
$extDataBarObj->setBorder((bool) (string) $dataBarAttribute->border);
}
if ($dataBarAttribute->gradient) {
$extDataBarObj->setGradient((bool) (string) $dataBarAttribute->gradient);
}
if ($dataBarAttribute->direction) {
$extDataBarObj->setDirection((string) $dataBarAttribute->direction);
}
if ($dataBarAttribute->negativeBarBorderColorSameAsPositive) {
$extDataBarObj->setNegativeBarBorderColorSameAsPositive((bool) (string) $dataBarAttribute->negativeBarBorderColorSameAsPositive);
}
if ($dataBarAttribute->axisPosition) {
$extDataBarObj->setAxisPosition((string) $dataBarAttribute->axisPosition);
}
}
private static function parseExtDataBarElementChildrenFromXml(ConditionalDataBarExtension $extDataBarObj, SimpleXMLElement $dataBarXml, $ns): void
{
if ($dataBarXml->borderColor) {
$extDataBarObj->setBorderColor((string) $dataBarXml->borderColor->attributes()['rgb']);
}
if ($dataBarXml->negativeFillColor) {
$extDataBarObj->setNegativeFillColor((string) $dataBarXml->negativeFillColor->attributes()['rgb']);
}
if ($dataBarXml->negativeBorderColor) {
$extDataBarObj->setNegativeBorderColor((string) $dataBarXml->negativeBorderColor->attributes()['rgb']);
}
if ($dataBarXml->axisColor) {
$axisColorAttr = $dataBarXml->axisColor->attributes();
$extDataBarObj->setAxisColor((string) $axisColorAttr['rgb'], (string) $axisColorAttr['theme'], (string) $axisColorAttr['tint']);
}
$cfvoIndex = 0;
foreach ($dataBarXml->cfvo as $cfvo) {
$f = (string) $cfvo->children($ns['xm'])->f;
if ($cfvoIndex === 0) {
$extDataBarObj->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject((string) $cfvo->attributes()['type'], null, (empty($f) ? null : $f)));
}
if ($cfvoIndex === 1) {
$extDataBarObj->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject((string) $cfvo->attributes()['type'], null, (empty($f) ? null : $f)));
}
++$cfvoIndex;
}
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
*/
public function setId($id): self
{
$this->id = $id;
return $this;
}
public function getCfRule(): string
{
return $this->cfRule;
}
public function setCfRule(string $cfRule): self
{
$this->cfRule = $cfRule;
return $this;
}
public function getDataBarExt(): ConditionalDataBarExtension
{
return $this->dataBar;
}
public function setDataBarExt(ConditionalDataBarExtension $dataBar): self
{
$this->dataBar = $dataBar;
return $this;
}
public function getSqref(): string
{
return $this->sqref;
}
public function setSqref(string $sqref): self
{
$this->sqref = $sqref;
return $this;
}
}

View File

@ -8,6 +8,8 @@ use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper; use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter; use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Style\Conditional; use PhpOffice\PhpSpreadsheet\Style\Conditional;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormattingRuleExtension;
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column; use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule; use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
use PhpOffice\PhpSpreadsheet\Worksheet\SheetView; use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
@ -44,6 +46,7 @@ class Worksheet extends WriterPart
$objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing'); $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
$objWriter->writeAttribute('xmlns:x14', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main'); $objWriter->writeAttribute('xmlns:x14', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main');
$objWriter->writeAttribute('xmlns:xm', 'http://schemas.microsoft.com/office/excel/2006/main');
$objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); $objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006');
$objWriter->writeAttribute('mc:Ignorable', 'x14ac'); $objWriter->writeAttribute('mc:Ignorable', 'x14ac');
$objWriter->writeAttribute('xmlns:x14ac', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac'); $objWriter->writeAttribute('xmlns:x14ac', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac');
@ -114,6 +117,10 @@ class Worksheet extends WriterPart
// AlternateContent // AlternateContent
$this->writeAlternateContent($objWriter, $pSheet); $this->writeAlternateContent($objWriter, $pSheet);
// ConditionalFormattingRuleExtensionList
// (Must be inserted last. Not insert last, an Excel parse error will occur)
$this->writeExtLst($objWriter, $pSheet);
$objWriter->endElement(); $objWriter->endElement();
// Return // Return
@ -503,6 +510,94 @@ class Worksheet extends WriterPart
} }
} }
private static function writeExtConditionalFormattingElements(XMLWriter $objWriter, ConditionalFormattingRuleExtension $ruleExtension): void
{
$prefix = 'x14';
$objWriter->startElementNs($prefix, 'conditionalFormatting', null);
$objWriter->startElementNs($prefix, 'cfRule', null);
$objWriter->writeAttribute('type', $ruleExtension->getCfRule());
$objWriter->writeAttribute('id', $ruleExtension->getId());
$objWriter->startElementNs($prefix, 'dataBar', null);
$dataBar = $ruleExtension->getDataBarExt();
foreach ($dataBar->getXmlAttributes() as $attrKey => $val) {
$objWriter->writeAttribute($attrKey, $val);
}
$minCfvo = $dataBar->getMinimumConditionalFormatValueObject();
if ($minCfvo) {
$objWriter->startElementNs($prefix, 'cfvo', null);
$objWriter->writeAttribute('type', $minCfvo->getType());
if ($minCfvo->getCellFormula()) {
$objWriter->writeElement('xm:f', $minCfvo->getCellFormula());
}
$objWriter->endElement(); //end cfvo
}
$maxCfvo = $dataBar->getMaximumConditionalFormatValueObject();
if ($maxCfvo) {
$objWriter->startElementNs($prefix, 'cfvo', null);
$objWriter->writeAttribute('type', $maxCfvo->getType());
if ($maxCfvo->getCellFormula()) {
$objWriter->writeElement('xm:f', $maxCfvo->getCellFormula());
}
$objWriter->endElement(); //end cfvo
}
foreach ($dataBar->getXmlElements() as $elmKey => $elmAttr) {
$objWriter->startElementNs($prefix, $elmKey, null);
foreach ($elmAttr as $attrKey => $attrVal) {
$objWriter->writeAttribute($attrKey, $attrVal);
}
$objWriter->endElement(); //end elmKey
}
$objWriter->endElement(); //end dataBar
$objWriter->endElement(); //end cfRule
$objWriter->writeElement('xm:sqref', $ruleExtension->getSqref());
$objWriter->endElement(); //end conditionalFormatting
}
private static function writeDataBarElements(XMLWriter $objWriter, $dataBar): void
{
/** @var ConditionalDataBar $dataBar */
if ($dataBar) {
$objWriter->startElement('dataBar');
self::writeAttributeIf($objWriter, null !== $dataBar->getShowValue(), 'showValue', $dataBar->getShowValue() ? '1' : '0');
$minCfvo = $dataBar->getMinimumConditionalFormatValueObject();
if ($minCfvo) {
$objWriter->startElement('cfvo');
self::writeAttributeIf($objWriter, $minCfvo->getType(), 'type', (string) $minCfvo->getType());
self::writeAttributeIf($objWriter, $minCfvo->getValue(), 'val', (string) $minCfvo->getValue());
$objWriter->endElement();
}
$maxCfvo = $dataBar->getMaximumConditionalFormatValueObject();
if ($maxCfvo) {
$objWriter->startElement('cfvo');
self::writeAttributeIf($objWriter, $maxCfvo->getType(), 'type', (string) $maxCfvo->getType());
self::writeAttributeIf($objWriter, $maxCfvo->getValue(), 'val', (string) $maxCfvo->getValue());
$objWriter->endElement();
}
if ($dataBar->getColor()) {
$objWriter->startElement('color');
$objWriter->writeAttribute('rgb', $dataBar->getColor());
$objWriter->endElement();
}
$objWriter->endElement(); // end dataBar
if ($dataBar->getConditionalFormattingRuleExt()) {
$objWriter->startElement('extLst');
$extension = $dataBar->getConditionalFormattingRuleExt();
$objWriter->startElement('ext');
$objWriter->writeAttribute('uri', '{B025F937-C7B1-47D3-B67F-A62EFF666E3E}');
$objWriter->startElementNs('x14', 'id', null);
$objWriter->text($extension->getId());
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement(); //end extLst
}
}
}
/** /**
* Write ConditionalFormatting. * Write ConditionalFormatting.
* *
@ -529,7 +624,12 @@ class Worksheet extends WriterPart
// cfRule // cfRule
$objWriter->startElement('cfRule'); $objWriter->startElement('cfRule');
$objWriter->writeAttribute('type', $conditional->getConditionType()); $objWriter->writeAttribute('type', $conditional->getConditionType());
$objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode())); self::writeAttributeIf(
$objWriter,
($conditional->getConditionType() != Conditional::CONDITION_DATABAR),
'dxfId',
$this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode())
);
$objWriter->writeAttribute('priority', $id++); $objWriter->writeAttribute('priority', $id++);
self::writeAttributeif( self::writeAttributeif(
@ -548,7 +648,10 @@ class Worksheet extends WriterPart
self::writeOtherCondElements($objWriter, $conditional, $cellCoordinate); self::writeOtherCondElements($objWriter, $conditional, $cellCoordinate);
} }
$objWriter->endElement(); //<dataBar>
self::writeDataBarElements($objWriter, $conditional->getDataBar());
$objWriter->endElement(); //end cfRule
$objWriter->endElement(); $objWriter->endElement();
} }
@ -1279,4 +1382,38 @@ class Worksheet extends WriterPart
$objWriter->writeRaw($alternateContent); $objWriter->writeRaw($alternateContent);
} }
} }
/**
* write <ExtLst>
* only implementation conditionalFormattings.
*
* @url https://docs.microsoft.com/en-us/openspecs/office_standards/ms-xlsx/07d607af-5618-4ca2-b683-6a78dc0d9627
*/
private function writeExtLst(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet): void
{
$conditionalFormattingRuleExtList = [];
foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
/** @var Conditional $conditional */
foreach ($conditionalStyles as $conditional) {
$dataBar = $conditional->getDataBar();
if ($dataBar && $dataBar->getConditionalFormattingRuleExt()) {
$conditionalFormattingRuleExtList[] = $dataBar->getConditionalFormattingRuleExt();
}
}
}
if (count($conditionalFormattingRuleExtList) > 0) {
$conditionalFormattingRuleExtNsPrefix = 'x14';
$objWriter->startElement('extLst');
$objWriter->startElement('ext');
$objWriter->writeAttribute('uri', '{78C0D931-6437-407d-A8EE-F0AAD7539E65}');
$objWriter->startElementNs($conditionalFormattingRuleExtNsPrefix, 'conditionalFormattings', null);
foreach ($conditionalFormattingRuleExtList as $extension) {
self::writeExtConditionalFormattingElements($objWriter, $extension);
}
$objWriter->endElement(); //end conditionalFormattings
$objWriter->endElement(); //end ext
$objWriter->endElement(); //end extLst
}
}
} }

View File

@ -0,0 +1,325 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Conditional;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalDataBar;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\ConditionalFormatValueObject;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PHPUnit\Framework\TestCase;
class ConditionalFormattingDataBarXlsxTest extends TestCase
{
public function testLoadXlsxConditionalFormattingDataBar(): void
{
// Make sure Conditionals are read correctly from existing file
$filename = 'tests/data/Reader/XLSX/conditionalFormattingDataBarTest.xlsx';
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($filename);
$worksheet = $spreadsheet->getActiveSheet();
$this->pattern1Assertion($worksheet);
$this->pattern2Assertion($worksheet);
$this->pattern3Assertion($worksheet);
$this->pattern4Assertion($worksheet);
}
public function testReloadXlsxConditionalFormattingDataBar(): void
{
// Make sure conditionals from existing file are maintained across save
$filename = 'tests/data/Reader/XLSX/conditionalFormattingDataBarTest.xlsx';
$outfile = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
$reader = IOFactory::createReader('Xlsx');
$spreadshee1 = $reader->load($filename);
$writer = IOFactory::createWriter($spreadshee1, 'Xlsx');
$writer->save($outfile);
$spreadsheet = $reader->load($outfile);
unlink($outfile);
$worksheet = $spreadsheet->getActiveSheet();
$this->pattern1Assertion($worksheet);
$this->pattern2Assertion($worksheet);
$this->pattern3Assertion($worksheet);
$this->pattern4Assertion($worksheet);
}
public function testNewXlsxConditionalFormattingDataBar(): void
{
// Make sure blanks/non-blanks added by PhpSpreadsheet are handled correctly
$outfile = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
$spreadshee1 = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadshee1->getActiveSheet();
$sheet->setCellValue('A1', 1);
$sheet->setCellValue('A2', 2);
$sheet->setCellValue('A3', 3);
$sheet->setCellValue('A4', 4);
$sheet->setCellValue('A5', 5);
$cond1 = new Conditional();
$cond1->setConditionType(Conditional::CONDITION_DATABAR);
$cond1->setDataBar(new ConditionalDataBar());
$cond1->getDataBar()
->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('min'))
->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('max'))
->setColor(Color::COLOR_GREEN);
$cond = [$cond1];
$sheet->getStyle('A1:A5')->setConditionalStyles($cond);
$writer = IOFactory::createWriter($spreadshee1, 'Xlsx');
$writer->save($outfile);
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($outfile);
unlink($outfile);
$worksheet = $spreadsheet->getActiveSheet();
$conditionalStyle = $worksheet->getConditionalStyles('A1:A5');
self::assertNotEmpty($conditionalStyle);
/** @var Conditional $conditionalRule */
$conditionalRule = $conditionalStyle[0];
$conditions = $conditionalRule->getConditions();
self::assertNotEmpty($conditions);
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
self::assertNotEmpty($conditionalRule->getDataBar());
$dataBar = $conditionalRule->getDataBar();
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('min', $dataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('max', $dataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEquals(Color::COLOR_GREEN, $dataBar->getColor());
}
private function pattern1Assertion(Worksheet $worksheet): void
{
self::assertEquals(
"Type: Automatic, Automatic\nDirection: Automatic\nFills: Gradient\nAxis Position: Automatic",
$worksheet->getCell('A2')->getValue()
);
$conditionalStyle = $worksheet->getConditionalStyles('A3:A23');
self::assertNotEmpty($conditionalStyle);
/** @var Conditional $conditionalRule */
$conditionalRule = $conditionalStyle[0];
$dataBar = $conditionalRule->getDataBar();
self::assertNotEmpty($dataBar);
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('min', $dataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('max', $dataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEquals('FF638EC6', $dataBar->getColor());
self::assertNotEmpty($dataBar->getConditionalFormattingRuleExt());
//ext
$rule1ext = $dataBar->getConditionalFormattingRuleExt();
self::assertEquals('{72C64AE0-5CD9-164F-83D1-AB720F263E79}', $rule1ext->getId());
self::assertEquals('dataBar', $rule1ext->getCfRule());
self::assertEquals('A3:A23', $rule1ext->getSqref());
$extDataBar = $rule1ext->getDataBarExt();
self::assertNotEmpty($extDataBar);
$pattern1 = [
'minLength' => 0,
'maxLength' => 100,
'border' => true,
'gradient' => null,
'direction' => null,
'axisPosition' => null,
'negativeBarBorderColorSameAsPositive' => false,
'borderColor' => 'FF638EC6',
'negativeFillColor' => 'FFFF0000',
'negativeBorderColor' => 'FFFF0000',
];
foreach ($pattern1 as $key => $value) {
$funcName = 'get' . ucwords($key);
self::assertEquals($value, $extDataBar->$funcName(), __METHOD__ . '::' . $funcName . ' function patten');
}
self::assertNotEmpty($extDataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($extDataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('autoMin', $extDataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('autoMax', $extDataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertArrayHasKey('rgb', $extDataBar->getAxisColor());
self::assertEquals('FF000000', $extDataBar->getAxisColor()['rgb']);
}
private function pattern2Assertion(Worksheet $worksheet): void
{
self::assertEquals(
"Type: Number, Number\nValue: -5, 5\nDirection: Automatic\nFills: Solid\nAxis Position: Automatic",
$worksheet->getCell('B2')->getValue()
);
$conditionalStyle = $worksheet->getConditionalStyles('B3:B23');
self::assertNotEmpty($conditionalStyle);
/** @var Conditional $conditionalRule */
$conditionalRule = $conditionalStyle[0];
$dataBar = $conditionalRule->getDataBar();
self::assertNotEmpty($dataBar);
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('num', $dataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('num', $dataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEquals('-5', $dataBar->getMinimumConditionalFormatValueObject()->getValue());
self::assertEquals('5', $dataBar->getMaximumConditionalFormatValueObject()->getValue());
self::assertEquals('FF63C384', $dataBar->getColor());
self::assertNotEmpty($dataBar->getConditionalFormattingRuleExt());
//ext
$rule1ext = $dataBar->getConditionalFormattingRuleExt();
self::assertEquals('{98904F60-57F0-DF47-B480-691B20D325E3}', $rule1ext->getId());
self::assertEquals('dataBar', $rule1ext->getCfRule());
self::assertEquals('B3:B23', $rule1ext->getSqref());
$extDataBar = $rule1ext->getDataBarExt();
self::assertNotEmpty($extDataBar);
$pattern1 = [
'minLength' => 0,
'maxLength' => 100,
'border' => null,
'gradient' => false,
'direction' => null,
'axisPosition' => null,
'negativeBarBorderColorSameAsPositive' => null,
'borderColor' => null,
'negativeFillColor' => 'FFFF0000',
'negativeBorderColor' => null,
];
foreach ($pattern1 as $key => $value) {
$funcName = 'get' . ucwords($key);
self::assertEquals($value, $extDataBar->$funcName(), $funcName . ' function patten');
}
self::assertNotEmpty($extDataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($extDataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('num', $extDataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('num', $extDataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEquals('-5', $extDataBar->getMinimumConditionalFormatValueObject()->getCellFormula());
self::assertEquals('5', $extDataBar->getMaximumConditionalFormatValueObject()->getCellFormula());
self::assertArrayHasKey('rgb', $extDataBar->getAxisColor());
self::assertEquals('FF000000', $extDataBar->getAxisColor()['rgb']);
}
private function pattern3Assertion(Worksheet $worksheet): void
{
self::assertEquals(
"Type: Automatic, Automatic\nDirection: rightToLeft\nFills: Solid\nAxis Position: None",
$worksheet->getCell('C2')->getValue()
);
$conditionalStyle = $worksheet->getConditionalStyles('C3:C23');
self::assertNotEmpty($conditionalStyle);
/** @var Conditional $conditionalRule */
$conditionalRule = $conditionalStyle[0];
$dataBar = $conditionalRule->getDataBar();
self::assertNotEmpty($dataBar);
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('min', $dataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('max', $dataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEmpty($dataBar->getMinimumConditionalFormatValueObject()->getValue());
self::assertEmpty($dataBar->getMaximumConditionalFormatValueObject()->getValue());
self::assertEquals('FFFF555A', $dataBar->getColor());
self::assertNotEmpty($dataBar->getConditionalFormattingRuleExt());
//ext
$rule1ext = $dataBar->getConditionalFormattingRuleExt();
self::assertEquals('{453C04BA-7ABD-8548-8A17-D9CFD2BDABE9}', $rule1ext->getId());
self::assertEquals('dataBar', $rule1ext->getCfRule());
self::assertEquals('C3:C23', $rule1ext->getSqref());
$extDataBar = $rule1ext->getDataBarExt();
self::assertNotEmpty($extDataBar);
$pattern1 = [
'minLength' => 0,
'maxLength' => 100,
'border' => null,
'gradient' => false,
'direction' => 'rightToLeft',
'axisPosition' => 'none',
'negativeBarBorderColorSameAsPositive' => null,
'borderColor' => null,
'negativeFillColor' => 'FFFF0000',
'negativeBorderColor' => null,
];
foreach ($pattern1 as $key => $value) {
$funcName = 'get' . ucwords($key);
self::assertEquals($value, $extDataBar->$funcName(), $funcName . ' function patten');
}
self::assertNotEmpty($extDataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($extDataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('autoMin', $extDataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('autoMax', $extDataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEmpty($extDataBar->getMinimumConditionalFormatValueObject()->getCellFormula());
self::assertEmpty($extDataBar->getMaximumConditionalFormatValueObject()->getCellFormula());
self::assertArrayHasKey('rgb', $extDataBar->getAxisColor());
self::assertEmpty($extDataBar->getAxisColor()['rgb']);
}
private function pattern4Assertion(Worksheet $worksheet): void
{
self::assertEquals(
"type: formula, formula\nValue: =2+3, =10+10\nDirection: leftToRight\nShowDataBarOnly\nFills: Solid\nBorder: Solid\nAxis Position: Midpoint",
$worksheet->getCell('D2')->getValue()
);
$conditionalStyle = $worksheet->getConditionalStyles('D3:D23');
self::assertNotEmpty($conditionalStyle);
/** @var Conditional $conditionalRule */
$conditionalRule = $conditionalStyle[0];
$dataBar = $conditionalRule->getDataBar();
self::assertNotEmpty($dataBar);
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
self::assertTrue($dataBar->getShowValue());
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
self::assertEquals('formula', $dataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('formula', $dataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEquals('3+2', $dataBar->getMinimumConditionalFormatValueObject()->getValue());
self::assertEquals('10+10', $dataBar->getMaximumConditionalFormatValueObject()->getValue());
self::assertEquals('FFFF555A', $dataBar->getColor());
self::assertNotEmpty($dataBar->getConditionalFormattingRuleExt());
//ext
$rule1ext = $dataBar->getConditionalFormattingRuleExt();
self::assertEquals('{6C1E066A-E240-3D4A-98F8-8CC218B0DFD2}', $rule1ext->getId());
self::assertEquals('dataBar', $rule1ext->getCfRule());
self::assertEquals('D3:D23', $rule1ext->getSqref());
$extDataBar = $rule1ext->getDataBarExt();
self::assertNotEmpty($extDataBar);
$pattern1 = [
'minLength' => 0,
'maxLength' => 100,
'border' => true,
'gradient' => false,
'direction' => 'leftToRight',
'axisPosition' => 'middle',
'negativeBarBorderColorSameAsPositive' => null,
'borderColor' => 'FF000000',
'negativeFillColor' => 'FFFF0000',
'negativeBorderColor' => null,
];
foreach ($pattern1 as $key => $value) {
$funcName = 'get' . ucwords($key);
self::assertEquals($value, $extDataBar->$funcName(), $funcName . ' function patten');
}
self::assertNotEmpty($extDataBar->getMaximumConditionalFormatValueObject());
self::assertNotEmpty($extDataBar->getMinimumConditionalFormatValueObject());
self::assertEquals('formula', $extDataBar->getMinimumConditionalFormatValueObject()->getType());
self::assertEquals('formula', $extDataBar->getMaximumConditionalFormatValueObject()->getType());
self::assertEquals('3+2', $extDataBar->getMinimumConditionalFormatValueObject()->getCellFormula());
self::assertEquals('10+10', $extDataBar->getMaximumConditionalFormatValueObject()->getCellFormula());
self::assertArrayHasKey('rgb', $extDataBar->getAxisColor());
self::assertEquals('FF000000', $extDataBar->getAxisColor()['rgb']);
}
}