Merge branch 'master' into Issue-2874_Calculation-Engine-Quoted-Worksheet-Regexp
This commit is contained in:
commit
9f172733c7
|
|
@ -13,6 +13,10 @@ jobs:
|
||||||
- '8.0'
|
- '8.0'
|
||||||
- '8.1'
|
- '8.1'
|
||||||
|
|
||||||
|
include:
|
||||||
|
- php-version: '8.2'
|
||||||
|
experimental: true
|
||||||
|
|
||||||
name: PHP ${{ matrix.php-version }}
|
name: PHP ${{ matrix.php-version }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -39,7 +43,7 @@ jobs:
|
||||||
|
|
||||||
- name: Delete composer lock file
|
- name: Delete composer lock file
|
||||||
id: composer-lock
|
id: composer-lock
|
||||||
if: ${{ matrix.php-version == '8.1' }}
|
if: ${{ matrix.php-version == '8.1' || matrix.php-version == '8.2' }}
|
||||||
run: |
|
run: |
|
||||||
rm composer.lock
|
rm composer.lock
|
||||||
echo "::set-output name=flags::--ignore-platform-reqs"
|
echo "::set-output name=flags::--ignore-platform-reqs"
|
||||||
|
|
|
||||||
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added `removeComment()` method for Worksheet [PR #2875](https://github.com/PHPOffice/PhpSpreadsheet/pull/2875/files)
|
||||||
- Add point size option for scatter charts [Issue #2298](https://github.com/PHPOffice/PhpSpreadsheet/issues/2298) [PR #2801](https://github.com/PHPOffice/PhpSpreadsheet/pull/2801)
|
- Add point size option for scatter charts [Issue #2298](https://github.com/PHPOffice/PhpSpreadsheet/issues/2298) [PR #2801](https://github.com/PHPOffice/PhpSpreadsheet/pull/2801)
|
||||||
- Basic support for Xlsx reading/writing Chart Sheets [PR #2830](https://github.com/PHPOffice/PhpSpreadsheet/pull/2830)
|
- Basic support for Xlsx reading/writing Chart Sheets [PR #2830](https://github.com/PHPOffice/PhpSpreadsheet/pull/2830)
|
||||||
|
|
||||||
|
|
@ -18,12 +19,19 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850)
|
- Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850)
|
||||||
- Allow Csv Reader to treat string as contents of file [Issue #1285](https://github.com/PHPOffice/PhpSpreadsheet/issues/1285) [PR #2792](https://github.com/PHPOffice/PhpSpreadsheet/pull/2792)
|
- Allow Csv Reader to treat string as contents of file [Issue #1285](https://github.com/PHPOffice/PhpSpreadsheet/issues/1285) [PR #2792](https://github.com/PHPOffice/PhpSpreadsheet/pull/2792)
|
||||||
- Allow Csv Reader to store null string rather than leave cell empty [Issue #2840](https://github.com/PHPOffice/PhpSpreadsheet/issues/2840) [PR #2842](https://github.com/PHPOffice/PhpSpreadsheet/pull/2842)
|
- Allow Csv Reader to store null string rather than leave cell empty [Issue #2840](https://github.com/PHPOffice/PhpSpreadsheet/issues/2840) [PR #2842](https://github.com/PHPOffice/PhpSpreadsheet/pull/2842)
|
||||||
|
- Provide new Worksheet methods to identify if a row or column is "empty", making allowance for different definitions of "empty":
|
||||||
|
- Treat rows/columns containing no cell records as empty (default)
|
||||||
|
- Treat cells containing a null value as empty
|
||||||
|
- Treat cells containing an empty string as empty
|
||||||
|
|
||||||
### Changed
|
### 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.
|
- 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
|
See [the Discussion section on github](https://github.com/PHPOffice/PhpSpreadsheet/discussions/2821) for details of performance across versions
|
||||||
|
- Improved performance for removing rows/columns from a worksheet
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
|
@ -41,7 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Time interval formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772)
|
- Time interval formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772)
|
||||||
- Copy from Xls(x) to Html/Pdf loses drawings [PR #2788](https://github.com/PHPOffice/PhpSpreadsheet/pull/2788)
|
- Copy from Xls(x) to Html/Pdf loses drawings [PR #2788](https://github.com/PHPOffice/PhpSpreadsheet/pull/2788)
|
||||||
- Html Reader converting cell containing 0 to null string [Issue #2810](https://github.com/PHPOffice/PhpSpreadsheet/issues/2810) [PR #2813](https://github.com/PHPOffice/PhpSpreadsheet/pull/2813)
|
- Html Reader converting cell containing 0 to null string [Issue #2810](https://github.com/PHPOffice/PhpSpreadsheet/issues/2810) [PR #2813](https://github.com/PHPOffice/PhpSpreadsheet/pull/2813)
|
||||||
- Many fixes for Charts, especially, but not limited to, Scatter, Bubble, and Surface charts. [Issue #2762](https://github.com/PHPOffice/PhpSpreadsheet/issues/2762) [Issue #2299](https://github.com/PHPOffice/PhpSpreadsheet/issues/2299) [Issue #2700](https://github.com/PHPOffice/PhpSpreadsheet/issues/2700) [Issue #2817](https://github.com/PHPOffice/PhpSpreadsheet/issues/2817) [Issue #2763](https://github.com/PHPOffice/PhpSpreadsheet/issues/2763) [PR #2828](https://github.com/PHPOffice/PhpSpreadsheet/pull/2828) [PR #2841](https://github.com/PHPOffice/PhpSpreadsheet/pull/2841) [PR #2846](https://github.com/PHPOffice/PhpSpreadsheet/pull/2846) [PR #2852](https://github.com/PHPOffice/PhpSpreadsheet/pull/2852)
|
- Many fixes for Charts, especially, but not limited to, Scatter, Bubble, and Surface charts. [Issue #2762](https://github.com/PHPOffice/PhpSpreadsheet/issues/2762) [Issue #2299](https://github.com/PHPOffice/PhpSpreadsheet/issues/2299) [Issue #2700](https://github.com/PHPOffice/PhpSpreadsheet/issues/2700) [Issue #2817](https://github.com/PHPOffice/PhpSpreadsheet/issues/2817) [Issue #2763](https://github.com/PHPOffice/PhpSpreadsheet/issues/2763) [Issue #2219](https://github.com/PHPOffice/PhpSpreadsheet/issues/2219) [PR #2828](https://github.com/PHPOffice/PhpSpreadsheet/pull/2828) [PR #2841](https://github.com/PHPOffice/PhpSpreadsheet/pull/2841) [PR #2846](https://github.com/PHPOffice/PhpSpreadsheet/pull/2846) [PR #2852](https://github.com/PHPOffice/PhpSpreadsheet/pull/2852) [PR #2856](https://github.com/PHPOffice/PhpSpreadsheet/pull/2856) [PR #2865](https://github.com/PHPOffice/PhpSpreadsheet/pull/2865) [PR #2872](https://github.com/PHPOffice/PhpSpreadsheet/pull/2872) [PR #2879](https://github.com/PHPOffice/PhpSpreadsheet/pull/2879)
|
||||||
|
|
||||||
## 1.23.0 - 2022-04-24
|
## 1.23.0 - 2022-04-24
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
"phpstan/phpstan": "^1.1",
|
"phpstan/phpstan": "^1.1",
|
||||||
"phpstan/phpstan-phpunit": "^1.0",
|
"phpstan/phpstan-phpunit": "^1.0",
|
||||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
"phpunit/phpunit": "^8.5 || ^9.0",
|
||||||
"squizlabs/php_codesniffer": "^3.6",
|
"squizlabs/php_codesniffer": "^3.7",
|
||||||
"tecnickcom/tcpdf": "^6.4"
|
"tecnickcom/tcpdf": "^6.4"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "2e09b120ad90fc0fbbc055e1f341910e",
|
"content-hash": "fa9fa4814df8320d600551ca8ec11883",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "ezyang/htmlpurifier",
|
"name": "ezyang/htmlpurifier",
|
||||||
|
|
@ -279,10 +279,6 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"enum"
|
"enum"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/myclabs/php-enum/issues",
|
|
||||||
"source": "https://github.com/myclabs/php-enum/tree/1.8.3"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/mnapoli",
|
"url": "https://github.com/mnapoli",
|
||||||
|
|
@ -811,12 +807,12 @@
|
||||||
"version": "dev-master",
|
"version": "dev-master",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
|
"url": "https://github.com/PHPCSStandards/composer-installer.git",
|
||||||
"reference": "7d5cb8826ed72d4ca4c07acf005bba2282e5a7c7"
|
"reference": "7d5cb8826ed72d4ca4c07acf005bba2282e5a7c7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/7d5cb8826ed72d4ca4c07acf005bba2282e5a7c7",
|
"url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/7d5cb8826ed72d4ca4c07acf005bba2282e5a7c7",
|
||||||
"reference": "7d5cb8826ed72d4ca4c07acf005bba2282e5a7c7",
|
"reference": "7d5cb8826ed72d4ca4c07acf005bba2282e5a7c7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
|
|
@ -830,7 +826,6 @@
|
||||||
"php-parallel-lint/php-parallel-lint": "^1.3.1",
|
"php-parallel-lint/php-parallel-lint": "^1.3.1",
|
||||||
"phpcompatibility/php-compatibility": "^9.0"
|
"phpcompatibility/php-compatibility": "^9.0"
|
||||||
},
|
},
|
||||||
"default-branch": true,
|
|
||||||
"type": "composer-plugin",
|
"type": "composer-plugin",
|
||||||
"extra": {
|
"extra": {
|
||||||
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
|
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
|
||||||
|
|
@ -999,10 +994,6 @@
|
||||||
"constructor",
|
"constructor",
|
||||||
"instantiate"
|
"instantiate"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
|
||||||
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://www.doctrine-project.org/sponsorship.html",
|
"url": "https://www.doctrine-project.org/sponsorship.html",
|
||||||
|
|
@ -1162,10 +1153,6 @@
|
||||||
],
|
],
|
||||||
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
||||||
"homepage": "https://github.com/dompdf/dompdf",
|
"homepage": "https://github.com/dompdf/dompdf",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/dompdf/dompdf/issues",
|
|
||||||
"source": "https://github.com/dompdf/dompdf/tree/v1.2.2"
|
|
||||||
},
|
|
||||||
"time": "2022-04-27T13:50:54+00:00"
|
"time": "2022-04-27T13:50:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -1366,11 +1353,6 @@
|
||||||
"php",
|
"php",
|
||||||
"utf-8"
|
"utf-8"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"docs": "http://mpdf.github.io",
|
|
||||||
"issues": "https://github.com/mpdf/mpdf/issues",
|
|
||||||
"source": "https://github.com/mpdf/mpdf"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://www.paypal.me/mpdf",
|
"url": "https://www.paypal.me/mpdf",
|
||||||
|
|
@ -1426,10 +1408,6 @@
|
||||||
"object",
|
"object",
|
||||||
"object graph"
|
"object graph"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
|
||||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
|
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
|
||||||
|
|
@ -1488,10 +1466,6 @@
|
||||||
"parser",
|
"parser",
|
||||||
"php"
|
"php"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
|
||||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2"
|
|
||||||
},
|
|
||||||
"time": "2021-11-30T19:35:32+00:00"
|
"time": "2021-11-30T19:35:32+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -1649,10 +1623,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Library for handling version information and constraints",
|
"description": "Library for handling version information and constraints",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/phar-io/version/issues",
|
|
||||||
"source": "https://github.com/phar-io/version/tree/3.2.1"
|
|
||||||
},
|
|
||||||
"time": "2022-02-21T01:04:05+00:00"
|
"time": "2022-02-21T01:04:05+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -1693,10 +1663,6 @@
|
||||||
],
|
],
|
||||||
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||||
"homepage": "https://github.com/PhenX/php-font-lib",
|
"homepage": "https://github.com/PhenX/php-font-lib",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/dompdf/php-font-lib/issues",
|
|
||||||
"source": "https://github.com/dompdf/php-font-lib/tree/0.5.4"
|
|
||||||
},
|
|
||||||
"time": "2021-12-17T19:44:54+00:00"
|
"time": "2021-12-17T19:44:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -1739,10 +1705,6 @@
|
||||||
],
|
],
|
||||||
"description": "A library to read, parse and export to PDF SVG files.",
|
"description": "A library to read, parse and export to PDF SVG files.",
|
||||||
"homepage": "https://github.com/PhenX/php-svg-lib",
|
"homepage": "https://github.com/PhenX/php-svg-lib",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/dompdf/php-svg-lib/issues",
|
|
||||||
"source": "https://github.com/dompdf/php-svg-lib/tree/0.4.1"
|
|
||||||
},
|
|
||||||
"time": "2022-03-07T12:52:04+00:00"
|
"time": "2022-03-07T12:52:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -1845,10 +1807,6 @@
|
||||||
"stream",
|
"stream",
|
||||||
"uri"
|
"uri"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/php-http/message-factory/issues",
|
|
||||||
"source": "https://github.com/php-http/message-factory/tree/master"
|
|
||||||
},
|
|
||||||
"time": "2015-12-19T14:08:53+00:00"
|
"time": "2015-12-19T14:08:53+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -2067,10 +2025,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
|
||||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
|
|
||||||
},
|
|
||||||
"time": "2022-03-15T21:29:03+00:00"
|
"time": "2022-03-15T21:29:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -2134,10 +2088,6 @@
|
||||||
"spy",
|
"spy",
|
||||||
"stub"
|
"stub"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/phpspec/prophecy/issues",
|
|
||||||
"source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
|
|
||||||
},
|
|
||||||
"time": "2021-12-08T12:19:24+00:00"
|
"time": "2021-12-08T12:19:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -2245,10 +2195,6 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"description": "PHPUnit extensions and rules for PHPStan",
|
"description": "PHPUnit extensions and rules for PHPStan",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
|
|
||||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.1.1"
|
|
||||||
},
|
|
||||||
"time": "2022-04-20T15:24:25+00:00"
|
"time": "2022-04-20T15:24:25+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -2316,10 +2262,6 @@
|
||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -2376,10 +2318,6 @@
|
||||||
"filesystem",
|
"filesystem",
|
||||||
"iterator"
|
"iterator"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -2439,10 +2377,6 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"process"
|
"process"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -2498,10 +2432,6 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"template"
|
"template"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -2557,10 +2487,6 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"timer"
|
"timer"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -2656,10 +2582,6 @@
|
||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://phpunit.de/sponsors.html",
|
"url": "https://phpunit.de/sponsors.html",
|
||||||
|
|
@ -2916,10 +2838,6 @@
|
||||||
"parser",
|
"parser",
|
||||||
"stylesheet"
|
"stylesheet"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues",
|
|
||||||
"source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0"
|
|
||||||
},
|
|
||||||
"time": "2021-12-11T13:40:54+00:00"
|
"time": "2021-12-11T13:40:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -2966,10 +2884,6 @@
|
||||||
],
|
],
|
||||||
"description": "Library for parsing CLI options",
|
"description": "Library for parsing CLI options",
|
||||||
"homepage": "https://github.com/sebastianbergmann/cli-parser",
|
"homepage": "https://github.com/sebastianbergmann/cli-parser",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3022,10 +2936,6 @@
|
||||||
],
|
],
|
||||||
"description": "Collection of value objects that represent the PHP code units",
|
"description": "Collection of value objects that represent the PHP code units",
|
||||||
"homepage": "https://github.com/sebastianbergmann/code-unit",
|
"homepage": "https://github.com/sebastianbergmann/code-unit",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3077,10 +2987,6 @@
|
||||||
],
|
],
|
||||||
"description": "Looks up which function or method a line of code belongs to",
|
"description": "Looks up which function or method a line of code belongs to",
|
||||||
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3151,10 +3057,6 @@
|
||||||
"compare",
|
"compare",
|
||||||
"equality"
|
"equality"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3208,10 +3110,6 @@
|
||||||
],
|
],
|
||||||
"description": "Library for calculating the complexity of PHP code units",
|
"description": "Library for calculating the complexity of PHP code units",
|
||||||
"homepage": "https://github.com/sebastianbergmann/complexity",
|
"homepage": "https://github.com/sebastianbergmann/complexity",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/complexity/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3274,10 +3172,6 @@
|
||||||
"unidiff",
|
"unidiff",
|
||||||
"unified diff"
|
"unified diff"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3337,10 +3231,6 @@
|
||||||
"environment",
|
"environment",
|
||||||
"hhvm"
|
"hhvm"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/environment/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3414,10 +3304,6 @@
|
||||||
"export",
|
"export",
|
||||||
"exporter"
|
"exporter"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3478,10 +3364,6 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"global state"
|
"global state"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/global-state/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3535,10 +3417,6 @@
|
||||||
],
|
],
|
||||||
"description": "Library for counting the lines of code in PHP source code",
|
"description": "Library for counting the lines of code in PHP source code",
|
||||||
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
|
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3592,10 +3470,6 @@
|
||||||
],
|
],
|
||||||
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
||||||
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3647,10 +3521,6 @@
|
||||||
],
|
],
|
||||||
"description": "Allows reflection of object attributes, including inherited and non-public ones",
|
"description": "Allows reflection of object attributes, including inherited and non-public ones",
|
||||||
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
|
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3710,10 +3580,6 @@
|
||||||
],
|
],
|
||||||
"description": "Provides functionality to recursively process PHP variables",
|
"description": "Provides functionality to recursively process PHP variables",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3765,10 +3631,6 @@
|
||||||
],
|
],
|
||||||
"description": "Provides a list of PHP built-in functions that operate on resources",
|
"description": "Provides a list of PHP built-in functions that operate on resources",
|
||||||
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3821,10 +3683,6 @@
|
||||||
],
|
],
|
||||||
"description": "Collection of value objects that represent the types of the PHP type system",
|
"description": "Collection of value objects that represent the types of the PHP type system",
|
||||||
"homepage": "https://github.com/sebastianbergmann/type",
|
"homepage": "https://github.com/sebastianbergmann/type",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/type/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/type/tree/3.0.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3874,10 +3732,6 @@
|
||||||
],
|
],
|
||||||
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
||||||
"homepage": "https://github.com/sebastianbergmann/version",
|
"homepage": "https://github.com/sebastianbergmann/version",
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/sebastianbergmann/version/issues",
|
|
||||||
"source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
|
@ -3960,16 +3814,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "squizlabs/php_codesniffer",
|
"name": "squizlabs/php_codesniffer",
|
||||||
"version": "3.6.2",
|
"version": "3.7.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
||||||
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
|
"reference": "a2cd51b45bcaef9c1f2a4bda48f2dd2fa2b95563"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
|
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/a2cd51b45bcaef9c1f2a4bda48f2dd2fa2b95563",
|
||||||
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
|
"reference": "a2cd51b45bcaef9c1f2a4bda48f2dd2fa2b95563",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -4007,12 +3861,7 @@
|
||||||
"phpcs",
|
"phpcs",
|
||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
"support": {
|
"time": "2022-06-13T06:31:38+00:00"
|
||||||
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
|
|
||||||
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
|
|
||||||
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
|
|
||||||
},
|
|
||||||
"time": "2021-12-12T21:44:58+00:00"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
|
|
@ -4603,9 +4452,6 @@
|
||||||
"polyfill",
|
"polyfill",
|
||||||
"portable"
|
"portable"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
|
@ -5381,10 +5227,6 @@
|
||||||
"pdf417",
|
"pdf417",
|
||||||
"qrcode"
|
"qrcode"
|
||||||
],
|
],
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/tecnickcom/TCPDF/issues",
|
|
||||||
"source": "https://github.com/tecnickcom/TCPDF/tree/6.4.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project",
|
"url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project",
|
||||||
|
|
@ -5526,5 +5368,5 @@
|
||||||
"ext-zlib": "*"
|
"ext-zlib": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "1.1.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1348,7 +1348,7 @@ Removing a merge can be done using the unmergeCells method:
|
||||||
$spreadsheet->getActiveSheet()->unmergeCells('A18:E22');
|
$spreadsheet->getActiveSheet()->unmergeCells('A18:E22');
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inserting rows/columns
|
## Inserting or Removing rows/columns
|
||||||
|
|
||||||
You can insert/remove rows/columns at a specific position. The following
|
You can insert/remove rows/columns at a specific position. The following
|
||||||
code inserts 2 new rows, right before row 7:
|
code inserts 2 new rows, right before row 7:
|
||||||
|
|
@ -1356,6 +1356,23 @@ code inserts 2 new rows, right before row 7:
|
||||||
```php
|
```php
|
||||||
$spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2);
|
$spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2);
|
||||||
```
|
```
|
||||||
|
while
|
||||||
|
```php
|
||||||
|
$spreadsheet->getActiveSheet()->removeRow(7, 2);
|
||||||
|
```
|
||||||
|
will remove 2 rows starting at row number 7 (ie. rows 7 and 8).
|
||||||
|
|
||||||
|
Equivalent methods exist for inserting/removing columns:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$spreadsheet->getActiveSheet()->removeColumn('C', 2);
|
||||||
|
```
|
||||||
|
|
||||||
|
All subsequent rows (or columns) will be moved to allow the insertion (or removal) with all formulae referencing thise cells adjusted accordingly.
|
||||||
|
|
||||||
|
Note that this is a fairly intensive process, particularly with large worksheets, and especially if you are inserting/removing rows/columns from near beginning of the worksheet.
|
||||||
|
|
||||||
|
If you need to insert/remove several consecutive rows/columns, always use the second argument rather than making multiple calls to insert/remove a single row/column if possible.
|
||||||
|
|
||||||
## Add a drawing to a worksheet
|
## Add a drawing to a worksheet
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1170,56 +1170,6 @@ parameters:
|
||||||
count: 2
|
count: 2
|
||||||
path: src/PhpSpreadsheet/Chart/DataSeries.php
|
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
|
|
||||||
path: src/PhpSpreadsheet/Chart/GridLines.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#3 \\$colorType of method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:setGlowColor\\(\\) expects string, string\\|null given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/GridLines.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$glowProperties has no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/GridLines.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$lineProperties has no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/GridLines.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$objectState has no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/GridLines.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$shadowProperties has no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/GridLines.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\GridLines\\:\\:\\$softEdges has no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Chart/GridLines.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend\\:\\:\\$layout \\(PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Layout\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Layout\\|null\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend\\:\\:\\$layout \\(PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Layout\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Layout\\|null\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -1275,36 +1225,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Chart/Properties.php
|
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\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Renderer\\\\JpGraph\\:\\:formatDataSetLabels\\(\\) has no return type specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3155,26 +3075,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:mbIsUpper\\(\\) has no return type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:mbIsUpper\\(\\) has parameter \\$character with no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:mbStrSplit\\(\\) has no return type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:mbStrSplit\\(\\) has parameter \\$string with no type specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:sanitizeUTF8\\(\\) should return string but returns string\\|false\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:sanitizeUTF8\\(\\) should return string but returns string\\|false\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3200,11 +3100,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Variable \\$textValue on left side of \\?\\? always exists and is not nullable\\.$#"
|
|
||||||
count: 3
|
|
||||||
path: src/PhpSpreadsheet/Shared/StringHelper.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\TimeZone\\:\\:validateTimeZone\\(\\) is unused\\.$#"
|
message: "#^Static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\TimeZone\\:\\:validateTimeZone\\(\\) is unused\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3655,11 +3550,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Worksheet/CellIterator.php
|
path: src/PhpSpreadsheet/Worksheet/CellIterator.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Column\\:\\:\\$parent \\(PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Worksheet/Column.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\:\\:\\$color \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\|null\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\:\\:\\$color \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Color\\|null\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3685,11 +3575,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Worksheet/PageSetup.php
|
path: src/PhpSpreadsheet/Worksheet/PageSetup.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Row\\:\\:\\$worksheet \\(PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Worksheet/Row.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\SheetView\\:\\:\\$sheetViewTypes has no type specified\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\SheetView\\:\\:\\$sheetViewTypes has no type specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -4460,11 +4345,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Else branch is unreachable because previous condition is always true\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$plotSeriesValues of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:writeBubbles\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|null, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|false given\\.$#"
|
message: "#^Parameter \\#1 \\$plotSeriesValues of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:writeBubbles\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|null, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues\\|false given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -4475,16 +4355,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, array\\|int\\|string given\\.$#"
|
|
||||||
count: 8
|
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, array\\|int\\|string\\|null given\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, float given\\.$#"
|
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, float given\\.$#"
|
||||||
count: 6
|
count: 6
|
||||||
|
|
@ -4500,11 +4370,6 @@ parameters:
|
||||||
count: 42
|
count: 42
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, string\\|null given\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#6 \\$yAxis of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:writeCategoryAxis\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis\\|null given\\.$#"
|
message: "#^Parameter \\#6 \\$yAxis of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:writeCategoryAxis\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Axis\\|null given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -4525,16 +4390,6 @@ parameters:
|
||||||
count: 2
|
count: 2
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
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
|
|
||||||
path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:\\$calculateCellValues has no type specified\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:\\$calculateCellValues has no type specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -3088,7 +3088,7 @@ class Calculation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test whether we have any language data for this language (any locale)
|
// Test whether we have any language data for this language (any locale)
|
||||||
if (in_array($language, self::$validLocaleLanguages)) {
|
if (in_array($language, self::$validLocaleLanguages, true)) {
|
||||||
// initialise language/locale settings
|
// initialise language/locale settings
|
||||||
self::$localeFunctions = [];
|
self::$localeFunctions = [];
|
||||||
self::$localeArgumentSeparator = ',';
|
self::$localeArgumentSeparator = ',';
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ class Functions
|
||||||
if ($condition === '') {
|
if ($condition === '') {
|
||||||
return '=""';
|
return '=""';
|
||||||
}
|
}
|
||||||
if (!is_string($condition) || !in_array($condition[0], ['>', '<', '='])) {
|
if (!is_string($condition) || !in_array($condition[0], ['>', '<', '='], true)) {
|
||||||
$condition = self::operandSpecialHandling($condition);
|
$condition = self::operandSpecialHandling($condition);
|
||||||
if (is_bool($condition)) {
|
if (is_bool($condition)) {
|
||||||
return '=' . ($condition ? 'TRUE' : 'FALSE');
|
return '=' . ($condition ? 'TRUE' : 'FALSE');
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class ErrorValue
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return in_array($value, ExcelError::$errorCodes) || $value === ExcelError::CALC();
|
return in_array($value, ExcelError::$errorCodes, true) || $value === ExcelError::CALC();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class ExcelError
|
||||||
/**
|
/**
|
||||||
* List of error codes.
|
* List of error codes.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
public static $errorCodes = [
|
public static $errorCodes = [
|
||||||
'null' => '#NULL!',
|
'null' => '#NULL!',
|
||||||
|
|
@ -60,7 +60,7 @@ class ExcelError
|
||||||
*
|
*
|
||||||
* @return string #NULL!
|
* @return string #NULL!
|
||||||
*/
|
*/
|
||||||
public static function null()
|
public static function null(): string
|
||||||
{
|
{
|
||||||
return self::$errorCodes['null'];
|
return self::$errorCodes['null'];
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ class ExcelError
|
||||||
*
|
*
|
||||||
* @return string #NUM!
|
* @return string #NUM!
|
||||||
*/
|
*/
|
||||||
public static function NAN()
|
public static function NAN(): string
|
||||||
{
|
{
|
||||||
return self::$errorCodes['num'];
|
return self::$errorCodes['num'];
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ class ExcelError
|
||||||
*
|
*
|
||||||
* @return string #REF!
|
* @return string #REF!
|
||||||
*/
|
*/
|
||||||
public static function REF()
|
public static function REF(): string
|
||||||
{
|
{
|
||||||
return self::$errorCodes['reference'];
|
return self::$errorCodes['reference'];
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +100,7 @@ class ExcelError
|
||||||
*
|
*
|
||||||
* @return string #N/A!
|
* @return string #N/A!
|
||||||
*/
|
*/
|
||||||
public static function NA()
|
public static function NA(): string
|
||||||
{
|
{
|
||||||
return self::$errorCodes['na'];
|
return self::$errorCodes['na'];
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +112,7 @@ class ExcelError
|
||||||
*
|
*
|
||||||
* @return string #VALUE!
|
* @return string #VALUE!
|
||||||
*/
|
*/
|
||||||
public static function VALUE()
|
public static function VALUE(): string
|
||||||
{
|
{
|
||||||
return self::$errorCodes['value'];
|
return self::$errorCodes['value'];
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +124,7 @@ class ExcelError
|
||||||
*
|
*
|
||||||
* @return string #NAME?
|
* @return string #NAME?
|
||||||
*/
|
*/
|
||||||
public static function NAME()
|
public static function NAME(): string
|
||||||
{
|
{
|
||||||
return self::$errorCodes['name'];
|
return self::$errorCodes['name'];
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +134,7 @@ class ExcelError
|
||||||
*
|
*
|
||||||
* @return string #DIV/0!
|
* @return string #DIV/0!
|
||||||
*/
|
*/
|
||||||
public static function DIV0()
|
public static function DIV0(): string
|
||||||
{
|
{
|
||||||
return self::$errorCodes['divisionbyzero'];
|
return self::$errorCodes['divisionbyzero'];
|
||||||
}
|
}
|
||||||
|
|
@ -142,9 +142,9 @@ class ExcelError
|
||||||
/**
|
/**
|
||||||
* CALC.
|
* CALC.
|
||||||
*
|
*
|
||||||
* @return string #Not Yet Implemented
|
* @return string #CALC!
|
||||||
*/
|
*/
|
||||||
public static function CALC()
|
public static function CALC(): string
|
||||||
{
|
{
|
||||||
return '#CALC!';
|
return '#CALC!';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ class HLookup extends LookupBase
|
||||||
// break if we have passed possible keys
|
// break if we have passed possible keys
|
||||||
$bothNumeric = is_numeric($lookupValue) && is_numeric($rowData);
|
$bothNumeric = is_numeric($lookupValue) && is_numeric($rowData);
|
||||||
$bothNotNumeric = !is_numeric($lookupValue) && !is_numeric($rowData);
|
$bothNotNumeric = !is_numeric($lookupValue) && !is_numeric($rowData);
|
||||||
$cellDataLower = StringHelper::strToLower($rowData);
|
$cellDataLower = StringHelper::strToLower((string) $rowData);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$notExactMatch &&
|
$notExactMatch &&
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ class VLookup extends LookupBase
|
||||||
foreach ($lookupArray as $rowKey => $rowData) {
|
foreach ($lookupArray as $rowKey => $rowData) {
|
||||||
$bothNumeric = is_numeric($lookupValue) && is_numeric($rowData[$column]);
|
$bothNumeric = is_numeric($lookupValue) && is_numeric($rowData[$column]);
|
||||||
$bothNotNumeric = !is_numeric($lookupValue) && !is_numeric($rowData[$column]);
|
$bothNotNumeric = !is_numeric($lookupValue) && !is_numeric($rowData[$column]);
|
||||||
$cellDataLower = StringHelper::strToLower($rowData[$column]);
|
$cellDataLower = StringHelper::strToLower((string) $rowData[$column]);
|
||||||
|
|
||||||
// break if we have passed possible keys
|
// break if we have passed possible keys
|
||||||
if (
|
if (
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,11 @@ class Cell
|
||||||
*
|
*
|
||||||
* @param mixed $value Value
|
* @param mixed $value Value
|
||||||
* @param string $dataType Explicit data type, see DataType::TYPE_*
|
* @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
|
* @return Cell
|
||||||
*/
|
*/
|
||||||
|
|
@ -210,7 +215,7 @@ class Cell
|
||||||
// set the value according to data type
|
// set the value according to data type
|
||||||
switch ($dataType) {
|
switch ($dataType) {
|
||||||
case DataType::TYPE_NULL:
|
case DataType::TYPE_NULL:
|
||||||
$this->value = $value;
|
$this->value = null;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DataType::TYPE_STRING2:
|
case DataType::TYPE_STRING2:
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class DataType
|
||||||
/**
|
/**
|
||||||
* List of error codes.
|
* List of error codes.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array<string, int>
|
||||||
*/
|
*/
|
||||||
private static $errorCodes = [
|
private static $errorCodes = [
|
||||||
'#NULL!' => 0,
|
'#NULL!' => 0,
|
||||||
|
|
@ -36,7 +36,7 @@ class DataType
|
||||||
/**
|
/**
|
||||||
* Get list of error codes.
|
* Get list of error codes.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array<string, int>
|
||||||
*/
|
*/
|
||||||
public static function getErrorCodes()
|
public static function getErrorCodes()
|
||||||
{
|
{
|
||||||
|
|
@ -48,7 +48,7 @@ class DataType
|
||||||
*
|
*
|
||||||
* @param null|RichText|string $textValue Value to sanitize to an Excel string
|
* @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)
|
public static function checkString($textValue)
|
||||||
{
|
{
|
||||||
|
|
@ -58,7 +58,7 @@ class DataType
|
||||||
}
|
}
|
||||||
|
|
||||||
// string must never be longer than 32,767 characters, truncate if necessary
|
// 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"
|
// we require that newline is represented as "\n" in core, not as "\r\n" or "\r"
|
||||||
$textValue = str_replace(["\r\n", "\r"], "\n", $textValue);
|
$textValue = str_replace(["\r\n", "\r"], "\n", $textValue);
|
||||||
|
|
|
||||||
|
|
@ -50,88 +50,6 @@ class Axis extends Properties
|
||||||
'alpha' => 0,
|
'alpha' => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* Line Properties.
|
|
||||||
*
|
|
||||||
* @var mixed[]
|
|
||||||
*/
|
|
||||||
private $lineProperties = [
|
|
||||||
'type' => self::EXCEL_COLOR_TYPE_ARGB,
|
|
||||||
'value' => null,
|
|
||||||
'alpha' => 0,
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Line Style Properties.
|
|
||||||
*
|
|
||||||
* @var mixed[]
|
|
||||||
*/
|
|
||||||
private $lineStyleProperties = [
|
|
||||||
'width' => '9525',
|
|
||||||
'compound' => self::LINE_STYLE_COMPOUND_SIMPLE,
|
|
||||||
'dash' => self::LINE_STYLE_DASH_SOLID,
|
|
||||||
'cap' => self::LINE_STYLE_CAP_FLAT,
|
|
||||||
'join' => self::LINE_STYLE_JOIN_BEVEL,
|
|
||||||
'arrow' => [
|
|
||||||
'head' => [
|
|
||||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
|
||||||
'size' => self::LINE_STYLE_ARROW_SIZE_5,
|
|
||||||
],
|
|
||||||
'end' => [
|
|
||||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
|
||||||
'size' => self::LINE_STYLE_ARROW_SIZE_8,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shadow 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,
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Glow Properties.
|
|
||||||
*
|
|
||||||
* @var mixed[]
|
|
||||||
*/
|
|
||||||
private $glowProperties = [
|
|
||||||
'size' => null,
|
|
||||||
'color' => [
|
|
||||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
|
||||||
'value' => 'black',
|
|
||||||
'alpha' => 40,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Soft Edge Properties.
|
|
||||||
*
|
|
||||||
* @var mixed[]
|
|
||||||
*/
|
|
||||||
private $softEdges = [
|
|
||||||
'size' => null,
|
|
||||||
];
|
|
||||||
|
|
||||||
private const NUMERIC_FORMAT = [
|
private const NUMERIC_FORMAT = [
|
||||||
Properties::FORMAT_CODE_NUMBER,
|
Properties::FORMAT_CODE_NUMBER,
|
||||||
Properties::FORMAT_CODE_DATE,
|
Properties::FORMAT_CODE_DATE,
|
||||||
|
|
@ -179,33 +97,39 @@ class Axis extends Properties
|
||||||
return (bool) $this->axisNumber['numeric'];
|
return (bool) $this->axisNumber['numeric'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setAxisOption(string $key, ?string $value): void
|
||||||
|
{
|
||||||
|
if (!empty($value)) {
|
||||||
|
$this->axisOptions[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set Axis Options Properties.
|
* Set Axis Options Properties.
|
||||||
*
|
|
||||||
* @param string $axisLabels
|
|
||||||
* @param string $horizontalCrossesValue
|
|
||||||
* @param string $horizontalCrosses
|
|
||||||
* @param string $axisOrientation
|
|
||||||
* @param string $majorTmt
|
|
||||||
* @param string $minorTmt
|
|
||||||
* @param string $minimum
|
|
||||||
* @param string $maximum
|
|
||||||
* @param string $majorUnit
|
|
||||||
* @param string $minorUnit
|
|
||||||
*/
|
*/
|
||||||
public function setAxisOptionsProperties($axisLabels, $horizontalCrossesValue = null, $horizontalCrosses = null, $axisOrientation = null, $majorTmt = null, $minorTmt = null, $minimum = null, $maximum = null, $majorUnit = null, $minorUnit = null): void
|
public function setAxisOptionsProperties(
|
||||||
{
|
string $axisLabels,
|
||||||
$this->axisOptions['axis_labels'] = (string) $axisLabels;
|
?string $horizontalCrossesValue = null,
|
||||||
($horizontalCrossesValue !== null) ? $this->axisOptions['horizontal_crosses_value'] = (string) $horizontalCrossesValue : null;
|
?string $horizontalCrosses = null,
|
||||||
($horizontalCrosses !== null) ? $this->axisOptions['horizontal_crosses'] = (string) $horizontalCrosses : null;
|
?string $axisOrientation = null,
|
||||||
($axisOrientation !== null) ? $this->axisOptions['orientation'] = (string) $axisOrientation : null;
|
?string $majorTmt = null,
|
||||||
($majorTmt !== null) ? $this->axisOptions['major_tick_mark'] = (string) $majorTmt : null;
|
?string $minorTmt = null,
|
||||||
($minorTmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minorTmt : null;
|
?string $minimum = null,
|
||||||
($minorTmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minorTmt : null;
|
?string $maximum = null,
|
||||||
($minimum !== null) ? $this->axisOptions['minimum'] = (string) $minimum : null;
|
?string $majorUnit = null,
|
||||||
($maximum !== null) ? $this->axisOptions['maximum'] = (string) $maximum : null;
|
?string $minorUnit = null
|
||||||
($majorUnit !== null) ? $this->axisOptions['major_unit'] = (string) $majorUnit : null;
|
): void {
|
||||||
($minorUnit !== null) ? $this->axisOptions['minor_unit'] = (string) $minorUnit : null;
|
$this->axisOptions['axis_labels'] = $axisLabels;
|
||||||
|
$this->setAxisOption('horizontal_crosses_value', $horizontalCrossesValue);
|
||||||
|
$this->setAxisOption('horizontal_crosses', $horizontalCrosses);
|
||||||
|
$this->setAxisOption('orientation', $axisOrientation);
|
||||||
|
$this->setAxisOption('major_tick_mark', $majorTmt);
|
||||||
|
$this->setAxisOption('minor_tick_mark', $minorTmt);
|
||||||
|
$this->setAxisOption('minor_tick_mark', $minorTmt);
|
||||||
|
$this->setAxisOption('minimum', $minimum);
|
||||||
|
$this->setAxisOption('maximum', $maximum);
|
||||||
|
$this->setAxisOption('major_unit', $majorUnit);
|
||||||
|
$this->setAxisOption('minor_unit', $minorUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -213,7 +137,7 @@ class Axis extends Properties
|
||||||
*
|
*
|
||||||
* @param string $property
|
* @param string $property
|
||||||
*
|
*
|
||||||
* @return string
|
* @return ?string
|
||||||
*/
|
*/
|
||||||
public function getAxisOptionsProperty($property)
|
public function getAxisOptionsProperty($property)
|
||||||
{
|
{
|
||||||
|
|
@ -233,27 +157,15 @@ class Axis extends Properties
|
||||||
/**
|
/**
|
||||||
* Set Fill Property.
|
* Set Fill Property.
|
||||||
*
|
*
|
||||||
* @param string $color
|
* @param ?string $color
|
||||||
* @param int $alpha
|
* @param ?int $alpha
|
||||||
* @param string $AlphaType
|
* @param ?string $AlphaType
|
||||||
*/
|
*/
|
||||||
public function setFillParameters($color, $alpha = 0, $AlphaType = self::EXCEL_COLOR_TYPE_ARGB): void
|
public function setFillParameters($color, $alpha = null, $AlphaType = self::EXCEL_COLOR_TYPE_ARGB): void
|
||||||
{
|
{
|
||||||
$this->fillProperties = $this->setColorProperties($color, $alpha, $AlphaType);
|
$this->fillProperties = $this->setColorProperties($color, $alpha, $AlphaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Line Property.
|
|
||||||
*
|
|
||||||
* @param string $color
|
|
||||||
* @param int $alpha
|
|
||||||
* @param string $alphaType
|
|
||||||
*/
|
|
||||||
public function setLineParameters($color, $alpha = 0, $alphaType = self::EXCEL_COLOR_TYPE_ARGB): void
|
|
||||||
{
|
|
||||||
$this->lineProperties = $this->setColorProperties($color, $alpha, $alphaType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Fill Property.
|
* Get Fill Property.
|
||||||
*
|
*
|
||||||
|
|
@ -263,309 +175,33 @@ class Axis extends Properties
|
||||||
*/
|
*/
|
||||||
public function getFillProperty($property)
|
public function getFillProperty($property)
|
||||||
{
|
{
|
||||||
return $this->fillProperties[$property];
|
return (string) $this->fillProperties[$property];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Line Property.
|
* Get Line Color Property.
|
||||||
*
|
*
|
||||||
* @param string $property
|
* @param string $propertyName
|
||||||
*
|
*
|
||||||
* @return string
|
* @return null|int|string
|
||||||
*/
|
*/
|
||||||
public function getLineProperty($property)
|
public function getLineProperty($propertyName)
|
||||||
{
|
{
|
||||||
return $this->lineProperties[$property];
|
return $this->lineProperties['color'][$propertyName];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var string */
|
||||||
* Set Line Style Properties.
|
private $crossBetween = ''; // 'between' or 'midCat' might be better
|
||||||
*
|
|
||||||
* @param float $lineWidth
|
|
||||||
* @param string $compoundType
|
|
||||||
* @param string $dashType
|
|
||||||
* @param string $capType
|
|
||||||
* @param string $joinType
|
|
||||||
* @param string $headArrowType
|
|
||||||
* @param string $headArrowSize
|
|
||||||
* @param string $endArrowType
|
|
||||||
* @param string $endArrowSize
|
|
||||||
*/
|
|
||||||
public function setLineStyleProperties($lineWidth = null, $compoundType = null, $dashType = null, $capType = null, $joinType = null, $headArrowType = null, $headArrowSize = null, $endArrowType = null, $endArrowSize = null): void
|
|
||||||
{
|
|
||||||
($lineWidth !== null) ? $this->lineStyleProperties['width'] = $this->getExcelPointsWidth((float) $lineWidth) : null;
|
|
||||||
($compoundType !== null) ? $this->lineStyleProperties['compound'] = (string) $compoundType : null;
|
|
||||||
($dashType !== null) ? $this->lineStyleProperties['dash'] = (string) $dashType : null;
|
|
||||||
($capType !== null) ? $this->lineStyleProperties['cap'] = (string) $capType : null;
|
|
||||||
($joinType !== null) ? $this->lineStyleProperties['join'] = (string) $joinType : null;
|
|
||||||
($headArrowType !== null) ? $this->lineStyleProperties['arrow']['head']['type'] = (string) $headArrowType : null;
|
|
||||||
($headArrowSize !== null) ? $this->lineStyleProperties['arrow']['head']['size'] = (string) $headArrowSize : null;
|
|
||||||
($endArrowType !== null) ? $this->lineStyleProperties['arrow']['end']['type'] = (string) $endArrowType : null;
|
|
||||||
($endArrowSize !== null) ? $this->lineStyleProperties['arrow']['end']['size'] = (string) $endArrowSize : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public function setCrossBetween(string $crossBetween): self
|
||||||
* Get Line Style Property.
|
|
||||||
*
|
|
||||||
* @param array|string $elements
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLineStyleProperty($elements)
|
|
||||||
{
|
{
|
||||||
return $this->getArrayElementsValue($this->lineStyleProperties, $elements);
|
$this->crossBetween = $crossBetween;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Line Style Arrow Excel Width.
|
|
||||||
*
|
|
||||||
* @param string $arrow
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLineStyleArrowWidth($arrow)
|
|
||||||
{
|
|
||||||
return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'w');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Line Style Arrow Excel Length.
|
|
||||||
*
|
|
||||||
* @param string $arrow
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLineStyleArrowLength($arrow)
|
|
||||||
{
|
|
||||||
return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'len');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Properties.
|
|
||||||
*
|
|
||||||
* @param int $shadowPresets
|
|
||||||
* @param string $colorValue
|
|
||||||
* @param string $colorType
|
|
||||||
* @param null|int|string $colorAlpha
|
|
||||||
* @param null|float $blur
|
|
||||||
* @param null|int $angle
|
|
||||||
* @param null|float $distance
|
|
||||||
*/
|
|
||||||
public function setShadowProperties($shadowPresets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void
|
|
||||||
{
|
|
||||||
$this->setShadowPresetsProperties((int) $shadowPresets)
|
|
||||||
->setShadowColor(
|
|
||||||
$colorValue ?? $this->shadowProperties['color']['value'],
|
|
||||||
(int) ($colorAlpha ?? $this->shadowProperties['color']['alpha']),
|
|
||||||
$colorType ?? $this->shadowProperties['color']['type']
|
|
||||||
)
|
|
||||||
->setShadowBlur($blur)
|
|
||||||
->setShadowAngle($angle)
|
|
||||||
->setShadowDistance($distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Color.
|
|
||||||
*
|
|
||||||
* @param int $presets
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowPresetsProperties($presets)
|
|
||||||
{
|
|
||||||
$this->shadowProperties['presets'] = $presets;
|
|
||||||
$this->setShadowPropertiesMapValues($this->getShadowPresetsMap($presets));
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getCrossBetween(): string
|
||||||
* Set Shadow Properties from Mapped Values.
|
|
||||||
*
|
|
||||||
* @param mixed $reference
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowPropertiesMapValues(array $propertiesMap, &$reference = null)
|
|
||||||
{
|
{
|
||||||
$base_reference = $reference;
|
return $this->crossBetween;
|
||||||
foreach ($propertiesMap as $property_key => $property_val) {
|
|
||||||
if (is_array($property_val)) {
|
|
||||||
if ($reference === null) {
|
|
||||||
$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;
|
|
||||||
} else {
|
|
||||||
$reference[$property_key] = $property_val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Color.
|
|
||||||
*
|
|
||||||
* @param null|string $color
|
|
||||||
* @param null|int $alpha
|
|
||||||
* @param null|string $alphaType
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowColor($color, $alpha, $alphaType)
|
|
||||||
{
|
|
||||||
$this->shadowProperties['color'] = $this->setColorProperties($color, $alpha, $alphaType);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Blur.
|
|
||||||
*
|
|
||||||
* @param null|float $blur
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowBlur($blur)
|
|
||||||
{
|
|
||||||
if ($blur !== null) {
|
|
||||||
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Angle.
|
|
||||||
*
|
|
||||||
* @param null|int $angle
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowAngle($angle)
|
|
||||||
{
|
|
||||||
if ($angle !== null) {
|
|
||||||
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Distance.
|
|
||||||
*
|
|
||||||
* @param null|float $distance
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowDistance($distance)
|
|
||||||
{
|
|
||||||
if ($distance !== null) {
|
|
||||||
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Shadow Property.
|
|
||||||
*
|
|
||||||
* @param string|string[] $elements
|
|
||||||
*
|
|
||||||
* @return null|array|int|string
|
|
||||||
*/
|
|
||||||
public function getShadowProperty($elements)
|
|
||||||
{
|
|
||||||
return $this->getArrayElementsValue($this->shadowProperties, $elements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Glow Properties.
|
|
||||||
*
|
|
||||||
* @param float $size
|
|
||||||
* @param null|string $colorValue
|
|
||||||
* @param null|int $colorAlpha
|
|
||||||
* @param null|string $colorType
|
|
||||||
*/
|
|
||||||
public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void
|
|
||||||
{
|
|
||||||
$this->setGlowSize($size)
|
|
||||||
->setGlowColor(
|
|
||||||
$colorValue ?? $this->glowProperties['color']['value'],
|
|
||||||
$colorAlpha ?? (int) $this->glowProperties['color']['alpha'],
|
|
||||||
$colorType ?? $this->glowProperties['color']['type']
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Glow Property.
|
|
||||||
*
|
|
||||||
* @param array|string $property
|
|
||||||
*
|
|
||||||
* @return null|string
|
|
||||||
*/
|
|
||||||
public function getGlowProperty($property)
|
|
||||||
{
|
|
||||||
return $this->getArrayElementsValue($this->glowProperties, $property);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Glow Color.
|
|
||||||
*
|
|
||||||
* @param float $size
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setGlowSize($size)
|
|
||||||
{
|
|
||||||
if ($size !== null) {
|
|
||||||
$this->glowProperties['size'] = $this->getExcelPointsWidth($size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Glow Color.
|
|
||||||
*
|
|
||||||
* @param string $color
|
|
||||||
* @param int $alpha
|
|
||||||
* @param string $colorType
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setGlowColor($color, $alpha, $colorType)
|
|
||||||
{
|
|
||||||
$this->glowProperties['color'] = $this->setColorProperties($color, $alpha, $colorType);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Soft Edges Size.
|
|
||||||
*
|
|
||||||
* @param float $size
|
|
||||||
*/
|
|
||||||
public function setSoftEdges($size): void
|
|
||||||
{
|
|
||||||
if ($size !== null) {
|
|
||||||
$this->softEdges['size'] = (string) $this->getExcelPointsWidth($size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Soft Edges Size.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getSoftEdgesSize()
|
|
||||||
{
|
|
||||||
return $this->softEdges['size'];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,9 @@ class DataSeriesValues
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $schemeClr = '';
|
private $schemeClr = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $prstClr = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Line Width.
|
* Line Width.
|
||||||
*
|
*
|
||||||
|
|
@ -262,7 +265,7 @@ class DataSeriesValues
|
||||||
/**
|
/**
|
||||||
* Set fill color for series.
|
* Set fill color for series.
|
||||||
*
|
*
|
||||||
* @param null|string|string[] $color HEX color or array with HEX colors
|
* @param string|string[] $color HEX color or array with HEX colors
|
||||||
*
|
*
|
||||||
* @return DataSeriesValues
|
* @return DataSeriesValues
|
||||||
*/
|
*/
|
||||||
|
|
@ -270,10 +273,14 @@ class DataSeriesValues
|
||||||
{
|
{
|
||||||
if (is_array($color)) {
|
if (is_array($color)) {
|
||||||
foreach ($color as $colorValue) {
|
foreach ($color as $colorValue) {
|
||||||
$this->validateColor($colorValue);
|
if (substr($colorValue, 0, 1) !== '*' && substr($colorValue, 0, 1) !== '/') {
|
||||||
|
$this->validateColor($colorValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->validateColor("$color");
|
if (substr($color, 0, 1) !== '*' && substr($color, 0, 1) !== '/') {
|
||||||
|
$this->validateColor("$color");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$this->fillColor = $color;
|
$this->fillColor = $color;
|
||||||
|
|
||||||
|
|
@ -470,4 +477,16 @@ class DataSeriesValues
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPrstClr(): string
|
||||||
|
{
|
||||||
|
return $this->prstClr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPrstClr(string $prstClr): self
|
||||||
|
{
|
||||||
|
$this->prstClr = $prstClr;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,445 +10,4 @@ namespace PhpOffice\PhpSpreadsheet\Chart;
|
||||||
*/
|
*/
|
||||||
class GridLines extends Properties
|
class GridLines extends Properties
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Properties of Class:
|
|
||||||
* Object State (State for Minor Tick Mark) @var bool
|
|
||||||
* Line Properties @var array of mixed
|
|
||||||
* Shadow Properties @var array of mixed
|
|
||||||
* Glow Properties @var array of mixed
|
|
||||||
* Soft Properties @var array of mixed.
|
|
||||||
*/
|
|
||||||
private $objectState = false;
|
|
||||||
|
|
||||||
private $lineProperties = [
|
|
||||||
'color' => [
|
|
||||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
|
||||||
'value' => null,
|
|
||||||
'alpha' => 0,
|
|
||||||
],
|
|
||||||
'style' => [
|
|
||||||
'width' => '9525',
|
|
||||||
'compound' => self::LINE_STYLE_COMPOUND_SIMPLE,
|
|
||||||
'dash' => self::LINE_STYLE_DASH_SOLID,
|
|
||||||
'cap' => self::LINE_STYLE_CAP_FLAT,
|
|
||||||
'join' => self::LINE_STYLE_JOIN_BEVEL,
|
|
||||||
'arrow' => [
|
|
||||||
'head' => [
|
|
||||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
|
||||||
'size' => self::LINE_STYLE_ARROW_SIZE_5,
|
|
||||||
],
|
|
||||||
'end' => [
|
|
||||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
|
||||||
'size' => self::LINE_STYLE_ARROW_SIZE_8,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
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 $glowProperties = [
|
|
||||||
'size' => null,
|
|
||||||
'color' => [
|
|
||||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
|
||||||
'value' => 'black',
|
|
||||||
'alpha' => 40,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
private $softEdges = [
|
|
||||||
'size' => null,
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Object State.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getObjectState()
|
|
||||||
{
|
|
||||||
return $this->objectState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change Object State to True.
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function activateObject()
|
|
||||||
{
|
|
||||||
$this->objectState = true;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Line Color Properties.
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
* @param int $alpha
|
|
||||||
* @param string $colorType
|
|
||||||
*/
|
|
||||||
public function setLineColorProperties($value, $alpha = 0, $colorType = self::EXCEL_COLOR_TYPE_STANDARD): void
|
|
||||||
{
|
|
||||||
$this->activateObject()
|
|
||||||
->lineProperties['color'] = $this->setColorProperties(
|
|
||||||
$value,
|
|
||||||
$alpha,
|
|
||||||
$colorType
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Line Color Properties.
|
|
||||||
*
|
|
||||||
* @param float $lineWidth
|
|
||||||
* @param string $compoundType
|
|
||||||
* @param string $dashType
|
|
||||||
* @param string $capType
|
|
||||||
* @param string $joinType
|
|
||||||
* @param string $headArrowType
|
|
||||||
* @param string $headArrowSize
|
|
||||||
* @param string $endArrowType
|
|
||||||
* @param string $endArrowSize
|
|
||||||
*/
|
|
||||||
public function setLineStyleProperties($lineWidth = null, $compoundType = null, $dashType = null, $capType = null, $joinType = null, $headArrowType = null, $headArrowSize = null, $endArrowType = null, $endArrowSize = null): void
|
|
||||||
{
|
|
||||||
$this->activateObject();
|
|
||||||
($lineWidth !== null)
|
|
||||||
? $this->lineProperties['style']['width'] = $this->getExcelPointsWidth((float) $lineWidth)
|
|
||||||
: null;
|
|
||||||
($compoundType !== null)
|
|
||||||
? $this->lineProperties['style']['compound'] = (string) $compoundType
|
|
||||||
: null;
|
|
||||||
($dashType !== null)
|
|
||||||
? $this->lineProperties['style']['dash'] = (string) $dashType
|
|
||||||
: null;
|
|
||||||
($capType !== null)
|
|
||||||
? $this->lineProperties['style']['cap'] = (string) $capType
|
|
||||||
: null;
|
|
||||||
($joinType !== null)
|
|
||||||
? $this->lineProperties['style']['join'] = (string) $joinType
|
|
||||||
: null;
|
|
||||||
($headArrowType !== null)
|
|
||||||
? $this->lineProperties['style']['arrow']['head']['type'] = (string) $headArrowType
|
|
||||||
: null;
|
|
||||||
($headArrowSize !== null)
|
|
||||||
? $this->lineProperties['style']['arrow']['head']['size'] = (string) $headArrowSize
|
|
||||||
: null;
|
|
||||||
($endArrowType !== null)
|
|
||||||
? $this->lineProperties['style']['arrow']['end']['type'] = (string) $endArrowType
|
|
||||||
: null;
|
|
||||||
($endArrowSize !== null)
|
|
||||||
? $this->lineProperties['style']['arrow']['end']['size'] = (string) $endArrowSize
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Line Color Property.
|
|
||||||
*
|
|
||||||
* @param string $propertyName
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLineColorProperty($propertyName)
|
|
||||||
{
|
|
||||||
return $this->lineProperties['color'][$propertyName];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Line Style Property.
|
|
||||||
*
|
|
||||||
* @param array|string $elements
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLineStyleProperty($elements)
|
|
||||||
{
|
|
||||||
return $this->getArrayElementsValue($this->lineProperties['style'], $elements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Glow Properties.
|
|
||||||
*
|
|
||||||
* @param float $size
|
|
||||||
* @param string $colorValue
|
|
||||||
* @param int $colorAlpha
|
|
||||||
* @param string $colorType
|
|
||||||
*/
|
|
||||||
public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void
|
|
||||||
{
|
|
||||||
$this
|
|
||||||
->activateObject()
|
|
||||||
->setGlowSize($size)
|
|
||||||
->setGlowColor($colorValue, $colorAlpha, $colorType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Glow Color Property.
|
|
||||||
*
|
|
||||||
* @param string $propertyName
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getGlowColor($propertyName)
|
|
||||||
{
|
|
||||||
return $this->glowProperties['color'][$propertyName];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Glow Size.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getGlowSize()
|
|
||||||
{
|
|
||||||
return $this->glowProperties['size'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Glow Size.
|
|
||||||
*
|
|
||||||
* @param float $size
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setGlowSize($size)
|
|
||||||
{
|
|
||||||
$this->glowProperties['size'] = $this->getExcelPointsWidth((float) $size);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Glow Color.
|
|
||||||
*
|
|
||||||
* @param string $color
|
|
||||||
* @param int $alpha
|
|
||||||
* @param string $colorType
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setGlowColor($color, $alpha, $colorType)
|
|
||||||
{
|
|
||||||
if ($color !== null) {
|
|
||||||
$this->glowProperties['color']['value'] = (string) $color;
|
|
||||||
}
|
|
||||||
if ($alpha !== null) {
|
|
||||||
$this->glowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha);
|
|
||||||
}
|
|
||||||
if ($colorType !== null) {
|
|
||||||
$this->glowProperties['color']['type'] = (string) $colorType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Line Style Arrow Parameters.
|
|
||||||
*
|
|
||||||
* @param string $arrowSelector
|
|
||||||
* @param string $propertySelector
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLineStyleArrowParameters($arrowSelector, $propertySelector)
|
|
||||||
{
|
|
||||||
return $this->getLineStyleArrowSize($this->lineProperties['style']['arrow'][$arrowSelector]['size'], $propertySelector);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Properties.
|
|
||||||
*
|
|
||||||
* @param int $presets
|
|
||||||
* @param string $colorValue
|
|
||||||
* @param string $colorType
|
|
||||||
* @param string $colorAlpha
|
|
||||||
* @param string $blur
|
|
||||||
* @param int $angle
|
|
||||||
* @param float $distance
|
|
||||||
*/
|
|
||||||
public function setShadowProperties($presets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void
|
|
||||||
{
|
|
||||||
$this->activateObject()
|
|
||||||
->setShadowPresetsProperties((int) $presets)
|
|
||||||
->setShadowColor(
|
|
||||||
$colorValue ?? $this->shadowProperties['color']['value'],
|
|
||||||
$colorAlpha === null ? (int) $this->shadowProperties['color']['alpha'] : $this->getTrueAlpha($colorAlpha),
|
|
||||||
$colorType ?? $this->shadowProperties['color']['type']
|
|
||||||
)
|
|
||||||
->setShadowBlur((float) $blur)
|
|
||||||
->setShadowAngle($angle)
|
|
||||||
->setShadowDistance($distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Presets Properties.
|
|
||||||
*
|
|
||||||
* @param int $presets
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowPresetsProperties($presets)
|
|
||||||
{
|
|
||||||
$this->shadowProperties['presets'] = $presets;
|
|
||||||
$this->setShadowPropertiesMapValues($this->getShadowPresetsMap($presets));
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Properties Values.
|
|
||||||
*
|
|
||||||
* @param mixed $reference
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowPropertiesMapValues(array $propertiesMap, &$reference = null)
|
|
||||||
{
|
|
||||||
$base_reference = $reference;
|
|
||||||
foreach ($propertiesMap as $property_key => $property_val) {
|
|
||||||
if (is_array($property_val)) {
|
|
||||||
if ($reference === null) {
|
|
||||||
$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;
|
|
||||||
} else {
|
|
||||||
$reference[$property_key] = $property_val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Color.
|
|
||||||
*
|
|
||||||
* @param string $color
|
|
||||||
* @param int $alpha
|
|
||||||
* @param string $colorType
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowColor($color, $alpha, $colorType)
|
|
||||||
{
|
|
||||||
if ($color !== null) {
|
|
||||||
$this->shadowProperties['color']['value'] = (string) $color;
|
|
||||||
}
|
|
||||||
if ($alpha !== null) {
|
|
||||||
$this->shadowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha);
|
|
||||||
}
|
|
||||||
if ($colorType !== null) {
|
|
||||||
$this->shadowProperties['color']['type'] = (string) $colorType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Blur.
|
|
||||||
*
|
|
||||||
* @param float $blur
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowBlur($blur)
|
|
||||||
{
|
|
||||||
if ($blur !== null) {
|
|
||||||
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Angle.
|
|
||||||
*
|
|
||||||
* @param int $angle
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowAngle($angle)
|
|
||||||
{
|
|
||||||
if ($angle !== null) {
|
|
||||||
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Shadow Distance.
|
|
||||||
*
|
|
||||||
* @param float $distance
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
private function setShadowDistance($distance)
|
|
||||||
{
|
|
||||||
if ($distance !== null) {
|
|
||||||
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Shadow Property.
|
|
||||||
*
|
|
||||||
* @param string|string[] $elements
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getShadowProperty($elements)
|
|
||||||
{
|
|
||||||
return $this->getArrayElementsValue($this->shadowProperties, $elements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Soft Edges Size.
|
|
||||||
*
|
|
||||||
* @param float $size
|
|
||||||
*/
|
|
||||||
public function setSoftEdgesSize($size): void
|
|
||||||
{
|
|
||||||
if ($size !== null) {
|
|
||||||
$this->activateObject();
|
|
||||||
$this->softEdges['size'] = (string) $this->getExcelPointsWidth($size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Soft Edges Size.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getSoftEdgesSize()
|
|
||||||
{
|
|
||||||
return $this->softEdges['size'];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -632,16 +632,6 @@ class Html extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure mb_convert_encoding returns string.
|
|
||||||
*
|
|
||||||
* @param mixed $result
|
|
||||||
*/
|
|
||||||
private static function ensureString($result): string
|
|
||||||
{
|
|
||||||
return is_string($result) ? $result : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
|
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
|
||||||
*
|
*
|
||||||
|
|
@ -660,8 +650,8 @@ class Html extends BaseReader
|
||||||
$dom = new DOMDocument();
|
$dom = new DOMDocument();
|
||||||
// Reload the HTML file into the DOM object
|
// Reload the HTML file into the DOM object
|
||||||
try {
|
try {
|
||||||
$convert = mb_convert_encoding($this->securityScanner->scanFile($filename), 'HTML-ENTITIES', 'UTF-8');
|
$convert = $this->securityScanner->scanFile($filename);
|
||||||
$loaded = $dom->loadHTML(self::ensureString($convert));
|
$loaded = $dom->loadHTML($convert);
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
$loaded = false;
|
$loaded = false;
|
||||||
}
|
}
|
||||||
|
|
@ -683,8 +673,8 @@ class Html extends BaseReader
|
||||||
$dom = new DOMDocument();
|
$dom = new DOMDocument();
|
||||||
// Reload the HTML file into the DOM object
|
// Reload the HTML file into the DOM object
|
||||||
try {
|
try {
|
||||||
$convert = mb_convert_encoding($this->securityScanner->scan($content), 'HTML-ENTITIES', 'UTF-8');
|
$convert = $this->securityScanner->scan($content);
|
||||||
$loaded = $dom->loadHTML(self::ensureString($convert));
|
$loaded = $dom->loadHTML($convert);
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
$loaded = false;
|
$loaded = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -414,7 +414,7 @@ class Xlsx extends BaseReader
|
||||||
[$workbookBasename, $xmlNamespaceBase] = $this->getWorkbookBaseName();
|
[$workbookBasename, $xmlNamespaceBase] = $this->getWorkbookBaseName();
|
||||||
$drawingNS = self::REL_TO_DRAWING[$xmlNamespaceBase] ?? Namespaces::DRAWINGML;
|
$drawingNS = self::REL_TO_DRAWING[$xmlNamespaceBase] ?? Namespaces::DRAWINGML;
|
||||||
$chartNS = self::REL_TO_CHART[$xmlNamespaceBase] ?? Namespaces::CHART;
|
$chartNS = self::REL_TO_CHART[$xmlNamespaceBase] ?? Namespaces::CHART;
|
||||||
$wbRels = $this->loadZip("xl/_rels/${workbookBasename}.rels", Namespaces::RELATIONSHIPS);
|
$wbRels = $this->loadZip("xl/_rels/{$workbookBasename}.rels", Namespaces::RELATIONSHIPS);
|
||||||
$theme = null;
|
$theme = null;
|
||||||
$this->styleReader = new Styles();
|
$this->styleReader = new Styles();
|
||||||
foreach ($wbRels->Relationship as $relx) {
|
foreach ($wbRels->Relationship as $relx) {
|
||||||
|
|
@ -1849,11 +1849,6 @@ class Xlsx extends BaseReader
|
||||||
|
|
||||||
private static function dirAdd($base, $add): string
|
private static function dirAdd($base, $add): string
|
||||||
{
|
{
|
||||||
$add = "$add";
|
|
||||||
if (substr($add, 0, 4) === '/xl/') {
|
|
||||||
$add = substr($add, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (string) preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
|
return (string) preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Axis;
|
use PhpOffice\PhpSpreadsheet\Chart\Axis;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\GridLines;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||||
|
|
@ -71,6 +72,7 @@ class Chart
|
||||||
$rotX = $rotY = $rAngAx = $perspective = null;
|
$rotX = $rotY = $rAngAx = $perspective = null;
|
||||||
$xAxis = new Axis();
|
$xAxis = new Axis();
|
||||||
$yAxis = new Axis();
|
$yAxis = new Axis();
|
||||||
|
$majorGridlines = $minorGridlines = null;
|
||||||
foreach ($chartElementsC as $chartElementKey => $chartElement) {
|
foreach ($chartElementsC as $chartElementKey => $chartElement) {
|
||||||
switch ($chartElementKey) {
|
switch ($chartElementKey) {
|
||||||
case 'chart':
|
case 'chart':
|
||||||
|
|
@ -98,6 +100,14 @@ class Chart
|
||||||
$XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
$XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
||||||
}
|
}
|
||||||
$this->readEffects($chartDetail, $xAxis);
|
$this->readEffects($chartDetail, $xAxis);
|
||||||
|
if (isset($chartDetail->spPr)) {
|
||||||
|
$sppr = $chartDetail->spPr->children($this->aNamespace);
|
||||||
|
if (isset($sppr->solidFill)) {
|
||||||
|
$axisColorArray = $this->readColor($sppr->solidFill);
|
||||||
|
$xAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->setAxisProperties($chartDetail, $xAxis);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'dateAx':
|
case 'dateAx':
|
||||||
|
|
@ -108,26 +118,62 @@ class Chart
|
||||||
break;
|
break;
|
||||||
case 'valAx':
|
case 'valAx':
|
||||||
$whichAxis = null;
|
$whichAxis = null;
|
||||||
if (isset($chartDetail->title, $chartDetail->axPos)) {
|
$axPos = null;
|
||||||
$axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
|
if (isset($chartDetail->axPos)) {
|
||||||
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
|
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
|
||||||
|
|
||||||
switch ($axPos) {
|
switch ($axPos) {
|
||||||
case 't':
|
case 't':
|
||||||
case 'b':
|
case 'b':
|
||||||
$XaxisLabel = $axisLabel;
|
|
||||||
$whichAxis = $xAxis;
|
$whichAxis = $xAxis;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
case 'l':
|
case 'l':
|
||||||
$YaxisLabel = $axisLabel;
|
|
||||||
$whichAxis = $yAxis;
|
$whichAxis = $yAxis;
|
||||||
|
|
||||||
break;
|
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);
|
$this->readEffects($chartDetail, $whichAxis);
|
||||||
|
if ($whichAxis !== null && isset($chartDetail->spPr)) {
|
||||||
|
$sppr = $chartDetail->spPr->children($this->aNamespace);
|
||||||
|
if (isset($sppr->solidFill)) {
|
||||||
|
$axisColorArray = $this->readColor($sppr->solidFill);
|
||||||
|
$whichAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->majorGridlines)) {
|
||||||
|
$majorGridlines = new GridLines();
|
||||||
|
if (isset($chartDetail->majorGridlines->spPr)) {
|
||||||
|
$this->readEffects($chartDetail->majorGridlines, $majorGridlines);
|
||||||
|
$this->readLineStyle($chartDetail->majorGridlines, $majorGridlines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->minorGridlines)) {
|
||||||
|
$minorGridlines = new GridLines();
|
||||||
|
if (isset($chartDetail->minorGridlines->spPr)) {
|
||||||
|
$this->readEffects($chartDetail->minorGridlines, $minorGridlines);
|
||||||
|
$this->readLineStyle($chartDetail->minorGridlines, $minorGridlines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->setAxisProperties($chartDetail, $whichAxis);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'barChart':
|
case 'barChart':
|
||||||
|
|
@ -249,7 +295,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)) {
|
if (is_int($rotX)) {
|
||||||
$chart->setRotX($rotX);
|
$chart->setRotX($rotX);
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +377,9 @@ class Chart
|
||||||
$pointSize = null;
|
$pointSize = null;
|
||||||
$noFill = false;
|
$noFill = false;
|
||||||
$schemeClr = '';
|
$schemeClr = '';
|
||||||
|
$prstClr = '';
|
||||||
$bubble3D = false;
|
$bubble3D = false;
|
||||||
|
$dPtColors = [];
|
||||||
foreach ($seriesDetails as $seriesKey => $seriesDetail) {
|
foreach ($seriesDetails as $seriesKey => $seriesDetail) {
|
||||||
switch ($seriesKey) {
|
switch ($seriesKey) {
|
||||||
case 'idx':
|
case 'idx':
|
||||||
|
|
@ -355,7 +403,24 @@ class Chart
|
||||||
$noFill = true;
|
$noFill = true;
|
||||||
}
|
}
|
||||||
if (isset($children->solidFill)) {
|
if (isset($children->solidFill)) {
|
||||||
$this->readColor($children->solidFill, $srgbClr, $schemeClr);
|
$this->readColor($children->solidFill, $srgbClr, $schemeClr, $prstClr);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'dPt':
|
||||||
|
$dptIdx = (int) self::getAttribute($seriesDetail->idx, 'val', 'string');
|
||||||
|
if (isset($seriesDetail->spPr)) {
|
||||||
|
$children = $seriesDetail->spPr->children($this->aNamespace);
|
||||||
|
if (isset($children->solidFill)) {
|
||||||
|
$arrayColors = $this->readColor($children->solidFill);
|
||||||
|
if ($arrayColors['type'] === 'srgbClr') {
|
||||||
|
$dptColors[$dptIdx] = $arrayColors['value'];
|
||||||
|
} elseif ($arrayColors['type'] === 'prstClr') {
|
||||||
|
$dptColors[$dptIdx] = '/' . $arrayColors['value'];
|
||||||
|
} else {
|
||||||
|
$dptColors[$dptIdx] = '*' . $arrayColors['value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -366,7 +431,7 @@ class Chart
|
||||||
if (count($seriesDetail->spPr) === 1) {
|
if (count($seriesDetail->spPr) === 1) {
|
||||||
$ln = $seriesDetail->spPr->children($this->aNamespace);
|
$ln = $seriesDetail->spPr->children($this->aNamespace);
|
||||||
if (isset($ln->solidFill)) {
|
if (isset($ln->solidFill)) {
|
||||||
$this->readColor($ln->solidFill, $srgbClr, $schemeClr);
|
$this->readColor($ln->solidFill, $srgbClr, $schemeClr, $prstClr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,6 +498,16 @@ class Chart
|
||||||
if (isset($seriesValues[$seriesIndex])) {
|
if (isset($seriesValues[$seriesIndex])) {
|
||||||
$seriesValues[$seriesIndex]->setSchemeClr($schemeClr);
|
$seriesValues[$seriesIndex]->setSchemeClr($schemeClr);
|
||||||
}
|
}
|
||||||
|
} elseif ($prstClr) {
|
||||||
|
if (isset($seriesLabel[$seriesIndex])) {
|
||||||
|
$seriesLabel[$seriesIndex]->setPrstClr($prstClr);
|
||||||
|
}
|
||||||
|
if (isset($seriesCategory[$seriesIndex])) {
|
||||||
|
$seriesCategory[$seriesIndex]->setPrstClr($prstClr);
|
||||||
|
}
|
||||||
|
if (isset($seriesValues[$seriesIndex])) {
|
||||||
|
$seriesValues[$seriesIndex]->setPrstClr($prstClr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($bubble3D) {
|
if ($bubble3D) {
|
||||||
if (isset($seriesLabel[$seriesIndex])) {
|
if (isset($seriesLabel[$seriesIndex])) {
|
||||||
|
|
@ -445,6 +520,17 @@ class Chart
|
||||||
$seriesValues[$seriesIndex]->setBubble3D($bubble3D);
|
$seriesValues[$seriesIndex]->setBubble3D($bubble3D);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!empty($dptColors)) {
|
||||||
|
if (isset($seriesLabel[$seriesIndex])) {
|
||||||
|
$seriesLabel[$seriesIndex]->setFillColor($dptColors);
|
||||||
|
}
|
||||||
|
if (isset($seriesCategory[$seriesIndex])) {
|
||||||
|
$seriesCategory[$seriesIndex]->setFillColor($dptColors);
|
||||||
|
}
|
||||||
|
if (isset($seriesValues[$seriesIndex])) {
|
||||||
|
$seriesValues[$seriesIndex]->setFillColor($dptColors);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** @phpstan-ignore-next-line */
|
/** @phpstan-ignore-next-line */
|
||||||
|
|
@ -893,7 +979,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
|
private function readEffects(SimpleXMLElement $chartDetail, $chartObject): void
|
||||||
{
|
{
|
||||||
|
|
@ -905,42 +991,212 @@ class Chart
|
||||||
if (isset($sppr->effectLst->glow)) {
|
if (isset($sppr->effectLst->glow)) {
|
||||||
$axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / Properties::POINTS_WIDTH_MULTIPLIER;
|
$axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / Properties::POINTS_WIDTH_MULTIPLIER;
|
||||||
if ($axisGlowSize != 0.0) {
|
if ($axisGlowSize != 0.0) {
|
||||||
$srgbClr = $schemeClr = '';
|
$colorArray = $this->readColor($sppr->effectLst->glow);
|
||||||
$colorArray = $this->readColor($sppr->effectLst->glow, $srgbClr, $schemeClr);
|
|
||||||
$chartObject->setGlowProperties($axisGlowSize, $colorArray['value'], $colorArray['alpha'], $colorArray['type']);
|
$chartObject->setGlowProperties($axisGlowSize, $colorArray['value'], $colorArray['alpha'], $colorArray['type']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($sppr->effectLst->softEdge)) {
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$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 function readColor(SimpleXMLElement $colorXml, ?string &$srgbClr, ?string &$schemeClr): array
|
private const SHADOW_TYPES = [
|
||||||
|
'outerShdw',
|
||||||
|
'innerShdw',
|
||||||
|
];
|
||||||
|
|
||||||
|
private function readColor(SimpleXMLElement $colorXml, ?string &$srgbClr = null, ?string &$schemeClr = null, ?string &$prstClr = null): array
|
||||||
{
|
{
|
||||||
$result = [
|
$result = [
|
||||||
'type' => null,
|
'type' => null,
|
||||||
'value' => null,
|
'value' => null,
|
||||||
'alpha' => null,
|
'alpha' => null,
|
||||||
];
|
];
|
||||||
if (isset($colorXml->srgbClr)) {
|
foreach (Properties::EXCEL_COLOR_TYPES as $type) {
|
||||||
$result['type'] = Properties::EXCEL_COLOR_TYPE_ARGB;
|
if (isset($colorXml->$type)) {
|
||||||
$result['value'] = $srgbClr = self::getAttribute($colorXml->srgbClr, 'val', 'string');
|
$result['type'] = $type;
|
||||||
if (isset($colorXml->srgbClr->alpha)) {
|
$result['value'] = self::getAttribute($colorXml->$type, 'val', 'string');
|
||||||
$alpha = (int) self::getAttribute($colorXml->srgbClr->alpha, 'val', 'string');
|
if ($type === Properties::EXCEL_COLOR_TYPE_ARGB) {
|
||||||
$alpha = 100 - (int) ($alpha / 1000);
|
$srgbClr = $result['value'];
|
||||||
$result['alpha'] = $alpha;
|
} elseif ($type === Properties::EXCEL_COLOR_TYPE_SCHEME) {
|
||||||
}
|
$schemeClr = $result['value'];
|
||||||
} elseif (isset($colorXml->schemeClr)) {
|
} elseif ($type === Properties::EXCEL_COLOR_TYPE_STANDARD) {
|
||||||
$result['type'] = Properties::EXCEL_COLOR_TYPE_SCHEME;
|
$prstClr = $result['value'];
|
||||||
$result['value'] = $schemeClr = self::getAttribute($colorXml->schemeClr, 'val', 'string');
|
}
|
||||||
if (isset($colorXml->schemeClr->alpha)) {
|
if (isset($colorXml->$type->alpha)) {
|
||||||
$alpha = (int) self::getAttribute($colorXml->schemeClr->alpha, 'val', 'string');
|
$alpha = (int) self::getAttribute($colorXml->$type->alpha, 'val', 'string');
|
||||||
$alpha = 100 - (int) ($alpha / 1000);
|
$alpha = 100 - (int) ($alpha / 1000);
|
||||||
$result['alpha'] = $alpha;
|
$result['alpha'] = $alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null|GridLines $chartObject may be extended to include other types
|
||||||
|
*/
|
||||||
|
private function readLineStyle(SimpleXMLElement $chartDetail, $chartObject): void
|
||||||
|
{
|
||||||
|
if (!isset($chartObject, $chartDetail->spPr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$sppr = $chartDetail->spPr->children($this->aNamespace);
|
||||||
|
|
||||||
|
if (!isset($sppr->ln)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$lineWidth = null;
|
||||||
|
/** @var string */
|
||||||
|
$lineWidthTemp = self::getAttribute($sppr->ln, 'w', 'string');
|
||||||
|
if (is_numeric($lineWidthTemp)) {
|
||||||
|
$lineWidth = Properties::xmlToPoints($lineWidthTemp);
|
||||||
|
}
|
||||||
|
/** @var string */
|
||||||
|
$compoundType = self::getAttribute($sppr->ln, 'cmpd', 'string');
|
||||||
|
/** @var string */
|
||||||
|
$dashType = self::getAttribute($sppr->ln->prstDash, 'val', 'string');
|
||||||
|
/** @var string */
|
||||||
|
$capType = self::getAttribute($sppr->ln, 'cap', 'string');
|
||||||
|
if (isset($sppr->ln->miter)) {
|
||||||
|
$joinType = Properties::LINE_STYLE_JOIN_MITER;
|
||||||
|
} elseif (isset($sppr->ln->bevel)) {
|
||||||
|
$joinType = Properties::LINE_STYLE_JOIN_BEVEL;
|
||||||
|
} else {
|
||||||
|
$joinType = '';
|
||||||
|
}
|
||||||
|
$headArrowType = '';
|
||||||
|
$headArrowSize = '';
|
||||||
|
$endArrowType = '';
|
||||||
|
$endArrowSize = '';
|
||||||
|
/** @var string */
|
||||||
|
$headArrowType = self::getAttribute($sppr->ln->headEnd, 'type', 'string');
|
||||||
|
/** @var string */
|
||||||
|
$headArrowWidth = self::getAttribute($sppr->ln->headEnd, 'w', 'string');
|
||||||
|
/** @var string */
|
||||||
|
$headArrowLength = self::getAttribute($sppr->ln->headEnd, 'len', 'string');
|
||||||
|
/** @var string */
|
||||||
|
$endArrowType = self::getAttribute($sppr->ln->tailEnd, 'type', 'string');
|
||||||
|
/** @var string */
|
||||||
|
$endArrowWidth = self::getAttribute($sppr->ln->tailEnd, 'w', 'string');
|
||||||
|
/** @var string */
|
||||||
|
$endArrowLength = self::getAttribute($sppr->ln->tailEnd, 'len', 'string');
|
||||||
|
$chartObject->setLineStyleProperties(
|
||||||
|
$lineWidth,
|
||||||
|
$compoundType,
|
||||||
|
$dashType,
|
||||||
|
$capType,
|
||||||
|
$joinType,
|
||||||
|
$headArrowType,
|
||||||
|
$headArrowSize,
|
||||||
|
$endArrowType,
|
||||||
|
$endArrowSize,
|
||||||
|
$headArrowWidth,
|
||||||
|
$headArrowLength,
|
||||||
|
$endArrowWidth,
|
||||||
|
$endArrowLength
|
||||||
|
);
|
||||||
|
$colorArray = $this->readColor($sppr->ln->solidFill);
|
||||||
|
$chartObject->setColorPropertiesArray($colorArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setAxisProperties(SimpleXMLElement $chartDetail, ?Axis $whichAxis): void
|
||||||
|
{
|
||||||
|
if (!isset($whichAxis)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->crossBetween)) {
|
||||||
|
$whichAxis->setCrossBetween((string) self::getAttribute($chartDetail->crossBetween, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->majorTickMark)) {
|
||||||
|
$whichAxis->setAxisOption('major_tick_mark', (string) self::getAttribute($chartDetail->majorTickMark, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->minorTickMark)) {
|
||||||
|
$whichAxis->setAxisOption('minor_tick_mark', (string) self::getAttribute($chartDetail->minorTickMark, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->tickLblPos)) {
|
||||||
|
$whichAxis->setAxisOption('axis_labels', (string) self::getAttribute($chartDetail->tickLblPos, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->crosses)) {
|
||||||
|
$whichAxis->setAxisOption('horizontal_crosses', (string) self::getAttribute($chartDetail->crosses, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->crossesAt)) {
|
||||||
|
$whichAxis->setAxisOption('horizontal_crosses_value', (string) self::getAttribute($chartDetail->crossesAt, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->scaling->orientation)) {
|
||||||
|
$whichAxis->setAxisOption('orientation', (string) self::getAttribute($chartDetail->scaling->orientation, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->scaling->max)) {
|
||||||
|
$whichAxis->setAxisOption('maximum', (string) self::getAttribute($chartDetail->scaling->max, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->scaling->min)) {
|
||||||
|
$whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->scaling->min)) {
|
||||||
|
$whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->majorUnit)) {
|
||||||
|
$whichAxis->setAxisOption('major_unit', (string) self::getAttribute($chartDetail->majorUnit, 'val', 'string'));
|
||||||
|
}
|
||||||
|
if (isset($chartDetail->minorUnit)) {
|
||||||
|
$whichAxis->setAxisOption('minor_unit', (string) self::getAttribute($chartDetail->minorUnit, 'val', 'string'));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,6 @@ class ReferenceHelper
|
||||||
Worksheet $worksheet
|
Worksheet $worksheet
|
||||||
): void {
|
): void {
|
||||||
$remove = ($numberOfColumns < 0 || $numberOfRows < 0);
|
$remove = ($numberOfColumns < 0 || $numberOfRows < 0);
|
||||||
$allCoordinates = $worksheet->getCoordinates();
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$this->cellReferenceHelper === null ||
|
$this->cellReferenceHelper === null ||
|
||||||
|
|
@ -394,12 +393,13 @@ class ReferenceHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find missing coordinates. This is important when inserting column before the last column
|
// Find missing coordinates. This is important when inserting column before the last column
|
||||||
|
$cellCollection = $worksheet->getCellCollection();
|
||||||
$missingCoordinates = array_filter(
|
$missingCoordinates = array_filter(
|
||||||
array_map(function ($row) use ($highestColumn) {
|
array_map(function ($row) use ($highestColumn) {
|
||||||
return $highestColumn . $row;
|
return $highestColumn . $row;
|
||||||
}, range(1, $highestRow)),
|
}, range(1, $highestRow)),
|
||||||
function ($coordinate) use ($allCoordinates) {
|
function ($coordinate) use ($cellCollection) {
|
||||||
return !in_array($coordinate, $allCoordinates);
|
return $cellCollection->has($coordinate) === false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -408,16 +408,15 @@ class ReferenceHelper
|
||||||
foreach ($missingCoordinates as $coordinate) {
|
foreach ($missingCoordinates as $coordinate) {
|
||||||
$worksheet->createNewCell($coordinate);
|
$worksheet->createNewCell($coordinate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh all coordinates
|
|
||||||
$allCoordinates = $worksheet->getCoordinates();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through cells, bottom-up, and change cell coordinate
|
$allCoordinates = $worksheet->getCoordinates();
|
||||||
if ($remove) {
|
if ($remove) {
|
||||||
// It's faster to reverse and pop than to use unshift, especially with large cell collections
|
// It's faster to reverse and pop than to use unshift, especially with large cell collections
|
||||||
$allCoordinates = array_reverse($allCoordinates);
|
$allCoordinates = array_reverse($allCoordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Loop through cells, bottom-up, and change cell coordinate
|
||||||
while ($coordinate = array_pop($allCoordinates)) {
|
while ($coordinate = array_pop($allCoordinates)) {
|
||||||
$cell = $worksheet->getCell($coordinate);
|
$cell = $worksheet->getCell($coordinate);
|
||||||
$cellIndex = Coordinate::columnIndexFromString($cell->getColumn());
|
$cellIndex = Coordinate::columnIndexFromString($cell->getColumn());
|
||||||
|
|
@ -924,34 +923,43 @@ class ReferenceHelper
|
||||||
|
|
||||||
private function clearColumnStrips(int $highestRow, int $beforeColumn, int $numberOfColumns, Worksheet $worksheet): void
|
private function clearColumnStrips(int $highestRow, int $beforeColumn, int $numberOfColumns, Worksheet $worksheet): void
|
||||||
{
|
{
|
||||||
for ($i = 1; $i <= $highestRow - 1; ++$i) {
|
$startColumnId = Coordinate::stringFromColumnIndex($beforeColumn + $numberOfColumns);
|
||||||
for ($j = $beforeColumn - 1 + $numberOfColumns; $j <= $beforeColumn - 2; ++$j) {
|
$endColumnId = Coordinate::stringFromColumnIndex($beforeColumn);
|
||||||
$coordinate = Coordinate::stringFromColumnIndex($j + 1) . $i;
|
|
||||||
$worksheet->removeConditionalStyles($coordinate);
|
for ($row = 1; $row <= $highestRow - 1; ++$row) {
|
||||||
if ($worksheet->cellExists($coordinate)) {
|
for ($column = $startColumnId; $column !== $endColumnId; ++$column) {
|
||||||
$worksheet->getCell($coordinate)->setValueExplicit('', DataType::TYPE_NULL);
|
$coordinate = $column . $row;
|
||||||
$worksheet->getCell($coordinate)->setXfIndex(0);
|
$this->clearStripCell($worksheet, $coordinate);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function clearRowStrips(string $highestColumn, int $beforeColumn, int $beforeRow, int $numberOfRows, Worksheet $worksheet): void
|
private function clearRowStrips(string $highestColumn, int $beforeColumn, int $beforeRow, int $numberOfRows, Worksheet $worksheet): void
|
||||||
{
|
{
|
||||||
$lastColumnIndex = Coordinate::columnIndexFromString($highestColumn) - 1;
|
$startColumnId = Coordinate::stringFromColumnIndex($beforeColumn);
|
||||||
|
++$highestColumn;
|
||||||
|
|
||||||
for ($i = $beforeColumn - 1; $i <= $lastColumnIndex; ++$i) {
|
for ($column = $startColumnId; $column !== $highestColumn; ++$column) {
|
||||||
for ($j = $beforeRow + $numberOfRows; $j <= $beforeRow - 1; ++$j) {
|
for ($row = $beforeRow + $numberOfRows; $row <= $beforeRow - 1; ++$row) {
|
||||||
$coordinate = Coordinate::stringFromColumnIndex($i + 1) . $j;
|
$coordinate = $column . $row;
|
||||||
$worksheet->removeConditionalStyles($coordinate);
|
$this->clearStripCell($worksheet, $coordinate);
|
||||||
if ($worksheet->cellExists($coordinate)) {
|
|
||||||
$worksheet->getCell($coordinate)->setValueExplicit('', DataType::TYPE_NULL);
|
|
||||||
$worksheet->getCell($coordinate)->setXfIndex(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function clearStripCell(Worksheet $worksheet, string $coordinate): void
|
||||||
|
{
|
||||||
|
$worksheet->removeConditionalStyles($coordinate);
|
||||||
|
$worksheet->setHyperlink($coordinate);
|
||||||
|
$worksheet->setDataValidation($coordinate);
|
||||||
|
$worksheet->removeComment($coordinate);
|
||||||
|
|
||||||
|
if ($worksheet->cellExists($coordinate)) {
|
||||||
|
$worksheet->getCell($coordinate)->setValueExplicit(null, DataType::TYPE_NULL);
|
||||||
|
$worksheet->getCell($coordinate)->setXfIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function adjustAutoFilter(Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns): void
|
private function adjustAutoFilter(Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns): void
|
||||||
{
|
{
|
||||||
$autoFilter = $worksheet->getAutoFilter();
|
$autoFilter = $worksheet->getAutoFilter();
|
||||||
|
|
|
||||||
|
|
@ -329,12 +329,8 @@ class StringHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters.
|
* Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters.
|
||||||
*
|
|
||||||
* @param string $textValue
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function sanitizeUTF8($textValue)
|
public static function sanitizeUTF8(string $textValue): string
|
||||||
{
|
{
|
||||||
if (self::getIsIconvEnabled()) {
|
if (self::getIsIconvEnabled()) {
|
||||||
$textValue = @iconv('UTF-8', 'UTF-8', $textValue);
|
$textValue = @iconv('UTF-8', 'UTF-8', $textValue);
|
||||||
|
|
@ -349,12 +345,8 @@ class StringHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a string contains UTF8 data.
|
* Check if a string contains UTF8 data.
|
||||||
*
|
|
||||||
* @param string $textValue
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public static function isUTF8($textValue)
|
public static function isUTF8(string $textValue): bool
|
||||||
{
|
{
|
||||||
return $textValue === '' || preg_match('/^./su', $textValue) === 1;
|
return $textValue === '' || preg_match('/^./su', $textValue) === 1;
|
||||||
}
|
}
|
||||||
|
|
@ -364,10 +356,8 @@ class StringHelper
|
||||||
* point as decimal separator in case locale is other than English.
|
* point as decimal separator in case locale is other than English.
|
||||||
*
|
*
|
||||||
* @param mixed $numericValue
|
* @param mixed $numericValue
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function formatNumber($numericValue)
|
public static function formatNumber($numericValue): string
|
||||||
{
|
{
|
||||||
if (is_float($numericValue)) {
|
if (is_float($numericValue)) {
|
||||||
return str_replace(',', '.', $numericValue);
|
return str_replace(',', '.', $numericValue);
|
||||||
|
|
@ -385,10 +375,8 @@ class StringHelper
|
||||||
*
|
*
|
||||||
* @param string $textValue UTF-8 encoded string
|
* @param string $textValue UTF-8 encoded string
|
||||||
* @param mixed[] $arrcRuns Details of rich text runs in $value
|
* @param mixed[] $arrcRuns Details of rich text runs in $value
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function UTF8toBIFF8UnicodeShort($textValue, $arrcRuns = [])
|
public static function UTF8toBIFF8UnicodeShort(string $textValue, array $arrcRuns = []): string
|
||||||
{
|
{
|
||||||
// character count
|
// character count
|
||||||
$ln = self::countCharacters($textValue, 'UTF-8');
|
$ln = self::countCharacters($textValue, 'UTF-8');
|
||||||
|
|
@ -419,10 +407,8 @@ class StringHelper
|
||||||
* see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3.
|
* see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3.
|
||||||
*
|
*
|
||||||
* @param string $textValue UTF-8 encoded string
|
* @param string $textValue UTF-8 encoded string
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function UTF8toBIFF8UnicodeLong($textValue)
|
public static function UTF8toBIFF8UnicodeLong(string $textValue): string
|
||||||
{
|
{
|
||||||
// character count
|
// character count
|
||||||
$ln = self::countCharacters($textValue, 'UTF-8');
|
$ln = self::countCharacters($textValue, 'UTF-8');
|
||||||
|
|
@ -436,13 +422,10 @@ class StringHelper
|
||||||
/**
|
/**
|
||||||
* Convert string from one encoding to another.
|
* Convert string from one encoding to another.
|
||||||
*
|
*
|
||||||
* @param string $textValue
|
|
||||||
* @param string $to Encoding to convert to, e.g. 'UTF-8'
|
* @param string $to Encoding to convert to, e.g. 'UTF-8'
|
||||||
* @param string $from Encoding to convert from, e.g. 'UTF-16LE'
|
* @param string $from Encoding to convert from, e.g. 'UTF-16LE'
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function convertEncoding($textValue, $to, $from)
|
public static function convertEncoding(string $textValue, string $to, string $from): string
|
||||||
{
|
{
|
||||||
if (self::getIsIconvEnabled()) {
|
if (self::getIsIconvEnabled()) {
|
||||||
$result = iconv($from, $to . self::$iconvOptions, $textValue);
|
$result = iconv($from, $to . self::$iconvOptions, $textValue);
|
||||||
|
|
@ -457,52 +440,45 @@ class StringHelper
|
||||||
/**
|
/**
|
||||||
* Get character count.
|
* Get character count.
|
||||||
*
|
*
|
||||||
* @param string $textValue
|
|
||||||
* @param string $encoding Encoding
|
* @param string $encoding Encoding
|
||||||
*
|
*
|
||||||
* @return int Character count
|
* @return int Character count
|
||||||
*/
|
*/
|
||||||
public static function countCharacters($textValue, $encoding = 'UTF-8')
|
public static function countCharacters(string $textValue, string $encoding = 'UTF-8'): int
|
||||||
{
|
{
|
||||||
return mb_strlen($textValue ?? '', $encoding);
|
return mb_strlen($textValue, $encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a substring of a UTF-8 encoded string.
|
* Get a substring of a UTF-8 encoded string.
|
||||||
*
|
*
|
||||||
* @param null|string $textValue UTF-8 encoded string
|
* @param string $textValue UTF-8 encoded string
|
||||||
* @param int $offset Start offset
|
* @param int $offset Start offset
|
||||||
* @param int $length Maximum number of characters in substring
|
* @param int $length Maximum number of characters in substring
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function substring($textValue, $offset, $length = 0)
|
public static function substring(string $textValue, int $offset, int $length = 0): string
|
||||||
{
|
{
|
||||||
return mb_substr($textValue ?? '', $offset, $length, 'UTF-8');
|
return mb_substr($textValue, $offset, $length, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a UTF-8 encoded string to upper case.
|
* Convert a UTF-8 encoded string to upper case.
|
||||||
*
|
*
|
||||||
* @param string $textValue UTF-8 encoded string
|
* @param string $textValue UTF-8 encoded string
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function strToUpper($textValue)
|
public static function strToUpper(string $textValue): string
|
||||||
{
|
{
|
||||||
return mb_convert_case($textValue ?? '', MB_CASE_UPPER, 'UTF-8');
|
return mb_convert_case($textValue, MB_CASE_UPPER, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a UTF-8 encoded string to lower case.
|
* Convert a UTF-8 encoded string to lower case.
|
||||||
*
|
*
|
||||||
* @param string $textValue UTF-8 encoded string
|
* @param string $textValue UTF-8 encoded string
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function strToLower($textValue)
|
public static function strToLower(string $textValue): string
|
||||||
{
|
{
|
||||||
return mb_convert_case($textValue ?? '', MB_CASE_LOWER, 'UTF-8');
|
return mb_convert_case($textValue, MB_CASE_LOWER, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -510,24 +486,27 @@ class StringHelper
|
||||||
* (uppercase every first character in each word, lower case all other characters).
|
* (uppercase every first character in each word, lower case all other characters).
|
||||||
*
|
*
|
||||||
* @param string $textValue UTF-8 encoded string
|
* @param string $textValue UTF-8 encoded string
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function strToTitle($textValue)
|
public static function strToTitle(string $textValue): string
|
||||||
{
|
{
|
||||||
return mb_convert_case($textValue, MB_CASE_TITLE, 'UTF-8');
|
return mb_convert_case($textValue, MB_CASE_TITLE, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function mbIsUpper($character)
|
public static function mbIsUpper(string $character): bool
|
||||||
{
|
{
|
||||||
return mb_strtolower($character, 'UTF-8') != $character;
|
return mb_strtolower($character, 'UTF-8') !== $character;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function mbStrSplit($string)
|
/**
|
||||||
|
* Splits a UTF-8 string into an array of individual characters.
|
||||||
|
*/
|
||||||
|
public static function mbStrSplit(string $string): array
|
||||||
{
|
{
|
||||||
// Split at all position not after the start: ^
|
// Split at all position not after the start: ^
|
||||||
// and not before the end: $
|
// and not before the end: $
|
||||||
return preg_split('/(?<!^)(?!$)/u', $string);
|
$split = preg_split('/(?<!^)(?!$)/u', $string);
|
||||||
|
|
||||||
|
return ($split === false) ? [] : $split;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -535,10 +514,8 @@ class StringHelper
|
||||||
* and all lowercase characters become uppercase.
|
* and all lowercase characters become uppercase.
|
||||||
*
|
*
|
||||||
* @param string $textValue UTF-8 encoded string
|
* @param string $textValue UTF-8 encoded string
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function strCaseReverse($textValue)
|
public static function strCaseReverse(string $textValue): string
|
||||||
{
|
{
|
||||||
$characters = self::mbStrSplit($textValue);
|
$characters = self::mbStrSplit($textValue);
|
||||||
foreach ($characters as &$character) {
|
foreach ($characters as &$character) {
|
||||||
|
|
@ -557,10 +534,8 @@ class StringHelper
|
||||||
* and convert it to a numeric if it is.
|
* and convert it to a numeric if it is.
|
||||||
*
|
*
|
||||||
* @param string $operand string value to test
|
* @param string $operand string value to test
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public static function convertToNumberIfFraction(&$operand)
|
public static function convertToNumberIfFraction(string &$operand): bool
|
||||||
{
|
{
|
||||||
if (preg_match('/^' . self::STRING_REGEXP_FRACTION . '$/i', $operand, $match)) {
|
if (preg_match('/^' . self::STRING_REGEXP_FRACTION . '$/i', $operand, $match)) {
|
||||||
$sign = ($match[1] == '-') ? '-' : '+';
|
$sign = ($match[1] == '-') ? '-' : '+';
|
||||||
|
|
@ -578,10 +553,8 @@ class StringHelper
|
||||||
/**
|
/**
|
||||||
* Get the decimal separator. If it has not yet been set explicitly, try to obtain number
|
* Get the decimal separator. If it has not yet been set explicitly, try to obtain number
|
||||||
* formatting information from locale.
|
* formatting information from locale.
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function getDecimalSeparator()
|
public static function getDecimalSeparator(): string
|
||||||
{
|
{
|
||||||
if (!isset(self::$decimalSeparator)) {
|
if (!isset(self::$decimalSeparator)) {
|
||||||
$localeconv = localeconv();
|
$localeconv = localeconv();
|
||||||
|
|
@ -603,7 +576,7 @@ class StringHelper
|
||||||
*
|
*
|
||||||
* @param string $separator Character for decimal separator
|
* @param string $separator Character for decimal separator
|
||||||
*/
|
*/
|
||||||
public static function setDecimalSeparator($separator): void
|
public static function setDecimalSeparator(string $separator): void
|
||||||
{
|
{
|
||||||
self::$decimalSeparator = $separator;
|
self::$decimalSeparator = $separator;
|
||||||
}
|
}
|
||||||
|
|
@ -611,10 +584,8 @@ class StringHelper
|
||||||
/**
|
/**
|
||||||
* Get the thousands separator. If it has not yet been set explicitly, try to obtain number
|
* Get the thousands separator. If it has not yet been set explicitly, try to obtain number
|
||||||
* formatting information from locale.
|
* formatting information from locale.
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function getThousandsSeparator()
|
public static function getThousandsSeparator(): string
|
||||||
{
|
{
|
||||||
if (!isset(self::$thousandsSeparator)) {
|
if (!isset(self::$thousandsSeparator)) {
|
||||||
$localeconv = localeconv();
|
$localeconv = localeconv();
|
||||||
|
|
@ -636,7 +607,7 @@ class StringHelper
|
||||||
*
|
*
|
||||||
* @param string $separator Character for thousands separator
|
* @param string $separator Character for thousands separator
|
||||||
*/
|
*/
|
||||||
public static function setThousandsSeparator($separator): void
|
public static function setThousandsSeparator(string $separator): void
|
||||||
{
|
{
|
||||||
self::$thousandsSeparator = $separator;
|
self::$thousandsSeparator = $separator;
|
||||||
}
|
}
|
||||||
|
|
@ -644,10 +615,8 @@ class StringHelper
|
||||||
/**
|
/**
|
||||||
* Get the currency code. If it has not yet been set explicitly, try to obtain the
|
* Get the currency code. If it has not yet been set explicitly, try to obtain the
|
||||||
* symbol information from locale.
|
* symbol information from locale.
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function getCurrencyCode()
|
public static function getCurrencyCode(): string
|
||||||
{
|
{
|
||||||
if (!empty(self::$currencyCode)) {
|
if (!empty(self::$currencyCode)) {
|
||||||
return self::$currencyCode;
|
return self::$currencyCode;
|
||||||
|
|
@ -674,7 +643,7 @@ class StringHelper
|
||||||
*
|
*
|
||||||
* @param string $currencyCode Character for currency code
|
* @param string $currencyCode Character for currency code
|
||||||
*/
|
*/
|
||||||
public static function setCurrencyCode($currencyCode): void
|
public static function setCurrencyCode(string $currencyCode): void
|
||||||
{
|
{
|
||||||
self::$currencyCode = $currencyCode;
|
self::$currencyCode = $currencyCode;
|
||||||
}
|
}
|
||||||
|
|
@ -682,11 +651,11 @@ class StringHelper
|
||||||
/**
|
/**
|
||||||
* Convert SYLK encoded string to UTF-8.
|
* Convert SYLK encoded string to UTF-8.
|
||||||
*
|
*
|
||||||
* @param string $textValue
|
* @param string $textValue SYLK encoded string
|
||||||
*
|
*
|
||||||
* @return string UTF-8 encoded string
|
* @return string UTF-8 encoded string
|
||||||
*/
|
*/
|
||||||
public static function SYLKtoUTF8($textValue)
|
public static function SYLKtoUTF8(string $textValue): string
|
||||||
{
|
{
|
||||||
self::buildCharacterSets();
|
self::buildCharacterSets();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@ class TimeZone
|
||||||
*
|
*
|
||||||
* @return bool Success or failure
|
* @return bool Success or failure
|
||||||
*/
|
*/
|
||||||
private static function validateTimeZone($timezoneName)
|
private static function validateTimeZone(string $timezoneName): bool
|
||||||
{
|
{
|
||||||
return in_array($timezoneName, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC));
|
return in_array($timezoneName, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -33,7 +33,7 @@ class TimeZone
|
||||||
*
|
*
|
||||||
* @return bool Success or failure
|
* @return bool Success or failure
|
||||||
*/
|
*/
|
||||||
public static function setTimeZone($timezoneName)
|
public static function setTimeZone(string $timezoneName): bool
|
||||||
{
|
{
|
||||||
if (self::validateTimezone($timezoneName)) {
|
if (self::validateTimezone($timezoneName)) {
|
||||||
self::$timezone = $timezoneName;
|
self::$timezone = $timezoneName;
|
||||||
|
|
@ -49,7 +49,7 @@ class TimeZone
|
||||||
*
|
*
|
||||||
* @return string Timezone (e.g. 'Europe/London')
|
* @return string Timezone (e.g. 'Europe/London')
|
||||||
*/
|
*/
|
||||||
public static function getTimeZone()
|
public static function getTimeZone(): string
|
||||||
{
|
{
|
||||||
return self::$timezone;
|
return self::$timezone;
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +63,7 @@ class TimeZone
|
||||||
*
|
*
|
||||||
* @return int Number of seconds for timezone adjustment
|
* @return int Number of seconds for timezone adjustment
|
||||||
*/
|
*/
|
||||||
public static function getTimeZoneAdjustment($timezoneName, $timestamp)
|
public static function getTimeZoneAdjustment(?string $timezoneName, $timestamp): int
|
||||||
{
|
{
|
||||||
$timezoneName = $timezoneName ?? self::$timezone;
|
$timezoneName = $timezoneName ?? self::$timezone;
|
||||||
$dtobj = Date::dateTimeFromTimestamp("$timestamp");
|
$dtobj = Date::dateTimeFromTimestamp("$timestamp");
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,9 @@ class Formatter
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ignore square-$-brackets prefix in format string, like "[$-411]ge.m.d", "[$-010419]0%", etc
|
||||||
|
$format = (string) preg_replace('/^\[\$-[^\]]*\]/', '', $format);
|
||||||
|
|
||||||
$format = (string) preg_replace_callback(
|
$format = (string) preg_replace_callback(
|
||||||
'/(["])(?:(?=(\\\\?))\\2.)*?\\1/u',
|
'/(["])(?:(?=(\\\\?))\\2.)*?\\1/u',
|
||||||
function ($matches) {
|
function ($matches) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@ use PhpOffice\PhpSpreadsheet\Collection\Cells;
|
||||||
*/
|
*/
|
||||||
abstract class CellIterator implements Iterator
|
abstract class CellIterator implements Iterator
|
||||||
{
|
{
|
||||||
|
public const TREAT_NULL_VALUE_AS_EMPTY_CELL = 1;
|
||||||
|
|
||||||
|
public const TREAT_EMPTY_STRING_AS_EMPTY_CELL = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worksheet to iterate.
|
* Worksheet to iterate.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class Column
|
||||||
*
|
*
|
||||||
* @var Worksheet
|
* @var Worksheet
|
||||||
*/
|
*/
|
||||||
private $parent;
|
private $worksheet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column index.
|
* Column index.
|
||||||
|
|
@ -23,10 +23,10 @@ class Column
|
||||||
*
|
*
|
||||||
* @param string $columnIndex
|
* @param string $columnIndex
|
||||||
*/
|
*/
|
||||||
public function __construct(?Worksheet $parent = null, $columnIndex = 'A')
|
public function __construct(Worksheet $worksheet, $columnIndex = 'A')
|
||||||
{
|
{
|
||||||
// Set parent and column index
|
// Set parent and column index
|
||||||
$this->parent = $parent;
|
$this->worksheet = $worksheet;
|
||||||
$this->columnIndex = $columnIndex;
|
$this->columnIndex = $columnIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ class Column
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
// @phpstan-ignore-next-line
|
// @phpstan-ignore-next-line
|
||||||
$this->parent = null;
|
$this->worksheet = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -57,6 +57,53 @@ class Column
|
||||||
*/
|
*/
|
||||||
public function getCellIterator($startRow = 1, $endRow = null)
|
public function getCellIterator($startRow = 1, $endRow = null)
|
||||||
{
|
{
|
||||||
return new ColumnCellIterator($this->parent, $this->columnIndex, $startRow, $endRow);
|
return new ColumnCellIterator($this->worksheet, $this->columnIndex, $startRow, $endRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the column contains no cells. By default, this means that no cell records exist in the
|
||||||
|
* collection for this column. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the column will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the column will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the column
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmpty(int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
$nullValueCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
$emptyStringCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
$cellIterator = $this->getCellIterator();
|
||||||
|
$cellIterator->setIterateOnlyExistingCells(true);
|
||||||
|
foreach ($cellIterator as $cell) {
|
||||||
|
$value = $cell->getValue();
|
||||||
|
if ($value === null && $nullValueCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($value === '' && $emptyStringCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns bound worksheet.
|
||||||
|
*/
|
||||||
|
public function getWorksheet(): Worksheet
|
||||||
|
{
|
||||||
|
return $this->worksheet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class Row
|
||||||
*
|
*
|
||||||
* @param int $rowIndex
|
* @param int $rowIndex
|
||||||
*/
|
*/
|
||||||
public function __construct(?Worksheet $worksheet = null, $rowIndex = 1)
|
public function __construct(Worksheet $worksheet, $rowIndex = 1)
|
||||||
{
|
{
|
||||||
// Set parent and row index
|
// Set parent and row index
|
||||||
$this->worksheet = $worksheet;
|
$this->worksheet = $worksheet;
|
||||||
|
|
@ -59,6 +59,45 @@ class Row
|
||||||
return new RowCellIterator($this->worksheet, $this->rowIndex, $startColumn, $endColumn);
|
return new RowCellIterator($this->worksheet, $this->rowIndex, $startColumn, $endColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the row contains no cells. By default, this means that no cell records exist in the
|
||||||
|
* collection for this row. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the row will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the row will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the row
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmpty(int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
$nullValueCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
$emptyStringCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
$cellIterator = $this->getCellIterator();
|
||||||
|
$cellIterator->setIterateOnlyExistingCells(true);
|
||||||
|
foreach ($cellIterator as $cell) {
|
||||||
|
$value = $cell->getValue();
|
||||||
|
if ($value === null && $nullValueCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($value === '' && $emptyStringCellIsEmpty === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns bound worksheet.
|
* Returns bound worksheet.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1177,6 +1177,11 @@ class Worksheet implements IComparable
|
||||||
* or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object.
|
* or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object.
|
||||||
* @param mixed $value Value of the cell
|
* @param mixed $value Value of the cell
|
||||||
* @param string $dataType Explicit data type, see DataType::TYPE_*
|
* @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
|
* @return $this
|
||||||
*/
|
*/
|
||||||
|
|
@ -1199,6 +1204,11 @@ class Worksheet implements IComparable
|
||||||
* @param int $row Numeric row coordinate of the cell
|
* @param int $row Numeric row coordinate of the cell
|
||||||
* @param mixed $value Value of the cell
|
* @param mixed $value Value of the cell
|
||||||
* @param string $dataType Explicit data type, see DataType::TYPE_*
|
* @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
|
* @return $this
|
||||||
*/
|
*/
|
||||||
|
|
@ -1752,31 +1762,39 @@ class Worksheet implements IComparable
|
||||||
{
|
{
|
||||||
$range = Functions::trimSheetFromCellReference(Validations::validateCellRange($range));
|
$range = Functions::trimSheetFromCellReference(Validations::validateCellRange($range));
|
||||||
|
|
||||||
if (preg_match('/^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/', $range, $matches) === 1) {
|
if (strpos($range, ':') === false) {
|
||||||
$this->mergeCells[$range] = $range;
|
$range .= ":{$range}";
|
||||||
$firstRow = (int) $matches[2];
|
}
|
||||||
$lastRow = (int) $matches[4];
|
|
||||||
$firstColumn = $matches[1];
|
|
||||||
$lastColumn = $matches[3];
|
|
||||||
$firstColumnIndex = Coordinate::columnIndexFromString($firstColumn);
|
|
||||||
$lastColumnIndex = Coordinate::columnIndexFromString($lastColumn);
|
|
||||||
$numberRows = $lastRow - $firstRow;
|
|
||||||
$numberColumns = $lastColumnIndex - $firstColumnIndex;
|
|
||||||
|
|
||||||
// create upper left cell if it does not already exist
|
if (preg_match('/^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/', $range, $matches) !== 1) {
|
||||||
$upperLeft = "{$firstColumn}{$firstRow}";
|
throw new Exception('Merge must be on a valid range of cells.');
|
||||||
if (!$this->cellExists($upperLeft)) {
|
}
|
||||||
$this->getCell($upperLeft)->setValueExplicit(null, DataType::TYPE_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blank out the rest of the cells in the range (if they exist)
|
$this->mergeCells[$range] = $range;
|
||||||
if ($numberRows > $numberColumns) {
|
$firstRow = (int) $matches[2];
|
||||||
$this->clearMergeCellsByColumn($firstColumn, $lastColumn, $firstRow, $lastRow, $upperLeft);
|
$lastRow = (int) $matches[4];
|
||||||
} else {
|
$firstColumn = $matches[1];
|
||||||
$this->clearMergeCellsByRow($firstColumn, $lastColumnIndex, $firstRow, $lastRow, $upperLeft);
|
$lastColumn = $matches[3];
|
||||||
}
|
$firstColumnIndex = Coordinate::columnIndexFromString($firstColumn);
|
||||||
|
$lastColumnIndex = Coordinate::columnIndexFromString($lastColumn);
|
||||||
|
$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)) {
|
||||||
|
$this->getCell($upperLeft)->setValueExplicit(null, DataType::TYPE_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blank out the rest of the cells in the range (if they exist)
|
||||||
|
if ($numberRows > $numberColumns) {
|
||||||
|
$this->clearMergeCellsByColumn($firstColumn, $lastColumn, $firstRow, $lastRow, $upperLeft);
|
||||||
} else {
|
} else {
|
||||||
throw new Exception('Merge must be set on a range of cells.');
|
$this->clearMergeCellsByRow($firstColumn, $lastColumnIndex, $firstRow, $lastRow, $upperLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -2582,6 +2600,33 @@ class Worksheet implements IComparable
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove comment from cell.
|
||||||
|
*
|
||||||
|
* @param array<int>|CellAddress|string $cellCoordinate Coordinate of the cell as a string, eg: 'C5';
|
||||||
|
* or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function removeComment($cellCoordinate)
|
||||||
|
{
|
||||||
|
$cellAddress = Functions::trimSheetFromCellReference(Validations::validateCellAddress($cellCoordinate));
|
||||||
|
|
||||||
|
if (Coordinate::coordinateIsRange($cellAddress)) {
|
||||||
|
throw new Exception('Cell coordinate string can not be a range of cells.');
|
||||||
|
} elseif (strpos($cellAddress, '$') !== false) {
|
||||||
|
throw new Exception('Cell coordinate string must not be absolute.');
|
||||||
|
} elseif ($cellAddress == '') {
|
||||||
|
throw new Exception('Cell coordinate can not be zero-length string.');
|
||||||
|
}
|
||||||
|
// Check if we have a comment for this cell and delete it
|
||||||
|
if (isset($this->comments[$cellAddress])) {
|
||||||
|
unset($this->comments[$cellAddress]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get comment for cell.
|
* Get comment for cell.
|
||||||
*
|
*
|
||||||
|
|
@ -3232,6 +3277,66 @@ class Worksheet implements IComparable
|
||||||
return clone $this;
|
return clone $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the specified row contains no cells. By default, this means that no cell records
|
||||||
|
* exist in the collection for this row. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the row will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the row will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the row
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmptyRow(int $rowId, int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$iterator = new RowIterator($this, $rowId, $rowId);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $row->isEmpty($definitionOfEmptyFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean true if the specified column contains no cells. By default, this means that no cell records
|
||||||
|
* exist in the collection for this column. false will be returned otherwise.
|
||||||
|
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||||
|
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||||
|
* cells, then the column will be considered empty.
|
||||||
|
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||||
|
* string value cells, then the column will be considered empty.
|
||||||
|
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
* If the only cells in the collection are null value or empty string value cells, then the column
|
||||||
|
* will be considered empty.
|
||||||
|
*
|
||||||
|
* @param int $definitionOfEmptyFlags
|
||||||
|
* Possible Flag Values are:
|
||||||
|
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||||
|
*/
|
||||||
|
public function isEmptyColumn(string $columnId, int $definitionOfEmptyFlags = 0): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$iterator = new ColumnIterator($this, $columnId, $columnId);
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$column = $iterator->current();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $column->isEmpty($definitionOfEmptyFlags);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1744,7 +1744,7 @@ class Html extends BaseWriter
|
||||||
while ($c++ < $e) {
|
while ($c++ < $e) {
|
||||||
$baseCell = $this->isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell'];
|
$baseCell = $this->isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell'];
|
||||||
|
|
||||||
if (!in_array($baseCell, $adjustedBaseCells)) {
|
if (!in_array($baseCell, $adjustedBaseCells, true)) {
|
||||||
// subtract rowspan by 1
|
// subtract rowspan by 1
|
||||||
--$this->isBaseCell[$sheetIndex][$baseCell[0]][$baseCell[1]]['rowspan'];
|
--$this->isBaseCell[$sheetIndex][$baseCell[0]][$baseCell[1]]['rowspan'];
|
||||||
$adjustedBaseCells[] = $baseCell;
|
$adjustedBaseCells[] = $baseCell;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use PhpOffice\PhpSpreadsheet\Chart\GridLines;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\Properties;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||||
|
|
@ -248,11 +249,11 @@ class Chart extends WriterPart
|
||||||
$groupType = $plotGroup->getPlotType();
|
$groupType = $plotGroup->getPlotType();
|
||||||
if ($groupType == $chartType) {
|
if ($groupType == $chartType) {
|
||||||
$plotStyle = $plotGroup->getPlotStyle();
|
$plotStyle = $plotGroup->getPlotStyle();
|
||||||
if ($groupType === DataSeries::TYPE_RADARCHART) {
|
if (!empty($plotStyle) && $groupType === DataSeries::TYPE_RADARCHART) {
|
||||||
$objWriter->startElement('c:radarStyle');
|
$objWriter->startElement('c:radarStyle');
|
||||||
$objWriter->writeAttribute('val', $plotStyle);
|
$objWriter->writeAttribute('val', $plotStyle);
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
} elseif ($groupType === DataSeries::TYPE_SCATTERCHART) {
|
} elseif (!empty($plotStyle) && $groupType === DataSeries::TYPE_SCATTERCHART) {
|
||||||
$objWriter->startElement('c:scatterStyle');
|
$objWriter->startElement('c:scatterStyle');
|
||||||
$objWriter->writeAttribute('val', $plotStyle);
|
$objWriter->writeAttribute('val', $plotStyle);
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
@ -430,10 +431,22 @@ class Chart extends WriterPart
|
||||||
}
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:scaling');
|
$objWriter->startElement('c:scaling');
|
||||||
$objWriter->startElement('c:orientation');
|
if ($yAxis->getAxisOptionsProperty('maximum') !== null) {
|
||||||
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('orientation'));
|
$objWriter->startElement('c:max');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('maximum'));
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
if ($yAxis->getAxisOptionsProperty('minimum') !== null) {
|
||||||
|
$objWriter->startElement('c:min');
|
||||||
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minimum'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
if (!empty($yAxis->getAxisOptionsProperty('orientation'))) {
|
||||||
|
$objWriter->startElement('c:orientation');
|
||||||
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('orientation'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
$objWriter->endElement(); // c:scaling
|
||||||
|
|
||||||
$objWriter->startElement('c:delete');
|
$objWriter->startElement('c:delete');
|
||||||
$objWriter->writeAttribute('val', 0);
|
$objWriter->writeAttribute('val', 0);
|
||||||
|
|
@ -485,47 +498,67 @@ class Chart extends WriterPart
|
||||||
$objWriter->writeAttribute('sourceLinked', $yAxis->getAxisNumberSourceLinked());
|
$objWriter->writeAttribute('sourceLinked', $yAxis->getAxisNumberSourceLinked());
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
||||||
$objWriter->startElement('c:majorTickMark');
|
if (!empty($yAxis->getAxisOptionsProperty('major_tick_mark'))) {
|
||||||
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_tick_mark'));
|
$objWriter->startElement('c:majorTickMark');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_tick_mark'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:minorTickMark');
|
if (!empty($yAxis->getAxisOptionsProperty('minor_tick_mark'))) {
|
||||||
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_tick_mark'));
|
$objWriter->startElement('c:minorTickMark');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_tick_mark'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:tickLblPos');
|
if (!empty($yAxis->getAxisOptionsProperty('axis_labels'))) {
|
||||||
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels'));
|
$objWriter->startElement('c:tickLblPos');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('axis_labels'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:spPr');
|
$objWriter->startElement('c:spPr');
|
||||||
|
if (!empty($yAxis->getFillProperty('value'))) {
|
||||||
|
$objWriter->startElement('a:solidFill');
|
||||||
|
$objWriter->startElement('a:' . $yAxis->getFillProperty('type'));
|
||||||
|
$objWriter->writeAttribute('val', $yAxis->getFillProperty('value'));
|
||||||
|
$alpha = $yAxis->getFillProperty('alpha');
|
||||||
|
if (is_numeric($alpha)) {
|
||||||
|
$objWriter->startElement('a:alpha');
|
||||||
|
$objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
$objWriter->endElement();
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
$objWriter->startElement('a:effectLst');
|
$objWriter->startElement('a:effectLst');
|
||||||
if ($yAxis->getGlowProperty('size') !== null) {
|
$this->writeGlow($objWriter, $yAxis);
|
||||||
$objWriter->startElement('a:glow');
|
$this->writeShadow($objWriter, $yAxis);
|
||||||
$objWriter->writeAttribute('rad', $yAxis->getGlowProperty('size'));
|
$this->writeSoftEdge($objWriter, $yAxis);
|
||||||
$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
|
|
||||||
}
|
|
||||||
$objWriter->endElement(); // effectLst
|
$objWriter->endElement(); // effectLst
|
||||||
$objWriter->endElement(); // spPr
|
$objWriter->endElement(); // spPr
|
||||||
|
|
||||||
|
if ($yAxis->getAxisOptionsProperty('major_unit') !== null) {
|
||||||
|
$objWriter->startElement('c:majorUnit');
|
||||||
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('major_unit'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($yAxis->getAxisOptionsProperty('minor_unit') !== null) {
|
||||||
|
$objWriter->startElement('c:minorUnit');
|
||||||
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('minor_unit'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
if ($id2 !== '0') {
|
if ($id2 !== '0') {
|
||||||
$objWriter->startElement('c:crossAx');
|
$objWriter->startElement('c:crossAx');
|
||||||
$objWriter->writeAttribute('val', $id2);
|
$objWriter->writeAttribute('val', $id2);
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
||||||
$objWriter->startElement('c:crosses');
|
if (!empty($yAxis->getAxisOptionsProperty('horizontal_crosses'))) {
|
||||||
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('horizontal_crosses'));
|
$objWriter->startElement('c:crosses');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $yAxis->getAxisOptionsProperty('horizontal_crosses'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:auto');
|
$objWriter->startElement('c:auto');
|
||||||
|
|
@ -580,11 +613,13 @@ class Chart extends WriterPart
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:orientation');
|
if (!empty($xAxis->getAxisOptionsProperty('orientation'))) {
|
||||||
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('orientation'));
|
$objWriter->startElement('c:orientation');
|
||||||
|
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('orientation'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$objWriter->endElement();
|
$objWriter->endElement(); // c:scaling
|
||||||
$objWriter->endElement();
|
|
||||||
|
|
||||||
$objWriter->startElement('c:delete');
|
$objWriter->startElement('c:delete');
|
||||||
$objWriter->writeAttribute('val', 0);
|
$objWriter->writeAttribute('val', 0);
|
||||||
|
|
@ -597,104 +632,12 @@ class Chart extends WriterPart
|
||||||
$objWriter->startElement('c:majorGridlines');
|
$objWriter->startElement('c:majorGridlines');
|
||||||
$objWriter->startElement('c:spPr');
|
$objWriter->startElement('c:spPr');
|
||||||
|
|
||||||
if ($majorGridlines->getLineColorProperty('value') !== null) {
|
$this->writeGridlinesLn($objWriter, $majorGridlines);
|
||||||
$objWriter->startElement('a:ln');
|
|
||||||
$objWriter->writeAttribute('w', $majorGridlines->getLineStyleProperty('width'));
|
|
||||||
$objWriter->startElement('a:solidFill');
|
|
||||||
$objWriter->startElement("a:{$majorGridlines->getLineColorProperty('type')}");
|
|
||||||
$objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('value'));
|
|
||||||
$objWriter->startElement('a:alpha');
|
|
||||||
$objWriter->writeAttribute('val', $majorGridlines->getLineColorProperty('alpha'));
|
|
||||||
$objWriter->endElement(); //end alpha
|
|
||||||
$objWriter->endElement(); //end srgbClr
|
|
||||||
$objWriter->endElement(); //end solidFill
|
|
||||||
|
|
||||||
$objWriter->startElement('a:prstDash');
|
|
||||||
$objWriter->writeAttribute('val', $majorGridlines->getLineStyleProperty('dash'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
|
|
||||||
if ($majorGridlines->getLineStyleProperty('join') == 'miter') {
|
|
||||||
$objWriter->startElement('a:miter');
|
|
||||||
$objWriter->writeAttribute('lim', '800000');
|
|
||||||
$objWriter->endElement();
|
|
||||||
} else {
|
|
||||||
$objWriter->startElement('a:bevel');
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($majorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) {
|
|
||||||
$objWriter->startElement('a:headEnd');
|
|
||||||
$objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'type']));
|
|
||||||
$objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('head', 'w'));
|
|
||||||
$objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('head', 'len'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($majorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) {
|
|
||||||
$objWriter->startElement('a:tailEnd');
|
|
||||||
$objWriter->writeAttribute('type', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'type']));
|
|
||||||
$objWriter->writeAttribute('w', $majorGridlines->getLineStyleArrowParameters('end', 'w'));
|
|
||||||
$objWriter->writeAttribute('len', $majorGridlines->getLineStyleArrowParameters('end', 'len'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
$objWriter->endElement(); //end ln
|
|
||||||
}
|
|
||||||
$objWriter->startElement('a:effectLst');
|
$objWriter->startElement('a:effectLst');
|
||||||
|
$this->writeGlow($objWriter, $majorGridlines);
|
||||||
if ($majorGridlines->getGlowSize() !== null) {
|
$this->writeShadow($objWriter, $majorGridlines);
|
||||||
$objWriter->startElement('a:glow');
|
$this->writeSoftEdge($objWriter, $majorGridlines);
|
||||||
$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
|
|
||||||
}
|
|
||||||
|
|
||||||
$objWriter->endElement(); //end effectLst
|
$objWriter->endElement(); //end effectLst
|
||||||
$objWriter->endElement(); //end spPr
|
$objWriter->endElement(); //end spPr
|
||||||
|
|
@ -704,105 +647,14 @@ class Chart extends WriterPart
|
||||||
$objWriter->startElement('c:minorGridlines');
|
$objWriter->startElement('c:minorGridlines');
|
||||||
$objWriter->startElement('c:spPr');
|
$objWriter->startElement('c:spPr');
|
||||||
|
|
||||||
if ($minorGridlines->getLineColorProperty('value') !== null) {
|
$this->writeGridlinesLn($objWriter, $minorGridlines);
|
||||||
$objWriter->startElement('a:ln');
|
|
||||||
$objWriter->writeAttribute('w', $minorGridlines->getLineStyleProperty('width'));
|
|
||||||
$objWriter->startElement('a:solidFill');
|
|
||||||
$objWriter->startElement("a:{$minorGridlines->getLineColorProperty('type')}");
|
|
||||||
$objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('value'));
|
|
||||||
$objWriter->startElement('a:alpha');
|
|
||||||
$objWriter->writeAttribute('val', $minorGridlines->getLineColorProperty('alpha'));
|
|
||||||
$objWriter->endElement(); //end alpha
|
|
||||||
$objWriter->endElement(); //end srgbClr
|
|
||||||
$objWriter->endElement(); //end solidFill
|
|
||||||
|
|
||||||
$objWriter->startElement('a:prstDash');
|
|
||||||
$objWriter->writeAttribute('val', $minorGridlines->getLineStyleProperty('dash'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
|
|
||||||
if ($minorGridlines->getLineStyleProperty('join') == 'miter') {
|
|
||||||
$objWriter->startElement('a:miter');
|
|
||||||
$objWriter->writeAttribute('lim', '800000');
|
|
||||||
$objWriter->endElement();
|
|
||||||
} else {
|
|
||||||
$objWriter->startElement('a:bevel');
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($minorGridlines->getLineStyleProperty(['arrow', 'head', 'type']) !== null) {
|
|
||||||
$objWriter->startElement('a:headEnd');
|
|
||||||
$objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'head', 'type']));
|
|
||||||
$objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('head', 'w'));
|
|
||||||
$objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('head', 'len'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($minorGridlines->getLineStyleProperty(['arrow', 'end', 'type']) !== null) {
|
|
||||||
$objWriter->startElement('a:tailEnd');
|
|
||||||
$objWriter->writeAttribute('type', $minorGridlines->getLineStyleProperty(['arrow', 'end', 'type']));
|
|
||||||
$objWriter->writeAttribute('w', $minorGridlines->getLineStyleArrowParameters('end', 'w'));
|
|
||||||
$objWriter->writeAttribute('len', $minorGridlines->getLineStyleArrowParameters('end', 'len'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
$objWriter->endElement(); //end ln
|
|
||||||
}
|
|
||||||
|
|
||||||
$objWriter->startElement('a:effectLst');
|
$objWriter->startElement('a:effectLst');
|
||||||
|
$this->writeGlow($objWriter, $minorGridlines);
|
||||||
if ($minorGridlines->getGlowSize() !== null) {
|
$this->writeShadow($objWriter, $minorGridlines);
|
||||||
$objWriter->startElement('a:glow');
|
$this->writeSoftEdge($objWriter, $minorGridlines);
|
||||||
$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
|
|
||||||
}
|
|
||||||
|
|
||||||
$objWriter->endElement(); //end effectLst
|
$objWriter->endElement(); //end effectLst
|
||||||
|
|
||||||
$objWriter->endElement(); //end spPr
|
$objWriter->endElement(); //end spPr
|
||||||
$objWriter->endElement(); //end minorGridLines
|
$objWriter->endElement(); //end minorGridLines
|
||||||
}
|
}
|
||||||
|
|
@ -851,138 +703,48 @@ class Chart extends WriterPart
|
||||||
$objWriter->writeAttribute('sourceLinked', $xAxis->getAxisNumberSourceLinked());
|
$objWriter->writeAttribute('sourceLinked', $xAxis->getAxisNumberSourceLinked());
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
||||||
$objWriter->startElement('c:majorTickMark');
|
if (!empty($xAxis->getAxisOptionsProperty('major_tick_mark'))) {
|
||||||
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_tick_mark'));
|
$objWriter->startElement('c:majorTickMark');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('major_tick_mark'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:minorTickMark');
|
if (!empty($xAxis->getAxisOptionsProperty('minor_tick_mark'))) {
|
||||||
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_tick_mark'));
|
$objWriter->startElement('c:minorTickMark');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('minor_tick_mark'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:tickLblPos');
|
if (!empty($xAxis->getAxisOptionsProperty('axis_labels'))) {
|
||||||
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('axis_labels'));
|
$objWriter->startElement('c:tickLblPos');
|
||||||
$objWriter->endElement();
|
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('axis_labels'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:spPr');
|
$objWriter->startElement('c:spPr');
|
||||||
|
|
||||||
if ($xAxis->getFillProperty('value') !== null) {
|
if (!empty($xAxis->getFillProperty('value'))) {
|
||||||
$objWriter->startElement('a:solidFill');
|
$objWriter->startElement('a:solidFill');
|
||||||
$objWriter->startElement('a:' . $xAxis->getFillProperty('type'));
|
$objWriter->startElement('a:' . $xAxis->getFillProperty('type'));
|
||||||
$objWriter->writeAttribute('val', $xAxis->getFillProperty('value'));
|
$objWriter->writeAttribute('val', $xAxis->getFillProperty('value'));
|
||||||
$objWriter->startElement('a:alpha');
|
$alpha = $xAxis->getFillProperty('alpha');
|
||||||
$objWriter->writeAttribute('val', $xAxis->getFillProperty('alpha'));
|
if (is_numeric($alpha)) {
|
||||||
$objWriter->endElement();
|
$objWriter->startElement('a:alpha');
|
||||||
|
$objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
$objWriter->startElement('a:ln');
|
$this->writeGridlinesLn($objWriter, $xAxis);
|
||||||
|
|
||||||
$objWriter->writeAttribute('w', $xAxis->getLineStyleProperty('width'));
|
|
||||||
$objWriter->writeAttribute('cap', $xAxis->getLineStyleProperty('cap'));
|
|
||||||
$objWriter->writeAttribute('cmpd', $xAxis->getLineStyleProperty('compound'));
|
|
||||||
|
|
||||||
if ($xAxis->getLineProperty('value') !== null) {
|
|
||||||
$objWriter->startElement('a:solidFill');
|
|
||||||
$objWriter->startElement('a:' . $xAxis->getLineProperty('type'));
|
|
||||||
$objWriter->writeAttribute('val', $xAxis->getLineProperty('value'));
|
|
||||||
$objWriter->startElement('a:alpha');
|
|
||||||
$objWriter->writeAttribute('val', $xAxis->getLineProperty('alpha'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
$objWriter->endElement();
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
$objWriter->startElement('a:prstDash');
|
|
||||||
$objWriter->writeAttribute('val', $xAxis->getLineStyleProperty('dash'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
|
|
||||||
if ($xAxis->getLineStyleProperty('join') == 'miter') {
|
|
||||||
$objWriter->startElement('a:miter');
|
|
||||||
$objWriter->writeAttribute('lim', '800000');
|
|
||||||
$objWriter->endElement();
|
|
||||||
} else {
|
|
||||||
$objWriter->startElement('a:bevel');
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($xAxis->getLineStyleProperty(['arrow', 'head', 'type']) !== null) {
|
|
||||||
$objWriter->startElement('a:headEnd');
|
|
||||||
$objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'head', 'type']));
|
|
||||||
$objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('head'));
|
|
||||||
$objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('head'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($xAxis->getLineStyleProperty(['arrow', 'end', 'type']) !== null) {
|
|
||||||
$objWriter->startElement('a:tailEnd');
|
|
||||||
$objWriter->writeAttribute('type', $xAxis->getLineStyleProperty(['arrow', 'end', 'type']));
|
|
||||||
$objWriter->writeAttribute('w', $xAxis->getLineStyleArrowWidth('end'));
|
|
||||||
$objWriter->writeAttribute('len', $xAxis->getLineStyleArrowLength('end'));
|
|
||||||
$objWriter->endElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
$objWriter->endElement();
|
|
||||||
|
|
||||||
$objWriter->startElement('a:effectLst');
|
$objWriter->startElement('a:effectLst');
|
||||||
|
$this->writeGlow($objWriter, $xAxis);
|
||||||
if ($xAxis->getGlowProperty('size') !== null) {
|
$this->writeShadow($objWriter, $xAxis);
|
||||||
$objWriter->startElement('a:glow');
|
$this->writeSoftEdge($objWriter, $xAxis);
|
||||||
$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();
|
|
||||||
}
|
|
||||||
|
|
||||||
$objWriter->endElement(); //effectList
|
$objWriter->endElement(); //effectList
|
||||||
|
|
||||||
$objWriter->endElement(); //end spPr
|
$objWriter->endElement(); //end spPr
|
||||||
|
|
||||||
if ($id1 !== '0') {
|
if ($id1 !== '0') {
|
||||||
|
|
@ -995,14 +757,20 @@ class Chart extends WriterPart
|
||||||
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses_value'));
|
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses_value'));
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
} else {
|
} else {
|
||||||
$objWriter->startElement('c:crosses');
|
$crosses = $xAxis->getAxisOptionsProperty('horizontal_crosses');
|
||||||
$objWriter->writeAttribute('val', $xAxis->getAxisOptionsProperty('horizontal_crosses'));
|
if ($crosses) {
|
||||||
$objWriter->endElement();
|
$objWriter->startElement('c:crosses');
|
||||||
|
$objWriter->writeAttribute('val', $crosses);
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:crossBetween');
|
$crossBetween = $xAxis->getCrossBetween();
|
||||||
$objWriter->writeAttribute('val', 'midCat');
|
if ($crossBetween !== '') {
|
||||||
$objWriter->endElement();
|
$objWriter->startElement('c:crossBetween');
|
||||||
|
$objWriter->writeAttribute('val', $crossBetween);
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
if ($xAxis->getAxisOptionsProperty('major_unit') !== null) {
|
if ($xAxis->getAxisOptionsProperty('major_unit') !== null) {
|
||||||
$objWriter->startElement('c:majorUnit');
|
$objWriter->startElement('c:majorUnit');
|
||||||
|
|
@ -1109,6 +877,9 @@ class Chart extends WriterPart
|
||||||
*/
|
*/
|
||||||
private function writePlotSeriesValuesElement(XMLWriter $objWriter, $val = 3, $fillColor = 'FF9900'): void
|
private function writePlotSeriesValuesElement(XMLWriter $objWriter, $val = 3, $fillColor = 'FF9900'): void
|
||||||
{
|
{
|
||||||
|
if ($fillColor === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$objWriter->startElement('c:dPt');
|
$objWriter->startElement('c:dPt');
|
||||||
$objWriter->startElement('c:idx');
|
$objWriter->startElement('c:idx');
|
||||||
$objWriter->writeAttribute('val', $val);
|
$objWriter->writeAttribute('val', $val);
|
||||||
|
|
@ -1120,8 +891,16 @@ class Chart extends WriterPart
|
||||||
|
|
||||||
$objWriter->startElement('c:spPr');
|
$objWriter->startElement('c:spPr');
|
||||||
$objWriter->startElement('a:solidFill');
|
$objWriter->startElement('a:solidFill');
|
||||||
$objWriter->startElement('a:srgbClr');
|
if (substr($fillColor, 0, 1) === '*') {
|
||||||
$objWriter->writeAttribute('val', $fillColor);
|
$objWriter->startElement('a:schemeClr');
|
||||||
|
$objWriter->writeAttribute('val', substr($fillColor, 1));
|
||||||
|
} elseif (substr($fillColor, 0, 1) === '/') {
|
||||||
|
$objWriter->startElement('a:prstClr');
|
||||||
|
$objWriter->writeAttribute('val', substr($fillColor, 1));
|
||||||
|
} else {
|
||||||
|
$objWriter->startElement('a:srgbClr');
|
||||||
|
$objWriter->writeAttribute('val', $fillColor);
|
||||||
|
}
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
@ -1206,7 +985,7 @@ class Chart extends WriterPart
|
||||||
$fillColorValues = $plotSeriesValues->getFillColor();
|
$fillColorValues = $plotSeriesValues->getFillColor();
|
||||||
if ($fillColorValues !== null && is_array($fillColorValues)) {
|
if ($fillColorValues !== null && is_array($fillColorValues)) {
|
||||||
foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) {
|
foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) {
|
||||||
$this->writePlotSeriesValuesElement($objWriter, $dataKey, ($fillColorValues[$dataKey] ?? 'FF9900'));
|
$this->writePlotSeriesValuesElement($objWriter, $dataKey, $fillColorValues[$dataKey] ?? '');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->writePlotSeriesValuesElement($objWriter);
|
$this->writePlotSeriesValuesElement($objWriter);
|
||||||
|
|
@ -1228,7 +1007,7 @@ class Chart extends WriterPart
|
||||||
$groupType == DataSeries::TYPE_LINECHART
|
$groupType == DataSeries::TYPE_LINECHART
|
||||||
|| $groupType == DataSeries::TYPE_STOCKCHART
|
|| $groupType == DataSeries::TYPE_STOCKCHART
|
||||||
|| ($groupType === DataSeries::TYPE_SCATTERCHART && $plotSeriesValues !== false && !$plotSeriesValues->getScatterLines())
|
|| ($groupType === DataSeries::TYPE_SCATTERCHART && $plotSeriesValues !== false && !$plotSeriesValues->getScatterLines())
|
||||||
|| ($plotSeriesValues !== false && $plotSeriesValues->getSchemeClr())
|
|| ($plotSeriesValues !== false && ($plotSeriesValues->getSchemeClr() || $plotSeriesValues->getPrstClr()))
|
||||||
) {
|
) {
|
||||||
$plotLineWidth = 12700;
|
$plotLineWidth = 12700;
|
||||||
if ($plotSeriesValues) {
|
if ($plotSeriesValues) {
|
||||||
|
|
@ -1236,10 +1015,21 @@ class Chart extends WriterPart
|
||||||
}
|
}
|
||||||
|
|
||||||
$objWriter->startElement('c:spPr');
|
$objWriter->startElement('c:spPr');
|
||||||
$schemeClr = $plotLabel ? $plotLabel->getSchemeClr() : null;
|
$schemeClr = $typeClr = '';
|
||||||
|
if ($plotLabel) {
|
||||||
|
$schemeClr = $plotLabel->getSchemeClr();
|
||||||
|
if ($schemeClr) {
|
||||||
|
$typeClr = 'schemeClr';
|
||||||
|
} else {
|
||||||
|
$schemeClr = $plotLabel->getPrstClr();
|
||||||
|
if ($schemeClr) {
|
||||||
|
$typeClr = 'prstClr';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if ($schemeClr) {
|
if ($schemeClr) {
|
||||||
$objWriter->startElement('a:solidFill');
|
$objWriter->startElement('a:solidFill');
|
||||||
$objWriter->startElement('a:schemeClr');
|
$objWriter->startElement("a:$typeClr");
|
||||||
$objWriter->writeAttribute('val', $schemeClr);
|
$objWriter->writeAttribute('val', $schemeClr);
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
|
|
@ -1658,4 +1448,169 @@ class Chart extends WriterPart
|
||||||
|
|
||||||
$objWriter->endElement();
|
$objWriter->endElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write shadow properties.
|
||||||
|
*
|
||||||
|
* @param Axis|GridLines $xAxis
|
||||||
|
*/
|
||||||
|
private function writeShadow(XMLWriter $objWriter, $xAxis): void
|
||||||
|
{
|
||||||
|
if (empty($xAxis->getShadowProperty('effect'))) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write Line Style for Gridlines.
|
||||||
|
*
|
||||||
|
* @param Axis|GridLines $gridlines
|
||||||
|
*/
|
||||||
|
private function writeGridlinesLn(XMLWriter $objWriter, $gridlines): void
|
||||||
|
{
|
||||||
|
$objWriter->startElement('a:ln');
|
||||||
|
$widthTemp = $gridlines->getLineStyleProperty('width');
|
||||||
|
if (is_numeric($widthTemp)) {
|
||||||
|
$objWriter->writeAttribute('w', Properties::pointsToXml((float) $widthTemp));
|
||||||
|
}
|
||||||
|
$this->writeNotEmpty($objWriter, 'cap', $gridlines->getLineStyleProperty('cap'));
|
||||||
|
$this->writeNotEmpty($objWriter, 'cmpd', $gridlines->getLineStyleProperty('compound'));
|
||||||
|
if (!empty($gridlines->getLineColorProperty('value'))) {
|
||||||
|
$objWriter->startElement('a:solidFill');
|
||||||
|
$objWriter->startElement("a:{$gridlines->getLineColorProperty('type')}");
|
||||||
|
$objWriter->writeAttribute('val', (string) $gridlines->getLineColorProperty('value'));
|
||||||
|
$alpha = $gridlines->getLineColorProperty('alpha');
|
||||||
|
if (is_numeric($alpha)) {
|
||||||
|
$objWriter->startElement('a:alpha');
|
||||||
|
$objWriter->writeAttribute('val', Properties::alphaToXml((int) $alpha));
|
||||||
|
$objWriter->endElement(); // alpha
|
||||||
|
}
|
||||||
|
$objWriter->endElement(); //end srgbClr
|
||||||
|
$objWriter->endElement(); //end solidFill
|
||||||
|
}
|
||||||
|
|
||||||
|
$dash = $gridlines->getLineStyleProperty('dash');
|
||||||
|
if (!empty($dash)) {
|
||||||
|
$objWriter->startElement('a:prstDash');
|
||||||
|
$this->writeNotEmpty($objWriter, 'val', $dash);
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($gridlines->getLineStyleProperty('join') === 'miter') {
|
||||||
|
$objWriter->startElement('a:miter');
|
||||||
|
$objWriter->writeAttribute('lim', '800000');
|
||||||
|
$objWriter->endElement();
|
||||||
|
} elseif ($gridlines->getLineStyleProperty('join') === 'bevel') {
|
||||||
|
$objWriter->startElement('a:bevel');
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($gridlines->getLineStyleProperty(['arrow', 'head', 'type'])) {
|
||||||
|
$objWriter->startElement('a:headEnd');
|
||||||
|
$objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'head', 'type']));
|
||||||
|
$this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowParameters('head', 'w'));
|
||||||
|
$this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowParameters('head', 'len'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($gridlines->getLineStyleProperty(['arrow', 'end', 'type'])) {
|
||||||
|
$objWriter->startElement('a:tailEnd');
|
||||||
|
$objWriter->writeAttribute('type', $gridlines->getLineStyleProperty(['arrow', 'end', 'type']));
|
||||||
|
$this->writeNotEmpty($objWriter, 'w', $gridlines->getLineStyleArrowParameters('end', 'w'));
|
||||||
|
$this->writeNotEmpty($objWriter, 'len', $gridlines->getLineStyleArrowParameters('end', 'len'));
|
||||||
|
$objWriter->endElement();
|
||||||
|
}
|
||||||
|
$objWriter->endElement(); //end ln
|
||||||
|
}
|
||||||
|
|
||||||
|
private function writeNotEmpty(XMLWriter $objWriter, string $name, ?string $value): void
|
||||||
|
{
|
||||||
|
if ($value !== null && $value !== '') {
|
||||||
|
$objWriter->writeAttribute($name, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ class MergedCellTest extends TestCase
|
||||||
$sheet->mergeCells($range);
|
$sheet->mergeCells($range);
|
||||||
self::fail("Expected invalid merge range $range");
|
self::fail("Expected invalid merge range $range");
|
||||||
} catch (SpreadException $e) {
|
} 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();
|
$spreadSheet = new Spreadsheet();
|
||||||
|
|
||||||
$dataSheet = $spreadSheet->getActiveSheet();
|
$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, 'Invalid');
|
||||||
$this->setBadRange($dataSheet, '1');
|
$this->setBadRange($dataSheet, '1');
|
||||||
$this->setBadRange($dataSheet, 'C');
|
$this->setBadRange($dataSheet, 'C');
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||||
|
|
@ -106,21 +106,21 @@ class AxisGlowTest extends AbstractFunctional
|
||||||
);
|
);
|
||||||
$yAxis = $chart->getChartAxisY();
|
$yAxis = $chart->getChartAxisY();
|
||||||
$xAxis = $chart->getChartAxisX();
|
$xAxis = $chart->getChartAxisX();
|
||||||
$yAxis->setGlowProperties(10, 'FFFF00', 30, Properties::EXCEL_COLOR_TYPE_ARGB);
|
$yGlowSize = 10.0;
|
||||||
$expectedSize = 127000.0;
|
$yAxis->setGlowProperties($yGlowSize, 'FFFF00', 30, Properties::EXCEL_COLOR_TYPE_ARGB);
|
||||||
$expectedGlowColor = [
|
$expectedGlowColor = [
|
||||||
'type' => 'srgbClr',
|
'type' => 'srgbClr',
|
||||||
'value' => 'FFFF00',
|
'value' => 'FFFF00',
|
||||||
'alpha' => '70000',
|
'alpha' => 30,
|
||||||
];
|
];
|
||||||
$yAxis->setSoftEdges(2.5);
|
$softEdgesY = 2.5;
|
||||||
$xAxis->setSoftEdges(5);
|
$yAxis->setSoftEdges($softEdgesY);
|
||||||
$expectedSoftEdgesY = '31750';
|
$softEdgesX = 5;
|
||||||
$expectedSoftEdgesX = '63500';
|
$xAxis->setSoftEdges($softEdgesX);
|
||||||
self::assertEquals($expectedSize, $yAxis->getGlowProperty('size'));
|
self::assertEquals($yGlowSize, $yAxis->getGlowProperty('size'));
|
||||||
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
|
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
|
||||||
self::assertEquals($expectedSoftEdgesY, $yAxis->getSoftEdgesSize());
|
self::assertEquals($softEdgesY, $yAxis->getSoftEdgesSize());
|
||||||
self::assertEquals($expectedSoftEdgesX, $xAxis->getSoftEdgesSize());
|
self::assertEquals($softEdgesX, $xAxis->getSoftEdgesSize());
|
||||||
|
|
||||||
// Set the position where the chart should appear in the worksheet
|
// Set the position where the chart should appear in the worksheet
|
||||||
$chart->setTopLeftPosition('A7');
|
$chart->setTopLeftPosition('A7');
|
||||||
|
|
@ -142,9 +142,9 @@ class AxisGlowTest extends AbstractFunctional
|
||||||
$chart2 = $charts2[0];
|
$chart2 = $charts2[0];
|
||||||
self::assertNotNull($chart2);
|
self::assertNotNull($chart2);
|
||||||
$yAxis2 = $chart2->getChartAxisY();
|
$yAxis2 = $chart2->getChartAxisY();
|
||||||
self::assertEquals($expectedSize, $yAxis2->getGlowProperty('size'));
|
self::assertEquals($yGlowSize, $yAxis2->getGlowProperty('size'));
|
||||||
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
|
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
|
||||||
self::assertEquals($expectedSoftEdgesY, $yAxis2->getSoftEdgesSize());
|
self::assertEquals($softEdgesY, $yAxis2->getSoftEdgesSize());
|
||||||
$xAxis2 = $chart2->getChartAxisX();
|
$xAxis2 = $chart2->getChartAxisX();
|
||||||
self::assertNull($xAxis2->getGlowProperty('size'));
|
self::assertNull($xAxis2->getGlowProperty('size'));
|
||||||
$reloadedSpreadsheet->disconnectWorksheets();
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
|
@ -229,14 +229,14 @@ class AxisGlowTest extends AbstractFunctional
|
||||||
$yAxisLabel // yAxisLabel
|
$yAxisLabel // yAxisLabel
|
||||||
);
|
);
|
||||||
$yAxis = $chart->getChartAxisX(); // deliberate
|
$yAxis = $chart->getChartAxisX(); // deliberate
|
||||||
$yAxis->setGlowProperties(20, 'accent1', 20, Properties::EXCEL_COLOR_TYPE_SCHEME);
|
$yGlowSize = 20.0;
|
||||||
$expectedSize = 254000.0;
|
$yAxis->setGlowProperties($yGlowSize, 'accent1', 20, Properties::EXCEL_COLOR_TYPE_SCHEME);
|
||||||
$expectedGlowColor = [
|
$expectedGlowColor = [
|
||||||
'type' => 'schemeClr',
|
'type' => 'schemeClr',
|
||||||
'value' => 'accent1',
|
'value' => 'accent1',
|
||||||
'alpha' => '80000',
|
'alpha' => 20,
|
||||||
];
|
];
|
||||||
self::assertEquals($expectedSize, $yAxis->getGlowProperty('size'));
|
self::assertEquals($yGlowSize, $yAxis->getGlowProperty('size'));
|
||||||
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
|
self::assertEquals($expectedGlowColor, $yAxis->getGlowProperty('color'));
|
||||||
|
|
||||||
// Set the position where the chart should appear in the worksheet
|
// Set the position where the chart should appear in the worksheet
|
||||||
|
|
@ -259,7 +259,7 @@ class AxisGlowTest extends AbstractFunctional
|
||||||
$chart2 = $charts2[0];
|
$chart2 = $charts2[0];
|
||||||
self::assertNotNull($chart2);
|
self::assertNotNull($chart2);
|
||||||
$yAxis2 = $chart2->getChartAxisX(); // deliberate
|
$yAxis2 = $chart2->getChartAxisX(); // deliberate
|
||||||
self::assertEquals($expectedSize, $yAxis2->getGlowProperty('size'));
|
self::assertEquals($yGlowSize, $yAxis2->getGlowProperty('size'));
|
||||||
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
|
self::assertEquals($expectedGlowColor, $yAxis2->getGlowProperty('color'));
|
||||||
$xAxis2 = $chart2->getChartAxisY(); // deliberate
|
$xAxis2 = $chart2->getChartAxisY(); // deliberate
|
||||||
self::assertNull($xAxis2->getGlowProperty('size'));
|
self::assertNull($xAxis2->getGlowProperty('size'));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,226 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\Axis;
|
||||||
|
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 AxisPropertiesTest extends AbstractFunctional
|
||||||
|
{
|
||||||
|
public function readCharts(XlsxReader $reader): void
|
||||||
|
{
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeCharts(XlsxWriter $writer): void
|
||||||
|
{
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAxisProperties(): 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)');
|
||||||
|
$xAxis = new Axis();
|
||||||
|
$xAxis->setFillParameters('FF0000', null, 'srgbClr');
|
||||||
|
self::assertSame('FF0000', $xAxis->getFillProperty('value'));
|
||||||
|
self::assertSame('', $xAxis->getFillProperty('alpha'));
|
||||||
|
self::assertSame('srgbClr', $xAxis->getFillProperty('type'));
|
||||||
|
|
||||||
|
$xAxis->setAxisOptionsProperties(
|
||||||
|
Properties::AXIS_LABELS_HIGH, // axisLabels,
|
||||||
|
null, // $horizontalCrossesValue,
|
||||||
|
Properties::HORIZONTAL_CROSSES_MAXIMUM, //horizontalCrosses
|
||||||
|
Properties::ORIENTATION_REVERSED, //axisOrientation
|
||||||
|
Properties::TICK_MARK_INSIDE, //majorTmt
|
||||||
|
Properties::TICK_MARK_OUTSIDE, //minorTmt
|
||||||
|
'8', //minimum
|
||||||
|
'68', //maximum
|
||||||
|
'20', //majorUnit
|
||||||
|
'5' //minorUnit
|
||||||
|
);
|
||||||
|
self::assertSame(Properties::AXIS_LABELS_HIGH, $xAxis->getAxisOptionsProperty('axis_labels'));
|
||||||
|
self::assertNull($xAxis->getAxisOptionsProperty('horizontal_crosses_value'));
|
||||||
|
self::assertSame(Properties::HORIZONTAL_CROSSES_MAXIMUM, $xAxis->getAxisOptionsProperty('horizontal_crosses'));
|
||||||
|
self::assertSame(Properties::ORIENTATION_REVERSED, $xAxis->getAxisOptionsProperty('orientation'));
|
||||||
|
self::assertSame(Properties::TICK_MARK_INSIDE, $xAxis->getAxisOptionsProperty('major_tick_mark'));
|
||||||
|
self::assertSame(Properties::TICK_MARK_OUTSIDE, $xAxis->getAxisOptionsProperty('minor_tick_mark'));
|
||||||
|
self::assertSame('8', $xAxis->getAxisOptionsProperty('minimum'));
|
||||||
|
self::assertSame('68', $xAxis->getAxisOptionsProperty('maximum'));
|
||||||
|
self::assertSame('20', $xAxis->getAxisOptionsProperty('major_unit'));
|
||||||
|
self::assertSame('5', $xAxis->getAxisOptionsProperty('minor_unit'));
|
||||||
|
|
||||||
|
$yAxis = new Axis();
|
||||||
|
$yAxis->setFillParameters('accent1', 30, 'schemeClr');
|
||||||
|
self::assertSame('accent1', $yAxis->getFillProperty('value'));
|
||||||
|
self::assertSame('30', $yAxis->getFillProperty('alpha'));
|
||||||
|
self::assertSame('schemeClr', $yAxis->getFillProperty('type'));
|
||||||
|
|
||||||
|
// 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, // xAxis
|
||||||
|
$yAxis, // yAxis
|
||||||
|
null, //majorGridlines,
|
||||||
|
null // minorGridlines
|
||||||
|
);
|
||||||
|
$xAxis2 = $chart->getChartAxisX();
|
||||||
|
self::assertSame('FF0000', $xAxis2->getFillProperty('value'));
|
||||||
|
self::assertSame('', $xAxis2->getFillProperty('alpha'));
|
||||||
|
self::assertSame('srgbClr', $xAxis2->getFillProperty('type'));
|
||||||
|
|
||||||
|
self::assertSame(Properties::AXIS_LABELS_HIGH, $xAxis2->getAxisOptionsProperty('axis_labels'));
|
||||||
|
self::assertNull($xAxis2->getAxisOptionsProperty('horizontal_crosses_value'));
|
||||||
|
self::assertSame(Properties::HORIZONTAL_CROSSES_MAXIMUM, $xAxis2->getAxisOptionsProperty('horizontal_crosses'));
|
||||||
|
self::assertSame(Properties::ORIENTATION_REVERSED, $xAxis2->getAxisOptionsProperty('orientation'));
|
||||||
|
self::assertSame(Properties::TICK_MARK_INSIDE, $xAxis2->getAxisOptionsProperty('major_tick_mark'));
|
||||||
|
self::assertSame(Properties::TICK_MARK_OUTSIDE, $xAxis2->getAxisOptionsProperty('minor_tick_mark'));
|
||||||
|
self::assertSame('8', $xAxis2->getAxisOptionsProperty('minimum'));
|
||||||
|
self::assertSame('68', $xAxis2->getAxisOptionsProperty('maximum'));
|
||||||
|
self::assertSame('20', $xAxis2->getAxisOptionsProperty('major_unit'));
|
||||||
|
self::assertSame('5', $xAxis2->getAxisOptionsProperty('minor_unit'));
|
||||||
|
|
||||||
|
$yAxis2 = $chart->getChartAxisY();
|
||||||
|
self::assertSame('accent1', $yAxis2->getFillProperty('value'));
|
||||||
|
self::assertSame('30', $yAxis2->getFillProperty('alpha'));
|
||||||
|
self::assertSame('schemeClr', $yAxis2->getFillProperty('type'));
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
$xAxis3 = $chart2->getChartAxisX();
|
||||||
|
self::assertSame('FF0000', $xAxis3->getFillProperty('value'));
|
||||||
|
self::assertSame('', $xAxis3->getFillProperty('alpha'));
|
||||||
|
self::assertSame('srgbClr', $xAxis3->getFillProperty('type'));
|
||||||
|
|
||||||
|
self::assertSame(Properties::AXIS_LABELS_HIGH, $xAxis3->getAxisOptionsProperty('axis_labels'));
|
||||||
|
self::assertSame(Properties::TICK_MARK_INSIDE, $xAxis3->getAxisOptionsProperty('major_tick_mark'));
|
||||||
|
self::assertSame(Properties::TICK_MARK_OUTSIDE, $xAxis3->getAxisOptionsProperty('minor_tick_mark'));
|
||||||
|
self::assertNull($xAxis3->getAxisOptionsProperty('horizontal_crosses_value'));
|
||||||
|
self::assertSame(Properties::HORIZONTAL_CROSSES_MAXIMUM, $xAxis3->getAxisOptionsProperty('horizontal_crosses'));
|
||||||
|
self::assertSame(Properties::ORIENTATION_REVERSED, $xAxis3->getAxisOptionsProperty('orientation'));
|
||||||
|
self::assertSame('8', $xAxis3->getAxisOptionsProperty('minimum'));
|
||||||
|
self::assertSame('68', $xAxis3->getAxisOptionsProperty('maximum'));
|
||||||
|
self::assertSame('20', $xAxis3->getAxisOptionsProperty('major_unit'));
|
||||||
|
self::assertSame('5', $xAxis3->getAxisOptionsProperty('minor_unit'));
|
||||||
|
|
||||||
|
$yAxis3 = $chart2->getChartAxisY();
|
||||||
|
self::assertSame('accent1', $yAxis3->getFillProperty('value'));
|
||||||
|
self::assertSame('30', $yAxis3->getFillProperty('alpha'));
|
||||||
|
self::assertSame('schemeClr', $yAxis3->getFillProperty('type'));
|
||||||
|
|
||||||
|
$xAxis3->setAxisOrientation(Properties::ORIENTATION_NORMAL);
|
||||||
|
self::assertSame(Properties::ORIENTATION_NORMAL, $xAxis3->getAxisOptionsProperty('orientation'));
|
||||||
|
$xAxis3->setAxisOptionsProperties(
|
||||||
|
Properties::AXIS_LABELS_HIGH, // axisLabels,
|
||||||
|
'5' // $horizontalCrossesValue,
|
||||||
|
);
|
||||||
|
self::assertSame('5', $xAxis3->getAxisOptionsProperty('horizontal_crosses_value'));
|
||||||
|
|
||||||
|
$yAxis3->setLineColorProperties('0000FF', null, 'srgbClr');
|
||||||
|
self::assertSame('0000FF', $yAxis3->getLineProperty('value'));
|
||||||
|
self::assertNull($yAxis3->getLineProperty('alpha'));
|
||||||
|
self::assertSame('srgbClr', $yAxis3->getLineProperty('type'));
|
||||||
|
$yAxis3->setAxisNumberProperties(Properties::FORMAT_CODE_GENERAL);
|
||||||
|
self::assertFalse($yAxis3->getAxisIsNumericFormat());
|
||||||
|
$yAxis3->setAxisNumberProperties(Properties::FORMAT_CODE_NUMBER);
|
||||||
|
self::assertTrue($yAxis3->getAxisIsNumericFormat());
|
||||||
|
|
||||||
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Axis;
|
use PhpOffice\PhpSpreadsheet\Chart\Axis;
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Properties;
|
use PhpOffice\PhpSpreadsheet\Chart\Properties;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
|
@ -13,17 +12,6 @@ class Charts32XmlTest extends TestCase
|
||||||
// These tests can only be performed by examining xml.
|
// These tests can only be performed by examining xml.
|
||||||
private const DIRECTORY = 'samples' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR;
|
private const DIRECTORY = 'samples' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $outputFileName = '';
|
|
||||||
|
|
||||||
protected function tearDown(): void
|
|
||||||
{
|
|
||||||
if ($this->outputFileName !== '') {
|
|
||||||
unlink($this->outputFileName);
|
|
||||||
$this->outputFileName = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider providerScatterCharts
|
* @dataProvider providerScatterCharts
|
||||||
*/
|
*/
|
||||||
|
|
@ -33,25 +21,21 @@ class Charts32XmlTest extends TestCase
|
||||||
$reader = new XlsxReader();
|
$reader = new XlsxReader();
|
||||||
$reader->setIncludeCharts(true);
|
$reader->setIncludeCharts(true);
|
||||||
$spreadsheet = $reader->load($file);
|
$spreadsheet = $reader->load($file);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$charts = $sheet->getChartCollection();
|
||||||
|
self::assertCount(1, $charts);
|
||||||
|
$chart = $charts[0];
|
||||||
|
self::assertNotNull($chart);
|
||||||
|
|
||||||
$writer = new XlsxWriter($spreadsheet);
|
$writer = new XlsxWriter($spreadsheet);
|
||||||
$writer->setIncludeCharts(true);
|
$writer->setIncludeCharts(true);
|
||||||
$this->outputFileName = File::temporaryFilename();
|
$writerChart = new XlsxWriter\Chart($writer);
|
||||||
$writer->save($this->outputFileName);
|
$data = $writerChart->writeChart($chart);
|
||||||
$spreadsheet->disconnectWorksheets();
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
$file = 'zip://';
|
self::assertSame(1, substr_count($data, '<c:scatterStyle val='));
|
||||||
$file .= $this->outputFileName;
|
self::assertSame($expectedCount ? 1 : 0, substr_count($data, '<c:scatterStyle val="smoothMarker"/>'));
|
||||||
$file .= '#xl/charts/chart2.xml';
|
self::assertSame($expectedCount, substr_count($data, '<c:smooth val="1"/>'));
|
||||||
$data = file_get_contents($file);
|
|
||||||
// confirm that file contains expected tags
|
|
||||||
if ($data === false) {
|
|
||||||
self::fail('Unable to read file');
|
|
||||||
} else {
|
|
||||||
self::assertSame(1, substr_count($data, '<c:scatterStyle val='));
|
|
||||||
self::assertSame($expectedCount ? 1 : 0, substr_count($data, '<c:scatterStyle val="smoothMarker"/>'));
|
|
||||||
self::assertSame($expectedCount, substr_count($data, '<c:smooth val="1"/>'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providerScatterCharts(): array
|
public function providerScatterCharts(): array
|
||||||
|
|
@ -69,23 +53,20 @@ class Charts32XmlTest extends TestCase
|
||||||
$reader = new XlsxReader();
|
$reader = new XlsxReader();
|
||||||
$reader->setIncludeCharts(true);
|
$reader->setIncludeCharts(true);
|
||||||
$spreadsheet = $reader->load($file);
|
$spreadsheet = $reader->load($file);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$charts = $sheet->getChartCollection();
|
||||||
|
self::assertCount(1, $charts);
|
||||||
|
$chart = $charts[0];
|
||||||
|
self::assertNotNull($chart);
|
||||||
|
|
||||||
$writer = new XlsxWriter($spreadsheet);
|
$writer = new XlsxWriter($spreadsheet);
|
||||||
$writer->setIncludeCharts(true);
|
$writer->setIncludeCharts(true);
|
||||||
$this->outputFileName = File::temporaryFilename();
|
$writerChart = new XlsxWriter\Chart($writer);
|
||||||
$writer->save($this->outputFileName);
|
$data = $writerChart->writeChart($chart);
|
||||||
$spreadsheet->disconnectWorksheets();
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
$file = 'zip://';
|
|
||||||
$file .= $this->outputFileName;
|
|
||||||
$file .= '#xl/charts/chart1.xml';
|
|
||||||
$data = file_get_contents($file);
|
|
||||||
// confirm that file contains expected tags
|
// confirm that file contains expected tags
|
||||||
if ($data === false) {
|
self::assertSame(0, substr_count($data, '<c:cat>'));
|
||||||
self::fail('Unable to read file');
|
|
||||||
} else {
|
|
||||||
self::assertSame(0, substr_count($data, '<c:cat>'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,18 +97,11 @@ class Charts32XmlTest extends TestCase
|
||||||
|
|
||||||
$writer = new XlsxWriter($spreadsheet);
|
$writer = new XlsxWriter($spreadsheet);
|
||||||
$writer->setIncludeCharts(true);
|
$writer->setIncludeCharts(true);
|
||||||
$this->outputFileName = File::temporaryFilename();
|
$writerChart = new XlsxWriter\Chart($writer);
|
||||||
$writer->save($this->outputFileName);
|
$data = $writerChart->writeChart($chart);
|
||||||
$spreadsheet->disconnectWorksheets();
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
$file = 'zip://';
|
if ($numeric === true) {
|
||||||
$file .= $this->outputFileName;
|
|
||||||
$file .= '#xl/charts/chart2.xml';
|
|
||||||
$data = file_get_contents($file);
|
|
||||||
// confirm that file contains expected tags
|
|
||||||
if ($data === false) {
|
|
||||||
self::fail('Unable to read file');
|
|
||||||
} elseif ($numeric === true) {
|
|
||||||
self::assertSame(0, substr_count($data, '<c:catAx>'));
|
self::assertSame(0, substr_count($data, '<c:catAx>'));
|
||||||
self::assertSame(2, substr_count($data, '<c:valAx>'));
|
self::assertSame(2, substr_count($data, '<c:valAx>'));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -144,4 +118,31 @@ class Charts32XmlTest extends TestCase
|
||||||
[null],
|
[null],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAreaPrstClr(): void
|
||||||
|
{
|
||||||
|
$file = self::DIRECTORY . '32readwriteAreaChart4.xlsx';
|
||||||
|
$reader = new XlsxReader();
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
$spreadsheet = $reader->load($file);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$charts = $sheet->getChartCollection();
|
||||||
|
self::assertCount(1, $charts);
|
||||||
|
$chart = $charts[0];
|
||||||
|
self::assertNotNull($chart);
|
||||||
|
|
||||||
|
$writer = new XlsxWriter($spreadsheet);
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
$writerChart = new XlsxWriter\Chart($writer);
|
||||||
|
$data = $writerChart->writeChart($chart);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
|
||||||
|
self::assertSame(
|
||||||
|
1,
|
||||||
|
substr_count(
|
||||||
|
$data,
|
||||||
|
'</c:tx><c:spPr><a:solidFill><a:prstClr val="red"/>'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
|
namespace PhpOffice\PhpSpreadsheetTests\Chart;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
|
@ -0,0 +1,215 @@
|
||||||
|
<?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 GridlinesLineStyleTest extends AbstractFunctional
|
||||||
|
{
|
||||||
|
public function readCharts(XlsxReader $reader): void
|
||||||
|
{
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeCharts(XlsxWriter $writer): void
|
||||||
|
{
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLineStyles(): 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();
|
||||||
|
$width = 2;
|
||||||
|
$compound = Properties::LINE_STYLE_COMPOUND_THICKTHIN;
|
||||||
|
$dash = Properties::LINE_STYLE_DASH_ROUND_DOT;
|
||||||
|
$cap = Properties::LINE_STYLE_CAP_ROUND;
|
||||||
|
$join = Properties::LINE_STYLE_JOIN_MITER;
|
||||||
|
$headArrowType = Properties::LINE_STYLE_ARROW_TYPE_DIAMOND;
|
||||||
|
$headArrowSize = (string) Properties::LINE_STYLE_ARROW_SIZE_2;
|
||||||
|
$endArrowType = Properties::LINE_STYLE_ARROW_TYPE_OVAL;
|
||||||
|
$endArrowSize = (string) Properties::LINE_STYLE_ARROW_SIZE_3;
|
||||||
|
$majorGridlines->setLineStyleProperties(
|
||||||
|
$width,
|
||||||
|
$compound,
|
||||||
|
$dash,
|
||||||
|
$cap,
|
||||||
|
$join,
|
||||||
|
$headArrowType,
|
||||||
|
$headArrowSize,
|
||||||
|
$endArrowType,
|
||||||
|
$endArrowSize
|
||||||
|
);
|
||||||
|
$minorGridlines = new GridLines();
|
||||||
|
$minorGridlines->setLineColorProperties('00FF00', 30, 'srgbClr');
|
||||||
|
|
||||||
|
self::assertEquals($width, $majorGridlines->getLineStyleProperty('width'));
|
||||||
|
self::assertEquals($compound, $majorGridlines->getLineStyleProperty('compound'));
|
||||||
|
self::assertEquals($dash, $majorGridlines->getLineStyleProperty('dash'));
|
||||||
|
self::assertEquals($cap, $majorGridlines->getLineStyleProperty('cap'));
|
||||||
|
self::assertEquals($join, $majorGridlines->getLineStyleProperty('join'));
|
||||||
|
self::assertEquals($headArrowType, $majorGridlines->getLineStyleProperty(['arrow', 'head', 'type']));
|
||||||
|
self::assertEquals($headArrowSize, $majorGridlines->getLineStyleProperty(['arrow', 'head', 'size']));
|
||||||
|
self::assertEquals($endArrowType, $majorGridlines->getLineStyleProperty(['arrow', 'end', 'type']));
|
||||||
|
self::assertEquals($endArrowSize, $majorGridlines->getLineStyleProperty(['arrow', 'end', 'size']));
|
||||||
|
self::assertEquals('sm', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'w']));
|
||||||
|
self::assertEquals('med', $majorGridlines->getLineStyleProperty(['arrow', 'head', 'len']));
|
||||||
|
self::assertEquals('sm', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'w']));
|
||||||
|
self::assertEquals('lg', $majorGridlines->getLineStyleProperty(['arrow', 'end', 'len']));
|
||||||
|
self::assertEquals('sm', $majorGridlines->getLineStyleArrowWidth('end'));
|
||||||
|
self::assertEquals('lg', $majorGridlines->getLineStyleArrowLength('end'));
|
||||||
|
self::assertEquals('lg', $majorGridlines->getLineStyleArrowParameters('end', 'len'));
|
||||||
|
|
||||||
|
self::assertSame('00FF00', $minorGridlines->getLineColorProperty('value'));
|
||||||
|
self::assertSame(30, $minorGridlines->getLineColorProperty('alpha'));
|
||||||
|
self::assertSame('srgbClr', $minorGridlines->getLineColorProperty('type'));
|
||||||
|
|
||||||
|
// 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 // minorGridlines
|
||||||
|
);
|
||||||
|
$majorGridlines2 = $chart->getMajorGridlines();
|
||||||
|
self::assertEquals($width, $majorGridlines2->getLineStyleProperty('width'));
|
||||||
|
self::assertEquals($compound, $majorGridlines2->getLineStyleProperty('compound'));
|
||||||
|
self::assertEquals($dash, $majorGridlines2->getLineStyleProperty('dash'));
|
||||||
|
self::assertEquals($cap, $majorGridlines2->getLineStyleProperty('cap'));
|
||||||
|
self::assertEquals($join, $majorGridlines2->getLineStyleProperty('join'));
|
||||||
|
self::assertEquals($headArrowType, $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'type']));
|
||||||
|
self::assertEquals($headArrowSize, $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'size']));
|
||||||
|
self::assertEquals($endArrowType, $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'type']));
|
||||||
|
self::assertEquals($endArrowSize, $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'size']));
|
||||||
|
self::assertEquals('sm', $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'w']));
|
||||||
|
self::assertEquals('med', $majorGridlines2->getLineStyleProperty(['arrow', 'head', 'len']));
|
||||||
|
self::assertEquals('sm', $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'w']));
|
||||||
|
self::assertEquals('lg', $majorGridlines2->getLineStyleProperty(['arrow', 'end', 'len']));
|
||||||
|
|
||||||
|
$minorGridlines2 = $chart->getMinorGridlines();
|
||||||
|
self::assertSame('00FF00', $minorGridlines2->getLineColorProperty('value'));
|
||||||
|
self::assertSame(30, $minorGridlines2->getLineColorProperty('alpha'));
|
||||||
|
self::assertSame('srgbClr', $minorGridlines2->getLineColorProperty('type'));
|
||||||
|
|
||||||
|
// 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($width, $majorGridlines3->getLineStyleProperty('width'));
|
||||||
|
self::assertEquals($compound, $majorGridlines3->getLineStyleProperty('compound'));
|
||||||
|
self::assertEquals($dash, $majorGridlines3->getLineStyleProperty('dash'));
|
||||||
|
self::assertEquals($cap, $majorGridlines3->getLineStyleProperty('cap'));
|
||||||
|
self::assertEquals($join, $majorGridlines3->getLineStyleProperty('join'));
|
||||||
|
self::assertEquals($headArrowType, $majorGridlines3->getLineStyleProperty(['arrow', 'head', 'type']));
|
||||||
|
self::assertEquals($endArrowType, $majorGridlines3->getLineStyleProperty(['arrow', 'end', 'type']));
|
||||||
|
self::assertEquals('sm', $majorGridlines3->getLineStyleProperty(['arrow', 'head', 'w']));
|
||||||
|
self::assertEquals('med', $majorGridlines3->getLineStyleProperty(['arrow', 'head', 'len']));
|
||||||
|
self::assertEquals('sm', $majorGridlines3->getLineStyleProperty(['arrow', 'end', 'w']));
|
||||||
|
self::assertEquals('lg', $majorGridlines3->getLineStyleProperty(['arrow', 'end', 'len']));
|
||||||
|
|
||||||
|
$minorGridlines3 = $chart2->getMinorGridlines();
|
||||||
|
self::assertSame('00FF00', $minorGridlines3->getLineColorProperty('value'));
|
||||||
|
self::assertSame(30, $minorGridlines3->getLineColorProperty('alpha'));
|
||||||
|
self::assertSame('srgbClr', $minorGridlines3->getLineColorProperty('type'));
|
||||||
|
|
||||||
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||||
|
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 PieFillTest extends AbstractFunctional
|
||||||
|
{
|
||||||
|
public function readCharts(XlsxReader $reader): void
|
||||||
|
{
|
||||||
|
$reader->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeCharts(XlsxWriter $writer): void
|
||||||
|
{
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPieFill(): 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],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
// Custom colors for dataSeries (gray, blue, red, orange)
|
||||||
|
$colors = [
|
||||||
|
'cccccc',
|
||||||
|
'*accent1', // use schemeClr, was '00abb8',
|
||||||
|
'/green', // use prstClr, was 'b8292f',
|
||||||
|
'eb8500',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 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
|
||||||
|
$dataSeriesLabels1 = [
|
||||||
|
new DataSeriesValues(
|
||||||
|
DataSeriesValues::DATASERIES_TYPE_STRING,
|
||||||
|
'Worksheet!$C$1',
|
||||||
|
null,
|
||||||
|
1
|
||||||
|
), // 2011
|
||||||
|
];
|
||||||
|
// Set the X-Axis Labels
|
||||||
|
// Datatype
|
||||||
|
// Cell reference for data
|
||||||
|
// Format Code
|
||||||
|
// Number of datapoints in series
|
||||||
|
// Data values
|
||||||
|
// Data Marker
|
||||||
|
$xAxisTickValues1 = [
|
||||||
|
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
|
||||||
|
// Custom Colors
|
||||||
|
$dataSeriesValues1Element = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4);
|
||||||
|
$dataSeriesValues1Element->setFillColor($colors);
|
||||||
|
$dataSeriesValues1 = [$dataSeriesValues1Element];
|
||||||
|
|
||||||
|
// Build the dataseries
|
||||||
|
$series1 = new DataSeries(
|
||||||
|
DataSeries::TYPE_PIECHART, // plotType
|
||||||
|
null, // plotGrouping (Pie charts don't have any grouping)
|
||||||
|
range(0, count($dataSeriesValues1) - 1), // plotOrder
|
||||||
|
$dataSeriesLabels1, // plotLabel
|
||||||
|
$xAxisTickValues1, // plotCategory
|
||||||
|
$dataSeriesValues1 // plotValues
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set up a layout object for the Pie chart
|
||||||
|
$layout1 = new Layout();
|
||||||
|
$layout1->setShowVal(true);
|
||||||
|
$layout1->setShowPercent(true);
|
||||||
|
|
||||||
|
// Set the series in the plot area
|
||||||
|
$plotArea1 = new PlotArea($layout1, [$series1]);
|
||||||
|
// Set the chart legend
|
||||||
|
$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||||
|
|
||||||
|
$title1 = new Title('Test Pie Chart');
|
||||||
|
|
||||||
|
// Create the chart
|
||||||
|
$chart1 = new Chart(
|
||||||
|
'chart1', // name
|
||||||
|
$title1, // title
|
||||||
|
$legend1, // legend
|
||||||
|
$plotArea1, // plotArea
|
||||||
|
true, // plotVisibleOnly
|
||||||
|
DataSeries::EMPTY_AS_GAP, // displayBlanksAs
|
||||||
|
null, // xAxisLabel
|
||||||
|
null // no Y-Axis for Pie Chart
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set the position where the chart should appear in the worksheet
|
||||||
|
$chart1->setTopLeftPosition('A7');
|
||||||
|
$chart1->setBottomRightPosition('H20');
|
||||||
|
|
||||||
|
// Add the chart to the worksheet
|
||||||
|
$worksheet->addChart($chart1);
|
||||||
|
|
||||||
|
/** @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);
|
||||||
|
$plotArea2 = $chart2->getPlotArea();
|
||||||
|
$dataSeries2 = $plotArea2->getPlotGroup();
|
||||||
|
self::assertCount(1, $dataSeries2);
|
||||||
|
$plotValues = $dataSeries2[0]->getPlotValues();
|
||||||
|
self::assertCount(1, $plotValues);
|
||||||
|
$fillColors = $plotValues[0]->getFillColor();
|
||||||
|
self::assertSame($colors, $fillColors);
|
||||||
|
|
||||||
|
$writer = new XlsxWriter($reloadedSpreadsheet);
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
|
$writerChart = new XlsxWriter\Chart($writer);
|
||||||
|
$data = $writerChart->writeChart($chart2);
|
||||||
|
self::assertSame(1, substr_count($data, '<a:srgbClr val="cccccc"/>'));
|
||||||
|
self::assertSame(1, substr_count($data, '<a:schemeClr val="accent1"/>'));
|
||||||
|
self::assertSame(1, substr_count($data, '<a:prstClr val="green"/>'));
|
||||||
|
self::assertSame(1, substr_count($data, '<a:srgbClr val="eb8500"/>'));
|
||||||
|
self::assertSame(4, substr_count($data, '<c:dPt>'));
|
||||||
|
|
||||||
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ namespace PhpOffice\PhpSpreadsheetTests;
|
||||||
use PhpOffice\PhpSpreadsheet\Comment;
|
use PhpOffice\PhpSpreadsheet\Comment;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\TextElement;
|
use PhpOffice\PhpSpreadsheet\RichText\TextElement;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
@ -83,4 +84,14 @@ class CommentTest extends TestCase
|
||||||
$comment->setText($test);
|
$comment->setText($test);
|
||||||
self::assertEquals('This is a test comment', (string) $comment);
|
self::assertEquals('This is a test comment', (string) $comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRemoveComment(): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->getComment('A2')->getText()->createText('Comment to delete');
|
||||||
|
self::assertArrayHasKey('A2', $sheet->getComments());
|
||||||
|
$sheet->removeComment('A2');
|
||||||
|
self::assertEmpty($sheet->getComments());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class Issue2885Test extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $testbook = 'tests/data/Reader/XLSX/issue.2885.xlsx';
|
||||||
|
|
||||||
|
public function testIssue2885(): void
|
||||||
|
{
|
||||||
|
$filename = self::$testbook;
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load($filename);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('[$-809]0%', $sheet->getStyle('A1')->getNumberFormat()->getFormatCode());
|
||||||
|
|
||||||
|
$finishColumns = $sheet->getHighestColumn();
|
||||||
|
$rowsCount = $sheet->getHighestRow();
|
||||||
|
$rows = $sheet->rangeToArray("A1:{$finishColumns}{$rowsCount}");
|
||||||
|
self::assertSame('8%', $rows[0][0]);
|
||||||
|
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||||
|
|
||||||
|
class RibbonTest extends AbstractFunctional
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test read/rewrite spreadsheet with ribbon data.
|
||||||
|
*/
|
||||||
|
public function testRibbon(): void
|
||||||
|
{
|
||||||
|
// The following file is downloaded, with the author's
|
||||||
|
// permission, from:
|
||||||
|
// https://www.rondebruin.nl/win/s2/win003.htm
|
||||||
|
// It is renamed, including changing its extension to zip.
|
||||||
|
$filename = 'tests/data/Reader/XLSX/ribbon.donotopen.zip';
|
||||||
|
$reader = IOFactory::createReader('Xlsx');
|
||||||
|
$spreadsheet = $reader->load($filename);
|
||||||
|
self::assertTrue($spreadsheet->hasRibbon());
|
||||||
|
$target = $spreadsheet->getRibbonXMLData('target');
|
||||||
|
self::assertSame('customUI/customUI.xml', $target);
|
||||||
|
$data = $spreadsheet->getRibbonXMLData('data');
|
||||||
|
self::assertIsString($data);
|
||||||
|
self::assertSame(1522, strlen($data));
|
||||||
|
$vbaCode = (string) $spreadsheet->getMacrosCode();
|
||||||
|
self::assertSame(13312, strlen($vbaCode));
|
||||||
|
self::assertNull($spreadsheet->getRibbonBinObjects());
|
||||||
|
self::assertNull($spreadsheet->getRibbonBinObjects('names'));
|
||||||
|
self::assertNull($spreadsheet->getRibbonBinObjects('data'));
|
||||||
|
self::assertEmpty($spreadsheet->getRibbonBinObjects('types'));
|
||||||
|
self::assertNull($spreadsheet->getRibbonBinObjects('xxxxx'));
|
||||||
|
|
||||||
|
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
self::assertTrue($reloadedSpreadsheet->hasRibbon());
|
||||||
|
$ribbonData = $reloadedSpreadsheet->getRibbonXmlData();
|
||||||
|
self::assertIsArray($ribbonData);
|
||||||
|
self::assertSame($target, $ribbonData['target'] ?? '');
|
||||||
|
self::assertSame($data, $ribbonData['data'] ?? '');
|
||||||
|
self::assertSame($vbaCode, $reloadedSpreadsheet->getMacrosCode());
|
||||||
|
self::assertNull($reloadedSpreadsheet->getRibbonBinObjects());
|
||||||
|
$reloadedSpreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\CellIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\ColumnIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ColumnIteratorEmptyTest extends TestCase
|
||||||
|
{
|
||||||
|
private static function getPopulatedSheet(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('D2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('E2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('E3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('F2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('F3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('H3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H4', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnBasic
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumn(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty();
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnBasic(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', false],
|
||||||
|
['D', false],
|
||||||
|
['E', false],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnNullAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumnWithNull(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnNullAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', true],
|
||||||
|
['D', false],
|
||||||
|
['E', false],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumnWithEmptyString(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', false],
|
||||||
|
['D', true],
|
||||||
|
['E', false],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnNullAndEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyColumnWithNullAndEmptyString(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new ColumnIterator($sheet, 'A', 'I');
|
||||||
|
$iterator->seek($columnId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(
|
||||||
|
CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnNullAndEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', true],
|
||||||
|
['D', true],
|
||||||
|
['E', true],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\CellIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\RowIterator;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class RowIteratorEmptyTest extends TestCase
|
||||||
|
{
|
||||||
|
private static function getPopulatedSheet(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B3', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('B4', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B5', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C5', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B6', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C6', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B7', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C7', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B8', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C8', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('D8', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowBasic
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRow(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty();
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowBasic(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, false],
|
||||||
|
[4, false],
|
||||||
|
[5, false],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowNullAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRowWithNull(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowNullAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, true],
|
||||||
|
[4, false],
|
||||||
|
[5, false],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRowWithEmptyString(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, false],
|
||||||
|
[4, true],
|
||||||
|
[5, false],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowNullAndEmptyStringAsEmpty
|
||||||
|
*/
|
||||||
|
public function testIteratorEmptyRowWithNullAndEmptyString(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheet($spreadsheet);
|
||||||
|
$iterator = new RowIterator($sheet, 1, 9);
|
||||||
|
$iterator->seek($rowId);
|
||||||
|
$row = $iterator->current();
|
||||||
|
$isEmpty = $row->isEmpty(
|
||||||
|
CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||||
|
);
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowNullAndEmptyStringAsEmpty(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, true],
|
||||||
|
[4, true],
|
||||||
|
[5, true],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\CellIterator;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
|
@ -405,4 +407,100 @@ class WorksheetTest extends TestCase
|
||||||
self::assertSame($expectedData, $worksheet->toArray());
|
self::assertSame($expectedData, $worksheet->toArray());
|
||||||
self::assertSame($expectedHighestRow, $worksheet->getHighestRow());
|
self::assertSame($expectedHighestRow, $worksheet->getHighestRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getPopulatedSheetForEmptyRowTest(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B3', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('B4', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B5', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C5', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B6', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C6', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B7', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C7', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('B8', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('C8', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('D8', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getPopulatedSheetForEmptyColumnTest(Spreadsheet $spreadsheet): Worksheet
|
||||||
|
{
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValueExplicit('A1', 'Hello World', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('C2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('D2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('E2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('E3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('F2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('F3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G2', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('G3', 'PHP', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H2', null, DataType::TYPE_NULL);
|
||||||
|
$sheet->setCellValueExplicit('H3', '', DataType::TYPE_STRING);
|
||||||
|
$sheet->setCellValueExplicit('H4', 'PHP', DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
return $sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyRowProvider
|
||||||
|
*/
|
||||||
|
public function testIsEmptyRow(int $rowId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheetForEmptyRowTest($spreadsheet);
|
||||||
|
|
||||||
|
$isEmpty = $sheet->isEmptyRow($rowId, CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyRowProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[1, false],
|
||||||
|
[2, true],
|
||||||
|
[3, true],
|
||||||
|
[4, true],
|
||||||
|
[5, true],
|
||||||
|
[6, false],
|
||||||
|
[7, false],
|
||||||
|
[8, false],
|
||||||
|
[9, true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider emptyColumnProvider
|
||||||
|
*/
|
||||||
|
public function testIsEmptyColumn(string $columnId, bool $expectedEmpty): void
|
||||||
|
{
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$sheet = self::getPopulatedSheetForEmptyColumnTest($spreadsheet);
|
||||||
|
|
||||||
|
$isEmpty = $sheet->isEmptyColumn($columnId, CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||||
|
|
||||||
|
self::assertSame($expectedEmpty, $isEmpty);
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emptyColumnProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['A', false],
|
||||||
|
['B', true],
|
||||||
|
['C', true],
|
||||||
|
['D', true],
|
||||||
|
['E', true],
|
||||||
|
['F', false],
|
||||||
|
['G', false],
|
||||||
|
['H', false],
|
||||||
|
['I', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue