Merge branch 'master' into Row/Column_isEmpty-check

This commit is contained in:
Mark Baker 2022-06-10 17:34:11 +02:00 committed by GitHub
commit 0ef98ac044
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1338 additions and 565 deletions

View File

@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Changed
- Better enforcement of value modification to match specified datatype when using setValueExplicit()
- Relax validation of merge cells to allow merge for a single cell reference [Issue #2776](https://github.com/PHPOffice/PhpSpreadsheet/issues/2776)
- Memory and speed improvements, particularly for the Cell Collection, and the Writers.
See [the Discussion section on github](https://github.com/PHPOffice/PhpSpreadsheet/discussions/2821) for details of performance across versions

View File

@ -1170,21 +1170,11 @@ parameters:
count: 2
path: src/PhpSpreadsheet/Chart/DataSeries.php
-
message: "#^Parameter \\#1 \\$angle of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setShadowAngle\\(\\) expects int, int\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/GridLines.php
-
message: "#^Parameter \\#1 \\$color of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setGlowColor\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/GridLines.php
-
message: "#^Parameter \\#1 \\$distance of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setShadowDistance\\(\\) expects float, float\\|null given\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/GridLines.php
-
message: "#^Parameter \\#2 \\$alpha of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setGlowColor\\(\\) expects int, int\\|null given\\.$#"
count: 1
@ -1275,36 +1265,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Chart/Properties.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Properties\\:\\:getTrueAlpha\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Properties.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Properties\\:\\:getTrueAlpha\\(\\) has parameter \\$alpha with no type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Properties.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Properties\\:\\:setColorProperties\\(\\) has no return type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Properties.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Properties\\:\\:setColorProperties\\(\\) has parameter \\$alpha with no type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Properties.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Properties\\:\\:setColorProperties\\(\\) has parameter \\$color with no type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Properties.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Properties\\:\\:setColorProperties\\(\\) has parameter \\$colorType with no type specified\\.$#"
count: 1
path: src/PhpSpreadsheet/Chart/Properties.php
-
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Renderer\\\\JpGraph\\:\\:formatDataSetLabels\\(\\) has no return type specified\\.$#"
count: 1
@ -4467,12 +4427,12 @@ parameters:
-
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, array\\|int\\|string given\\.$#"
count: 8
count: 2
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
-
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, array\\|int\\|string\\|null given\\.$#"
count: 2
count: 1
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
-
@ -4515,11 +4475,6 @@ parameters:
count: 2
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
-
message: "#^Part \\$xAxis\\-\\>getShadowProperty\\('effect'\\) \\(array\\|int\\|string\\|null\\) of encapsed string cannot be cast to string\\.$#"
count: 1
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
-
message: "#^Part \\$xAxis\\-\\>getShadowProperty\\(\\['color', 'type'\\]\\) \\(array\\|int\\|string\\|null\\) of encapsed string cannot be cast to string\\.$#"
count: 1

View File

@ -202,6 +202,11 @@ class Cell
*
* @param mixed $value Value
* @param string $dataType Explicit data type, see DataType::TYPE_*
* Note that PhpSpreadsheet does not validate that the value and datatype are consistent, in using this
* method, then it is your responsibility as an end-user developer to validate that the value and
* the datatype match.
* If you do mismatch value and datatpe, then the value you enter may be changed to match the datatype
* that you specify.
*
* @return Cell
*/
@ -210,7 +215,7 @@ class Cell
// set the value according to data type
switch ($dataType) {
case DataType::TYPE_NULL:
$this->value = $value;
$this->value = null;
break;
case DataType::TYPE_STRING2:

View File

@ -48,7 +48,7 @@ class DataType
*
* @param null|RichText|string $textValue Value to sanitize to an Excel string
*
* @return null|RichText|string Sanitized value
* @return RichText|string Sanitized value
*/
public static function checkString($textValue)
{
@ -58,7 +58,7 @@ class DataType
}
// string must never be longer than 32,767 characters, truncate if necessary
$textValue = StringHelper::substring($textValue, 0, 32767);
$textValue = StringHelper::substring((string) $textValue, 0, 32767);
// we require that newline is represented as "\n" in core, not as "\r\n" or "\r"
$textValue = str_replace(["\r\n", "\r"], "\n", $textValue);

View File

@ -89,25 +89,7 @@ class Axis extends Properties
*
* @var mixed[]
*/
private $shadowProperties = [
'presets' => self::SHADOW_PRESETS_NOSHADOW,
'effect' => null,
'color' => [
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 40,
],
'size' => [
'sx' => null,
'sy' => null,
'kx' => null,
],
'blur' => null,
'direction' => null,
'distance' => null,
'algn' => null,
'rotWithShape' => null,
];
private $shadowProperties = Properties::PRESETS_OPTIONS[0];
/**
* Glow Properties.
@ -340,6 +322,20 @@ class Axis extends Properties
return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'len');
}
/**
* @param mixed $value
*/
public function setShadowProperty(string $propertyName, $value): self
{
if ($propertyName === 'color' && is_array($value)) {
$this->setShadowColor($value['value'], $value['alpha'], $value['type']);
} else {
$this->shadowProperties[$propertyName] = $value;
}
return $this;
}
/**
* Set Shadow Properties.
*
@ -379,6 +375,8 @@ class Axis extends Properties
return $this;
}
private const SHADOW_ARRAY_KEYS = ['size', 'color'];
/**
* Set Shadow Properties from Mapped Values.
*
@ -391,12 +389,10 @@ class Axis extends Properties
$base_reference = $reference;
foreach ($propertiesMap as $property_key => $property_val) {
if (is_array($property_val)) {
if ($reference === null) {
if (in_array($property_key, self::SHADOW_ARRAY_KEYS, true)) {
$reference = &$this->shadowProperties[$property_key];
} else {
$reference = &$reference[$property_key];
}
$this->setShadowPropertiesMapValues($property_val, $reference);
}
} else {
if ($base_reference === null) {
$this->shadowProperties[$property_key] = $property_val;
@ -435,7 +431,7 @@ class Axis extends Properties
private function setShadowBlur($blur)
{
if ($blur !== null) {
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur);
$this->shadowProperties['blur'] = $blur;
}
return $this;
@ -444,14 +440,14 @@ class Axis extends Properties
/**
* Set Shadow Angle.
*
* @param null|int $angle
* @param null|float|int $angle
*
* @return $this
*/
private function setShadowAngle($angle)
{
if ($angle !== null) {
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle);
if (is_numeric($angle)) {
$this->shadowProperties['direction'] = $angle;
}
return $this;
@ -467,7 +463,7 @@ class Axis extends Properties
private function setShadowDistance($distance)
{
if ($distance !== null) {
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance);
$this->shadowProperties['distance'] = $distance;
}
return $this;
@ -525,7 +521,7 @@ class Axis extends Properties
private function setGlowSize($size)
{
if ($size !== null) {
$this->glowProperties['size'] = $this->getExcelPointsWidth($size);
$this->glowProperties['size'] = $size;
}
return $this;
@ -555,7 +551,7 @@ class Axis extends Properties
public function setSoftEdges($size): void
{
if ($size !== null) {
$this->softEdges['size'] = (string) $this->getExcelPointsWidth($size);
$this->softEdges['size'] = $size;
}
}

View File

@ -45,25 +45,7 @@ class GridLines extends Properties
],
];
private $shadowProperties = [
'presets' => self::SHADOW_PRESETS_NOSHADOW,
'effect' => null,
'color' => [
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 85,
],
'size' => [
'sx' => null,
'sy' => null,
'kx' => null,
],
'blur' => null,
'direction' => null,
'distance' => null,
'algn' => null,
'rotWithShape' => null,
];
private $shadowProperties = Properties::PRESETS_OPTIONS[0];
private $glowProperties = [
'size' => null,
@ -202,6 +184,18 @@ class GridLines extends Properties
->setGlowColor($colorValue, $colorAlpha, $colorType);
}
/**
* Get Glow Property.
*
* @param array|string $property
*
* @return null|string
*/
public function getGlowProperty($property)
{
return $this->getArrayElementsValue($this->glowProperties, $property);
}
/**
* Get Glow Color Property.
*
@ -233,7 +227,7 @@ class GridLines extends Properties
*/
private function setGlowSize($size)
{
$this->glowProperties['size'] = $this->getExcelPointsWidth((float) $size);
$this->glowProperties['size'] = $size;
return $this;
}
@ -253,7 +247,7 @@ class GridLines extends Properties
$this->glowProperties['color']['value'] = (string) $color;
}
if ($alpha !== null) {
$this->glowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha);
$this->glowProperties['color']['alpha'] = (int) $alpha;
}
if ($colorType !== null) {
$this->glowProperties['color']['type'] = (string) $colorType;
@ -275,16 +269,27 @@ class GridLines extends Properties
return $this->getLineStyleArrowSize($this->lineProperties['style']['arrow'][$arrowSelector]['size'], $propertySelector);
}
/**
* @param mixed $value
*/
public function setShadowProperty(string $propertyName, $value): self
{
$this->activateObject();
$this->shadowProperties[$propertyName] = $value;
return $this;
}
/**
* Set Shadow Properties.
*
* @param int $presets
* @param string $colorValue
* @param string $colorType
* @param string $colorAlpha
* @param string $blur
* @param int $angle
* @param float $distance
* @param null|float|int|string $colorAlpha
* @param null|float $blur
* @param null|int $angle
* @param null|float $distance
*/
public function setShadowProperties($presets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void
{
@ -292,10 +297,10 @@ class GridLines extends Properties
->setShadowPresetsProperties((int) $presets)
->setShadowColor(
$colorValue ?? $this->shadowProperties['color']['value'],
$colorAlpha === null ? (int) $this->shadowProperties['color']['alpha'] : $this->getTrueAlpha($colorAlpha),
$colorAlpha === null ? (int) $this->shadowProperties['color']['alpha'] : (int) $colorAlpha,
$colorType ?? $this->shadowProperties['color']['type']
)
->setShadowBlur((float) $blur)
->setShadowBlur($blur)
->setShadowAngle($angle)
->setShadowDistance($distance);
}
@ -315,6 +320,8 @@ class GridLines extends Properties
return $this;
}
private const SHADOW_ARRAY_KEYS = ['size', 'color'];
/**
* Set Shadow Properties Values.
*
@ -327,12 +334,10 @@ class GridLines extends Properties
$base_reference = $reference;
foreach ($propertiesMap as $property_key => $property_val) {
if (is_array($property_val)) {
if ($reference === null) {
if (in_array($property_key, self::SHADOW_ARRAY_KEYS, true)) {
$reference = &$this->shadowProperties[$property_key];
} else {
$reference = &$reference[$property_key];
}
$this->setShadowPropertiesMapValues($property_val, $reference);
}
} else {
if ($base_reference === null) {
$this->shadowProperties[$property_key] = $property_val;
@ -360,7 +365,7 @@ class GridLines extends Properties
$this->shadowProperties['color']['value'] = (string) $color;
}
if ($alpha !== null) {
$this->shadowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha);
$this->shadowProperties['color']['alpha'] = (int) $alpha;
}
if ($colorType !== null) {
$this->shadowProperties['color']['type'] = (string) $colorType;
@ -372,14 +377,14 @@ class GridLines extends Properties
/**
* Set Shadow Blur.
*
* @param float $blur
* @param ?float $blur
*
* @return $this
*/
private function setShadowBlur($blur)
{
if ($blur !== null) {
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur);
$this->shadowProperties['blur'] = $blur;
}
return $this;
@ -388,14 +393,14 @@ class GridLines extends Properties
/**
* Set Shadow Angle.
*
* @param int $angle
* @param null|float|int|string $angle
*
* @return $this
*/
private function setShadowAngle($angle)
{
if ($angle !== null) {
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle);
if (is_numeric($angle)) {
$this->shadowProperties['direction'] = $angle;
}
return $this;
@ -404,14 +409,14 @@ class GridLines extends Properties
/**
* Set Shadow Distance.
*
* @param float $distance
* @param ?float $distance
*
* @return $this
*/
private function setShadowDistance($distance)
{
if ($distance !== null) {
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance);
$this->shadowProperties['distance'] = $distance;
}
return $this;
@ -434,11 +439,11 @@ class GridLines extends Properties
*
* @param float $size
*/
public function setSoftEdgesSize($size): void
public function setSoftEdges($size): void
{
if ($size !== null) {
$this->activateObject();
$this->softEdges['size'] = (string) $this->getExcelPointsWidth($size);
$this->softEdges['size'] = $size;
}
}

View File

@ -110,7 +110,10 @@ abstract class Properties
const SHADOW_PRESETS_PERSPECTIVE_UPPER_LEFT = 21;
const SHADOW_PRESETS_PERSPECTIVE_LOWER_RIGHT = 22;
const SHADOW_PRESETS_PERSPECTIVE_LOWER_LEFT = 23;
const POINTS_WIDTH_MULTIPLIER = 12700;
const ANGLE_MULTIPLIER = 60000; // direction and size-kx size-ky
const PERCENTAGE_MULTIPLIER = 100000; // size sx and sy
/**
* @param float $width
@ -122,27 +125,58 @@ abstract class Properties
return $width * self::POINTS_WIDTH_MULTIPLIER;
}
/**
* @param float $angle
*
* @return float
*/
protected function getExcelPointsAngle($angle)
public static function pointsToXml(float $width): string
{
return $angle * 60000;
return (string) (int) ($width * self::POINTS_WIDTH_MULTIPLIER);
}
protected function getTrueAlpha($alpha)
public static function xmlToPoints(string $width): float
{
return ((float) $width) / self::POINTS_WIDTH_MULTIPLIER;
}
public static function angleToXml(float $angle): string
{
return (string) (int) ($angle * self::ANGLE_MULTIPLIER);
}
public static function xmlToAngle(string $angle): float
{
return ((float) $angle) / self::ANGLE_MULTIPLIER;
}
public static function tenthOfPercentToXml(float $value): string
{
return (string) (int) ($value * self::PERCENTAGE_MULTIPLIER);
}
public static function xmlToTenthOfPercent(string $value): float
{
return ((float) $value) / self::PERCENTAGE_MULTIPLIER;
}
public static function alphaToXml(int $alpha): string
{
return (string) (100 - $alpha) . '000';
}
protected function setColorProperties($color, $alpha, $colorType)
/**
* @param float|int|string $alpha
*/
public static function alphaFromXml($alpha): int
{
return 100 - ((int) $alpha / 1000);
}
/**
* @param null|float|int|string $alpha
*/
protected function setColorProperties(?string $color, $alpha, ?string $colorType): array
{
return [
'type' => (string) $colorType,
'value' => (string) $color,
'alpha' => (string) $this->getTrueAlpha($alpha),
'type' => $colorType,
'value' => $color,
'alpha' => (int) $alpha,
];
}
@ -163,196 +197,217 @@ abstract class Properties
return $sizes[$arraySelector][$arrayKaySelector];
}
protected function getShadowPresetsMap($presetsOption)
{
$presets_options = [
protected const PRESETS_OPTIONS = [
//NONE
0 => [
'presets' => self::SHADOW_PRESETS_NOSHADOW,
'effect' => null,
'color' => [
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 40,
],
'size' => [
'sx' => null,
'sy' => null,
'kx' => null,
'ky' => null,
],
'blur' => null,
'direction' => null,
'distance' => null,
'algn' => null,
'rotWithShape' => null,
],
//OUTER
1 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'direction' => '2700000',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 2700000 / self::ANGLE_MULTIPLIER,
'algn' => 'tl',
'rotWithShape' => '0',
],
2 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'direction' => '5400000',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 5400000 / self::ANGLE_MULTIPLIER,
'algn' => 't',
'rotWithShape' => '0',
],
3 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'direction' => '8100000',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 8100000 / self::ANGLE_MULTIPLIER,
'algn' => 'tr',
'rotWithShape' => '0',
],
4 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'algn' => 'l',
'rotWithShape' => '0',
],
5 => [
'effect' => 'outerShdw',
'size' => [
'sx' => '102000',
'sy' => '102000',
'sx' => 102000 / self::PERCENTAGE_MULTIPLIER,
'sy' => 102000 / self::PERCENTAGE_MULTIPLIER,
],
'blur' => '63500',
'distance' => '38100',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'algn' => 'ctr',
'rotWithShape' => '0',
],
6 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'direction' => '10800000',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 10800000 / self::ANGLE_MULTIPLIER,
'algn' => 'r',
'rotWithShape' => '0',
],
7 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'direction' => '18900000',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 18900000 / self::ANGLE_MULTIPLIER,
'algn' => 'bl',
'rotWithShape' => '0',
],
8 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'direction' => '16200000',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 16200000 / self::ANGLE_MULTIPLIER,
'rotWithShape' => '0',
],
9 => [
'effect' => 'outerShdw',
'blur' => '50800',
'distance' => '38100',
'direction' => '13500000',
'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 13500000 / self::ANGLE_MULTIPLIER,
'algn' => 'br',
'rotWithShape' => '0',
],
//INNER
10 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'direction' => '2700000',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 2700000 / self::ANGLE_MULTIPLIER,
],
11 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'direction' => '5400000',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 5400000 / self::ANGLE_MULTIPLIER,
],
12 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'direction' => '8100000',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 8100000 / self::ANGLE_MULTIPLIER,
],
13 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
],
14 => [
'effect' => 'innerShdw',
'blur' => '114300',
'blur' => 114300 / self::POINTS_WIDTH_MULTIPLIER,
],
15 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'direction' => '10800000',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 10800000 / self::ANGLE_MULTIPLIER,
],
16 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'direction' => '18900000',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 18900000 / self::ANGLE_MULTIPLIER,
],
17 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'direction' => '16200000',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 16200000 / self::ANGLE_MULTIPLIER,
],
18 => [
'effect' => 'innerShdw',
'blur' => '63500',
'distance' => '50800',
'direction' => '13500000',
'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 13500000 / self::ANGLE_MULTIPLIER,
],
//perspective
19 => [
'effect' => 'outerShdw',
'blur' => '152400',
'distance' => '317500',
'blur' => 152400 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 317500 / self::POINTS_WIDTH_MULTIPLIER,
'size' => [
'sx' => '90000',
'sy' => '-19000',
'sx' => 90000 / self::PERCENTAGE_MULTIPLIER,
'sy' => -19000 / self::PERCENTAGE_MULTIPLIER,
],
'direction' => '5400000',
'direction' => 5400000 / self::ANGLE_MULTIPLIER,
'rotWithShape' => '0',
],
20 => [
'effect' => 'outerShdw',
'blur' => '76200',
'direction' => '18900000',
'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 18900000 / self::ANGLE_MULTIPLIER,
'size' => [
'sy' => '23000',
'kx' => '-1200000',
'sy' => 23000 / self::PERCENTAGE_MULTIPLIER,
'kx' => -1200000 / self::ANGLE_MULTIPLIER,
],
'algn' => 'bl',
'rotWithShape' => '0',
],
21 => [
'effect' => 'outerShdw',
'blur' => '76200',
'direction' => '13500000',
'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 13500000 / self::ANGLE_MULTIPLIER,
'size' => [
'sy' => '23000',
'kx' => '1200000',
'sy' => 23000 / self::PERCENTAGE_MULTIPLIER,
'kx' => 1200000 / self::ANGLE_MULTIPLIER,
],
'algn' => 'br',
'rotWithShape' => '0',
],
22 => [
'effect' => 'outerShdw',
'blur' => '76200',
'distance' => '12700',
'direction' => '2700000',
'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 12700 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 2700000 / self::ANGLE_MULTIPLIER,
'size' => [
'sy' => '-23000',
'kx' => '-800400',
'sy' => -23000 / self::PERCENTAGE_MULTIPLIER,
'kx' => -800400 / self::ANGLE_MULTIPLIER,
],
'algn' => 'bl',
'rotWithShape' => '0',
],
23 => [
'effect' => 'outerShdw',
'blur' => '76200',
'distance' => '12700',
'direction' => '8100000',
'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
'distance' => 12700 / self::POINTS_WIDTH_MULTIPLIER,
'direction' => 8100000 / self::ANGLE_MULTIPLIER,
'size' => [
'sy' => '-23000',
'kx' => '800400',
'sy' => -23000 / self::PERCENTAGE_MULTIPLIER,
'kx' => 800400 / self::ANGLE_MULTIPLIER,
],
'algn' => 'br',
'rotWithShape' => '0',
],
];
return $presets_options[$presetsOption];
protected function getShadowPresetsMap($presetsOption)
{
return self::PRESETS_OPTIONS[$presetsOption] ?? self::PRESETS_OPTIONS[0];
}
protected function getArrayElementsValue($properties, $elements)

