286 Commits

Author SHA1 Message Date
oleibman 7d0f2ad706 Avoid Hard-Coding Some Chart Xml Attributes
Writer/Xlsx/Chart hard-codes a lot of output values. While nobody has reported a problem involving these, it makes sense to me to copy those values over from what Xlsx/Reader/Chart read, rather than hard-coding them. This involves adding some new properties to Chart and Layout, all, naturally, initialized to the values that we have been hard-coding.
- Chart\date1904
- Chart\lang
- Chart\pageMargins
- Chart\pageSetup
- Layout\bodyPr

With one exception, I have not investigated any of the new properties in depth. That may come in time. The one I did look at is `date1904`. Chances are that it should match the equivalent spreadsheet setting, but it won't matter if there are no dates on your chart, and it often won't matter even if you do. It may well matter if you are using a `date axis`. While looking into that, it became apparent that some Shared Date conversions need to be a bit more flexible, specifying an optional `calendar` parameter rather than relying on the Spreadsheet `calendar` (which is not accessible while processing the chart) or the Shared\Date `calendar` (which is accessible).
2026-06-16 20:08:46 -07:00
oleibman c5e0e261d5 Merge pull request #4911 from oleibman/issue413
Chart DataTable
2026-06-13 03:36:44 +00:00
oleibman dbea64cb03 Chart DataTable
Fix #413, which went stale in 2018 and is now reopened. A DataTable can be used on a chart in place of a Legend (or in addition to one, but it doesn't really make sense to have both). The fix was substantially developed by @topaDev before the issue went stale. This PR provides basic support for reading and writing DataTables on charts. The new sample on this PR shows them in action. They have obscure features which are not implemented (e.g. `glow`); those will have to wait for another day.
2026-06-11 06:43:42 -07:00
oleibman 6a0d4ff527 No lumOff for Radar Charts
Fix #661 (marked stale in 2018, but now reopened). That issue was already mostly resolved by many changes to Xlsx Chart Writer logic some time ago. However, a new problem popped up. PR #2950 added `brightness` logic to Xlsx Reader and Writer. That was done primarily for the benefit of scatter charts. Xlsx Writer writes two brightness properties `lumMod` and `lumOff`. These values are complete complementary (if you know one, you know the other), so I am not sure why both are needed, but my scatter chart testing indicated that they were. It turns out that Radar charts can also set brightness, but, if the writer specifies both `lumMod` and `lumOff`, the resulting chart is slightly off. There may be more to this, but that's all I can deal with for now - I suppress writing `lumOff` if we're writing a radar chart. If there are other problems in this area, I will wait for them to be reported. None of the existing radar chart samples used the brightness properties; however, the example attached to 661 did. It is added as a new Sample, and tests are added.
2026-06-09 12:26:11 -07:00
oleibman 3d86f3d13c Update Samples
... demonstrating how Excel sorts.
2026-05-31 01:15:04 -07:00
oleibman 5c8c20686f Combine Dependabot Changes
Someting seemed to be wrong with push setup. We'll see if it's fixed.
2026-05-01 19:17:45 -07:00
oleibman 97aa5260d4 Ods Reader Style Support Part 3 - Borders
Continuing the work of PR #4810 and PR #4813. All "real" borders are implemented. Pseudo-borders (outline, vertical, horizontal, inside, and allBorders) are not because I'm not really sure how, or even if, Ods handles them. However, Sample20_Read_Ods demonstrates a way to emulate `outline` using just the real borders. In template OOCalcTest.ods cells B18:C19 are merged, and the merged cell has multi-colored borders, something which `outline` isn't able to do. Ods Reader handles this by assigning the border style first to cell B18 (which is what Ods wants, and it doesn't hurt Xlsx/Xls) and then to cells B18:C19 (which is what Xlsx and Xls want, and it doesn't hurt Ods).

Ods Reader changes still to come
- Style applied to entire row
- Style applied to entire column
- Parent styles?

Ods Writer changes still to come
- Style applied to entire row
- Style applied to entire column
- Parent styles?

