Commit Graph

1885 Commits

Author SHA1 Message Date
oleibman 0c8db6e7d2 Merge branch 'master' into issue1324 2025-08-07 20:33:00 -07:00
oleibman a4ee68bf1e Merge branch 'master' into issue484 2025-08-06 22:26:24 -07:00
oleibman fa2c32996a Merge branch 'master' into issue4588 2025-08-06 21:57:24 -07:00
oleibman 7689037b60 Additional Floating Point Precision Changes
Fix #1324, which went stale many years ago, and is now re-opened. It can be considered a follow-on to PR #4479 which was installed in May. The user complains of a *very* small loss of precision. This can be corrected by using `StringHelper::convertToString` in lieu of a simple cast from float to string in two places. `Style\NumberFormat\Formatter` is quite straightforward. `Writer\Csv` is a bit more complicated. If you put a float with more than 15 digits precision in a Csv, on opening it Excel will give a pop-up, saying something inaccurate like "We've corrected this for you - is that okay?" Better to avoid that by making sure to avoid too much precision when writing to Csv.
2025-08-06 17:53:04 -07:00
oleibman c4cd1b3410 Merge branch 'master' into issue4557date 2025-08-05 23:52:31 -07:00
oleibman 9c083e271d Header/Footer Images Expand "Location"
Fix #484. Fix #1318. Both went stale a long time ago. The images can currently specify their location as Left, Center, or Right. However, they also need to specify their type - first page, even pages, or odd pages (which is what is used when neither of the others is applicable). This is accomplished by adding 18 new constants to `Worksheet\HeaderFooter`, any of which can be specified as the second argument to `HeaderFooter::addImage`. Somewhat surprisingly, no changes are required to Xlsx Writer or Reader.

Xls Reader and Writer support header/footer, but do not support using images in them. No other readers nor writers support header/footer.
2025-08-04 18:15:19 -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 f65b0a2d10 Merge pull request #4570 from oleibman/complextests
Redo ComplexAssert
2025-08-03 15:56:42 +00:00
oleibman e78bca9668 Merge pull request #4556 from oleibman/xmlspace
Xlsx Writer Eliminate xml:space From Non-Text Nodes
2025-08-03 15:46:51 +00: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 6d8fc67512 Merge branch 'master' into deprecations 2025-08-02 19:07:45 -07:00
oleibman 20ac2f1940 Merge pull request #4527 from oleibman/issue4522
Minor Breaking Change to DefaultValueBinder
2025-08-03 01:48:03 +00:00
oleibman ac4befd2f7 Merge commit from fork 2025-08-02 18:06:29 -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 079dc87604 More Tweaks 2025-07-30 23:27:08 -07:00
oleibman c16eaeb6e4 Coverage Tweaks
See if we can satisfy Scrutinizer.
2025-07-30 20:55:02 -07:00
oleibman f1ce95eaa4 Shared/Date::isDateTime Handle Cells Which Calculate as Arrays
In issue #4557, the user complains, with some justification, about the way Excel handles certain calculations. We are not able to help with that problem. However, the user also notes a problem in Shared/Date when `isDateTime` has to evaluate a cell whose calculated value is an array. This is solved by flattening the calculated result to a single value.

It became obvious while working on this change that the code to set `instanceArrayReturnType` was kind of awkward. Simpler methods `returnArrayAsArray` and `returnArrayAsValue` are added to `Spreadsheet`. Even these started out a bit awkward because `Spreadsheet::calculationEngine` was defined as nullable, which really isn't true. It is allocated by the constructor, and never freed except in the destructor. It is no longer nullable.
2025-07-30 17:19:26 -07:00
oleibman 69b65d4e2a Xlsx Writer Eliminate xml:space From Non-Text Nodes
Fix #4542. PhpSpreadsheet has been writing attribute `xml:space="preserve"` to the `table` tag when writing a Table. According to the issue, Excel 2016 is treating the resulting file as corrupt. I do not have access to a version of Excel 2016 to confirm. This seems to be a bug with that release. Nevertheless, the OOXML spec, with over 100 references to `xml:space` does not indicate that it is a permitted attribute for `table`. It should only be specified for text nodes. This PR eliminates the undocumented, and unneeded, usage.