View File

@ -6,6 +6,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Chart\Axis;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\GridLines;
use PhpOffice\PhpSpreadsheet\Chart\Layout;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
@ -71,6 +72,7 @@ class Chart
$rotX = $rotY = $rAngAx = $perspective = null;
$xAxis = new Axis();
$yAxis = new Axis();
$majorGridlines = $minorGridlines = null;
foreach ($chartElementsC as $chartElementKey => $chartElement) {
switch ($chartElementKey) {
case 'chart':
@ -108,26 +110,52 @@ class Chart
break;
case 'valAx':
$whichAxis = null;
if (isset($chartDetail->title, $chartDetail->axPos)) {
$axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
$axPos = null;
if (isset($chartDetail->axPos)) {
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
switch ($axPos) {
case 't':
case 'b':
$XaxisLabel = $axisLabel;
$whichAxis = $xAxis;
break;
case 'r':
case 'l':
$YaxisLabel = $axisLabel;
$whichAxis = $yAxis;
break;
}
}
if (isset($chartDetail->title)) {
$axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
switch ($axPos) {
case 't':
case 'b':
$XaxisLabel = $axisLabel;
break;
case 'r':
case 'l':
$YaxisLabel = $axisLabel;
break;
}
}
$this->readEffects($chartDetail, $whichAxis);
if (isset($chartDetail->majorGridlines)) {
$majorGridlines = new GridLines();
if (isset($chartDetail->majorGridlines->spPr)) {
$this->readEffects($chartDetail->majorGridlines, $majorGridlines);
}
}
if (isset($chartDetail->minorGridlines)) {
$minorGridlines = new GridLines();
if (isset($chartDetail->minorGridlines->spPr)) {
$this->readEffects($chartDetail->minorGridlines, $minorGridlines);
}
}
break;
case 'barChart':
@ -249,7 +277,7 @@ class Chart
}
}
}
$chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, (string) $dispBlanksAs, $XaxisLabel, $YaxisLabel, $xAxis, $yAxis);
$chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, (string) $dispBlanksAs, $XaxisLabel, $YaxisLabel, $xAxis, $yAxis, $majorGridlines, $minorGridlines);
if (is_int($rotX)) {
$chart->setRotX($rotX);
}
@ -893,7 +921,7 @@ class Chart
}
/**
* @param null|Axis $chartObject may be extended to include other types
* @param null|Axis|GridLines $chartObject may be extended to include other types
*/
private function readEffects(SimpleXMLElement $chartDetail, $chartObject): void
{
@ -905,18 +933,75 @@ class Chart
if (isset($sppr->effectLst->glow)) {
$axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / Properties::POINTS_WIDTH_MULTIPLIER;
if ($axisGlowSize != 0.0) {
$srgbClr = $schemeClr = '';
$colorArray = $this->readColor($sppr->effectLst->glow, $srgbClr, $schemeClr);
$colorArray = $this->readColor($sppr->effectLst->glow);
$chartObject->setGlowProperties($axisGlowSize, $colorArray['value'], $colorArray['alpha'], $colorArray['type']);
}
}
if (isset($sppr->effectLst->softEdge)) {
$chartObject->setSoftEdges((float) self::getAttribute($sppr->effectLst->softEdge, 'rad', 'string') / Properties::POINTS_WIDTH_MULTIPLIER);
/** @var string */
$softEdgeSize = self::getAttribute($sppr->effectLst->softEdge, 'rad', 'string');
if (is_numeric($softEdgeSize)) {
$chartObject->setSoftEdges((float) Properties::xmlToPoints($softEdgeSize));
}
}
private function readColor(SimpleXMLElement $colorXml, ?string &$srgbClr, ?string &$schemeClr): array
$type = '';
foreach (self::SHADOW_TYPES as $shadowType) {
if (isset($sppr->effectLst->$shadowType)) {
$type = $shadowType;
break;
}
}
if ($type !== '') {
/** @var string */
$blur = self::getAttribute($sppr->effectLst->$type, 'blurRad', 'string');
$blur = is_numeric($blur) ? Properties::xmlToPoints($blur) : null;
/** @var string */
$dist = self::getAttribute($sppr->effectLst->$type, 'dist', 'string');
$dist = is_numeric($dist) ? Properties::xmlToPoints($dist) : null;
/** @var string */
$direction = self::getAttribute($sppr->effectLst->$type, 'dir', 'string');
$direction = is_numeric($direction) ? Properties::xmlToAngle($direction) : null;
$algn = self::getAttribute($sppr->effectLst->$type, 'algn', 'string');
$rot = self::getAttribute($sppr->effectLst->$type, 'rotWithShape', 'string');
$size = [];
foreach (['sx', 'sy'] as $sizeType) {
$sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string');
if (is_numeric($sizeValue)) {
$size[$sizeType] = Properties::xmlToTenthOfPercent((string) $sizeValue);
} else {
$size[$sizeType] = null;
}
}
foreach (['kx', 'ky'] as $sizeType) {
$sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string');
if (is_numeric($sizeValue)) {
$size[$sizeType] = Properties::xmlToAngle((string) $sizeValue);
} else {
$size[$sizeType] = null;
}
}
$colorArray = $this->readColor($sppr->effectLst->$type);
$chartObject
->setShadowProperty('effect', $type)
->setShadowProperty('blur', $blur)
->setShadowProperty('direction', $direction)
->setShadowProperty('distance', $dist)
->setShadowProperty('algn', $algn)
->setShadowProperty('rotWithShape', $rot)
->setShadowProperty('size', $size)
->setShadowProperty('color', $colorArray);
}
}
private const SHADOW_TYPES = [
'outerShdw',
'innerShdw',
];
private function readColor(SimpleXMLElement $colorXml, ?string &$srgbClr = null, ?string &$schemeClr = null): array
{
$result = [
'type' => null,
@ -927,16 +1012,27 @@ class Chart
$result['type'] = Properties::EXCEL_COLOR_TYPE_ARGB;
$result['value'] = $srgbClr = self::getAttribute($colorXml->srgbClr, 'val', 'string');
if (isset($colorXml->srgbClr->alpha)) {
$alpha = (int) self::getAttribute($colorXml->srgbClr->alpha, 'val', 'string');
$alpha = 100 - (int) ($alpha / 1000);
/** @var string */
$alpha = self::getAttribute($colorXml->srgbClr->alpha, 'val', 'string');
$alpha = Properties::alphaFromXml($alpha);
$result['alpha'] = $alpha;
}
} elseif (isset($colorXml->schemeClr)) {
$result['type'] = Properties::EXCEL_COLOR_TYPE_SCHEME;
$result['value'] = $schemeClr = self::getAttribute($colorXml->schemeClr, 'val', 'string');
if (isset($colorXml->schemeClr->alpha)) {
$alpha = (int) self::getAttribute($colorXml->schemeClr->alpha, 'val', 'string');
$alpha = 100 - (int) ($alpha / 1000);
/** @var string */
$alpha = self::getAttribute($colorXml->schemeClr->alpha, 'val', 'string');
$alpha = Properties::alphaFromXml($alpha);
$result['alpha'] = $alpha;
}
} elseif (isset($colorXml->prstClr)) {
$result['type'] = Properties::EXCEL_COLOR_TYPE_STANDARD;
$result['value'] = self::getAttribute($colorXml->prstClr, 'val', 'string');
if (isset($colorXml->prstClr->alpha)) {
/** @var string */
$alpha = self::getAttribute($colorXml->prstClr->alpha, 'val', 'string');
$alpha = Properties::alphaFromXml($alpha);
$result['alpha'] = $alpha;
}
}

View File

@ -1177,6 +1177,11 @@ class Worksheet implements IComparable
* or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object.
* @param mixed $value Value of the cell
* @param string $dataType Explicit data type, see DataType::TYPE_*
* Note that PhpSpreadsheet does not validate that the value and datatype are consistent, in using this
* method, then it is your responsibility as an end-user developer to validate that the value and
* the datatype match.
* If you do mismatch value and datatpe, then the value you enter may be changed to match the datatype
* that you specify.
*
* @return $this
*/
@ -1199,6 +1204,11 @@ class Worksheet implements IComparable
* @param int $row Numeric row coordinate of the cell
* @param mixed $value Value of the cell
* @param string $dataType Explicit data type, see DataType::TYPE_*
* Note that PhpSpreadsheet does not validate that the value and datatype are consistent, in using this
* method, then it is your responsibility as an end-user developer to validate that the value and
* the datatype match.
* If you do mismatch value and datatpe, then the value you enter may be changed to match the datatype
* that you specify.
*
* @return $this
*/
@ -1752,7 +1762,14 @@ class Worksheet implements IComparable
{
$range = Functions::trimSheetFromCellReference(Validations::validateCellRange($range));
if (preg_match('/^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/', $range, $matches) === 1) {
if (strpos($range, ':') === false) {
$range .= ":{$range}";
}
if (preg_match('/^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/', $range, $matches) !== 1) {
throw new Exception('Merge must be on a valid range of cells.');
}
$this->mergeCells[$range] = $range;
$firstRow = (int) $matches[2];
$lastRow = (int) $matches[4];
@ -1763,6 +1780,10 @@ class Worksheet implements IComparable
$numberRows = $lastRow - $firstRow;
$numberColumns = $lastColumnIndex - $firstColumnIndex;
if ($numberRows === 1 && $numberColumns === 1) {
return $this;
}
// create upper left cell if it does not already exist
$upperLeft = "{$firstColumn}{$firstRow}";
if (!$this->cellExists($upperLeft)) {
@ -1775,9 +1796,6 @@ class Worksheet implements IComparable
} else {
$this->clearMergeCellsByRow($firstColumn, $lastColumnIndex, $firstRow, $lastRow, $upperLeft);
}
} else {
throw new Exception('Merge must be set on a range of cells.');
}
return $this;
}

View File

@ -9,6 +9,7 @@ use PhpOffice\PhpSpreadsheet\Chart\GridLines;
use PhpOffice\PhpSpreadsheet\Chart\Layout;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
@ -499,22 +500,9 @@ class Chart extends WriterPart
$objWriter->startElement('c:spPr');
$objWriter->startElement('a:effectLst');
if ($yAxis->getGlowProperty('size') !== null) {
$objWriter->startElement('a:glow');
$objWriter->writeAttribute('rad', $yAxis->getGlowProperty('size'));
$objWriter->startElement("a:{$yAxis->getGlowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', (string) $yAxis->getGlowProperty(['color', 'value']));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', (string) $yAxis->getGlowProperty(['color', 'alpha']));
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
}
if ($yAxis->getSoftEdgesSize() !== null) {
$objWriter->startElement('a:softEdge');
$objWriter->writeAttribute('rad', $yAxis->getSoftEdgesSize());
$objWriter->endElement(); //end softEdge
}
$this->writeGlow($objWriter, $yAxis);
$this->writeShadow($objWriter, $yAxis);
$this->writeSoftEdge($objWriter, $yAxis);
$objWriter->endElement(); // effectLst
$objWriter->endElement(); // spPr
@ -640,61 +628,9 @@ class Chart extends WriterPart
$objWriter->endElement(); //end ln
}
$objWriter->startElement('a:effectLst');
if ($majorGridlines->getGlowSize() !== null) {
$objWriter->startElement('a:glow');
$objWriter->writeAttribute('rad', $majorGridlines->getGlowSize());
$objWriter->startElement("a:{$majorGridlines->getGlowColor('type')}");
$objWriter->writeAttribute('val', $majorGridlines->getGlowColor('value'));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', $majorGridlines->getGlowColor('alpha'));
$objWriter->endElement(); //end alpha
$objWriter->endElement(); //end schemeClr
$objWriter->endElement(); //end glow
}
if ($majorGridlines->getShadowProperty('presets') !== null) {
$objWriter->startElement("a:{$majorGridlines->getShadowProperty('effect')}");
if ($majorGridlines->getShadowProperty('blur') !== null) {
$objWriter->writeAttribute('blurRad', $majorGridlines->getShadowProperty('blur'));
}
if ($majorGridlines->getShadowProperty('distance') !== null) {
$objWriter->writeAttribute('dist', $majorGridlines->getShadowProperty('distance'));
}
if ($majorGridlines->getShadowProperty('direction') !== null) {
$objWriter->writeAttribute('dir', $majorGridlines->getShadowProperty('direction'));
}
if ($majorGridlines->getShadowProperty('algn') !== null) {
$objWriter->writeAttribute('algn', $majorGridlines->getShadowProperty('algn'));
}
if ($majorGridlines->getShadowProperty(['size', 'sx']) !== null) {
$objWriter->writeAttribute('sx', $majorGridlines->getShadowProperty(['size', 'sx']));
}
if ($majorGridlines->getShadowProperty(['size', 'sy']) !== null) {
$objWriter->writeAttribute('sy', $majorGridlines->getShadowProperty(['size', 'sy']));
}
if ($majorGridlines->getShadowProperty(['size', 'kx']) !== null) {
$objWriter->writeAttribute('kx', $majorGridlines->getShadowProperty(['size', 'kx']));
}
if ($majorGridlines->getShadowProperty('rotWithShape') !== null) {
$objWriter->writeAttribute('rotWithShape', $majorGridlines->getShadowProperty('rotWithShape'));
}
$objWriter->startElement("a:{$majorGridlines->getShadowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', $majorGridlines->getShadowProperty(['color', 'value']));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', $majorGridlines->getShadowProperty(['color', 'alpha']));
$objWriter->endElement(); //end alpha
$objWriter->endElement(); //end color:type
$objWriter->endElement(); //end shadow
}
if ($majorGridlines->getSoftEdgesSize() !== null) {
$objWriter->startElement('a:softEdge');
$objWriter->writeAttribute('rad', $majorGridlines->getSoftEdgesSize());
$objWriter->endElement(); //end softEdge
}
$this->writeGlow($objWriter, $majorGridlines);
$this->writeShadow($objWriter, $majorGridlines);
$this->writeSoftEdge($objWriter, $majorGridlines);
$objWriter->endElement(); //end effectLst
$objWriter->endElement(); //end spPr
@ -748,61 +684,11 @@ class Chart extends WriterPart
}
$objWriter->startElement('a:effectLst');
if ($minorGridlines->getGlowSize() !== null) {
$objWriter->startElement('a:glow');
$objWriter->writeAttribute('rad', $minorGridlines->getGlowSize());
$objWriter->startElement("a:{$minorGridlines->getGlowColor('type')}");
$objWriter->writeAttribute('val', $minorGridlines->getGlowColor('value'));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', $minorGridlines->getGlowColor('alpha'));
$objWriter->endElement(); //end alpha
$objWriter->endElement(); //end schemeClr
$objWriter->endElement(); //end glow
}
if ($minorGridlines->getShadowProperty('presets') !== null) {
$objWriter->startElement("a:{$minorGridlines->getShadowProperty('effect')}");
if ($minorGridlines->getShadowProperty('blur') !== null) {
$objWriter->writeAttribute('blurRad', $minorGridlines->getShadowProperty('blur'));
}
if ($minorGridlines->getShadowProperty('distance') !== null) {
$objWriter->writeAttribute('dist', $minorGridlines->getShadowProperty('distance'));
}
if ($minorGridlines->getShadowProperty('direction') !== null) {
$objWriter->writeAttribute('dir', $minorGridlines->getShadowProperty('direction'));
}
if ($minorGridlines->getShadowProperty('algn') !== null) {
$objWriter->writeAttribute('algn', $minorGridlines->getShadowProperty('algn'));
}
if ($minorGridlines->getShadowProperty(['size', 'sx']) !== null) {
$objWriter->writeAttribute('sx', $minorGridlines->getShadowProperty(['size', 'sx']));
}
if ($minorGridlines->getShadowProperty(['size', 'sy']) !== null) {
$objWriter->writeAttribute('sy', $minorGridlines->getShadowProperty(['size', 'sy']));
}
if ($minorGridlines->getShadowProperty(['size', 'kx']) !== null) {
$objWriter->writeAttribute('kx', $minorGridlines->getShadowProperty(['size', 'kx']));
}
if ($minorGridlines->getShadowProperty('rotWithShape') !== null) {
$objWriter->writeAttribute('rotWithShape', $minorGridlines->getShadowProperty('rotWithShape'));
}
$objWriter->startElement("a:{$minorGridlines->getShadowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', $minorGridlines->getShadowProperty(['color', 'value']));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', $minorGridlines->getShadowProperty(['color', 'alpha']));
$objWriter->endElement(); //end alpha
$objWriter->endElement(); //end color:type
$objWriter->endElement(); //end shadow
}
if ($minorGridlines->getSoftEdgesSize() !== null) {
$objWriter->startElement('a:softEdge');
$objWriter->writeAttribute('rad', $minorGridlines->getSoftEdgesSize());
$objWriter->endElement(); //end softEdge
}
$this->writeGlow($objWriter, $minorGridlines);
$this->writeShadow($objWriter, $minorGridlines);
$this->writeSoftEdge($objWriter, $minorGridlines);
$objWriter->endElement(); //end effectLst
$objWriter->endElement(); //end spPr
$objWriter->endElement(); //end minorGridLines
}
@ -925,64 +811,11 @@ class Chart extends WriterPart
$objWriter->endElement();
$objWriter->startElement('a:effectLst');
if ($xAxis->getGlowProperty('size') !== null) {
$objWriter->startElement('a:glow');
$objWriter->writeAttribute('rad', $xAxis->getGlowProperty('size'));
$objWriter->startElement("a:{$xAxis->getGlowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', (string) $xAxis->getGlowProperty(['color', 'value']));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', (string) $xAxis->getGlowProperty(['color', 'alpha']));
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
}
if ($xAxis->getShadowProperty('presets') !== null) {
$objWriter->startElement("a:{$xAxis->getShadowProperty('effect')}");
if ($xAxis->getShadowProperty('blur') !== null) {
$objWriter->writeAttribute('blurRad', $xAxis->getShadowProperty('blur'));
}
if ($xAxis->getShadowProperty('distance') !== null) {
$objWriter->writeAttribute('dist', $xAxis->getShadowProperty('distance'));
}
if ($xAxis->getShadowProperty('direction') !== null) {
$objWriter->writeAttribute('dir', $xAxis->getShadowProperty('direction'));
}
if ($xAxis->getShadowProperty('algn') !== null) {
$objWriter->writeAttribute('algn', $xAxis->getShadowProperty('algn'));
}
if ($xAxis->getShadowProperty(['size', 'sx']) !== null) {
$objWriter->writeAttribute('sx', $xAxis->getShadowProperty(['size', 'sx']));
}
if ($xAxis->getShadowProperty(['size', 'sy']) !== null) {
$objWriter->writeAttribute('sy', $xAxis->getShadowProperty(['size', 'sy']));
}
if ($xAxis->getShadowProperty(['size', 'kx']) !== null) {
$objWriter->writeAttribute('kx', $xAxis->getShadowProperty(['size', 'kx']));
}
if ($xAxis->getShadowProperty('rotWithShape') !== null) {
$objWriter->writeAttribute('rotWithShape', $xAxis->getShadowProperty('rotWithShape'));
}
$objWriter->startElement("a:{$xAxis->getShadowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', $xAxis->getShadowProperty(['color', 'value']));
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', $xAxis->getShadowProperty(['color', 'alpha']));
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
}
if ($xAxis->getSoftEdgesSize() !== null) {
$objWriter->startElement('a:softEdge');
$objWriter->writeAttribute('rad', $xAxis->getSoftEdgesSize());
$objWriter->endElement();
}
$this->writeGlow($objWriter, $xAxis);
$this->writeShadow($objWriter, $xAxis);
$this->writeSoftEdge($objWriter, $xAxis);
$objWriter->endElement(); //effectList
$objWriter->endElement(); //end spPr
if ($id1 !== '0') {
@ -1658,4 +1491,100 @@ class Chart extends WriterPart
$objWriter->endElement();
}
/**
* Write shadow properties.
*
* @param Axis|GridLines $xAxis
*/
private function writeShadow(XMLWriter $objWriter, $xAxis): void
{
if ($xAxis->getShadowProperty('effect') === null) {
return;
}
/** @var string */
$effect = $xAxis->getShadowProperty('effect');
$objWriter->startElement("a:$effect");
if (is_numeric($xAxis->getShadowProperty('blur'))) {
$objWriter->writeAttribute('blurRad', Properties::pointsToXml((float) $xAxis->getShadowProperty('blur')));
}
if (is_numeric($xAxis->getShadowProperty('distance'))) {
$objWriter->writeAttribute('dist', Properties::pointsToXml((float) $xAxis->getShadowProperty('distance')));
}
if (is_numeric($xAxis->getShadowProperty('direction'))) {
$objWriter->writeAttribute('dir', Properties::angleToXml((float) $xAxis->getShadowProperty('direction')));
}
if ($xAxis->getShadowProperty('algn') !== null) {
$objWriter->writeAttribute('algn', $xAxis->getShadowProperty('algn'));
}
foreach (['sx', 'sy'] as $sizeType) {
$sizeValue = $xAxis->getShadowProperty(['size', $sizeType]);
if (is_numeric($sizeValue)) {
$objWriter->writeAttribute($sizeType, Properties::tenthOfPercentToXml((float) $sizeValue));
}
}
foreach (['kx', 'ky'] as $sizeType) {
$sizeValue = $xAxis->getShadowProperty(['size', $sizeType]);
if (is_numeric($sizeValue)) {
$objWriter->writeAttribute($sizeType, Properties::angleToXml((float) $sizeValue));
}
}
if ($xAxis->getShadowProperty('rotWithShape') !== null) {
$objWriter->writeAttribute('rotWithShape', $xAxis->getShadowProperty('rotWithShape'));
}
$objWriter->startElement("a:{$xAxis->getShadowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', $xAxis->getShadowProperty(['color', 'value']));
$alpha = $xAxis->getShadowProperty(['color', 'alpha']);
if (is_numeric($alpha)) {
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha));
$objWriter->endElement();
}
$objWriter->endElement();
$objWriter->endElement();
}
/**
* Write glow properties.
*
* @param Axis|GridLines $yAxis
*/
private function writeGlow(XMLWriter $objWriter, $yAxis): void
{
$size = $yAxis->getGlowProperty('size');
if (empty($size)) {
return;
}
$objWriter->startElement('a:glow');
$objWriter->writeAttribute('rad', Properties::pointsToXml((float) $size));
$objWriter->startElement("a:{$yAxis->getGlowProperty(['color', 'type'])}");
$objWriter->writeAttribute('val', (string) $yAxis->getGlowProperty(['color', 'value']));
$alpha = $yAxis->getGlowProperty(['color', 'alpha']);
if (is_numeric($alpha)) {
$objWriter->startElement('a:alpha');
$objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha));
$objWriter->endElement(); // alpha
}
$objWriter->endElement(); // color
$objWriter->endElement(); // glow
}
/**
* Write soft edge properties.
*
* @param Axis|GridLines $yAxis
*/
private function writeSoftEdge(XMLWriter $objWriter, $yAxis): void
{
$softEdgeSize = $yAxis->getSoftEdgesSize();
if (empty($softEdgeSize)) {
return;
}
$objWriter->startElement('a:softEdge');
$objWriter->writeAttribute('rad', Properties::pointsToXml((float) $softEdgeSize));
$objWriter->endElement(); //end softEdge
}
}

