Commit Graph

274 Commits

Author SHA1 Message Date
oleibman f8f78a7ed3 String Increments and Php8.5
Fix #4600. String incrementation through the `++` operator is deprecated in Php 8.5. Because we make use of that operator to iterate through columns, we are particularly hard hit by that change - unaddressed, it causes over 2,000 errors in our test suite! It is, fortunately, not as difficult as I feared to correct. Replacing the `++` operator with a call to new method `StringHelper::stringIncrement` in 79 statements scattered over 31 source modules (in src, samples, test, and infra) eliminates all the messages in the test suite. It is possible that others are lurking, but I don't know a systematic way of determining if there are others. We'll stick with this for now, and deal with any others as they show up.

This PR will be applied to the master, release390, and release222 branches. It will not be applied to the release210 or release1291 branches, which will now accept security changes only.
2025-08-27 18:18:40 -07:00
oleibman 08f2f1bfd8 Merge pull request #4579 from oleibman/issue1637
Handle Google-only Formulas Exported from Google Sheets
2025-08-17 03:43:32 +00:00
oleibman 14a989a7e3 Handle Missing Defined Names Better
The original issue leading to this PR was fixed by correctly treating a token in Calculator as a function rather than a defined name. However, it *should* have worked even when treating it as a defined name. There was a problem because Calculator was raising an exception for a missing defined name rather than returning `#NAME?`. It is now changed to return the error.

That change initially had some adverse affects for functions ROW, ROWS, COLUMN, and COLUMNS. Those are fixed to handle the change correctly. As a bonus, a test for each which had been commented out, because it didn't work, is now uncommented and works correctly. One test for ISFORMULA and one for ISREF were also changed - the old expected result did not reflect Excel's behavior and the new one does.

Sheet title and Defined Name matching used `strtoupper` to achieve case-insensitive compares. This handles only ASCII characters. They are changed to use a conversion routine which handles non-ASCII UTF-8 character sets.
2025-08-12 09:21:26 -07:00
oleibman fa2c32996a Merge branch 'master' into issue4588 2025-08-06 21:57:24 -07:00
oleibman 79fca7601c Clean Up Some Engineering Tests
This came to light while cleaning up ComplexAssert. Many tests are calling `_calculateFormulaValue` rather than `calculateFormula`, and, as a result, have to be trimmed before asserting. This PR changes those calls, and does a bit more to simplify the tests. There are a lot of other non-Engineering tests which call `_calculateFormulaValue`, but none of those need to manipulate the result after the test.

This PR changes only tests, no source code.
2025-08-03 13:48:45 -07:00
oleibman 3dcdbcac3e Redo ComplexAssert
Its use is already causes an issue with Phpstan. It uses interfaces marked as internal by Phpunit, and it will not work with Phpunit 12. It is more complicated than needed. This PR corrects all these problems. It also corrects a handful of other problems that will show up with Phpunit 12. Only tests are changed - no source code.
2025-08-03 08:25:05 -07:00
oleibman 150b3849a8 Create Uninitialized Cell If Used in Calculation
Fix #4558. Fix #4530. 4558 deals with a problem with COUNTA. Excel does not count empty cells, but it does count literal nulls (usually empty parameters) in the argument list. PhpSpreadsheet has till now not created empty cells during calculation, and so winds up treating them as literals. It is changed to create the cell when appropriate.

4530 has a similar problem. When INDIRECT winds up evaluating an uninitialized cell, it treats it as a null literal, leading to incorrect results. It is now changed to create the missing cell.

A number of functions, almost all of them Financial, have a related problem. They test for a null literal when initializing some of their parameters, but they should be testing for null literal or cell containing null. They are changed to do the right thing.

SUMIF and related functions are slightly affected by this change, and are changed so that they are no longer affected.

New tests have been added. Only one existing test had to change. MergeBehaviorTest for `[12, '=5+1', '=A1/A2']`, where cell A2 was uninitialized formerly returned one row, but now returns a second all-null row because A2, by virtue of being used in a calculation, now winds up defined. I do not consider this a significant difference.
2025-07-31 23:58:05 -07:00
oleibman 5c643a890b Merge pull request #4491 from oleibman/filterparm
Minor Changes to FILTER Function
2025-06-01 16:04:59 +00:00
oleibman df3a069722 Merge pull request #4493 from oleibman/torow
TOCOL and TOROW
2025-06-01 16:04:23 +00:00
oleibman bd792ec985 Merge pull request #4492 from oleibman/vstack
VSTACK and HSTACK
2025-06-01 16:04:06 +00:00
oleibman f84724d13e Upgrade Phpstan
Too many problems with Dependabot update.
2025-06-01 08:41:13 -07:00
oleibman f3c3aba618 TOCOL and TOROW
TOCOL and TOROW were introduced to Excel in 2024, and will now be supported by PhpSpreadsheet. The documentation says that, under certain circumstances, "blanks" will be ignored. This seems demonstrably wrong. In the right circumstance, Excel will ignore nulls, not blanks. Further, when it decides to not ignore the nulls, it changes them to 0, which also seems insufficiently documented. PhpSpreadsheet will behave as Excel does.

I discovered some minor problems and some missing test conditions for the TRANSPOSE function while testing these. Those are now fixed.
2025-05-28 23:15:06 -07:00
oleibman e83eae9be7 VSTACK and HSTACK
Fix #4485. VSTACK and HSTACK were introduced to Excel in 2024, and will now be supported by PhpSpreadsheet. Special thanks to @SlowFox71, who posted some code to implement VSTACK in the linked issue. I didn't have to change much between that version and the one in this ticket.

Excel has at least one idiosyncrasy with these functions. If you try to stack 2 tables with, say, `=VSTACK(TABLE1, TABLE2)`, Excel will silently change it to `=VSTACK(TABLE1[], TABLE2[])` and all will be well. This would be difficult for PhpSpreadsheet to do. The problem is that, when Excel reads the formula without the square brackets, it calculates it as a `#NAME?` error. This is baffling, and all the more so because you can "correct" it by editing the formula *without changing anything*, hit enter, and the formula will magically work again. So, if you plan to stack tables using PhpSpreadsheet, you're probably best off using the square brackets.
2025-05-27 19:53:30 -07:00
oleibman 347980a3cb Minor Changes to FILTER Function
Its first parameter is typed as `array`. Like all Excel spreadsheet functions, it should be `mixed` to avoid TypeErrors. If an argument other than an array is supplied, Excel will return VALUE, and now PhpSpreadsheet will do so as well. This had not been unit-tested. In fact, all the unit tests take place outside of spreadsheet context. New tests in spreadsheet context are added.
2025-05-26 19:10:09 -07:00
oleibman 0552814d75 Merge pull request #4482 from oleibman/stan1009
Phpstan Level 10 (Final)
2025-05-26 03:25:00 +00:00
oleibman 170010076b Merge branch 'master' into issue4476 2025-05-24 22:30:13 -07:00
oleibman 5a9055ca6a Phpstan Level 10 (Final)
Fix all of Statistical. We can now use Level 10 going forward.
2025-05-22 17:48:30 -07:00
oleibman ef81f19996 More Precision for Float to String Casts
Fix #3899. Supersedes PR #4476, which will be changed to draft status and closed if this PR is merged.

A standard cast from float to string in PHP can drop trailing decimal positions. This can lead to problems above and beyond the usual problems associated with floating point. See the superseded PR for a more complete explanation.

`StringHelper::convertToString` is changed for how it handles floats. It will now do separate casts for the whole and decimal parts, and then combine the results. This affects `Cell::getValueString` and `Cell::getCalculatedValueString`. Xlsx Writer will now invoke `convertToString` before writing  a float to Xml. Ods Writer already uses `getValueString`, so no change is needed there. Xls Writer writes its float values in binary, so no change is needed there. Tests are added for all 3 writers.

Aside from fixing some problems, it might appear that this change introduces some new problems. For instance, setting a cell to `12345.6789` will now result in `12345.67890000000079` in the Xml. This difference is an illusion, merely a consequence of floating point rounding. If you run the following check under PhpUnit, it will pass:
```php
self::assertSame(12345.6789, 12345.67890000000079);
```
2025-05-20 23:35:50 -07:00
oleibman 645d9fea64 Phpstan Level 10 Prep Penultimate
Everything except Statistical.
2025-05-18 18:04:25 -07:00
oleibman 770eddf69d Still More Prep for Phpstan 10
Remaining:
- Calculation/LookupRef
- Calculation/Statistical
- Shared/OLE
- Odds and ends
2025-05-15 08:19:39 -07:00
oleibman 0e570a50cd Merge pull request #4467 from oleibman/stan1006
More prep for Phpstan 10
2025-05-15 01:31:13 +00:00
oleibman e6aacf72b0 Merge pull request #4466 from oleibman/issue407b
Ods Handling of Ceiling and Floor
2025-05-15 01:22:53 +00:00
oleibman 7db6e1f491 More prep for Phpstan 10 2025-05-12 22:59:34 -07:00
oleibman 01e97405f8 Tweaks for Gnumeric and Xls 2025-05-12 11:05:39 -07:00
oleibman e53a04b016 Start Calculation Changes 2025-05-08 22:44:13 -07:00
oleibman 5c94de34a9 More Phpstan Level 10 Prep - Readers
Also upgrade Phpstan.
2025-05-03 21:18:55 -07:00
oleibman 19555d6d96 Phpstan 10 and IterableValue Prep Part 2
There will probably be dozens, if not hundreds, of these before I'm ready to commit.
2025-04-18 23:27:29 -07:00
oleibman e32447c4be Phpstan Level 9: Last 2025-03-31 21:53:47 -07:00
oleibman bc315a3edc A Win For Scrutinizer!
It flagged a statement as dead code. It was correct - there was a typo in the variable name. But no tests had failed. The explanation was, of course, that this particular path was not adequately tested.

