Commit Graph

2310 Commits

Author SHA1 Message Date
gaoflow e88cd615cc Fix incomplete gamma convergence for GAMMA.DIST / CHISQ.DIST
The incomplete gamma primitive used a fixed 32-term power series with no
convergence test, so GAMMA.DIST, GAMMADIST, CHISQ.DIST(.RT), GAMMAINV and
CHISQ.INV were grossly wrong once the series argument reached ~32
(e.g. CHISQ.DIST.RT(80, 4) returned 0.806 instead of 1.74e-16).

Replace it with the standard convergence-tested regularized incomplete
gamma: series P(a,x) for x < a+1, continued fraction Q(a,x) for x >= a+1.
CHISQ.DIST.RT now uses Q directly so the right tail stays free of
1 - P cancellation. Consolidates the duplicate copy that already existed
privately in ChiSquared onto the shared primitive.
2026-08-04 08:25:36 +02:00
oleibman 8b4b934011 Merge pull request #4946 from gaoflow/fix-gammainv-tail-bracket-clamp
Expand GAMMAINV bracket so tail quantiles are not clamped
2026-08-04 02:43:29 +00:00
Feroz 21b641b8bc Merge branch 'master' into feature/sparklines 2026-08-02 23:52:33 +06:00
oleibman 85be5ac255 Merge pull request #4833 from kemo/perf/xls-reader-optimizations
Optimize XLS (BIFF8) reader performance with reduced per-cell overhead
2026-08-02 07:00:41 +00:00
Vincent Gao c497c12eb3 Evaluate GAMMA.INV via spreadsheet formula in tests; document bounded tail fallback 2026-07-29 04:59:19 +02:00
gaoflow 2a82540c1f Expand GAMMAINV bracket so tail quantiles are not clamped
GammaBase::calculateInverse fixed its upper bound at alpha*beta*5, so any
GAMMA.INV/GAMMAINV quantile larger than that was clamped to it: e.g.
GAMMAINV(0.9999, 1, 1) returned 5 rather than ~9.2103, breaking the
round-trip GAMMADIST(GAMMAINV(p)) == p.

Grow the upper bound geometrically until it brackets the root. If the CDF
stops increasing first (the series approximation is past its usable range)
keep the original bound instead of expanding into it, which also stops a
probability the series cannot reach from running the bound away.
2026-07-28 12:17:22 +02:00
saifulislamferoz 041c85060f Improve sparkline test coverage and harden reader
Add tests for previously-uncovered SparklineGroup setters (axis types,
manual limits, additional display options and colours) and a hand-crafted
Xlsx fixture exercising the reader's edge cases (non-sparkline ext, group
without sparklines, sparkline with empty sqref, missing colour elements).

Harden Reader/Xlsx/Sparklines against malformed input: guard the
sparklineGroup and sparkline iterations against a null children set so an
empty <x14:sparklineGroups> or <x14:sparklines> element no longer emits a
PHP warning.
2026-07-28 06:40:12 +06:00
saifulislamferoz 41c051f54d Add support for Excel sparklines
Implements native sparkline support (line, column, and win/loss) in the
Xlsx reader and writer, resolving issue #4941.

- New model classes under Worksheet/Sparkline: Sparkline, SparklineGroup,
  and the SparklineType enum.
- Worksheet gains a sparkline group collection with addSparkline(),
  addSparklineGroup(), getSparklineGroupCollection(), and
  removeSparklineGroupCollection(), plus deep-clone support.
- Reader/Xlsx/Sparklines parses x14:sparklineGroups from the sheet extLst.
- Writer/Xlsx/Worksheet emits x14:sparklineGroups; writeExtLst is
  refactored so conditional-formatting data bars and sparklines share a
  single extLst.
- Adds unit tests, an Xlsx round-trip test, a runnable sample, and docs.
2026-07-28 06:04:37 +06:00
oleibman 2601644333 Merge pull request #4907 from oleibman/nophp81
Drop Support for Php 8.1
2026-07-12 14:44:00 +00:00
oleibman dc455c45f9 Possibly Acceptable 2026-07-12 03:20:25 -07:00
oleibman 40bdbb3c90 WIP Testing 2026-07-12 01:53:11 -07:00
oleibman 0b136d1e6e Blip 2026-07-12 00:07:04 -07:00
oleibman 5d9c5a667f Not Sure Why Test Failed
Works locally, not on Github. Disabling for now, will continue to research.
2026-07-12 00:00:49 -07:00
oleibman 7ef7b25e85 Merge commit from fork 2026-07-11 23:13:06 -07:00
oleibman 85f2556b0b Merge commit from fork 2026-07-11 22:15:04 -07:00
oleibman 14c9ac65e4 Merge branch 'master' into perf/xls-reader-optimizations 2026-07-04 13:10:09 -07:00
oleibman 38be7742c8 Merge branch 'master' into nophp81 2026-07-04 13:08:33 -07:00
oleibman 7a69387e7b Extra Annotation 2026-07-02 20:20:25 -07:00
oleibman 3a2d9e4403 Delete Unused Test Member 2026-07-02 20:05:00 -07:00
oleibman 58cf6fe887 Update AutoColorTest.php 2026-07-02 19:28:48 -07:00
oleibman 4e28940dd7 Merge branch 'master' into nophp81 2026-07-02 17:47:57 -07:00
oleibman d8c6890861 Merge pull request #4926 from oleibman/issue4917
Very Minor Changes to Worksheet, Reader/Xlsx, and Worksheet/AutoFilter
2026-06-29 03:44:56 +00:00
oleibman 13edf0d8a2 More AutoFilter Tweaks 2026-06-25 17:08:15 -07:00
oleibman 8fd7c56ef0 Consistent HighestRow/Column After Row/Column Delete
Fix #943, which went stale a long time ago, and is now reopened. I believe that the specific problem in that issue was actually mostly resolved some time ago. However, `highestRow/Column` produces questionable results when the delete range overlaps the highest row/column. That is fixed by this PR.