View File

@ -100,7 +100,7 @@ class MergedCellTest extends TestCase
$sheet->mergeCells($range);
self::fail("Expected invalid merge range $range");
} catch (SpreadException $e) {
self::assertSame('Merge must be set on a range of cells.', $e->getMessage());
self::assertSame('Merge must be on a valid range of cells.', $e->getMessage());
}
}
@ -109,7 +109,8 @@ class MergedCellTest extends TestCase
$spreadSheet = new Spreadsheet();
$dataSheet = $spreadSheet->getActiveSheet();
$this->setBadRange($dataSheet, 'B1');
// TODO - Reinstate full validation and disallow single cell merging for version 2.0
// $this->setBadRange($dataSheet, 'B1');
$this->setBadRange($dataSheet, 'Invalid');
$this->setBadRange($dataSheet, '1');
$this->setBadRange($dataSheet, 'C');

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
@ -106,21 +106,21 @@ class AxisGlowTest extends AbstractFunctional
);
$yAxis = $chart->getChartAxisY();
$xAxis = $chart->getChartAxisX();
$yAxis->setGlowProperties(10, 'FFFF00', 30, Properties::EXCEL_COLOR_TYPE_ARGB);
$expectedSize = 127000.0;
$yGlowSize = 10.0;
$yAxis->setGlowProperties($yGlowSize, 'FFFF00', 30, Properties::EXCEL_COLOR_TYPE_ARGB);
$expectedGlowColor = [
'type' => 'srgbClr',
'value' => 'FFFF00',
'alpha' => '70000',
'alpha' => 30,
];
$yAxis->setSoftEdges(2.5);
$xAxis->setSoftEdges(5);
$expectedSoftEdgesY = '31750';
$expectedSoftEdgesX = '63500';
self::assertEquals($expectedSize, $yAxis->getGlowProperty('size'));
$softEdgesY = 2.5;
$yAxis->setSoftEdges($softEdgesY);
$softEdgesX = 5;
$xAxis->setSoftEdges($softEdgesX);
self::assertEquals($yGlowSize, $yAxis->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
self::assertEquals($expectedSoftEdgesY, $yAxis->getSoftEdgesSize());
self::assertEquals($expectedSoftEdgesX, $xAxis->getSoftEdgesSize());
self::assertEquals($softEdgesY, $yAxis->getSoftEdgesSize());
self::assertEquals($softEdgesX, $xAxis->getSoftEdgesSize());
// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A7');
@ -142,9 +142,9 @@ class AxisGlowTest extends AbstractFunctional
$chart2 = $charts2[0];
self::assertNotNull($chart2);
$yAxis2 = $chart2->getChartAxisY();
self::assertEquals($expectedSize, $yAxis2->getGlowProperty('size'));
self::assertEquals($yGlowSize, $yAxis2->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
self::assertEquals($expectedSoftEdgesY, $yAxis2->getSoftEdgesSize());
self::assertEquals($softEdgesY, $yAxis2->getSoftEdgesSize());
$xAxis2 = $chart2->getChartAxisX();
self::assertNull($xAxis2->getGlowProperty('size'));
$reloadedSpreadsheet->disconnectWorksheets();
@ -229,14 +229,14 @@ class AxisGlowTest extends AbstractFunctional
$yAxisLabel // yAxisLabel
);
$yAxis = $chart->getChartAxisX(); // deliberate
$yAxis->setGlowProperties(20, 'accent1', 20, Properties::EXCEL_COLOR_TYPE_SCHEME);
$expectedSize = 254000.0;
$yGlowSize = 20.0;
$yAxis->setGlowProperties($yGlowSize, 'accent1', 20, Properties::EXCEL_COLOR_TYPE_SCHEME);
$expectedGlowColor = [
'type' => 'schemeClr',
'value' => 'accent1',
'alpha' => '80000',
'alpha' => 20,
];
self::assertEquals($expectedSize, $yAxis->getGlowProperty('size'));
self::assertEquals($yGlowSize, $yAxis->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
// Set the position where the chart should appear in the worksheet
@ -259,7 +259,7 @@ class AxisGlowTest extends AbstractFunctional
$chart2 = $charts2[0];
self::assertNotNull($chart2);
$yAxis2 = $chart2->getChartAxisX(); // deliberate
self::assertEquals($expectedSize, $yAxis2->getGlowProperty('size'));
self::assertEquals($yGlowSize, $yAxis2->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
$xAxis2 = $chart2->getChartAxisY(); // deliberate
self::assertNull($xAxis2->getGlowProperty('size'));

View File

@ -0,0 +1,184 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
class AxisShadowTest extends AbstractFunctional
{
public function readCharts(XlsxReader $reader): void
{
$reader->setIncludeCharts(true);
}
public function writeCharts(XlsxWriter $writer): void
{
$writer->setIncludeCharts(true);
}
public function testGlowY(): void
{
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
['', 2010, 2011, 2012],
['Q1', 12, 15, 21],
['Q2', 56, 73, 86],
['Q3', 52, 61, 69],
['Q4', 30, 32, 0],
]
);
// Set the Labels for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesLabels = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
];
// Set the X-Axis Labels
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$xAxisTickValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
];
// Build the dataseries
$series = new DataSeries(
DataSeries::TYPE_AREACHART, // plotType
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
range(0, count($dataSeriesValues) - 1), // plotOrder
$dataSeriesLabels, // plotLabel
$xAxisTickValues, // plotCategory
$dataSeriesValues // plotValues
);
// Set the series in the plot area
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
$title = new Title('Test %age-Stacked Area Chart');
$yAxisLabel = new Title('Value ($k)');
// Create the chart
$chart = new Chart(
'chart1', // name
$title, // title
$legend, // legend
$plotArea, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // xAxisLabel
$yAxisLabel // yAxisLabel
);
$yAxis = $chart->getChartAxisY();
$expectedY = [
'effect' => 'outerShdw',
'algn' => 'tl',
'blur' => 5,
'direction' => 45,
'distance' => 3,
'rotWithShape' => 0,
'color' => [
'type' => Properties::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 40,
],
];
foreach ($expectedY as $key => $value) {
$yAxis->setShadowProperty($key, $value);
}
foreach ($expectedY as $key => $value) {
self::assertEquals($value, $yAxis->getShadowProperty($key), $key);
}
$xAxis = $chart->getChartAxisX();
$expectedX = [
'effect' => 'outerShdw',
'algn' => 'bl',
'blur' => 6,
'direction' => 315,
'distance' => 3,
'rotWithShape' => 0,
'size' => [
'sx' => null,
'sy' => 254,
'kx' => -94,
'ky' => null,
],
'color' => [
'type' => Properties::EXCEL_COLOR_TYPE_ARGB,
'value' => 'FF0000',
'alpha' => 20,
],
];
foreach ($expectedX as $key => $value) {
$xAxis->setShadowProperty($key, $value);
}
foreach ($expectedX as $key => $value) {
self::assertEquals($value, $xAxis->getShadowProperty($key), $key);
}
// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A7');
$chart->setBottomRightPosition('H20');
// Add the chart to the worksheet
$worksheet->addChart($chart);
/** @var callable */
$callableReader = [$this, 'readCharts'];
/** @var callable */
$callableWriter = [$this, 'writeCharts'];
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter);
$spreadsheet->disconnectWorksheets();
$sheet = $reloadedSpreadsheet->getActiveSheet();
$charts2 = $sheet->getChartCollection();
self::assertCount(1, $charts2);
$chart2 = $charts2[0];
self::assertNotNull($chart2);
$yAxis2 = $chart2->getChartAxisY();
foreach ($expectedY as $key => $value) {
self::assertEquals($value, $yAxis2->getShadowProperty($key), $key);
}
$xAxis2 = $chart2->getChartAxisX();
foreach ($expectedX as $key => $value) {
self::assertEquals($value, $xAxis2->getShadowProperty($key), $key);
}
$reloadedSpreadsheet->disconnectWorksheets();
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Axis;
use PhpOffice\PhpSpreadsheet\Chart\Chart;

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\RichText\RichText;

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\RichText\RichText;

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PHPUnit\Framework\TestCase;