Not currently on my to-do list
- Pseudo-borders
- Subscript and superscript fonts (these really only make sense for RichText, and I'm not sure how Ods handles RichText)
- Default border, alignment, and protection. I'm not convinced there's a use case. Ods handles its defaults in two different manners, and I don't want to spend the time trying to understand it without justification.
2026-02-19 17:54:39 -08:00
oleibman 0c64e18cbd Ods Reader Style Support Part 2 - Alignment, Protection, Default Fill
Continuing the work of PR #4810.

Ods Reader changes still to come
- Default border, alignment, protection
- Font
    - subscript
    - superscript
- Borders (up next)
- Style applied to entire row
- Style applied to entire column
- Parent styles?

Ods Writer changes still to come
- Default border, alignment, protections
- Style applied to entire row
- Style applied to entire column
- Parent styles?
2026-02-18 00:56:28 -08:00
oleibman 5f460e6ba7 Some Corrections
Sample 20_Read_Ods exposed some problems which are now corrected.
2026-02-16 01:19:26 -08:00
oleibman 53a72cb18a Slight Improvements for Currencies 2026-02-11 17:15:52 -08:00
oleibman fb55d1b6e4 Ods Writer Support Some Number Formats
Redo of PR #4799 due to failed attempt to resolve merge conflict.

Fix #4798. Partially address #3961. Ods Reader supports very little related to styling. Ods Writer supports many styling details, but has not heretofore supported Number Formatting. 3961 addresses both issues; I created 4798 specifically for the Writer side.

Writing number formats to Excel is pretty simple - you just supply a string and that is used directly in the Xml. Ods is much more complicated - it requires Xml nodes that give a complete description of the styling. For that reason, it is difficult and painstaking to convert from the string that Excel (and PhpSpreadsheet) uses to what Ods requires.

This PR provides code to support almost all the styles defined as constants in Style/NumberFormat. It also allows the user to add code to handle otherwise unhandled styles. New Sample55_DefinedStyles demonstrates the use of all the constant styles, plus the addition of a couple of custom styles. I may be amenable to adding some unsupported styles to the built-in list, but the custom style option will always be around in case I am being slow or unreasonable.

This PR does not fully support Ods Reader handling of styles. However, based on the new Writer output, it will often be able to guess the true type of numeric items and assign an appropriate style for that type. So, for example, if it can identify the field as a date, it will assign a date style. It will not always match the style in the sheet being read, but it is a big advance from just formatting the data as a generic number.
2026-02-10 23:48:49 -08:00
oleibman 15fbc9a9d9 Headers and Footers in Pdf
Fix #3159, at least as far as we can. Requester would probably prefer that we automatically translate the PhpSpreadsheet header and footer information to forms that the Pdf vendors can handle. That seems like it would be very difficult. On the other hand, we can add some new properties to the Pdf writers to make it *relatively* easy for the user to define their own headers and footers for the writers.

Mpdf, as mentioned in the issue, can already handle this in conjunction with the `editHtmlCallback` property. This is demonstraded in Sample21c, which is now renamed to something more descriptive, `Mpdf_Custom_Headers`. That is the only change needed for Mpdf.

Tcpdf, which currently automatically prevents any footers or headers, needs some new properties to allow them. Even with the new properties, a user would need to extend both PhpSpreadsheet's Tcpdf Writer, and the vendor's own class (extending that class is actually the vendor's recommendation). A new sample `Tcpdf_Custom_Headers` demonstrates how this would be done.

Dompdf has 2 ways to add headers and footers. One is pretty good at styling, but doesn't offer much flexibility for dynamic properties other than the current page number; it can't handle different odd/even/first headers, nor the number of pages in the document. The second makes the dynamic properties possible, but seems difficult to style. Two new samples `Dompdf_Custom_Headers` (using `editHtmlCallback`) and `Dompdf_Canvas_Headers` (using a new protected method `callPageScript`) illustrate the use of each.

None of the samples demonstrates the full capabilities of what can go into a header or footer. I consider that out of scope; enabling the ability is one thing, perfecting it is quite another.
2026-01-26 21:08:46 -08:00
oleibman 050743f179 Eliminate Redundant Line 2026-01-15 22:37:44 -08:00
oleibman 561308b307 Misused and Deprecated Html Attributes
The table attributes `border`, `cellspacing`, and `cellpadding` are used in Html Writer. They are deprecated in Html5 in favor of css attributes. Further, their use is redundant or outright wrong. Their use is eliminated. A sample is added to show how equivalents might be used.
2026-01-12 23:22:03 -08:00
oleibman 002f618416 More Tests and a Sample 2026-01-06 11:50:31 -08:00
oleibman 6fbeeb705b Use Default Style for Unstyled Tables
Using a default style looks better than leaving them unstyled. User has ability to ignore unstyled tables as before, but I don't know why one would want to.
2025-12-29 17:34:55 -08:00
oleibman c0e77c993f Miscellanea 2025-12-26 18:21:37 -08:00
oleibman 11d60f6ace Add Sample for Sort By Column 2025-12-13 10:24:07 -08:00
oleibman d727455173 Document Excel's Behavior When Sorting Different DataTypes 2025-12-11 17:37:17 -08:00
oleibman 0575e2062c Minor Modifications to Sample Names and Locations 2025-12-08 08:53:59 -08:00
oleibman 341b999976 Improve Sample Output 2025-12-04 17:55:18 -08:00
oleibman 8e4ebd97e1 Final Tweak (I Think) 2025-09-15 21:29:46 -07:00
oleibman 4b8f4e8d66 Upgrade Phpstan
A lot of changes since its last update, including one that I requested.
2025-09-11 20:02:57 -07:00
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
issa 782610d02b Add sample for Conditional Formatting with Icon Sets in Xlsx 2025-08-09 23:24:31 +09: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 eb486262fa Support Current Office Theme
A while back, Microsoft introduced changes to the default theme colors and fonts. We are adding support for this new theme so that users can use it easily on new spreadsheets if they wish. (It is already supported when using the Xlsx Reader to load an appropriate file.) The old theme was described by constants COLOR_SCHEME_2013_PLUS_NAME and COLOR_SCHEME_2013_PLUS; these are deprecated in favor of COLOR_SCHEME_2013_2022_NAME and COLOR_SCHEME_2013_2022. The new theme is described by constants COLOR_SCHEME_2023_PLUS_NAME and COLOR_SCHEME_2023_PLUS. PhpSpreadsheet's default theme remains COLOR_SCHEME_2007_2010, to avoid breaking changes.

A third optional parameter `$spreadsheet` is added to setThemeColorName. If specified, the default font names for the theme will be applied to the default style for the spreadsheet. You can thus use the new theme with its relatively new default `Aptos Narrow` font. IMHO, that isn't necessarily a good choice, but it is available. MS stores the new font in a different location than other system fonts, and that can lead to portability problems, e.g. if your spreadsheet uses Aptos and you export it to Html, browsers will not be able to find the font and a substitute font will be used.
2025-06-03 21:36:05 -07:00
oleibman 277c8d5615 Merge branch 'master' into issue1154 2025-06-01 09:17:22 -07:00
oleibman ba079b3967 Various Writers RichText TextElement Should Inherit Cell Style
Fix #1154, which went stale over 5 years ago, and is now reopened. RichText elements can be a Run, which sets its own style, or a TextElement, which doesn't. As the issue states, TextElement handling is inconsistent. This PR forces it to inherit the style of the cell. As implemented, this will change it to a Run when it is read in, but there should be no practical difference as far as the end-user is concerned. There is no change as far as Run is concerned. The user suggested 3 options - TextElement and Run both inherit for any unspecified style elements, TextElement inherits and Run does not, neither inherits. Option 2 makes most sense to me. Option 1 may not even be possible (we can't tell if, say, the user explicityl set Italic to false, or if that was just the default choice).

Tests are added for all of Xlsx, Xls, and Html. Html reading of RichText elements is not well-supported. The tests are fairly difficult to understand. A new sample is added to demonstrate this change.
2025-05-25 21:22:12 -07:00
oleibman c35cc943e8 Hyperlink Styles
Fix #1632. Excel automatically supplies a style for cells which contain hyperlinks (e.g. underlined, and blue text changing to purple after the link has been followed). PhpSpreadsheet cannot handle the style automatically. The user can, with some effort, specify a style for the cell which mimics Excel's choice (except for the color change after following).

Examining a sheet with a hyperlink created through Excel, it appears that Excel creates 3 different entries in styles.xml, one for cellStyleXfs, one for cellXfs, and one for cellStyles. It is difficult for me to figure out how they interrelate. This is especially so since PhpSpreadsheet outputs only 1 entry (for the default style) for each of cellStyles and cellStyleXfs. However, it appears that only the cellXfs entry is required, and, when it specifies a font whose color specifies `theme="10"` rather than an rgb value, the style works as expected.

In order to implement this, it is necessary to add a `theme` property, with setter and getter, to Style/Color. There are 12 possible values for theme, 0-11 representing 0=dk1 1=lt1 2=dk2 3=lt2 4-9=accent1-6 10=hlink 11=folHlink. This PR is mainly to allow the use of hlink, but the others are also usable if a use case arises for them. If a theme is set for Color, Xlsx Writer will use the theme rather than rgb when generating the color xml. Other writers will continue to use rgb rather than theme, so there is a use case for setting both if you want to generate both Xlsx and some other format.

The `theme` property will, for now, be ignored except for Font. There is probably a case to be made for using it for Fill, and maybe for Border and other areas that I haven't yet considered. I will wait for someone to make that case before adding those.

In order to make it as easy as possible to use this, a method `setHyperlinkTheme` is added to both Style/Color and Style/Font. The one in Color sets `theme` to the appropriate value. The one in Font calls the one in Color, and also sets `underline` on (this will be honored by other writers in addition to Xlsx).

Samples which use hyperlinks are updated to use `setHyperlinkTheme`. So is `Reader\Xlsx\HyperlinkTest`, with appropriate tests added.
2025-05-20 22:54:08 -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 f1a61c4c6b Phpstan Tweaks
Phpstan level 10 reports an enormous number of errors. So does the excluded missingType.iterableValue. I do not plan to introduce either any time soon. But I will submit piecemeal changes from time to time. Changes will be mostly limited to phpdoc type declarations.
2025-04-06 18:14:59 -07:00
oleibman ecbd702628 Phpstan and Samples
Phpstan hasn't identified any errors in Samples in a long time. But, as it turns out, one particular error is suppressed:
```
Variable $helper might not be defined.
```
This error would be generated by almost all samples, and the errors that it suppresses will become problematic if we move to Level 10. We are not yet committed to doing that, but it is pretty easy to write a script to change the samples so that error no longer happens, and there isn't really any reason to delay doing so. The results of that script constitute this PR.
2025-04-05 13:54:20 -07:00
oleibman e32447c4be Phpstan Level 9: Last 2025-03-31 21:53:47 -07:00
oleibman 584c8662d7 Final Touch-up 2025-03-26 23:47:03 -07:00
Mikko a67e778b50 Conditional and table formatting support for html writer 2025-03-26 15:30:33 +02:00
oleibman 19055da8b6 Better Handling of Chart DisplayBlanksAs
Fix #4411. User copied some code from a PHPExcel program which set DisplayAsBlanks to `0`. This resulted in what Excel deemed a corrupt spreadsheet using PhpSpreadsheet. The only values allowed for that field are `gap`, `zero` (not `0`), and `span`. PHPExcel used `0` as a default, and got away with it because it ignored the value entirely when writing out the spreadsheet, using `gap` all the time.

I had to choose between throwing an exception and just using the default when an attempt is made to set that property to an invalid value. An exception just seems more punitive than helpful to me, especially if we want people to migrate from PHPExcel, which still seems to have a large user base. So I've gone with using `gap` in place of an invalid value. Note that, according to https://learn.microsoft.com/ru-ru/openspecs/office_standards/ms-oe376/b5c5c694-21d9-437c-9a4a-21e0e843eed8, `gap` is used as the default whenever it is permitted for the chart in question; and, when it isn't permitted, the chart will use its default method (which will always be `zero`).

There were no tests nor samples for this property. All the tests and samples which use it use only `gap`. I have added a small test, and a new sample to illustrate the difference between the 3 options.
2025-03-19 20:21:14 -07:00
oleibman c84960fb69 Phpstan Level 9 - Part 2 of Many 2025-03-08 23:22:15 -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 898fa0bf60 Phpstan Bleeding Edge Part 1 of Many
We currently use Phpstan Release 1. Release 2 has been available for some time, and we would like to stay current if possible. In order to get to Release 2, we first have to pass the "bleeding edge" tests for Release 1. I will do this by generating a new baseline using bleeding edge, then fix the baseline errors over several different PR's. This is the first of those.
2025-02-12 07:48:32 -08:00
oleibman 4d6db5d1a7 Merge branch 'master' into arraysexplicit 2025-02-06 22:44:41 -08:00
oleibman 3c02232b2a Merge branch 'master' into pdfchart 2025-01-29 17:40:05 -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 4a2b731ec2 Pdf Charts and Drawings
Fix #4129. Fix #4168. Html Writer, which all the Pdf writers use, defines its charts and drawings (henceforth I will just use charts for this discussion) using position:absolute and z-index. Browsers handle this correctly, but none of the Pdf writers do, and I can't think of an alternative method of styling them. The result is that the charts take up too much or too little room on the Pdf.

I suggested in the two discussions that treating the areas covered by the charts as merged cells might mitigate the problem. I think there are too many unknowns to do so automatically (and see next paragraph). However, adding to Spreadsheet new methods `mergeChartCellsForPdf` and `mergeDrawingCellsForPdf` allows the end user to do this if desired. The new methods are exercised for charts in samples/Chart/32_Chart_read_write_PDF, the results of which are much improved as a result. New samples/Pdf/21f_Drawing_mpdf does likewise for drawings.

The new methods alter the spreadsheet they are working on, which could be a problem if you still wish to work with the spreadsheet after writing it to Pdf. In that case, making a copy of the spreadsheet, then calling the new methods on the copy, and writing the copy to Pdf is probably best.
2025-01-25 19:20:37 -08:00
oleibman ed66270d9c Merge pull request #4325 from oleibman/sampsup
Fix 2 Samples
2025-01-22 03:16:48 +00:00
oleibman 191bf214d9 Fix 2 Samples
Custom properties would be better in this context using j (no leading 0) rather than d (leading 0) for day of month.

Properties has the same problem, and also needs backslashes before p to make it part of a <sup> tag.
2025-01-21 19:10:54 -08:00
oleibman 9b122cd028 Use Composer/Pcre Part 1 of Many
The native preg functions (preg_match, preg_replace, etc.) often require us to add a lot of useless boilerplate code to satisfy Phpstan, Scrutinizer, etc. Composer/Pcre offers us a way to remove that boilerplate, thereby giving us a cleaner codebase. I decided to try it on a few modules, and saw a result that clearly demonstrated the usefulness of doing this (aside from the cleaner codebase).

Sample 22_Reader_issue1767 reads an Xlsx spreadsheet with complex sheet names used in defined names, and writes it to Xlsx and Xls output files. When I changed Writer/Xls/Parser to use Composer/Pcre, this sample failed in many different places writing the Xls file. It turns out that some regexes were failing not because the string didn't match, but because the regex encountered "catastrophic backtracing". Composer/Pcre throws an exception when this happens; the native preg_match does return false, but we were not checking for that. The regexes in question are now changed to something which works, and formal unit tests are added for them. Finding this previously undetected error indicates that we should proceed with this change.

An alternative to using Composer/Pcre would be to test for false after all the preg calls. I have done this in the two samples changed with this PR. That seems adequate for a small number of changes, but it really just makes for more clutter considering the large number of regexps that we use in our code. I think Composer/Pcre is a better choice.

It isn't quite transparent. Composer forces all regexps to use PREG_UNMATCHED_AS_NULL, so some match fields will now be null instead of null-string (or non-existent if the unmatched field comes at the end). Our test suite doesn't report any problem (yet) due to this change, although Phpstan is sensitive to it. Several Phpstan annotations were eliminated due to this change, but some others are now needed.

It is not necessary to do this all at once. This PR addresses all the calls in Writer. I intend to address other components in several tickets.
2025-01-17 09:44:45 -08:00
oleibman 700a80346b Merge commit from fork
* Validate Post Item in Convert-Online.php

* Correct Samples - Currency, Accounting, and Downloader

* Smarter Color Formatting for Currency

* Use helper->log Rather than echo in Convert-Online

Responding to comment from @PowerKiki about use of echo for error messages. I do not believe that an exception is warranted, but other scripts use helper->log for error messages, and now so will this one.
2024-12-25 19:11:31 -08:00
oleibman 5c3ae52446 Fix Minor Break Handling Drawings
Fix #4241. Some security batches caused a minor break in Drawings, forcing `setWorksheet` to come after `setPath`. Although the problem is easily fixed in user code, this was not an intended change. Some slight recoding restores the earlier functionality where the order of calls was not important, without sacrificing the security gains. This change will be back-ported to the other active branches to which the security patch had been applied.
2024-11-25 19:54:38 -08:00
oleibman 7a1370c869 Allow Omitting Chart Border
Fix #562.
2024-10-09 06:37:25 -07:00