Investigating further, PhpSpreadsheet also writes this attribute for `workbook`, `styleSheet`, and `worksheet` tags. It is again undocumented and unneeded in those cases. Although all Excel releases, including 2016, apparently tolerate such usage, this PR also eliminates those.

Finally, there is one case where PhpSpreadsheet omits this tag when it is needed. When writing a cell whose data type is an inline string, and the string contains leading or trailing whitespace, the text tag needs to specify `xml:space`, and is now changed to do so.
2025-07-26 00:08:33 -07:00
oleibman a12a0d0271 Eliminate Deprecated Constants
In Theme, change COLOR_SCHEME_2013_PLUS_NAME to private (use COLOR_SCHEME_2013_2022_NAME instead), and delete COLOR_SCHEME_2013_PLUS (use COLOR_SCHEME_2013_2022).
2025-07-24 01:27:56 -07:00
oleibman 59e20db22f Merge branch 'master' into blockimages 2025-07-22 21:32:24 -07:00
oleibman b489fb3a17 Merge branch 'master' into issue4539 2025-07-21 21:23:15 -07:00
oleibman 3538c7e0af Merge branch 'master' into issue4537 2025-07-21 20:52:07 -07:00
oleibman dfb9411da7 Merge branch 'master' into replacedummy 2025-07-20 18:03:39 -07:00
oleibman 6b3cb42db2 Merge branch 'master' into issue4522 2025-07-19 16:54:27 -07:00
oleibman 36dd484c86 Merge branch 'master' into issue347 2025-07-18 23:28:48 -07:00
oleibman 4403ffc7e5 Merge branch 'master' into replacedummy 2025-07-18 22:47:10 -07:00
oleibman f1477b130f Allow Replace of Dummy Function with Custom Function
Custom functions were introduced recently, with a restriction that non-custom functions could not be replaced. However, reviewing a recent issue has led me to the conclusion that it might sometimes be impractical to implement an Excel function in PhpSpreadsheet for all users, but it could still be helpful to some users to offer an implementation anyhow.

The Excel ASC function is currently unimplemented in PhpSpreadsheet, and is a candidate for replacement using the functionality added in this PR. This PR supersedes PR #4513, which I will now close, and its earlier incarnation PR #4511. For reasons discussed in 4513, I don't see a way forward for implementing the Excel ASC function in a way that would be generally usable. However, this PR would permit a user to implement ASC in a way which would satisfy the user's local requirements. See the new `testReplaceDummyFunction`; I think, or at least hope, that, despite the deficiencies of 4511 and 4513, this might satisfy the author's requirement.
2025-07-18 22:01:59 -07:00
oleibman a9c6cbe146 All Readers - Allow or Forbid Fetching of External Images
Add to all readers the option to allow or forbid fetching external images. This is unconditionally allowed now. The default will be set to "allow", so no code changes are necessary. However, we are giving consideration to changing the default.
2025-07-18 21:22:09 -07:00
oleibman 450c900ccd Merge branch 'master' into issue1104 2025-07-17 21:44:59 -07:00
oleibman 7c1da83f8d Merge branch 'master' into readdynam 2025-07-17 21:31:08 -07:00
oleibman 2735c40179 StyleMerger Use Copy Of baseStyle
Using baseStyle directly can lead to the by-reference problems associated with Cell and Style.
2025-07-17 07:45:55 -07:00
oleibman ffeaa42583 Emulate Xlsx More Closely
Xlsx conditional styles cannot be used to change alignment, nor font family, nor font size.

Conditional::getStyle currently allocates a new style as an unconditional style; it is changed to do so a conditional ctyle.

Border should not be conditionally merged if borderStyle is OMIT.

Inline Css was generating `class="gridlines gridlinesp"` for all cells. It is changed to use the worksheet settings to decide which classes to use.
2025-07-16 22:11:53 -07:00
oleibman a15091737f Html Writer Conditional Formatting Inline Css
Fix #4539. Conditional Formatting was recently added to Html Writer. It works fine when not using inline Css. However, when using inline Css, the code inadvertently added 2 different `style` attributes (one for the unconditional style and one for the conditional style) to the same cell. This is not valid html, and results in losing the conditional styling. This PR combines the two `style` attributes into one, which will now come after the `class`, `colspan`, and `rowspan` attributes.

