diff --git a/composer.lock b/composer.lock index a50b4734a4..2567436ebe 100644 --- a/composer.lock +++ b/composer.lock @@ -473,30 +473,38 @@ }, { "name": "composer/pcre", - "version": "3.1.4", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "04229f163664973f68f38f6f73d917799168ef24" + "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", - "reference": "04229f163664973f68f38f6f73d917799168ef24", + "url": "https://api.github.com/repos/composer/pcre/zipball/ea4ab6f9580a4fd221e0418f2c357cdd39102a90", + "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, + "conflict": { + "phpstan/phpstan": "<1.11.8" + }, "require-dev": { - "phpstan/phpstan": "^1.3", + "phpstan/phpstan": "^1.11.8", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { @@ -524,7 +532,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.4" + "source": "https://github.com/composer/pcre/tree/3.2.0" }, "funding": [ { @@ -540,20 +548,20 @@ "type": "tidelift" } ], - "time": "2024-05-27T13:40:54+00:00" + "time": "2024-07-25T09:36:02+00:00" }, { "name": "composer/semver", - "version": "3.4.0", + "version": "3.4.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", "shasum": "" }, "require": { @@ -605,7 +613,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" + "source": "https://github.com/composer/semver/tree/3.4.2" }, "funding": [ { @@ -621,7 +629,7 @@ "type": "tidelift" } ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2024-07-12T11:35:52+00:00" }, { "name": "composer/xdebug-handler", @@ -1047,16 +1055,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.59.3", + "version": "v3.61.1", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29" + "reference": "94a87189f55814e6cabca2d9a33b06de384a2ab8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/30ba9ecc2b0e5205e578fe29973c15653d9bfd29", - "reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/94a87189f55814e6cabca2d9a33b06de384a2ab8", + "reference": "94a87189f55814e6cabca2d9a33b06de384a2ab8", "shasum": "" }, "require": { @@ -1138,7 +1146,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.59.3" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.61.1" }, "funding": [ { @@ -1146,7 +1154,7 @@ "type": "github" } ], - "time": "2024-06-16T14:17:03+00:00" + "time": "2024-07-31T14:33:15+00:00" }, { "name": "masterminds/html5", @@ -1497,16 +1505,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "shasum": "" }, "require": { @@ -1517,7 +1525,7 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -1549,9 +1557,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2024-07-01T20:03:41+00:00" }, { "name": "paragonie/random_compat", @@ -1785,16 +1793,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.11.5", + "version": "1.11.8", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "490f0ae1c92b082f154681d7849aee776a7c1443" + "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/490f0ae1c92b082f154681d7849aee776a7c1443", - "reference": "490f0ae1c92b082f154681d7849aee776a7c1443", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", + "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", "shasum": "" }, "require": { @@ -1839,7 +1847,7 @@ "type": "github" } ], - "time": "2024-06-17T15:10:54+00:00" + "time": "2024-07-24T07:01:22+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -2216,16 +2224,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.24", + "version": "10.5.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015" + "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5f124e3e3e561006047b532fd0431bf5bb6b9015", - "reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e9e80872b4e8064401788ee8a32d40b4455318f", + "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f", "shasum": "" }, "require": { @@ -2235,26 +2243,26 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.5", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-invoker": "^4.0", - "phpunit/php-text-template": "^3.0", - "phpunit/php-timer": "^6.0", - "sebastian/cli-parser": "^2.0", - "sebastian/code-unit": "^2.0", - "sebastian/comparator": "^5.0", - "sebastian/diff": "^5.0", - "sebastian/environment": "^6.0", - "sebastian/exporter": "^5.1", - "sebastian/global-state": "^6.0.1", - "sebastian/object-enumerator": "^5.0", - "sebastian/recursion-context": "^5.0", - "sebastian/type": "^4.0", - "sebastian/version": "^4.0" + "phpunit/php-code-coverage": "^10.1.15", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.1", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -2297,7 +2305,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.24" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.29" }, "funding": [ { @@ -2313,7 +2321,7 @@ "type": "tidelift" } ], - "time": "2024-06-20T13:09:54+00:00" + "time": "2024-07-30T11:08:00+00:00" }, { "name": "psr/container", @@ -2842,31 +2850,31 @@ }, { "name": "react/socket", - "version": "v1.15.0", + "version": "v1.16.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038" + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/216d3aec0b87f04a40ca04f481e6af01bdd1d038", - "reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038", + "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.0", - "react/dns": "^1.11", + "react/dns": "^1.13", "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.6 || ^1.2.1", - "react/stream": "^1.2" + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" }, "require-dev": { "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", + "react/async": "^4.3 || ^3.3 || ^2", "react/promise-stream": "^1.4", - "react/promise-timer": "^1.10" + "react/promise-timer": "^1.11" }, "type": "library", "autoload": { @@ -2910,7 +2918,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.15.0" + "source": "https://github.com/reactphp/socket/tree/v1.16.0" }, "funding": [ { @@ -2918,7 +2926,7 @@ "type": "open_collective" } ], - "time": "2023-12-15T11:02:10+00:00" + "time": "2024-07-26T10:38:09+00:00" }, { "name": "react/stream", @@ -3000,16 +3008,16 @@ }, { "name": "sabberworm/php-css-parser", - "version": "v8.5.1", + "version": "v8.6.0", "source": { "type": "git", "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152" + "reference": "d2fb94a9641be84d79c7548c6d39bbebba6e9a70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/4a3d572b0f8b28bb6fd016ae8bbfc445facef152", - "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d2fb94a9641be84d79c7548c6d39bbebba6e9a70", + "reference": "d2fb94a9641be84d79c7548c6d39bbebba6e9a70", "shasum": "" }, "require": { @@ -3059,9 +3067,9 @@ ], "support": { "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.5.1" + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.6.0" }, - "time": "2024-02-15T16:41:13+00:00" + "time": "2024-07-01T07:33:21+00:00" }, { "name": "sebastian/cli-parser", @@ -4053,16 +4061,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.1", + "version": "3.10.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877" + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/8f90f7a53ce271935282967f53d0894f8f1ff877", - "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", "shasum": "" }, "require": { @@ -4129,20 +4137,20 @@ "type": "open_collective" } ], - "time": "2024-05-22T21:24:41+00:00" + "time": "2024-07-21T23:26:44+00:00" }, { "name": "symfony/console", - "version": "v6.4.9", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9" + "reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9", - "reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9", + "url": "https://api.github.com/repos/symfony/console/zipball/504974cbe43d05f83b201d6498c206f16fc0cdbc", + "reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc", "shasum": "" }, "require": { @@ -4207,7 +4215,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.9" + "source": "https://github.com/symfony/console/tree/v6.4.10" }, "funding": [ { @@ -4223,7 +4231,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:49:33+00:00" + "time": "2024-07-26T12:30:32+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4516,16 +4524,16 @@ }, { "name": "symfony/finder", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "3ef977a43883215d560a2cecb82ec8e62131471c" + "reference": "af29198d87112bebdd397bd7735fbd115997824c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/3ef977a43883215d560a2cecb82ec8e62131471c", - "reference": "3ef977a43883215d560a2cecb82ec8e62131471c", + "url": "https://api.github.com/repos/symfony/finder/zipball/af29198d87112bebdd397bd7735fbd115997824c", + "reference": "af29198d87112bebdd397bd7735fbd115997824c", "shasum": "" }, "require": { @@ -4560,7 +4568,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.8" + "source": "https://github.com/symfony/finder/tree/v6.4.10" }, "funding": [ { @@ -4576,7 +4584,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-24T07:06:38+00:00" }, { "name": "symfony/options-resolver", @@ -5327,16 +5335,16 @@ }, { "name": "symfony/string", - "version": "v6.4.9", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "76792dbd99690a5ebef8050d9206c60c59e681d7" + "reference": "ccf9b30251719567bfd46494138327522b9a9446" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/76792dbd99690a5ebef8050d9206c60c59e681d7", - "reference": "76792dbd99690a5ebef8050d9206c60c59e681d7", + "url": "https://api.github.com/repos/symfony/string/zipball/ccf9b30251719567bfd46494138327522b9a9446", + "reference": "ccf9b30251719567bfd46494138327522b9a9446", "shasum": "" }, "require": { @@ -5393,7 +5401,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.9" + "source": "https://github.com/symfony/string/tree/v6.4.10" }, "funding": [ { @@ -5409,7 +5417,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:25:38+00:00" + "time": "2024-07-22T10:21:14+00:00" }, { "name": "tecnickcom/tcpdf", @@ -5561,5 +5569,5 @@ "platform-overrides": { "php": "8.1.99" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index c6f20364e7..8d622d4e6a 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -69,8 +69,6 @@ class Calculation /** * Instance of this class. - * - * @var ?Calculation */ private static ?Calculation $instance = null; @@ -3272,10 +3270,8 @@ private static function translateFormula(array $from, array $to, string $formula return $formula; } - /** @var ?array */ private static ?array $functionReplaceFromExcel; - /** @var ?array */ private static ?array $functionReplaceToLocale; /** @@ -3321,10 +3317,8 @@ public function translateFormulaToLocale(string $formula): string ); } - /** @var ?array */ private static ?array $functionReplaceFromLocale; - /** @var ?array */ private static ?array $functionReplaceToExcel; /** @@ -5087,9 +5081,10 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell if ($cell === null || $pCellWorksheet === null) { return $this->raiseFormulaError("undefined name '$token'"); } + $specifiedWorksheet = trim($matches[2], "'"); $this->debugLog->writeDebugLog('Evaluating Defined Name %s', $definedName); - $namedRange = DefinedName::resolveName($definedName, $pCellWorksheet); + $namedRange = DefinedName::resolveName($definedName, $pCellWorksheet, $specifiedWorksheet); // If not Defined Name, try as Table. if ($namedRange === null && $this->spreadsheet !== null) { $table = $this->spreadsheet->getTableByName($definedName); @@ -5114,7 +5109,7 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell return $this->raiseFormulaError("undefined name '$definedName'"); } - $result = $this->evaluateDefinedName($cell, $namedRange, $pCellWorksheet, $stack); + $result = $this->evaluateDefinedName($cell, $namedRange, $pCellWorksheet, $stack, $specifiedWorksheet !== ''); if (isset($storeKey)) { $branchStore[$storeKey] = $result; } @@ -5593,10 +5588,10 @@ private function addCellReference(array $args, bool $passCellReference, array|st return $args; } - private function evaluateDefinedName(Cell $cell, DefinedName $namedRange, Worksheet $cellWorksheet, Stack $stack): mixed + private function evaluateDefinedName(Cell $cell, DefinedName $namedRange, Worksheet $cellWorksheet, Stack $stack, bool $ignoreScope = false): mixed { $definedNameScope = $namedRange->getScope(); - if ($definedNameScope !== null && $definedNameScope !== $cellWorksheet) { + if ($definedNameScope !== null && $definedNameScope !== $cellWorksheet && !$ignoreScope) { // The defined name isn't in our current scope, so #REF $result = ExcelError::REF(); $stack->push('Error', $result, $namedRange->getName()); diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Helpers.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Helpers.php index 94ffa4c4d3..1e9af6cb5a 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Helpers.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Helpers.php @@ -19,6 +19,8 @@ class Helpers */ public static function isLeapYear(int|string $year): bool { + $year = (int) $year; + return (($year % 4) === 0) && (($year % 100) !== 0) || (($year % 400) === 0); } diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php index 0af421143f..d8c53b476f 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php @@ -52,7 +52,7 @@ public static function fromString(null|array|string|int|bool|float $timeValue): $arraySplit = preg_split('/[\/:\-\s]/', $timeValue) ?: []; if ((count($arraySplit) == 2 || count($arraySplit) == 3) && $arraySplit[0] > 24) { - $arraySplit[0] = ($arraySplit[0] % 24); + $arraySplit[0] = ((int) $arraySplit[0] % 24); $timeValue = implode(':', $arraySplit); } diff --git a/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php b/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php index 833c5734e9..ad68ec133b 100644 --- a/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php +++ b/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php @@ -165,7 +165,7 @@ public static function rate( $guess = ($guess === null) ? 0.1 : Functions::flattenSingleValue($guess); try { - $numberOfPeriods = CashFlowValidations::validateInt($numberOfPeriods); + $numberOfPeriods = CashFlowValidations::validateFloat($numberOfPeriods); $payment = CashFlowValidations::validateFloat($payment); $presentValue = CashFlowValidations::validatePresentValue($presentValue); $futureValue = CashFlowValidations::validateFutureValue($futureValue); @@ -193,7 +193,7 @@ public static function rate( return $close ? $rate : ExcelError::NAN(); } - private static function rateNextGuess(float $rate, int $numberOfPeriods, float $payment, float $presentValue, float $futureValue, int $type): string|float + private static function rateNextGuess(float $rate, float $numberOfPeriods, float $payment, float $presentValue, float $futureValue, int $type): string|float { if ($rate == 0.0) { return ExcelError::NAN(); diff --git a/src/PhpSpreadsheet/Cell/Cell.php b/src/PhpSpreadsheet/Cell/Cell.php index 6aed63f205..9ddafce1bd 100644 --- a/src/PhpSpreadsheet/Cell/Cell.php +++ b/src/PhpSpreadsheet/Cell/Cell.php @@ -50,8 +50,6 @@ class Cell implements Stringable /** * The collection of cells that this cell belongs to (i.e. The Cell Collection for the parent Worksheet). - * - * @var ?Cells */ private ?Cells $parent; diff --git a/src/PhpSpreadsheet/Chart/Properties.php b/src/PhpSpreadsheet/Chart/Properties.php index 655e79c85e..3e02a964fc 100644 --- a/src/PhpSpreadsheet/Chart/Properties.php +++ b/src/PhpSpreadsheet/Chart/Properties.php @@ -105,7 +105,6 @@ abstract class Properties protected bool $objectState = false; // used only for minor gridlines - /** @var ?float */ protected ?float $glowSize = null; protected ChartColor $glowColor; diff --git a/src/PhpSpreadsheet/Helper/Html.php b/src/PhpSpreadsheet/Helper/Html.php index 2e9f185d0d..e690ae6525 100644 --- a/src/PhpSpreadsheet/Helper/Html.php +++ b/src/PhpSpreadsheet/Helper/Html.php @@ -533,13 +533,10 @@ class Html 'yellowgreen' => '9acd32', ]; - /** @var ?string */ private ?string $face = null; - /** @var ?string */ private ?string $size = null; - /** @var ?string */ private ?string $color = null; private bool $bold = false; diff --git a/src/PhpSpreadsheet/Reader/Csv/Delimiter.php b/src/PhpSpreadsheet/Reader/Csv/Delimiter.php index d13156f315..92ec0b5d3b 100644 --- a/src/PhpSpreadsheet/Reader/Csv/Delimiter.php +++ b/src/PhpSpreadsheet/Reader/Csv/Delimiter.php @@ -17,7 +17,6 @@ class Delimiter protected int $numberLines = 0; - /** @var ?string */ protected ?string $delimiter = null; /** diff --git a/src/PhpSpreadsheet/Reader/Html.php b/src/PhpSpreadsheet/Reader/Html.php index cc4a4859a9..2a2ffc410c 100644 --- a/src/PhpSpreadsheet/Reader/Html.php +++ b/src/PhpSpreadsheet/Reader/Html.php @@ -627,7 +627,10 @@ protected function processDomElement(DOMNode $element, Worksheet $sheet, int &$r { foreach ($element->childNodes as $child) { if ($child instanceof DOMText) { - $domText = (string) preg_replace('/\s+/u', ' ', trim($child->nodeValue ?? '')); + $domText = (string) preg_replace('/\s+/', ' ', trim($child->nodeValue ?? '')); + if ($domText === "\u{a0}") { + $domText = ''; + } if (is_string($cellContent)) { // simply append the text if the cell content is a plain text string $cellContent .= $domText; diff --git a/src/PhpSpreadsheet/Reader/Ods/PageSettings.php b/src/PhpSpreadsheet/Reader/Ods/PageSettings.php index f3e956c91f..fd35de5b90 100644 --- a/src/PhpSpreadsheet/Reader/Ods/PageSettings.php +++ b/src/PhpSpreadsheet/Reader/Ods/PageSettings.php @@ -55,22 +55,22 @@ private function readPageSettingStyles(DOMDocument $styleDom): void foreach ($styles as $styleSet) { $styleName = $styleSet->getAttributeNS($this->stylesNs, 'name'); - $pageLayoutProperties = $styleSet->getElementsByTagNameNS($this->stylesNs, 'page-layout-properties')[0]; - $styleOrientation = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-orientation'); - $styleScale = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'scale-to'); - $stylePrintOrder = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-page-order'); - $centered = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'table-centering'); - - $marginLeft = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-left'); - $marginRight = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-right'); - $marginTop = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-top'); - $marginBottom = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-bottom'); - $header = $styleSet->getElementsByTagNameNS($this->stylesNs, 'header-style')[0]; - $headerProperties = $header->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0]; - $marginHeader = isset($headerProperties) ? $headerProperties->getAttributeNS($this->stylesFo, 'min-height') : null; - $footer = $styleSet->getElementsByTagNameNS($this->stylesNs, 'footer-style')[0]; - $footerProperties = $footer->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0]; - $marginFooter = isset($footerProperties) ? $footerProperties->getAttributeNS($this->stylesFo, 'min-height') : null; + $pageLayoutProperties = $styleSet->getElementsByTagNameNS($this->stylesNs, 'page-layout-properties')->item(0); + $styleOrientation = $pageLayoutProperties?->getAttributeNS($this->stylesNs, 'print-orientation'); + $styleScale = $pageLayoutProperties?->getAttributeNS($this->stylesNs, 'scale-to'); + $stylePrintOrder = $pageLayoutProperties?->getAttributeNS($this->stylesNs, 'print-page-order'); + $centered = $pageLayoutProperties?->getAttributeNS($this->stylesNs, 'table-centering'); + + $marginLeft = $pageLayoutProperties?->getAttributeNS($this->stylesFo, 'margin-left'); + $marginRight = $pageLayoutProperties?->getAttributeNS($this->stylesFo, 'margin-right'); + $marginTop = $pageLayoutProperties?->getAttributeNS($this->stylesFo, 'margin-top'); + $marginBottom = $pageLayoutProperties?->getAttributeNS($this->stylesFo, 'margin-bottom'); + $header = $styleSet->getElementsByTagNameNS($this->stylesNs, 'header-style')->item(0); + $headerProperties = $header?->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')?->item(0); + $marginHeader = $headerProperties?->getAttributeNS($this->stylesFo, 'min-height'); + $footer = $styleSet->getElementsByTagNameNS($this->stylesNs, 'footer-style')->item(0); + $footerProperties = $footer?->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')?->item(0); + $marginFooter = $footerProperties?->getAttributeNS($this->stylesFo, 'min-height'); $this->pageLayoutStyles[$styleName] = (object) [ 'orientation' => $styleOrientation ?: PageSetup::ORIENTATION_DEFAULT, diff --git a/src/PhpSpreadsheet/Reader/Security/XmlScanner.php b/src/PhpSpreadsheet/Reader/Security/XmlScanner.php index 979325a44c..3946ed00e9 100644 --- a/src/PhpSpreadsheet/Reader/Security/XmlScanner.php +++ b/src/PhpSpreadsheet/Reader/Security/XmlScanner.php @@ -35,15 +35,11 @@ private static function forceString(mixed $arg): string private function toUtf8(string $xml): string { - $pattern = '/encoding="(.*?)"/'; - $result = preg_match($pattern, $xml, $matches); - $charset = strtoupper($result ? $matches[1] : 'UTF-8'); - + $charset = $this->findCharSet($xml); if ($charset !== 'UTF-8') { $xml = self::forceString(mb_convert_encoding($xml, 'UTF-8', $charset)); - $result = preg_match($pattern, $xml, $matches); - $charset = strtoupper($result ? $matches[1] : 'UTF-8'); + $charset = $this->findCharSet($xml); if ($charset !== 'UTF-8') { throw new Reader\Exception('Suspicious Double-encoded XML, spreadsheet file load() aborted to prevent XXE/XEE attacks'); } @@ -52,6 +48,22 @@ private function toUtf8(string $xml): string return $xml; } + private function findCharSet(string $xml): string + { + $patterns = [ + '/encoding="([^"]*]?)"/', + "/encoding='([^']*?)'/", + ]; + + foreach ($patterns as $pattern) { + if (preg_match($pattern, $xml, $matches)) { + return strtoupper($matches[1]); + } + } + + return 'UTF-8'; + } + /** * Scan the XML for use of attributes() ?? []; - if (isset($printOptions['gridLinesSet']) && self::boolean((string) $printOptions['gridLinesSet'])) { - $this->worksheet->setShowGridlines(true); - } + // Spec is weird. gridLines (default false) + // and gridLinesSet (default true) must both be true. if (isset($printOptions['gridLines']) && self::boolean((string) $printOptions['gridLines'])) { - $this->worksheet->setPrintGridlines(true); + if (!isset($printOptions['gridLinesSet']) || self::boolean((string) $printOptions['gridLinesSet'])) { + $this->worksheet->setPrintGridlines(true); + } } if (isset($printOptions['horizontalCentered']) && self::boolean((string) $printOptions['horizontalCentered'])) { $this->worksheet->getPageSetup()->setHorizontalCentered(true); diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php index e35d6f3e86..0672854ad7 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php @@ -19,8 +19,6 @@ class Styles extends BaseParserClass { /** * Theme instance. - * - * @var ?Theme */ private ?Theme $theme = null; diff --git a/src/PhpSpreadsheet/ReferenceHelper.php b/src/PhpSpreadsheet/ReferenceHelper.php index c8acfd8cf7..cdbe37861c 100644 --- a/src/PhpSpreadsheet/ReferenceHelper.php +++ b/src/PhpSpreadsheet/ReferenceHelper.php @@ -24,8 +24,6 @@ class ReferenceHelper /** * Instance of this class. - * - * @var ?ReferenceHelper */ private static ?ReferenceHelper $instance = null; diff --git a/src/PhpSpreadsheet/RichText/Run.php b/src/PhpSpreadsheet/RichText/Run.php index 3bc980c78d..6a6ccdd4bc 100644 --- a/src/PhpSpreadsheet/RichText/Run.php +++ b/src/PhpSpreadsheet/RichText/Run.php @@ -9,8 +9,6 @@ class Run extends TextElement implements ITextElement { /** * Font. - * - * @var ?Font */ private ?Font $font; diff --git a/src/PhpSpreadsheet/Settings.php b/src/PhpSpreadsheet/Settings.php index 58d75164bb..7f727a8cc6 100644 --- a/src/PhpSpreadsheet/Settings.php +++ b/src/PhpSpreadsheet/Settings.php @@ -27,8 +27,6 @@ class Settings /** * The cache implementation to be used for cell collection. - * - * @var ?CacheInterface */ private static ?CacheInterface $cache = null; diff --git a/src/PhpSpreadsheet/Shared/Escher.php b/src/PhpSpreadsheet/Shared/Escher.php index 8b9b3df115..9eb9956a2f 100644 --- a/src/PhpSpreadsheet/Shared/Escher.php +++ b/src/PhpSpreadsheet/Shared/Escher.php @@ -6,15 +6,11 @@ class Escher { /** * Drawing Group Container. - * - * @var ?Escher\DggContainer */ private ?Escher\DggContainer $dggContainer = null; /** * Drawing Container. - * - * @var ?Escher\DgContainer */ private ?Escher\DgContainer $dgContainer = null; diff --git a/src/PhpSpreadsheet/Shared/Escher/DggContainer.php b/src/PhpSpreadsheet/Shared/Escher/DggContainer.php index 9b0c9bb263..d0bf1bb5a1 100644 --- a/src/PhpSpreadsheet/Shared/Escher/DggContainer.php +++ b/src/PhpSpreadsheet/Shared/Escher/DggContainer.php @@ -21,8 +21,6 @@ class DggContainer /** * BLIP Store Container. - * - * @var ?DggContainer\BstoreContainer */ private ?DggContainer\BstoreContainer $bstoreContainer = null; diff --git a/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php index 0f5bf31d76..98e3656cf9 100644 --- a/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php +++ b/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -25,8 +25,6 @@ class BSE /** * The BLIP (Big Large Image or Picture). - * - * @var ?BSE\Blip */ private ?BSE\Blip $blip = null; diff --git a/src/PhpSpreadsheet/Spreadsheet.php b/src/PhpSpreadsheet/Spreadsheet.php index e571cc4f6b..bcea8e6a74 100644 --- a/src/PhpSpreadsheet/Spreadsheet.php +++ b/src/PhpSpreadsheet/Spreadsheet.php @@ -558,6 +558,9 @@ public function addSheet(Worksheet $worksheet, ?int $sheetIndex = null): Workshe if ($this->activeSheetIndex >= $sheetIndex) { ++$this->activeSheetIndex; } + if ($this->activeSheetIndex < 0) { + $this->activeSheetIndex = 0; + } } if ($worksheet->getParent() === null) { diff --git a/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardAbstract.php b/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardAbstract.php index 02d0680932..953a55934c 100644 --- a/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardAbstract.php +++ b/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardAbstract.php @@ -9,9 +9,6 @@ abstract class WizardAbstract { - /** - * @var ?Style - */ protected ?Style $style = null; protected string $expression; diff --git a/src/PhpSpreadsheet/Style/Font.php b/src/PhpSpreadsheet/Style/Font.php index 232959de9b..b96cfca601 100644 --- a/src/PhpSpreadsheet/Style/Font.php +++ b/src/PhpSpreadsheet/Style/Font.php @@ -38,10 +38,8 @@ class Font extends Supervisor private string $strikeType = ''; - /** @var ?ChartColor */ private ?ChartColor $underlineColor = null; - /** @var ?ChartColor */ private ?ChartColor $chartColor = null; // end of chart title items diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 0bb64ba594..7afa82b5d9 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -3684,7 +3684,9 @@ public function applyStylesFromArray(string $coordinate, array $styleArray): boo $originalSelected = $this->selectedCells; $this->getStyle($coordinate)->applyFromArray($styleArray); $this->selectedCells = $originalSelected; - $spreadsheet->setActiveSheetIndex($activeSheetIndex); + if ($activeSheetIndex >= 0) { + $spreadsheet->setActiveSheetIndex($activeSheetIndex); + } return true; } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/SetupTeardownDatabases.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/SetupTeardownDatabases.php index 5094d8ea4b..51cd049971 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Database/SetupTeardownDatabases.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Database/SetupTeardownDatabases.php @@ -14,14 +14,8 @@ class SetupTeardownDatabases extends TestCase { protected const RESULT_CELL = 'Z1'; - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AllSetupTeardown.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AllSetupTeardown.php index b51a8509a7..bd1ea8a799 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AllSetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Financial/AllSetupTeardown.php @@ -15,14 +15,8 @@ class AllSetupTeardown extends TestCase { private string $compatibilityMode; - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AllSetupTeardown.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AllSetupTeardown.php index 9d41cedc3e..5db3c9b918 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AllSetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Logical/AllSetupTeardown.php @@ -15,14 +15,8 @@ class AllSetupTeardown extends TestCase { private string $compatibilityMode; - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/AllSetupTeardown.php b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/AllSetupTeardown.php index 93240fa008..da8d350e4a 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/AllSetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/AllSetupTeardown.php @@ -15,14 +15,8 @@ class AllSetupTeardown extends TestCase { protected string $compatibilityMode; - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/AllSetupTeardown.php b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/AllSetupTeardown.php index d4594cc67d..ca55bfa653 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/AllSetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/MathTrig/AllSetupTeardown.php @@ -15,14 +15,8 @@ class AllSetupTeardown extends TestCase { private string $compatibilityMode; - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AllSetupTeardown.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AllSetupTeardown.php index f1a660e47b..8aaf6e73f6 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AllSetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Statistical/AllSetupTeardown.php @@ -16,14 +16,8 @@ class AllSetupTeardown extends TestCase { private string $compatibilityMode; - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/AllSetupTeardown.php b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/AllSetupTeardown.php index a24822476d..ddb1d92021 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/AllSetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/TextData/AllSetupTeardown.php @@ -18,14 +18,8 @@ class AllSetupTeardown extends TestCase private string $locale; - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/Web/WebServiceTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/Web/WebServiceTest.php index 6c05513a90..48c528c6ac 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/Web/WebServiceTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/Web/WebServiceTest.php @@ -15,7 +15,6 @@ class WebServiceTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/Cell/CellDetachTest.php b/tests/PhpSpreadsheetTests/Cell/CellDetachTest.php index efd2dca04d..faec5dbd91 100644 --- a/tests/PhpSpreadsheetTests/Cell/CellDetachTest.php +++ b/tests/PhpSpreadsheetTests/Cell/CellDetachTest.php @@ -11,7 +11,6 @@ class CellDetachTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/NamedRange2Test.php b/tests/PhpSpreadsheetTests/NamedRange2Test.php index dcf038c52f..9061d6e1e0 100644 --- a/tests/PhpSpreadsheetTests/NamedRange2Test.php +++ b/tests/PhpSpreadsheetTests/NamedRange2Test.php @@ -12,7 +12,6 @@ class NamedRange2Test extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function setUp(): void diff --git a/tests/PhpSpreadsheetTests/NamedRange3Test.php b/tests/PhpSpreadsheetTests/NamedRange3Test.php new file mode 100644 index 0000000000..c25dec5612 --- /dev/null +++ b/tests/PhpSpreadsheetTests/NamedRange3Test.php @@ -0,0 +1,52 @@ +getActiveSheet(); + $sheet1->setTitle('sheet1'); + $sheet1->setCellValue('B1', 100); + $sheet1->setCellValue('B2', 200); + $sheet1->setCellValue('B3', 300); + $sheet1->setCellValue('B4', 400); + $sheet1->setCellValue('B5', 500); + + $sheet2 = $spreadsheet->createsheet(); + $sheet2->setTitle('sheet2'); + $sheet2->setCellValue('A1', 10); + $sheet2->setCellValue('A2', 20); + $sheet2->setCellValue('A3', 30); + $sheet2->setCellValue('A4', 40); + $sheet2->setCellValue('A5', 50); + + $spreadsheet->addNamedRange( + new NamedRange('somecells', $sheet2, '$A$1:$A$5', true) + ); + $spreadsheet->addNamedRange( + new NamedRange('cellsonsheet1', $sheet1, '$B$1:$B$5') + ); + + $sheet1->getCell('G1')->setValue('=SUM(cellsonsheet1)'); + self::assertSame(1500, $sheet1->getCell('G1')->getCalculatedValue()); + $sheet1->getCell('G2')->setValue('=SUM(sheet2!somecells)'); + self::assertSame(150, $sheet1->getCell('G2')->getCalculatedValue()); + $sheet1->getCell('G3')->setValue('=SUM(somecells)'); + self::assertSame('#NAME?', $sheet1->getCell('G3')->getCalculatedValue()); + $sheet1->getCell('G4')->setValue('=SUM(sheet2!cellsonsheet1)'); + self::assertSame(1500, $sheet1->getCell('G4')->getCalculatedValue()); + $sheet1->getCell('G5')->setValue('=SUM(sheet2xxx!cellsonsheet1)'); + self::assertSame('#NAME?', $sheet1->getCell('G5')->getCalculatedValue()); + + $spreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/PhpSpreadsheetTests/Reader/Html/Issue1284Test.php b/tests/PhpSpreadsheetTests/Reader/Html/Issue1284Test.php new file mode 100644 index 0000000000..6faee356db --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Html/Issue1284Test.php @@ -0,0 +1,36 @@ +getActiveSheet(); + $osheet->getCell('A1')->setValue('# item 1'); + $osheet->getCell('A2')->setValue("$ideographicSpace# item 2"); + $osheet->getCell('A3')->setValue("$ideographicSpace$ideographicSpace# item 3"); + $osheet->getCell('A4')->setValue("$nbsp# item\t4"); + $osheet->getCell('A5')->setValue("$nbsp$nbsp# item 5"); + + $spreadsheet = $this->writeAndReload($spreadsheetOld, 'Html'); + $spreadsheetOld->disconnectWorksheets(); + + $sheet = $spreadsheet->getActiveSheet(); + self::assertSame('# item 1', $sheet->getCell('A1')->getValue(), 'nothing changed'); + self::assertSame("$ideographicSpace# item 2", $sheet->getCell('A2')->getValue(), 'nothing changed including 1 ideographic space'); + self::assertSame("$ideographicSpace$ideographicSpace# item 3", $sheet->getCell('A3')->getValue(), 'nothing changed including 2 ideographic spaces'); + self::assertSame("$nbsp# item 4", $sheet->getCell('A4')->getValue(), 'nbsp unchanged, 2 spaces reduced to 1, tab changed to space'); + self::assertSame("$nbsp$nbsp# item 5", $sheet->getCell('A5')->getValue(), 'many spaces reduced to 1'); + + $spreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/PhpSpreadsheetTests/Reader/Ods/Issue4099Test.php b/tests/PhpSpreadsheetTests/Reader/Ods/Issue4099Test.php new file mode 100644 index 0000000000..2b38181a67 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Ods/Issue4099Test.php @@ -0,0 +1,28 @@ +file . '#styles.xml'; + $contents = (string) file_get_contents($zipFile); + self::assertStringContainsString('page-layout ', $contents); + self::assertStringNotContainsString('header-style', $contents); + self::assertStringNotContainsString('footer-style', $contents); + $reader = new OdsReader(); + $spreadsheet = $reader->load($this->file); + $sheet = $spreadsheet->getActiveSheet(); + self::assertSame('FirstCell', $sheet->getCell('A1')->getValue()); + $spreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/PhpSpreadsheetTests/Reader/Xls/LoadSheetsOnlyTest.php b/tests/PhpSpreadsheetTests/Reader/Xls/LoadSheetsOnlyTest.php index 5edcbe6d39..c8c543afd1 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xls/LoadSheetsOnlyTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xls/LoadSheetsOnlyTest.php @@ -11,7 +11,6 @@ class LoadSheetsOnlyTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; private static string $testbook = 'tests/data/Reader/XLS/HiddenSheet.xls'; diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/GridlinesTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/GridlinesTest.php new file mode 100644 index 0000000000..5387ea738c --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/GridlinesTest.php @@ -0,0 +1,50 @@ +getActiveSheet(); + $sheet2 = $spreadsheet->createSheet(); + $sheet2->setTitle('deliberatelyblank'); + $sheet1->setShowGridlines($display); + $sheet1->setPrintGridlines($print); + $sheet1->fromArray( + [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], + ] + ); + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx'); + $spreadsheet->disconnectWorksheets(); + $rsheet1 = $reloadedSpreadsheet->getSheet(0); + $rsheet2 = $reloadedSpreadsheet->getSheet(1); + self::assertSame($display, $rsheet1->getShowGridlines()); + self::assertSame($print, $rsheet1->getPrintGridlines()); + self::assertTrue($rsheet2->getShowGridlines()); + self::assertFalse($rsheet2->getPrintGridlines()); + $reloadedSpreadsheet->disconnectWorksheets(); + } + + public static function loadDataProvider(): array + { + return [ + [true, true], + [true, false], + [false, true], + [false, false], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/LoadSheetsOnlyTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/LoadSheetsOnlyTest.php index 93739b6352..5c70a7521b 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/LoadSheetsOnlyTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/LoadSheetsOnlyTest.php @@ -11,7 +11,6 @@ class LoadSheetsOnlyTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; private static string $testbook = 'tests/data/Reader/XLSX/HiddenSheet.xlsx'; diff --git a/tests/PhpSpreadsheetTests/Reader/Xml/PageSetupTest.php b/tests/PhpSpreadsheetTests/Reader/Xml/PageSetupTest.php index 47d831241d..63e64709f8 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xml/PageSetupTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xml/PageSetupTest.php @@ -15,9 +15,6 @@ class PageSetupTest extends TestCase private const MARGIN_UNIT_CONVERSION = 2.54; // Inches to cm - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; private string $filename = 'tests/data/Reader/Xml/PageSetup.xml'; diff --git a/tests/PhpSpreadsheetTests/Reader/Xml/XmlLoadTest.php b/tests/PhpSpreadsheetTests/Reader/Xml/XmlLoadTest.php index beded2509e..b3ff5cb358 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xml/XmlLoadTest.php +++ b/tests/PhpSpreadsheetTests/Reader/Xml/XmlLoadTest.php @@ -14,7 +14,6 @@ class XmlLoadTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; private string $locale; diff --git a/tests/PhpSpreadsheetTests/Shared/Date2Test.php b/tests/PhpSpreadsheetTests/Shared/Date2Test.php index d1cbb2346f..f5e51728fc 100644 --- a/tests/PhpSpreadsheetTests/Shared/Date2Test.php +++ b/tests/PhpSpreadsheetTests/Shared/Date2Test.php @@ -12,7 +12,6 @@ class Date2Test extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; private int $calculateDateTimeType; diff --git a/tests/PhpSpreadsheetTests/SpreadsheetCoverageTest.php b/tests/PhpSpreadsheetTests/SpreadsheetCoverageTest.php index f9a6d126c6..91e4e9ce8e 100644 --- a/tests/PhpSpreadsheetTests/SpreadsheetCoverageTest.php +++ b/tests/PhpSpreadsheetTests/SpreadsheetCoverageTest.php @@ -10,10 +10,8 @@ class SpreadsheetCoverageTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet2 = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/SpreadsheetTest.php b/tests/PhpSpreadsheetTests/SpreadsheetTest.php index a3e7a9fd4f..a35ab101f3 100644 --- a/tests/PhpSpreadsheetTests/SpreadsheetTest.php +++ b/tests/PhpSpreadsheetTests/SpreadsheetTest.php @@ -11,7 +11,6 @@ class SpreadsheetTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php b/tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php index 1e232b72ae..02fce92ac9 100644 --- a/tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php +++ b/tests/PhpSpreadsheetTests/Style/AlignmentMiddleTest.php @@ -14,7 +14,6 @@ class AlignmentMiddleTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; private string $outputFileName = ''; diff --git a/tests/PhpSpreadsheetTests/Style/AlignmentTest.php b/tests/PhpSpreadsheetTests/Style/AlignmentTest.php index 1b93800047..32957d90fa 100644 --- a/tests/PhpSpreadsheetTests/Style/AlignmentTest.php +++ b/tests/PhpSpreadsheetTests/Style/AlignmentTest.php @@ -11,7 +11,6 @@ class AlignmentTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php b/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php index ac0ba30d88..334736e87d 100644 --- a/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php +++ b/tests/PhpSpreadsheetTests/Style/ConditionalFormatting/CellMatcherTest.php @@ -14,9 +14,6 @@ class CellMatcherTest extends TestCase { - /** - * @var ?Spreadsheet - */ protected ?Spreadsheet $spreadsheet = null; protected function loadSpreadsheet(): Spreadsheet diff --git a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php index ef3cfb4b3a..bdb512c52f 100644 --- a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/SetupTeardown.php @@ -10,14 +10,8 @@ class SetupTeardown extends TestCase { - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected int $maxRow = 4; diff --git a/tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowUndeprecatedTest.php b/tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowUndeprecatedTest.php index 2209bc3caf..0a761ada0d 100644 --- a/tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowUndeprecatedTest.php +++ b/tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowUndeprecatedTest.php @@ -14,7 +14,6 @@ class ByColumnAndRowUndeprecatedTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/Worksheet/Issue4112Test.php b/tests/PhpSpreadsheetTests/Worksheet/Issue4112Test.php new file mode 100644 index 0000000000..9b230a9c9b --- /dev/null +++ b/tests/PhpSpreadsheetTests/Worksheet/Issue4112Test.php @@ -0,0 +1,43 @@ +removeSheetByIndex(0); + $worksheet = new Worksheet($mySpreadsheet, 'addedsheet'); + self::assertSame(-1, $mySpreadsheet->getActiveSheetIndex()); + $mySpreadsheet->addSheet($worksheet, $sheetNumber); + self::assertSame('addedsheet', $mySpreadsheet->getActiveSheet()->getTitle()); + $row = 1; + $col = 1; + $worksheet->getCell([$col, $row])->setValue('id_uti'); + self::assertSame('id_uti', $worksheet->getCell([$col, $row])->getValue()); + $mySpreadsheet->disconnectWorksheets(); + } + + public static function providerSheetNumber(): array + { + return [ + 'problem case' => [0], + 'normal case' => [null], + 'negative 1 (as if there were no sheets)' => [-1], + 'diffeent negative number' => [-4], + 'positive number' => [4], + ]; + } +} diff --git a/tests/PhpSpreadsheetTests/Worksheet/Table/SetupTeardown.php b/tests/PhpSpreadsheetTests/Worksheet/Table/SetupTeardown.php index 192e76e4c8..404874dcd5 100644 --- a/tests/PhpSpreadsheetTests/Worksheet/Table/SetupTeardown.php +++ b/tests/PhpSpreadsheetTests/Worksheet/Table/SetupTeardown.php @@ -10,14 +10,8 @@ class SetupTeardown extends TestCase { - /** - * @var ?Spreadsheet - */ private ?Spreadsheet $spreadsheet = null; - /** - * @var ?Worksheet - */ private ?Worksheet $sheet = null; protected int $maxRow = 4; diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/FormulaErrTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/FormulaErrTest.php index 23398bf060..1fe717efad 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xls/FormulaErrTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xls/FormulaErrTest.php @@ -12,10 +12,8 @@ class FormulaErrTest extends AbstractFunctional { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; - /** @var ?Spreadsheet */ private ?Spreadsheet $reloadedSpreadsheet = null; private bool $allowThrow; diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php index 73e7239ce0..ac814b8ce3 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php @@ -11,7 +11,6 @@ class ParserTest extends TestCase { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/WorkbookTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/WorkbookTest.php index 253ea30392..a0296804b5 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xls/WorkbookTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xls/WorkbookTest.php @@ -14,7 +14,6 @@ class WorkbookTest extends TestCase { private Workbook $workbook; - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php index 74901dd40c..21e64f2a92 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xls/XlsGifBmpTest.php @@ -9,6 +9,7 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Worksheet\Drawing; use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing; +use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional; class XlsGifBmpTest extends AbstractFunctional @@ -83,6 +84,34 @@ public function testGif(): void $reloadedSpreadsheet->disconnectWorksheets(); } + public function testGifIssue4112(): void + { + $spreadsheet = new Spreadsheet(); + $spreadsheet->removeSheetByIndex(0); + $sheet = new Worksheet($spreadsheet, 'Insured List'); + $spreadsheet->addSheet($sheet, 0); + + // Add a drawing to the worksheet + $drawing = new Drawing(); + $drawing->setName('Letters G, I, and G'); + $drawing->setDescription('Handwritten G, I, and F'); + $drawing->setPath(__DIR__ . '/../../../../samples/images/gif.gif'); + $drawing->setHeight(36); + $drawing->setWorksheet($sheet); + $drawing->setCoordinates('A1'); + + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xls'); + $spreadsheet->disconnectWorksheets(); + $worksheet = $reloadedSpreadsheet->getActiveSheet(); + $drawings = $worksheet->getDrawingCollection(); + self::assertCount(1, $drawings); + foreach ($worksheet->getDrawingCollection() as $drawing) { + $mimeType = ($drawing instanceof MemoryDrawing) ? $drawing->getMimeType() : 'notmemorydrawing'; + self::assertEquals('image/png', $mimeType); + } + $reloadedSpreadsheet->disconnectWorksheets(); + } + public function testInvalidTimestamp(): void { $this->expectException(ReaderException::class); diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/CalculationErrorTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/CalculationErrorTest.php index 85d246fb00..8a22768ff4 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xlsx/CalculationErrorTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/CalculationErrorTest.php @@ -11,10 +11,8 @@ class CalculationErrorTest extends AbstractFunctional { - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; - /** @var ?Spreadsheet */ private ?Spreadsheet $reloadedSpreadsheet = null; protected function tearDown(): void diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/LocaleFloatsTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/LocaleFloatsTest.php index c4d5b25e16..9c691f4c80 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xlsx/LocaleFloatsTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/LocaleFloatsTest.php @@ -17,10 +17,8 @@ class LocaleFloatsTest extends AbstractFunctional private string $originalLocale; - /** @var ?Spreadsheet */ private ?Spreadsheet $spreadsheet = null; - /** @var ?Spreadsheet */ private ?Spreadsheet $reloadedSpreadsheet = null; protected function setUp(): void diff --git a/tests/data/Calculation/Financial/RATE.php b/tests/data/Calculation/Financial/RATE.php index f5a5ab4920..bea4ce9a1c 100644 --- a/tests/data/Calculation/Financial/RATE.php +++ b/tests/data/Calculation/Financial/RATE.php @@ -29,6 +29,18 @@ -250, 5000, ], + [ + 0.017929869399484, + 24.99, + -250, + 5000, + ], + [ + 0.016581855, + 24.5, + -250, + 5000, + ], [ 0.016550119066711999, 24, diff --git a/tests/data/Reader/Ods/issue.4099.ods b/tests/data/Reader/Ods/issue.4099.ods new file mode 100644 index 0000000000..26b17ecbd3 Binary files /dev/null and b/tests/data/Reader/Ods/issue.4099.ods differ diff --git a/tests/data/Reader/Xml/XEETestInvalidUTF-7-single-quote.xml b/tests/data/Reader/Xml/XEETestInvalidUTF-7-single-quote.xml new file mode 100644 index 0000000000..9fc7eba723 --- /dev/null +++ b/tests/data/Reader/Xml/XEETestInvalidUTF-7-single-quote.xml @@ -0,0 +1,2 @@ + + +ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-toreplace+ACA-+ACI-xxe+AF8-test+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-sst+ACA-xmlns+AD0-+ACI-http://schemas.openxmlformats.org/spreadsheetml/2006/main+ACI-+ACA-count+AD0-+ACI-2+ACI-+ACA-uniqueCount+AD0-+ACI-1+ACI-+AD4-+ADw-si+AD4-+ADw-t+AD4-+ACY-toreplace+ADs-+ADw-/t+AD4-+ADw-/si+AD4-+ADw-/sst+AD4- diff --git a/tests/data/Reader/Xml/XEETestValidUTF-8-single-quote.xml b/tests/data/Reader/Xml/XEETestValidUTF-8-single-quote.xml new file mode 100644 index 0000000000..e478c7d408 --- /dev/null +++ b/tests/data/Reader/Xml/XEETestValidUTF-8-single-quote.xml @@ -0,0 +1,4 @@ + + + test: Valid +