Fix for 3 Issues Involving ReadXlsx and NamedRange (#1742)

* Fix for 3 Issues Involving ReadXlsx and NamedRange

Issues #1686 and #1723, which provide sample spreadsheets, are probably
solved by this ticket. Issue #1730 is also probably solved, but I have
no way to verify.

There are two problems with how PhpSpreadsheet is handling things now.
Although the first problem is much less severe, and isn't really a factor
in the issues named above, it is helpful to get it out of the way first.
If you define a named range in Excel, and then delete the sheet where
the range exists, Excel saves the range as #REF!. If there is a cell which
references the range, it will similarly have the value #REF! when you open
the Excel file.
Currently, PhpSpreadsheet discards the #REF! definition, so a cell which
references the range will appear as #NAME? rather than #REF!.
This PR changes the behavior so that PhpSpreadsheet retains the #REF!
definition, and cells which reference it will appear as #REF!.

The second problem is the more severe, and is, I believe, responsible
for the 3 issues identified above.
If you define a named range and the sheet on which the range is defined
does not exist at the time, Excel will save the range as something like:

'[1]Unknown Sheet'!$A$1

If a cell references such a range, Excel will again display #REF!.
PhpSpreadsheet currently throws an Exception when it encounters
such a definition while reading the file. This PR changes
the behavior so that PhpSpreadsheet saves the definition as #REF!,
and cells which reference it will behave similarly.

For the record, I will note that Excel does not magically recalculate when a
missing sheet is subsequently added, despite the fact that the reference
might now become resolvable. PhpSpreadsheet behaves likewise.

* Remove Dead Code in Test

Identified it after push but before merge.
This commit is contained in:
oleibman 2020-12-10 09:08:10 -08:00 committed by GitHub
parent ff04c8502a
commit 497a934374
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 2 deletions

View File

@ -1280,7 +1280,7 @@ class Xlsx extends BaseReader
} }
// Valid range? // Valid range?
if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') { if ($extractedRange == '') {
continue; continue;
} }
@ -1350,7 +1350,7 @@ class Xlsx extends BaseReader
$extractedRange = (string) $definedName; $extractedRange = (string) $definedName;
// Valid range? // Valid range?
if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') { if ($extractedRange == '') {
continue; continue;
} }
@ -1398,6 +1398,9 @@ class Xlsx extends BaseReader
$locatedSheet = $excel->getSheetByName($extractedSheetName); $locatedSheet = $excel->getSheetByName($extractedSheetName);
} }
if ($locatedSheet === null && !DefinedName::testIfFormula($definedRange)) {
$definedRange = '#REF!';
}
$excel->addDefinedName(DefinedName::createInstance((string) $definedName['name'], $locatedSheet, $definedRange, false)); $excel->addDefinedName(DefinedName::createInstance((string) $definedName['name'], $locatedSheet, $definedRange, false));
} }
} }

View File

@ -0,0 +1,22 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PHPUnit\Framework\TestCase;
class NamedRangeTest extends TestCase
{
public static function testBug1686b(): void
{
$xlsxFile = 'tests/data/Reader/XLSX/bug1686b.xlsx';
$reader = new Xlsx();
$spreadsheet = $reader->load($xlsxFile);
$sheet = $spreadsheet->getActiveSheet();
self::assertEquals(2.1, $sheet->getCell('A1')->getCalculatedValue());
self::assertEquals('#REF!', $sheet->getCell('A2')->getCalculatedValue());
self::assertEquals('#REF!', $sheet->getCell('A3')->getCalculatedValue());
self::assertEquals('#NAME?', $sheet->getCell('A4')->getCalculatedValue());
self::assertEquals('#REF!', $sheet->getCell('A5')->getCalculatedValue());
}
}

Binary file not shown.