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

Fix for #1449 / Removing rows or columns that include range edges #2096

Closed
wants to merge 2 commits into from

Conversation

jabouillei
Copy link

  • a bugfix
  • a new feature

Checklist:

Why this change is needed?

Removing rows or columns that overlap the edge of a range should adjust the edges of the range.
Also, formulas in column A should be adjusted even if only 5 columns are being removed starting with column G. (A formula in column A may refer to a range that includes column G.)

Pasting from April 28, 2020 commit to jabouillei/PHPExcel...

The problems with removing rows or columns in PHPExcel/PhpSpreadsheet
are more extensive than I recognized with my previous post/patch. For
example, removing all of the columns associated with a merged range of
cells results in there continuing to be a merged range of cells that
doesn't belong. I've updated the ReferenceHelper to return an empty
string for the updated range if the range has been eliminated by a
removal and updated the callers to the best of my understanding. For
example, in the case of merged ranges, receiving an empty string means
the merged range should be discarded. In the case of recomputing the
freezePane, and empty string is the perfect value to pass to the
worksheet.

I also recognized why an "if (...) { continue; }" was present that I
removed in my previous patch. That "if" block does cause problems for
the leading columns in the case of a removal, but it should be fixed,
not removed. I've updated it to only skip the columns that are being
removed.
@jabouillei
Copy link
Author

jabouillei commented May 14, 2021

I was concerned that my patch/pull request might be causing errors with complex Excel files, but I am now confident that is not the case. The "unreadable content" is due to something that changed between 14.1 and 17.1. This pull request is solid. Unfortunately, I'll be returning to 14.1 because of the other issues, but please incorporate this pull request. Someone else will probably be helped by it at some point and it will avoid needing to merge again when I get back to PHPSpreadsheet someday. I was disappointed to find the fix was never incorporated in 14.1.

--- The rest of this comment is about the unrelated issue ---

I'm getting "unreadable content" errors regarding complex Excel files from our client when I use 17.1. (The client sends us an Excel file and we update it using PHPSpreadsheet and send it back.) I can't release our client's Excel file as a sample and I haven't been able to create a simple spreadsheet that exhibits the error, so I won't file a bug report. I put some hours into debugging, but it would take many more hours than I have available to spend on it. Perhaps someone reading this will understand - With 14.1, only clean definedNames ended up in the workbook.xml; with 17.1, ranges that PHPSpreadsheet didn't understand become "#REF!" or something involving "#REF!" and Excel reports that there is unreadable content. Excel fixes it, but it isn't presentable to clients.

Example: Excel produces a file that includes
<definedName name="ae">'[1]DataPg2-Universe'!$A$13</definedName>
We process the file and use PHP Spreadsheet to output it back into Excel and (using 17.1) it comes out with
<definedName name="ae">#REF!</definedName>
I reverted to 14.1 and the resulting workbook.xml was much smaller. All of the strange definedNames were removed. I have no idea why Excel put them in there in the first place. This smells to me like a problem with Excel including garbage in a file and 17.1 converting it to worse garbage while 14.1 stripped it.
I tried simply skipping any defined names that include #REF! in Writer/Xlsx/DefinedNames.php, but that wasn't enough to make Excel happy.

@jabouillei jabouillei changed the title Fix for #1449 Fix for #1449 / Removing rows or columns that include range edges May 17, 2021
Copy link
Member

@MarkBaker MarkBaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to provide unit tests to prove that these changes actually work as expected. I know that the ReferenceHelper isn't well covered by unit tests at the moment; but this is quite a significant change, making it difficult to assess

@truthptn
Copy link

We've been using this patch for years. I do have a small unit test that I used to kick the tires when attempting to use 17.1.

<?php
require_once('PHPSpreadsheet/autoload.php');
require_once('PHPSpreadsheet/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php');
$objReader = PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
$objReader->setIncludeCharts(true);
$content = $objReader->load('mergedtest2021.xlsx');
foreach ($content->getWorksheetIterator() as $worksheet) {
    $worksheet->removeColumn('F',4);
    //$worksheet->removeRow(3,3);
}
$objWriter = PhpOffice\PhpSpreadsheet\IOFactory::createWriter($content, 'Xlsx');
$objWriter->setPreCalculateFormulas(false);
$objWriter->setIncludeCharts(true);
$objWriter->save('mergedtest2021_after.xlsx');
?>

I suspect the "setIncludeCharts()" is not relevant and is just there because my original testing was with a client file that included charts and this test is based on the original test from when I first wrote the patch for PHPExcel.

Here is the simple little Excel file for use with the test case:
mergedtest2021.xlsx

Copy link
Member

@PowerKiKi PowerKiKi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This need to support PHP 8, pass CI and include at least some basic unit tests to be merged

@jabouillei
Copy link
Author

jabouillei commented Oct 30, 2021 via email

oleibman added a commit to oleibman/PhpSpreadsheet that referenced this pull request Apr 20, 2023
This PR will probably remain in draft status for some time. It needs updates, and I need more time to understand exactly what it is doing. It is a replacement for PR PHPOffice#2096, intended as a fix for issue PHPOffice#1449. That PR has been stuck, with a good deal of acrimony, for over 2 years. In the interim, all the parameters for the functions involved were renamed, the functions were refactored to have fewer parameters with new class properties replacing the missing parameters, special code was added for absolute references, and code was refactored putting some of the methods involved in a new class under a new method name. In addition, the original PR was not Php8-compliant (one of the sticking points regarding implementing it), and there were a great many formatting problems (another sticking point). This has made it very difficult to figure out exactly what was intended in the original PR.

This PR (a) addresses some of the issues associated with the original issue (deleting columns/rows at the end of a range passed to a formula *on the same sheet*), and (b) does not cause any existing tests to fail. Many more unit tests are needed (another sticking point); in particular, there are changes involving data validations, comments, defined names, and other elements which are not adequately tested.

Aside from those, PhpSpreadsheet does not adjust formulas on a different sheet which involve deleted rows/columns, and it should, as Excel does.

Similarly, it appears that Excel doesn't do anything extraordinary when the right/bottom part of the range is deleted, but when the left/top part is deleted, it converts the range to #REF! at least some of the time. This needs more research; if confirmed, it needs to be added to PhpSpreadsheet.
@oleibman
Copy link
Collaborator

Closing. Superseded by 3528.

@oleibman oleibman closed this Apr 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

5 participants