View File

@ -1,6 +1,6 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\IOFactory;

View File

@ -0,0 +1,187 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\GridLines;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
class GridlinesShadowGlowTest extends AbstractFunctional
{
public function readCharts(XlsxReader $reader): void
{
$reader->setIncludeCharts(true);
}
public function writeCharts(XlsxWriter $writer): void
{
$writer->setIncludeCharts(true);
}
public function testGlowY(): void
{
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
['', 2010, 2011, 2012],
['Q1', 12, 15, 21],
['Q2', 56, 73, 86],
['Q3', 52, 61, 69],
['Q4', 30, 32, 0],
]
);
// Set the Labels for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesLabels = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
];
// Set the X-Axis Labels
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$xAxisTickValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
];
// Build the dataseries
$series = new DataSeries(
DataSeries::TYPE_LINECHART, // plotType
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
range(0, count($dataSeriesValues) - 1), // plotOrder
$dataSeriesLabels, // plotLabel
$xAxisTickValues, // plotCategory
$dataSeriesValues // plotValues
);
// Set the series in the plot area
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
$title = new Title('Test %age-Stacked Area Chart');
$yAxisLabel = new Title('Value ($k)');
$majorGridlines = new GridLines();
$majorGlowSize = 10.0;
$majorGridlines->setGlowProperties($majorGlowSize, 'FFFF00', 30, Properties::EXCEL_COLOR_TYPE_ARGB);
$softEdgeSize = 2.5;
$majorGridlines->setSoftEdges($softEdgeSize);
$expectedGlowColor = [
'type' => 'srgbClr',
'value' => 'FFFF00',
'alpha' => 30,
];
self::assertEquals($majorGlowSize, $majorGridlines->getGlowProperty('size'));
self::assertEquals($majorGlowSize, $majorGridlines->getGlowSize());
self::assertEquals($expectedGlowColor['value'], $majorGridlines->getGlowColor('value'));
self::assertEquals($expectedGlowColor, $majorGridlines->getGlowProperty('color'));
self::assertEquals($softEdgeSize, $majorGridlines->getSoftEdgesSize());
$minorGridlines = new GridLines();
$expectedShadow = [
'effect' => 'outerShdw',
'algn' => 'tl',
'blur' => 4,
'direction' => 45,
'distance' => 3,
'rotWithShape' => 0,
'color' => [
'type' => Properties::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 40,
],
];
foreach ($expectedShadow as $key => $value) {
$minorGridlines->setShadowProperty($key, $value);
}
foreach ($expectedShadow as $key => $value) {
self::assertEquals($value, $minorGridlines->getShadowProperty($key), $key);
}
// Create the chart
$chart = new Chart(
'chart1', // name
$title, // title
$legend, // legend
$plotArea, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // xAxisLabel
$yAxisLabel, // yAxisLabel
null, // xAxis
null, // yAxis
$majorGridlines,
$minorGridlines
);
$majorGridlines2 = $chart->getMajorGridlines();
self::assertEquals($majorGlowSize, $majorGridlines2->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $majorGridlines2->getGlowProperty('color'));
self::assertEquals($softEdgeSize, $majorGridlines2->getSoftEdgesSize());
$minorGridlines2 = $chart->getMinorGridlines();
foreach ($expectedShadow as $key => $value) {
self::assertEquals($value, $minorGridlines2->getShadowProperty($key), $key);
}
// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A7');
$chart->setBottomRightPosition('H20');
// Add the chart to the worksheet
$worksheet->addChart($chart);
/** @var callable */
$callableReader = [$this, 'readCharts'];
/** @var callable */
$callableWriter = [$this, 'writeCharts'];
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx', $callableReader, $callableWriter);
$spreadsheet->disconnectWorksheets();
$sheet = $reloadedSpreadsheet->getActiveSheet();
$charts2 = $sheet->getChartCollection();
self::assertCount(1, $charts2);
$chart2 = $charts2[0];
self::assertNotNull($chart2);
$majorGridlines3 = $chart2->getMajorGridlines();
self::assertEquals($majorGlowSize, $majorGridlines3->getGlowProperty('size'));
self::assertEquals($expectedGlowColor, $majorGridlines3->getGlowProperty('color'));
self::assertEquals($softEdgeSize, $majorGridlines3->getSoftEdgesSize());
$minorGridlines3 = $chart->getMinorGridlines();
foreach ($expectedShadow as $key => $value) {
self::assertEquals($value, $minorGridlines3->getShadowProperty($key), $key);
}
$reloadedSpreadsheet->disconnectWorksheets();
}
}