PhpSpreadsheet extends Excel (dating back to PHPExcel) by allowing the ordinal form of days in the DATE function, implemented as "take the numeric portion if the field is a string consisting of a numeric portion followed by some alphabetics". Whether or not this is a good idea, it would be a breaking change to eliminate it, so that's not going to happen. However, the same logic has been applied to month, and I don't see a use case for that, so I'm eliminating it - any non-numeric string used as the month parameter will now result in a VALUE error. It also turns out that Excel accepts null, false, and true for the month, and PhpSpreadsheet will now do likewise.
2025-03-23 12:33:01 -07:00
oleibman b2d885fc4c Merge branch 'master' into stan2lv901 2025-03-07 21:55:50 -08:00
oleibman d1d12ed92d Phpstan Level 9 - Part 1 of Many
Dealing mostly with mixed variable type. In a great many cases, problems can be resolved replacing `getValue` with `getValueString` or `getCalculatedValue` with `getCalculatedValueString`.
2025-03-05 21:59:54 -08:00
oleibman a67a981d5e BIN2DEC, OCT2DEC, HEX2DEC Return Numbers Rather than Strings
Fix #4383.
2025-03-02 01:16:14 -08:00
oleibman 44ed8a8b6d Merge branch 'master' into issue4381 2025-02-28 16:17:52 -08:00
oleibman db6e6ebd72 3rd Parameter for AVERAGEIF/SUMIF Can Also Be #REF! 2025-02-25 20:11:23 -08:00
oleibman 990e3ec3a3 Handle #REF! As Argument to COUNTIF, AVERAGEIF, SUMIF
Fix #4381. The report refers to COUNTIF, but AVERAGEIF and SUMIF, which are implemented in the same module, exhibit the same behavior. (There may be others, but, for now, I will just fix those 3.)

Most methods which implement Excel functions should accept mixed arguments, so that they won't throw exceptions when calculated. Of course, MS often doesn't give much guidance as to how unexpected arguments should be handled. It at least seems clear that MS will often substitute #REF! for some arguments, and will return #REF! as the result in such cases. My test indicates that a formula using, say, #DIV/0! in lieu of #REF! will cause Excel to deem the spreadsheet corrupt. So, I think I am just going to deal with #REF! and let other unexpected values continue to throw exceptions.
2025-02-24 21:40:12 -08:00
oleibman 771b3f1784 Update OFFSET
Fix #4376.
2025-02-19 20:35:42 -08:00
oleibman 8930e634a1 Add Some Tests 2025-02-17 17:58:17 -08:00
oleibman ec773bbed9 Phpstan Bleeding Edge Part 2 of Many
This will be the biggest of these changes. It takes care of all of the remaining problems in tests. I will handle the problems in src more slowly.
2025-02-15 19:18:39 -08:00
oleibman 37b6ca4979 Allow php-cs-fixer to Handle Implicit Backslashes
Its defaults are to unescape within single quotes, and escape within double quotes and here-docs. Right now, it leaves everything as-is, which means our code is inconsistent and need not be. Further, although dealing with complex regular expressions will never be easy, I find it much easier to figure out what's going on when superfluous back-slashes are removed.

These changes were all made automatically using the "fix" script, so should be reliable. They, of course, pass all unit tests.
2025-02-08 00:11:01 -08:00
oleibman e637713de9 Make Explicit Array Return Type When Tests Require It
When the Dynamic Array PR #3962 was introduced, it left the default as Return Array as Value. At some point, the default should be changed to Return Array as Array. This would, of course, be a breaking change, one which will not be part of Release 4. However, it will possibly be part of Release 5.