Aside from the new tests, this PR changes an unusually large number of existing tests. While this might normally be considered a red flag, it is not a problem here. All of the changes involve merely changing the order of attributes within html tags; none of them affect how the generated html would appear in a browser.
2025-07-15 22:22:34 -07:00
oleibman b82756de76 Don't Use htmlspecialchars When Formatting Xml
Fix #4537. PhpSpreadsheet currently changes apostrophes in text values to `'`. This is perfectly valid Xml. Issue was opened because R does not handle this correctly; this is unquestionably a bug on R's part. So I was not inclined to do anything about it. However ...

User suggested a change to how `htmlspecialchars` was called. Investigating the use of that routine in PhpSpreadsheet, I found that there was some double escaping going on for cells whose type was set to `TYPE_INLINE` - `htmlspecialchars` escaped the string correctly, but it was later written as Xml using a method which escaped the data a second time. So, a real bug in PhpSpreadsheet after all.

There was one call to `htmlspecialchars` in `Shared\XmlWriter`. I replaced `writeRaw(htmlspecialchars(...))` with `text(...)`. And one call in `Writer\Xlsx\Worksheet`, the source of the double escaping bug above; the call to `htmlspecialchars` can just be eliminated there.

Making those changes, the only remaining calls to `htmlspecialchars` are in `Writer\Html`, where they belong. As a bonus, apostrophes now wind up unescaped, so R will be satisfied (even though they should fix their bug).
2025-07-15 21:53:43 -07:00
oleibman 250394d128 Preserve 0x0a In Strings If Desired
Fix #347, which had gone stale but is now reopened. PhpSpreadsheet is automatically replacing CR-LF and CR with LF. The reason for this is unknown, although I suggest a possibility in the issue. I am not willing to make this a breaking change. This PR adds a new property `preserveCr` with setter and getter to DefaultValueBinder (and, by extension, to StringValueBinder and AdvancedValueBinder). The property defaults to false, but users who wish to preserve CR-LF and CR can set it to true for a Spreadsheet or a Reader.
2025-07-15 00:26:20 -07:00
oleibman 2d676462a3 Merge pull request #4532 from oleibman/builtinnumfmt
Excel Inappropriate Number Format Substitution
2025-07-15 06:41:18 +00:00
oleibman b5af16def9 Merge branch 'master' into issue4528 2025-07-14 23:22:15 -07:00
oleibman 98f464b41f Writer Html/Pdf Support RTL Alignment of Table
Fix #1104, which went stale over 6 years ago, and is now reopened. This PR addresses the alignment of the table, not alignment of text. Support is added for the following:

- Html. Full support.
- Mpdf. Full support, except that, when mixed LTR and RTL worksheets are output, all tables will be on the left of the page (but will be properly aligned).
- Tcpdf. Full support when all worksheets being output are RTL; no support when mixed LTR and RTL worksheets are output.
- Dompdf. No support.
2025-07-14 00:22:54 -07:00
oleibman 159059595e Minor Tweaks 2025-07-11 17:13:53 -07:00
oleibman ae4df820bf Xlsx Reader Use Dynamic Arrays if Spreadsheet Did So
By default, when an Xlsx spreadsheet is read, its calculation engine is set to `RETURN_ARRAY_AS_VALUE` for array formulas. The user does have the option to change this. However, the presence of certain metadata in the file indicates that it was saved as if `RETURN_ARRAY_AS_ARRAY` was in use. This PR tests for the metadata, and, if present, sets `...ARRAY` rather than `...VALUE`. This eliminates the need for any extra action on the user's part.
2025-07-10 18:11:41 -07:00
oleibman ace1755238 Excel Inappropriate Number Format Substitution
My system short date format is set to `yyyy-mm-dd`.
I used Excel to create a spreadsheet, and included some dates, specifying `yyyy-mm-dd` formatting. When I looked at the resulting spreadsheet, I was surprised to see that Excel had stored the style not as `yyyy-mm-dd`, but rather as builtin style 14 (system short date format). Apparently the fact that the Excel styling matched my system choice was sufficient for it to override my choice! This is an astonishingly user-hostile implementation. Even though there are formats which, by design, "respond to changes in regional date and time settings", and even though the format I selected was not among those, Excel decided it was appropriate to vary the display even when I said I wanted an unvarying format.

