298 Commits

Author SHA1 Message Date
oleibman 1876d6062f Permit Ignoring 'Misleading Format' Tag
Building on PR #3508 and PR #4393, which allowed ignoring 5 different cell 'errors'. Adding this new one should have been dead easy, but MS, in its own inscrutable way, decided to complicate this by making the xml attribute require its very own namespace, unlike any of its relatives.

There are supposed to be several ways to activate this tag. One is to enter a date in cell A1, then in cell B1 enter the formula `=A1`, and set B1's numeric format to `General`.
2026-06-16 19:45:13 -07:00
oleibman 9019a9c9da Merge commit from fork 2026-04-18 23:43:10 -07:00
oleibman 5d6d7d537f Merge branch 'master' into csvnonutf8 2026-04-05 00:03:05 -07:00
oleibman 162fd2ce5b Add Unit Test 2026-03-27 22:54:55 -07:00
oleibman 38a8330748 More Extendability for CSV Reader
A follow-up to PR #4837. PR #4827, to which I am not necessarily committed, shows that there could be a use case for letting a user perform customized logic to convert a non-UTF8-encoded CSV. In addition, several other CSV Reader properties require the use of static or locale properties, which is somewhat problematic; this PR allows them to be set as instance variables, falling back to static/locale only when unset.
2026-03-27 16:16:45 -07:00
oleibman 686f034e96 Merge pull request #4831 from oleibman/issue4823
Xlsx Writer Support Data URI for Images
2026-03-21 05:57:43 +00:00
oleibman dfab88262a Xlsx Writer Support Data URI for Images
Fix #4823. When writing a spreadsheet to Html, a data Uri can be used if `embedImages` is true. Reading such an Html spreadsheet and attempting to write it to Xlsx results in an Exception. It should be noted that Excel itself cannot open the Html properly; none of the images are present.

The PhpSpreadsheet problem arises not with the inclusion of the image, but rather with attempting to include the appropriate entry in `[ContentTypes].xml`. This PR corrects that problem.

For the record, Xls Writer does not have a problem with this situation. Just to demonstrate that, a parallel test for Xls Writer is added in addition to the new Xlsx Writer test.
2026-03-10 19:52:51 -07:00
oleibman 75680f4612 A Bit More Flexibility
And some more tests.
2026-03-09 14:50:04 -07:00
oleibman 3570cf16d1 More Coverage 2026-03-04 11:02:14 -08:00
oleibman 8fd5535fce Coverage Tweak 2026-03-03 20:42:27 -08:00
oleibman 40f7cd00db Consistent Usage of Column and Row Limits
We have identical constants defined in several places, and use literals in others. We aren't consistent in checking limits. This PR makes the use of the constants in Cell/AddressRange the "official" source, deprecates all other constants, and substitutes the constants wherever literals are used. A number of different edge case tests are added.

During testing, I discovered that `columnIndexFromString` correctly throws an exception for 4-character string, but allows `XFE` through `ZZZ`, all of which are also invalid. There are similar inconsistencies with related routines, and this PR attempts to make them operate consistently. One suprise is that throwing for `row=0` causes serious regression problems, so it continues to be permitted (but the high row limit is enforced).

Further, Reference Helper sometimes dips into negative numbers, resulting in totally unexpected results (-1 affects column Z, -2 column Y, etc.). It is changed to ignore rows and columns outside the limits.
2026-03-03 19:04:11 -08:00
oleibman 015afae320 Ods Reader Style Support (Last) - Column Styles (Partial)
Continuing the work of PR #4810 and PR #4813 and PR #4814. According to the spec for LibreOffice, the xml for both coluns and rows allow a `default-cell-style-name` attribute. However, my testing indicates that using that attribute with a row doesn't result in the results I would expect; furthermore, LibreOffice doesn't seem to use that attribute in association with a row (it does use it for columns). For rows, it fills the unpopulated rows in the cell with a repeated table cell with the appropriate style. These filler cells have been a source of problems for us, and I'm not willing to add them at this time (maybe in future). So, if a style is applied to a row in PhpSpreadsheet, it will be reflected in all cells in that row until `highestDataColumn`, but no further.

Since LibreOffice does support adding a style to a column both in the UI and the Xml, it should be a little easier. But its support is imcomplete as well - when reading a spreadsheet, the UI will apply the style only to the rows that are defined in the xml. Again, this requires filler rows for the rows beyond `highestDataRow`, and, again, I am not willing to add those. However, it is important to process the column style when reading because, unlike the case with rows, the cells which are defined in the column may omit style data altogether if the style matches the column style.