View File

@ -0,0 +1,157 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PHPUnit\Framework\TestCase;
class MultiplierTest extends TestCase
{
public function testMultiplier(): void
{
$spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray(
[
['', 2010, 2011, 2012],
['Q1', 12, 15, 21],
['Q2', 56, 73, 86],
['Q3', 52, 61, 69],
['Q4', 30, 32, 0],
]
);
// Set the Labels for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesLabels = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012
];
// Set the X-Axis Labels
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$xAxisTickValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4
];
// Set the Data values for each data series we want to plot
// Datatype
// Cell reference for data
// Format Code
// Number of datapoints in series
// Data values
// Data Marker
$dataSeriesValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4),
];
// Build the dataseries
$series = new DataSeries(
DataSeries::TYPE_AREACHART, // plotType
DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping
range(0, count($dataSeriesValues) - 1), // plotOrder
$dataSeriesLabels, // plotLabel
$xAxisTickValues, // plotCategory
$dataSeriesValues // plotValues
);
// Set the series in the plot area
$plotArea = new PlotArea(null, [$series]);
// Set the chart legend
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
$title = new Title('Test %age-Stacked Area Chart');
$yAxisLabel = new Title('Value ($k)');
// Create the chart
$chart = new Chart(
'chart1', // name
$title, // title
$legend, // legend
$plotArea, // plotArea
true, // plotVisibleOnly
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
null, // xAxisLabel
$yAxisLabel // yAxisLabel
);
$xAxis = $chart->getChartAxisX();
$expectedX = [
'effect' => 'outerShdw',
'algn' => 'bl',
'blur' => 6,
'direction' => 315,
'distance' => 3,
'rotWithShape' => 0,
'size' => [
'sx' => null,
'sy' => 254,
'kx' => -94,
'ky' => null,
],
'color' => [
'type' => Properties::EXCEL_COLOR_TYPE_ARGB,
'value' => 'FF0000',
'alpha' => 20,
],
];
$expectedXmlX = [
'<a:outerShdw ',
' algn="bl"',
' blurRad="76200"',
' dir="18900000"',
' dist="38100"',
' rotWithShape="0"',
' sy="25400000"',
' kx="-5640000"',
'<a:srgbClr val="FF0000">',
'<a:alpha val="80000"/>',
];
$expectedXmlNoX = [
' sx=',
' ky=',
];
foreach ($expectedX as $key => $value) {
$xAxis->setShadowProperty($key, $value);
}
// Set the position where the chart should appear in the worksheet
$chart->setTopLeftPosition('A7');
$chart->setBottomRightPosition('H20');
// Add the chart to the worksheet
$worksheet->addChart($chart);
$writer = new XlsxWriter($spreadsheet);
$writer->setIncludeCharts(true);
$writerChart = new XlsxWriter\Chart($writer);
$data = $writerChart->writeChart($chart);
// confirm that file contains expected tags
foreach ($expectedXmlX as $expected) {
self::assertSame(1, substr_count($data, $expected), $expected);
}
foreach ($expectedXmlNoX as $expected) {
self::assertSame(0, substr_count($data, $expected), $expected);
}
$spreadsheet->disconnectWorksheets();
}
}