In addition, `removeRow/Column` allow the specification of a non-negative value for `numberOfRows/Columns`. But the expected results in those cases are not defined, and the actual results probably do not meet user expectations. I believe that very few, if any, users are taking advantage of this "feature", but we may as well straighten it out. For 0 rows/columns, I think it makes perfect sense to do nothing. As for negative - if `removeRow(5, 2)` says to remove 2 rows *starting* with 5, I think `removeRow(5, -2)` ought to remove (up to) 2 rows *ending* with 5. The undefined behaviors are changed to act as described in this paragraph.
2026-06-24 08:41:09 -07:00
oleibman 448fc02389 Merge branch 'master' into perf/xls-reader-optimizations 2026-06-20 21:18:45 -07:00
oleibman a8aeaaefed Merge pull request #4919 from oleibman/nogetfilter
Readers Should Directly Access readFilter
2026-06-21 04:01:01 +00:00
oleibman feb3b2e472 Merge pull request #4915 from oleibman/charttweaks
Avoid Hard-Coding Some Chart Xml Attributes
2026-06-21 03:26:36 +00:00
oleibman 4d185b711b Merge pull request #4914 from oleibman/misleading
Permit Ignoring 'Misleading Format' Tag
2026-06-21 03:26:12 +00:00
oleibman 0e81e6a4ce Merge branch 'master' into nogetfilter 2026-06-18 11:38:52 -07:00
oleibman b65aecdcec Readers Should Directly Access readFilter
A number of interesting performance ideas have been submitted by @kemo. PR #4833 optimizes Xls Reader in a number of different ways. One of those, slightly modified, is to use the protected `readFilter` property which is available to all classes which inherit from `BaseReader` (which all our supported readers do), rather than call the `getReadFilter` method to obtain it (often in a loop). That applies to all readers, not just Xls, and is such a good idea that I am fast-tracking it ahead of 4833. Gnumeric, Ods, Xls, Xlsx, and Xml will all receive small performance boosts from it. Csv already does this, so no change is needed there. Html and Slk do not appear to do any filtering; possibly work for another day.
2026-06-18 10:04:39 -07:00
oleibman e623d5411b WIP Why Is This File Needed? 2026-06-17 20:56:44 -07:00
oleibman 94abde43f8 Slightly More Coverage 2026-06-17 15:07:20 -07:00
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 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 c5e0e261d5 Merge pull request #4911 from oleibman/issue413
Chart DataTable
2026-06-13 03:36:44 +00:00
oleibman 961346a5d7 Merge pull request #4910 from oleibman/issue411
Allow Use of Multiple Ranges When Setting Style
2026-06-13 03:36:23 +00:00
oleibman 7a4574dcd1 Merge pull request #4909 from oleibman/issue863
Navigate Cell as Cursor
2026-06-13 03:35:59 +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 a028eea314 Allow Use of Multiple Ranges When Setting Style
Fix #411, which went stale in 2018 and is now reopened. You can get a style for a set of cells which uses multiple ranges, e.g. `A1:B2,C5:H10`, but we throw an exception if you try to change the style. I don't know how useful that is, but it's been requested and it's pretty easy to implement with recursion.

The comma in the ranges represents the `union` operator. `getStyle` is very permissive - it will allow almost anything to be specified. However, attempts to use a space as the `intersection` operator, or, indeed, many other nonsense strings, will still be permitted for `getStyle` but will continue to throw an Exception if an attempt is made to alter the style.
2026-06-11 06:30:20 -07:00
oleibman 46f4b8995a Additional Methods and Tests 2026-06-10 13:30:10 -07:00
oleibman b65783bdeb Navigate Cell as Cursor
Fix #863, which went stale in 2019 and is now reopened. Add methods to `Cell` which operate in a cursor-like manner, allowing you to change to cells on the right, left, down, or up.
2026-06-09 17:02:05 -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 1388efb080 Drop Support for Php 8.1
This PR will be merged at the end of this month. As the README says, we maintain support for Php Versions for six months beyond their end of life. That time has now arrived for 8.1.
2026-06-08 09:15:57 -07:00
oleibman fd5f72edd7 Merge pull request #4906 from oleibman/strikesubsup
Minor Coverage Improvement Reader/Xlsx
2026-06-08 03:21:59 +00:00
oleibman 1f7dd42482 Minor Coverage Improvement Reader/Xlsx 2026-06-07 20:03:44 -07:00
oleibman 45f6b78792 Merge branch 'master' into perf/xlsx-xmlreader-streaming 2026-06-07 07:10:21 -07:00
oleibman fd773844c2 Merge branch 'master' into perf/csv-streaming-encoding 2026-06-07 06:57:32 -07:00
oleibman 9698573e32 getChartIndex
It requires an index to an array which needs to be supplied as a string, even though the array is indexed exclusively by int. It is called only once in the code base, by some inefficient code which becomes much simpler when restructured and eliminates the call altogether. It is not independently tested. The use case for its existence is not clear. It should probably just be deprecated. However, for now, I'm just allowing the parameter to be int|string, rather than just string, and adding tests.
2026-06-04 12:40:57 -07:00
oleibman d80d762af1 Merge branch 'master' into issue4889 2026-06-01 08:06:46 -07:00
oleibman ad2285dac7 Merge pull request #4892 from oleibman/stanchanges
Phpstan Changes
2026-06-01 13:53:56 +00:00