There has till now been no support for `ReadDataOnly` (default false) and `ReadEmptyCells` (default true) for Ods Reader. These are now added. ReadEmptyCells is especially important and it would be sensible to usually set it to false. The reason is that LibreOffice usually supplies a width for all the columns mentioned in its row fillers, and PhpSpreadsheet needs to create ColumnDimensions for each of those as a result, resulting in much larger xml than one would expect when the spreadsheet is saved. This arose when I was testing this change - it has always been the case, but nobody has raised an issue about it. We avoid this problem by ignoring the extra columns for ReadEmptyCells false. But this requires a little redundancy in the code. We need to define styles for an entire column before we define styles for the cells in the column, but we don't need to define column widths beforehand. So, if ReadEmptyCells is false, we need to process the columns for styles, then process the cell data (so that we know what `highDataColumn` is), then process the columns again but this time for widths (ignoring columns beyond highDataColumn). If ReadEmptyCells is true, we can process column styles and widths in a single pass.
2026-02-23 17:22:08 -08:00
oleibman 97f63c801f Edge Case
If no `style:default-style` with `text-properties`, use style `Default` with `text-properties` for default.
2026-02-14 23:19:35 -08:00
oleibman 53a72cb18a Slight Improvements for Currencies 2026-02-11 17:15:52 -08:00
oleibman 6252ff325e Merge branch 'master' into fix/ods-read-filter-repeated-columns 2026-02-10 20:03:51 -08:00
oleibman ff03307cce Merge pull request #4801 from IndrekHaav/css-size
Add support for image CSS size in millimetres
2026-02-11 03:51:37 +00:00
QDenka b392854c9c Fix ODS reader column misalignment with read filter and number-columns-repeated
When using a read filter with the ODS reader, cells with
table:number-columns-repeated containing data were incorrectly handled.
The read filter was only checked for the first column of a repeated
group - if it didn't pass, the entire group was skipped, even if
other columns within the range should have passed the filter.

This caused column data misalignment where filtered columns would
either be missing or contain data from wrong positions.

The fix ensures that:
1. When the first column of a repeated group fails the filter, the
   reader checks if ANY column in the group passes before skipping
2. During data writing, each repeated column is individually checked
   against the read filter

Fixes PHPOffice/PhpSpreadsheet#4802
2026-02-08 13:54:04 +00:00
Indrek Haav eafca4a3a8 Add unit tests 2026-02-07 00:23:56 +02:00
oleibman c9b01653e7 Coverage Tweak 2026-01-31 00:40:47 -08:00
oleibman 50a7552f12 Option to Whitelist External Images
Loading external images from a spreadsheet can subject the caller to security exploits. For those who think they need something between not loading any external images (the default and our strong recommendation) or loading them all unconditionally (the current alternative), a callback can now be provided to indicate whether a specific image is okay to load. We continue to urge caution in using this option.
2026-01-30 22:43:21 -08:00
Thomas Lallement 059a75880e Merge branch 'master' into drawing-in-cell 2026-01-06 09:38:09 +01:00
oleibman 60a04419cc Rowspan in Html
Fix #1319, which went stale in 2020, and is now reopened. Rowspan is not showing up when saving some spreadsheets as Html. There is some logic concerning property `isSpannedRow` which indicates that this is deliberate, but I have no idea what purpose it serves. It leads directly to this issue, and also adversely affects (in a minor way) some samples (e.g. 17a_Html), where merged cells maintain their text but lose their top and bottom padding. After discarding this logic, the reported problem goes away, the samples look better, and no tests fail. So, whatever its purpose, it wasn't tested for. This PR permanently removes the property, and adds a little additional bulletproofing. A minor accommodation is needed for Tcpdf in one place.

This PR probably deletes more lines from Html Writer than it adds. It would not surprise me if this is one of those unusual cases where Coveralls reports a decrease in coverage despite the fact that all the new code is covered.
2026-01-01 16:34:56 -08:00
Thomas Lallement 35074f377b Finalize XLSX In-Cell Drawing Writer 2025-12-31 13:07:21 +01:00
Thomas Lallement 67f57394ac Merge branch 'PHPOffice:master' into patch-1 2025-12-31 12:04:31 +01:00
oleibman 84747121a1 Changes to WEBSERVICE
This PR started because the documentation on how to configure an Http client was out of date. However, as I investigated further, I found problems. GuzzleHttp, a client mentioned in the documentation, for example - it probably works fine when executed from a browser, but it does not work for `https:` requests from the Windows command line. See https://github.com/guzzle/guzzle/issues/2601, where a user notes that Guzzle's own program to demonstrate how to use it doesn't work, a result that I can confirm is still true. A linked explanation says that the solution is to explicitly specify a path to a CA bundle. For starters, this is impractical from our perspective. One possible solution is to change a php.ini option which is not needed for any other purpose, and which probably needs to change frequently - a burden on users who follow that route. An alternative solution is to use a method `request` to specify the path to the certificate store; this also will need to change from time to time, and, worse, the only method defined in ClientInterface is `sendRequest`, so using this solution isn't client-agnostic, which is a stated goal of https://github.com/PHPOffice/PhpSpreadsheet/commit/7cb4884b96174eb611621635e6fb603ef54178f7. Additionally, it is not clear why an external interface is needed rather than a call to file_get_contents, used elsewhere in PhpSpreadsheet, and not requiring a path to a certificate store.