This PR adds a new method `replaceBuiltinNumberFormat` to undo the damage that Excel does in such a situation. It also adds an `Excel Anomalies` document to the formal documentation, just to make situations like this readily available to the community.

BTW, Excel's sabotage can be avoided by using a number format style like `[Black]yyyy-mm-dd`.
2025-07-10 17:54:52 -07:00
oleibman 9708d72ee1 Ods Reader Process Nested table-row
Fix #4528. Fix #2507. Ods Reader expects `table:table-row` to descend directly from `table:table`. But it turns out that it can be nested under `table:table-header-rows`, `table:table-rows`, or `table:table-row-group`. Similar considerations apply to `table:table-column`. Ods Reader is changed to process the nesting tags, and therefore the nested tags underneath them. This is a major change, but it doesn't seem to have broken any existing tests or samples.

No attempt is made to add any of the nesting tags in Ods Writer.

It should be noted that 4528 has an additional problem, which has been reported as issue #4530. It is not fixed by this PR.
2025-07-08 12:52:55 -07:00
oleibman 170b058049 WIP Minor Breaking Change to DefaultValueBinder
Fix #4522. Although this is technically a breaking change, it is expected that very few, if any, existing programs will be affected. Nevertheless, DefaultValueBinder is implicitly used by the vast majority of programs out there, and I am reluctant to install a breaking change for something so widespread. So I will save this change for the next breaking release, which should be PhpSpreadsheet 5.0.0. There is no current schedule for that release.

For strings consisting entirely of digits, DefaultValueBinder treats the value as a string if greater than PHP_INT_MAX, or an int otherwise. This prevents the loss of precision in large integers. This treatment dates back to PHPExcel, and has been in place since 2014.

There are several problems with this approach. Excel itself maintains
[15 digits of precision](https://support.microsoft.com/en-us/office/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3).
So, string-vs-int should be decided at 999_999_999_999_999. This is much lower than PHP_INT_MAX for 64-bit, and much higher than for 32-bit. DefaultValueBinder is changed to use that new limit.

A second problem is that DefaultValueBinder is only making this adjustment for positive integers. It is changed to test absolute value.

A third problem is that DefaultValueBinder is making this adjustment only for strings, so that if you pass the number in as an int, it will not be adjusted (and will lose precision). It is changed to apply the same test for int.
2025-07-04 20:58:03 -07:00
oleibman 3eff3b475a Merge branch 'master' into issue4521 2025-07-04 12:54:53 -07:00
oleibman 019afe055a Merge branch 'master' into issue4451 2025-07-04 09:49:41 -07:00
oleibman bfd7dc8cee Recognize "New" Mimetype for Empty File
Fix #4521. Reader/Csv (which can be invoked by IOFactory::read), checks the mimetype of files if they don't have a csv/tsv extension. It allows empty files, whose mimetype was set to `inode/x-empty` for Php5.3.11 through Php7.3.33 (except for 5.4.0). For 5.3.1-5.3.10, 5.4.0, and 7.4.0+, the mimetype is `application/x-empty`. Reader/Csv recognizes the `inode` version but not the `application` version, which this PR adds.

The person who issued the report also noted that, for a file consisting of cr-lf, Php8.1.* and Php8.2.* report the mimetype as `application/octet-stream`, whereas all other releases report it as `text/plain`. The behavior of Php8.1/2 seems to be a bug, and I cannot possibly guess all the conditions that might lead to that bug. So I will not fix that problem. Anyone who is adversely affected by it can either add a `csv` extension to the filename, or upgrade to Php8.3+, or pre-process the file (e.g. to make it truly empty) before passing it to PhpSpreadsheet. A test case to document the problem is added for documentary purposes; the test will be skipped for Php8.1/2, but run for all other releases.
2025-06-30 21:06:17 -07:00
oleibman 84acafc0bf Merge branch 'master' into writestyles 2025-06-17 21:35:23 -07:00
oleibman 0dbe154e29 Merge pull request #4503 from oleibman/issue4502
AutoColor for LibreOffice Dark Mode
2025-06-18 04:22:45 +00:00
oleibman 30369ca036 Merge pull request #4501 from oleibman/issue2760
Allow Xlsx Reader/Writer to Process Font Charset
2025-06-18 04:21:17 +00:00
oleibman d38117ffe6 Eliminate Dead Statement 2025-06-12 16:48:59 -07:00