View File

@ -0,0 +1,183 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Axis;
use PhpOffice\PhpSpreadsheet\Chart\GridLines;
use PhpOffice\PhpSpreadsheet\Chart\Properties;
use PHPUnit\Framework\TestCase;
class ShadowPresetsTest extends TestCase
{
public function testGridlineShadowPresets(): void
{
$gridlines = new GridLines();
$gridlines->setShadowProperties(17);
$expectedShadow = [
'effect' => 'innerShdw',
'distance' => 4,
'direction' => 270,
'blur' => 5,
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($gridlines->getShadowProperty($key), $value, $key);
}
}
public function testGridlineShadowPresetsWithArray(): void
{
$gridlines = new GridLines();
$gridlines->setShadowProperties(20);
$expectedShadow = [
'effect' => 'outerShdw',
'blur' => 6,
'direction' => 315,
'size' => [
'sx' => null,
'sy' => 0.23,
'kx' => -20,
'ky' => null,
],
'algn' => 'bl',
'rotWithShape' => '0',
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($gridlines->getShadowProperty($key), $value, $key);
}
}
public function testAxisShadowPresets(): void
{
$axis = new Axis();
$axis->setShadowProperties(9);
$expectedShadow = [
'effect' => 'outerShdw',
'blur' => 4,
'distance' => 3,
'direction' => 225,
'algn' => 'br',
'rotWithShape' => '0',
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($axis->getShadowProperty($key), $value, $key);
}
}
public function testAxisShadowPresetsWithChanges(): void
{
$axis = new Axis();
$axis->setShadowProperties(
9, // preset
'FF0000', // colorValue
'srgbClr', // colorType
20, // alpha
6, // blur
30, // direction
4, // distance
);
$expectedShadow = [
'effect' => 'outerShdw',
'blur' => 6,
'distance' => 4,
'direction' => 30,
'algn' => 'br',
'rotWithShape' => '0',
'color' => [
'value' => 'FF0000',
'type' => 'srgbClr',
'alpha' => 20,
],
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($axis->getShadowProperty($key), $value, $key);
}
}
public function testGridlinesShadowPresetsWithChanges(): void
{
$gridline = new GridLines();
$gridline->setShadowProperties(
9, // preset
'FF0000', // colorValue
'srgbClr', // colorType
20, // alpha
6, // blur
30, // direction
4, // distance
);
$expectedShadow = [
'effect' => 'outerShdw',
'blur' => 6,
'distance' => 4,
'direction' => 30,
'algn' => 'br',
'rotWithShape' => '0',
'color' => [
'value' => 'FF0000',
'type' => 'srgbClr',
'alpha' => 20,
],
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($gridline->getShadowProperty($key), $value, $key);
}
}
public function testOutOfRangePresets(): void
{
$axis = new Axis();
$axis->setShadowProperties(99);
$expectedShadow = [
'presets' => Properties::SHADOW_PRESETS_NOSHADOW,
'effect' => null,
'color' => [
'type' => Properties::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 40,
],
'size' => [
'sx' => null,
'sy' => null,
'kx' => null,
'ky' => null,
],
'blur' => null,
'direction' => null,
'distance' => null,
'algn' => null,
'rotWithShape' => null,
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($value, $axis->getShadowProperty($key), $key);
}
}
public function testOutOfRangeGridlines(): void
{
$gridline = new GridLines();
$gridline->setShadowProperties(99);
$expectedShadow = [
'presets' => Properties::SHADOW_PRESETS_NOSHADOW,
'effect' => null,
'color' => [
'type' => Properties::EXCEL_COLOR_TYPE_STANDARD,
'value' => 'black',
'alpha' => 40,
],
'size' => [
'sx' => null,
'sy' => null,
'kx' => null,
'ky' => null,
],
'blur' => null,
'direction' => null,
'distance' => null,
'algn' => null,
'rotWithShape' => null,
];
foreach ($expectedShadow as $key => $value) {
self::assertEquals($value, $gridline->getShadowProperty($key), $key);
}
}
}