I also believe that automatically evaluating WEBSERVICE for any arbitrary argument is not a good idea. I am adding a domain whitelist which the user must populate. For domains not in the whitelist, the calculation will revert to `oldCalculatedValue`, which is good enough for pass-through purposes, which probably encompasses most cases. That is how Excel behaves by default - it disables WEBSERVICE calls when it opens a spreadsheet which contains them. For cases where the user adds a new WEBSERVICE call, there is a choice of whitelisting the domain, or getting the result in some other way and using `setCalculatedValue` to store it.

Finally, when a WEBSERVICE call *is* evaluated, it will now accept a cell-address argument rather than just a literal string as is now the case.
2025-12-19 10:12:50 -08:00
oleibman 1daaad2576 Xlsx Reader ListWorksheetInfo Honor readEmptyCells
Fix #3255, another oldie (3+ years). Allow the ability to only count rows and columns with data. To avoid a breaking change, keep present logic unless Reader `readEmptyCells` attribute is set to its non-default value, i.e. `false`. This adds very little overhead, and gives a result that I think many users would prefer.
2025-12-13 20:14:11 -08:00
oleibman 65c0477e88 Edge Case 2025-12-01 22:35:43 -08:00
oleibman 98ca50e9fe Handle Surrogates If Read
It is probably very anal of me to do this. Excel does it. I can't see it happening in the wild.
2025-12-01 16:57:42 -08:00
oleibman 0a96e52457 Additional Test 2025-11-27 23:43:31 -08:00
oleibman 0faea6c1c1 Slightly Better Support for Escaped Characters in Xlsx Reader/Writer
See [Discussion 4724](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4724)

PhpSpreadsheet converts all control characters (x00-x1f) in strings to and from a form which Excel recognizes (e.g. `x1c` becomes `_x001C_` when writing, and vice versa when reading). There have historically been 3 exceptions which go unconverted - tab (x09), line feed (new line) (x0a), and carriage return (x0d). PR #4536 removed those exceptions, but that caused some problems; these were fixed by PR #4619, but the exceptions were restored.

The referenced discussion deals with a spreadsheet with a cell containing `_x000D_`, carriage return. Although the writer no longer converts to that string on output, the reader should be able to handle it on input. In fact, the reader ought to handle any string of the form "underscore x 4-hex-digits underscore", whether or not it represents a control character.

And there's an interesting edge case. If a user enters into a cell the string `A_x0030_B`, it needs to be handled as-is. Excel handles this by writing it out as `A_x005F_x0030_B`, i.e. substituting `_x005F_` for the first underscore, so that the reader sees `_x005F_` (converting it to underscore) followed by `x0030_B` (no leading underscore, so no conversion). PhpSpreadsheet could probably handle this by converting all underscores on write, but I am trying to emulate Excel and do it only when needed.
2025-11-27 10:35:06 -08:00
oleibman d5b9ba68e2 New Tests 2025-10-23 12:18:59 -07:00
oleibman ee03c0a467 Add Some Coverage 2025-10-21 09:58:26 -07:00
oleibman c3a78e480d Xls Reader ListWorksheetInfo and New ListWorksheetDimensions
PR #4687 corrected how Xls Writer generated its Dimensions records. We ignore the Dimensions record on read since it does not affect our processing in the slightest. However, the PR raises the possibility that someone might wish to see the data in the Dimensions record. (The PR did an adequate test for retrieving Dimensions data, but it is not generalizable.) To accommodate such a case, we add a new ListWorksheetDimensions function to Xls Reader, similar to ListWorksheetInfo. As luck would have it, the spreadsheet with which I tested the new function produced incorrect results for ListWorksheetInfo, which was ignoring XLS_TYPE_MULRK records. So I added the necessary code to fix ListWorksheetInfo as well.
2025-10-21 07:12:20 -07:00
oleibman b5ba4ffa24 Merge pull request #4655 from oleibman/issue850
Better Support For Style Alignment Read Order
2025-10-11 19:26:32 +00:00
oleibman 7c9f42e9ea Merge pull request #4676 from oziriemeka/fix/4505-vml-namespace
Xlsx: register x and o namespaces for VML shapes; add test for #4505
2025-10-11 18:38:00 +00:00
oleibman db1aba6554 Better Sample File 2025-10-09 08:19:12 -07:00
karrakoliko b8687edd53 fix: do not trigger Undefined array key "x" 2025-10-04 16:15:27 +07:00
Emeka Oziri 8fcde62db6 Xlsx: register x and o namespaces for VML shapes; add test for #4505
Fixes SimpleXMLElement::xpath(): Undefined namespace prefix when reading VML comments/shapes by registering x: (Excel) and o: (Office) namespaces alongside v:.

