Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditional Range Unions and Intersections #4042

Merged
merged 6 commits into from
Jun 1, 2024

Conversation

oleibman
Copy link
Collaborator

Fix #4039. Excel sometimes stores the location for a Conditional as, say, B1:B10 C1:C10 rather than B1:C10. PhpSpreadsheet does not have a problem with this, but internally stores it as separate Conditionals, one for each range. (There may be more than 2.) User would like it stored as a single Conditional. Since the range is used as the index of an array which holds the conditionals, there is no technical reason why this can't be done. And it does seem like being able to change multiple ranges all at once has some advantages, whether you're doing it in PhpSpreadsheet or in Excel itself.

Making such a change in Xlsx Reader showed no problem in Xlsx Reader and Writer tests. A number of problems did show up in CellMatcherTest, and one in WizardFactoryTest. This was good news, because it meant some of our test spreadsheets used the same type of construction as the test spreadsheet supplied with the issue. So, if additional fixes make the test problems go away, I think no new tests are required. And a smattering of source changes did indeed result in a clean test suite once more.

This is a change, but I don't really think it should break anyone. So I don't think it's necessary to add an option to opt in to the old or new behavior. I could be wrong. I'll leave this ticket open for at least a couple of weeks to see if anyone thinks otherwise.

This is:

  • a bugfix (debatable)
  • a new feature
  • refactoring
  • additional unit tests

Checklist:

  • Changes are covered by unit tests
    • Changes are covered by existing unit tests
    • New unit tests have been added
  • Code style is respected
  • Commit message explains why the change is made (see https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
  • CHANGELOG.md contains a short summary of the change and a link to the pull request if applicable
  • Documentation is updated as necessary

Why this change is needed?

Provide an explanation of why this change is needed, with links to any Issues (if appropriate).
If this is a bugfix or a new feature, and there are no existing Issues, then please also create an issue that will make it easier to track progress with this PR.

Fix PHPOffice#4039. Excel sometimes stores the location for a Conditional as, say, `B1:B10 C1:C10` rather than `B1:C10`. PhpSpreadsheet does not have a problem with this, but internally stores it as separate Conditionals, one for each range. (There may be more than 2.) User would like it stored as a single Conditional. Since the range is used as the index of an array which holds the conditionals, there is no technical reason why this can't be done. And it does seem like being able to change multiple ranges all at once has some advantages, whether you're doing it in PhpSpreadsheet or in Excel itself.

Making such a change in Xlsx Reader showed no problem in Xlsx Reader and Writer tests. A number of problems did show up in CellMatcherTest, and one in WizardFactoryTest. This was good news, because it meant some of our test spreadsheets used the same type of construction as the test spreadsheet supplied with the issue. So, if additional fixes make the test problems go away, I think no new tests are required. And a smattering of source changes did indeed result in a clean test suite once more.

This is a change, but I don't really think it should break anyone. So I don't think it's necessary to add an option  to opt in to the old or new behavior. I could be wrong. I'll leave this ticket open for at least a couple of weeks to see if anyone thinks otherwise.
@oleibman
Copy link
Collaborator Author

There is additional discussion of this topic in issue #3206.

@oleibman
Copy link
Collaborator Author

And, following on that discussion, there is more Excel weirdness. Nominally, the intersection operation for cell ranges is a space, and the union operator is a comma. Now, let's take a look at a worksheet.
cond.union.intersect.xlsx
When we open the spreadsheet, and look at the range for the conditional style, what do we see?

=$A$1:$A$3,$C$1:$E$3

The separator is comma, and this is treated as a union, as intended. But ... what do we see in the Xml?

<conditionalFormatting sqref="A1:A3 C1:E3">

Here the separator is space, not comma. Excel is treating it as a union despite the apparent use of the intersection operator! And, not surprisingly, further testing seems to indicate that the use of comma as separator in the xml is treated by Excel as intersection, not union. I need to take some time to figure out how to differentiate ranges loaded from a spreadsheet vs. ranges entered via Worksheet::setConditionalStyles. Not to mention differentiating between the two in our own code.

So, expect some delay in merging this PR.

@oleibman oleibman marked this pull request as draft May 28, 2024 00:53
@oleibman oleibman changed the title Split Conditional Ranges WIP Split Conditional Ranges May 28, 2024
@oleibman
Copy link
Collaborator Author

Xls Reader expects only simple ranges, not union or intersection. Therefore, Xls Writer needs to split union ranges into separate ranges before writing.

@oleibman oleibman changed the title WIP Split Conditional Ranges WIP Conditional Range Unions May 28, 2024
@oleibman
Copy link
Collaborator Author

Updated branch to pull in some recent Conditional changes, not because PR is close to ready.

@oleibman oleibman changed the title WIP Conditional Range Unions WIP Conditional Range Unions and Intersections May 29, 2024
Provide a means to convert a range, possibly with unions and possibly with intersections, into something that both Excel and PhpSpreadsheet can handle. Intersections are changed into unions of the individual cells which they comprise. With this change, Xls Writer now handles intersections (previously it would have thrown an Exception or created a corrupt worksheet if this was attempted), and Xlsx Writer works correctly (it seemed to before, but Excel didn't understand what it wrote). Worksheet::getConditionalRange and ::getConditionalStyles would previously have thrown an Exception when presented with an intersection, and will no longer do so.

**NOTE:** Intersection support is limited to Conditional ranges. Use of intersections in other contexts will usually not achieve the desired result.
@oleibman oleibman marked this pull request as ready for review May 29, 2024 16:58
@oleibman oleibman changed the title WIP Conditional Range Unions and Intersections Conditional Range Unions and Intersections May 29, 2024
@oleibman
Copy link
Collaborator Author

Taking out of draft status. I think the code has gone as far as it needs. I need to think about whether additional tests are needed. AFAICT, intersection and union are now completely supported for Xlsx/Xls Conditional; but intersection may not be fully supported in other contexts.

@oleibman oleibman enabled auto-merge June 1, 2024 01:07
@oleibman oleibman added this pull request to the merge queue Jun 1, 2024
Merged via the queue into PHPOffice:master with commit 3360608 Jun 1, 2024
12 of 13 checks passed
@oleibman oleibman deleted the issue4039 branch June 1, 2024 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
1 participant