Rather than relying on the default setting, this PR explicitly sets Return Array as Value when tests require that setting. This will make it easier to identify potential breaks when the default is changed. The entire test suite will now succeed with either setting as default.

In making these changes, a few minor problems were discovered with how Array as Array is handled. These are fixed with this PR.
2025-01-25 19:40:12 -08:00
oleibman ee7ddf7ca8 CHOOSECOLS, CHOOSEROWS, DROP, TAKE, and EXPAND
These are 5 closely related functions for manipulating arrays. Now that dynamic arrays are part of PhpSpreadsheet, this PR implements those previously-unimplemented functions. Documentation undergoes a very minor change, since they are re-categorized as "Lookup and Reference", which is how Excel classifies them, rather than "Math and Trig".
2024-12-22 09:00:33 -08:00
oleibman 3078ea9f87 Additional Context Options for https, Restore Disabled Tests
Additional Context Options needed, at least sometimes, to read https images.
2024-12-12 00:10:02 -08:00
oleibman d647fe7ee7 Use Php Attributes Rather than Annotations for PhpUnit
With PhpUnit 10 came the ability to use Php attributes rather than doc-block annotations for things like "data provider". PhpUnit 11 deprecates the use of annotations, and PhpUnit 12 will not not permit their use. Since PhpUnit 11 requires Php8.2+, we cannot adopt it as long as we support Php8.1, which will continue to be the case for some time. However, there is no penalty for early adoption.

Php-cs-fixer can use:
```
'php_unit_attributes' => ['keep_annotations' => false],
```
This allows us to run `composer fix` to automate all the needed changes. No manual changes were needed for any of the test members.

With this change, PhpUnit 9 can no longer be used with the test suite. File composer.json is updated to reflect that reality, and phpunit9.xml.dist, which has been supplied in case anyone needed to use PhpUnit 9, is no longer required, and is thus deleted. For now, PhpUnit 11 is not being added as a possibility.

No source code is changed in this PR.
2024-11-23 20:56:26 -08:00
oleibman c6ede15401 Merge pull request #4148 from oleibman/stan9again4
Better Definitions for Mixed Parameters and Values Part 4 of Many
2024-10-07 17:31:02 +00:00
Owen Leibman 826451937e Better Definitions for Mixed Parameters and Values Part 4 of Many
Continuing work started with PR #4016, PR #4026, and PR #4060. Improve documentation within program by making explicit what types of values are allowed for variables described as "mixed". In order to avoid broken functionality, this is done mainly through doc-blocks. This will get us closer to Phpstan Level 9, but many changes will be needed before we can consider that.

After this PR, 231 changes remain, all in src/Calculation.
2024-08-24 22:08:13 -07:00
oleibman fa5ab52b66 VLOOKUP Handling of Strings and Number
Fix #1402, another in our "better late than never" series. Stalebot closed it in May 2020, and I have reopened it. @ljcag submitted the issue, and PR #1403 to resolve it, also marked stale. That change is more complicated than this one. Since there were no tests in that PR, and since this PR solves the original problem (test added), I will stick with this version, but will continue to study 1403 before merging.

This is also another in the "Excel doesn't believe in complete documentation" series. (See issue #3802 for a similar example.) Nothing that I have seen in the documentation suggests that a number will not match a numeric string, but that seems clearly to be the case. Despite the lack of complete documentation, PhpSpreadsheet implemented VLOOKUP with that in mind. Unfortunately, it did so by using `is_numeric` on its comparands, and so treats numeric strings as if they were numbers. This PR replaces those tests with `is_int() || is_float()`. The earlier PR used `is_string()` instead as a proxy for "not numeric" but that required other changes.
2024-08-20 00:02:48 -07:00
oleibman f3ae0bd944 Merge branch 'master' into atsign 2024-08-02 09:01:06 -07:00
oleibman b1e5e326ac Merge branch 'master' into issue4113 2024-08-02 08:42:52 -07:00
oleibman bbf9d15cb2 Php-cs-fixer Enforcing New Rules
The latest release seems to not want you to give a class element both a Php type and a doc-block type. I used the "fix" operand to delete the redundant doc-block declarations, with no other changes. So there should be no change to executable code.
2024-08-01 10:54:54 -07:00
oleibman 85629b77a0 More Extreme Cases 2024-07-31 12:47:19 -07:00