Includes:
- tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4505Test.php
- tests/data/Reader/XLSX/issue.4505.xlsx

Refs: https://github.com/PHPOffice/PhpSpreadsheet/issues/4505
2025-10-03 23:37:56 +01:00
Thomas Lallement 9920935fdb Support Read Image in Cell 2025-09-27 18:12:37 +02:00
oleibman dbff58a532 Better Support For Style Alignment Read Order
Fix #850 (marked stale many years ago, but now reopened). User had a typo in their script which would have caused problems no matter what. However, it exposed another problem. Style Alignment Read Order was supported only by the Xlsx Reader and Writer, but it could have been supported pretty easily for most other formats. This PR adds support for the following:

- Xls (read and write)
- Html (write, and read using inline styles). Html reader does not yet process most classes.
- Pdf (write). PhpSpreadsheet does not have a Pdf reader.
- Ods (write). PhpSpreadsheet does not yet support reading most Ods styles.
- Xml (read). PhpSpreadsheet does not have an Xml writer.
- Gnumeric (no change). It appears that the Gnumeric product does not support this attribute.
- Csv (no change). Csv does not support any styles.
- Slk (no change). Slk does not support non-Latin characters, so this attribute doesn't make sense for it.
2025-09-19 14:15:05 -07:00
oleibman fff2373b39 Merge branch 'master' into issue4584 2025-09-16 23:48:50 -07:00
oleibman 31d1cd7e17 Minor Tweaks 2025-09-14 01:20:24 -07:00
oleibman 9df8ceb5c0 Minor Improvements to Reader/Writer Coverage 2025-09-14 00:18:08 -07:00
oleibman dc25bc1ac4 Coverage Tweaks 2025-09-12 00:41:14 -07:00
oleibman 5082b35709 Conditional Formatting in extLst
Fix #4629. Excel Xml can specify Conditional Formatting in 2 ways - either using a `conditionalFormatting` tag as a child of `worksheet`, or in a slightly different manner as a child of `worksheet->extLst`. Although these are both handled by PhpSpreadsheet, the former is lost if there exists a latter whose cell range (`sqref`) matches it. This PR merges the former with the latter in that circumstance, preserving both.

The issue also notes that `font` and `stopIfTrue` are not handled correctly. Support for those was missing in the `extlst` handling, and is now added with this PR.
2025-09-05 11:13:09 -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 f51ec365c5 Handle Google-only Formulas Exported from Google Sheets
Fix #1637, which went stale but is now re-opened. When Google Sheets exports a document to Xlsx or Ods, it replaces Google-only formulas with something that Excel or LibreOffice can handle. In the test case accompanying this PR, cell C1 on Google Sheets contains `=flatten(A1:A5,B1:B5)`. On export, C1:C10 (the actual result is a 10*1 array) are changed to `=IFERROR(__xludf.DUMMYFUNCTION("flatten(A1:A5, B1:B5)"),1.0)`, where `1.0` is replaced by the calculated value for each cell in question.

The issue reports an Internal Error when evaluating such a formula. I am unable to duplicate that. However, PhpSpreadsheet evaluates the cell as a `#NAME?` error rather than the correct value (1.0 for cell C1). The reason is that `__xludf.DUMMYFUNCTION` does not match the regexp for formulas, but does match the regexp for defined names. Not finding such a defined name results in the Name error. Altering the formula regexp to recognize `__xludf.` is easy, and solves the problem.
2025-08-10 14:45:05 -07:00
issa a3588b2c22 Add test for unsupported icon sets 2025-08-09 07:23:18 +09:00
issa 0327b49060 Added Conditional Formatting: IconSet for Xlsx (#4560) 2025-08-07 08:59:11 +09:00
oleibman b489fb3a17 Merge branch 'master' into issue4539 2025-07-21 21:23:15 -07:00