mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-16 13:06:31 +00:00
Issue 3368 - Absolute References in Defined Names should always be updated when inserting/deleting rows/columns
Note: If we delete the entire range that is referenced by a Named Formula, MS Excel sets the value to #REF! PhpSpreadsheet still only does a basic adjustment, so the Named Formula will still reference Cells.
This commit is contained in:
@@ -412,7 +412,7 @@ class ReferenceHelper
|
||||
$cellCollection = $worksheet->getCellCollection();
|
||||
$missingCoordinates = array_filter(
|
||||
array_map(function ($row) use ($highestColumn) {
|
||||
return $highestColumn . $row;
|
||||
return "{$highestColumn}{$row}";
|
||||
}, range(1, $highestRow)),
|
||||
function ($coordinate) use ($cellCollection) {
|
||||
return $cellCollection->has($coordinate) === false;
|
||||
@@ -455,7 +455,7 @@ class ReferenceHelper
|
||||
$worksheet->getCell($newCoordinate)
|
||||
->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true));
|
||||
} else {
|
||||
// Formula should not be adjusted
|
||||
// Cell value should not be adjusted
|
||||
$worksheet->getCell($newCoordinate)->setValueExplicit($cell->getValue(), $cell->getDataType());
|
||||
}
|
||||
|
||||
@@ -609,7 +609,7 @@ class ReferenceHelper
|
||||
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||
$column = 100000;
|
||||
$row = 10000000 + (int) trim($match[3], '$');
|
||||
$cellIndex = $column . $row;
|
||||
$cellIndex = "{$column}{$row}";
|
||||
|
||||
$newCellTokens[$cellIndex] = preg_quote($toString, '/');
|
||||
$cellTokens[$cellIndex] = '/(?<!\d\$\!)' . preg_quote($fromString, '/') . '(?!\d)/i';
|
||||
@@ -634,7 +634,7 @@ class ReferenceHelper
|
||||
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||
$column = Coordinate::columnIndexFromString(trim($match[3], '$')) + 100000;
|
||||
$row = 10000000;
|
||||
$cellIndex = $column . $row;
|
||||
$cellIndex = "{$column}{$row}";
|
||||
|
||||
$newCellTokens[$cellIndex] = preg_quote($toString, '/');
|
||||
$cellTokens[$cellIndex] = '/(?<![A-Z\$\!])' . preg_quote($fromString, '/') . '(?![A-Z])/i';
|
||||
@@ -660,7 +660,7 @@ class ReferenceHelper
|
||||
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||
$column = Coordinate::columnIndexFromString(trim($column, '$')) + 100000;
|
||||
$row = (int) trim($row, '$') + 10000000;
|
||||
$cellIndex = $column . $row;
|
||||
$cellIndex = "{$column}{$row}";
|
||||
|
||||
$newCellTokens[$cellIndex] = preg_quote($toString, '/');
|
||||
$cellTokens[$cellIndex] = '/(?<![A-Z]\$\!)' . preg_quote($fromString, '/') . '(?!\d)/i';
|
||||
@@ -917,11 +917,18 @@ class ReferenceHelper
|
||||
$cellAddress = $definedName->getValue();
|
||||
$asFormula = ($cellAddress[0] === '=');
|
||||
if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) {
|
||||
/**
|
||||
* If we delete the entire range that is referenced by a Named Range, MS Excel sets the value to #REF!
|
||||
* PhpSpreadsheet still only does a basic adjustment, so the Named Range will still reference Cells.
|
||||
* Note that this applies only when deleting columns/rows; subsequent insertion won't fix the #REF!
|
||||
* TODO Can we work out a method to identify Named Ranges that cease to be valid, so that we can replace
|
||||
* them with a #REF!
|
||||
*/
|
||||
if ($asFormula === true) {
|
||||
$formula = $this->updateFormulaReferences($cellAddress, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle());
|
||||
$formula = $this->updateFormulaReferences($cellAddress, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true);
|
||||
$definedName->setValue($formula);
|
||||
} else {
|
||||
$definedName->setValue($this->updateCellReference(ltrim($cellAddress, '=')));
|
||||
$definedName->setValue($this->updateCellReference(ltrim($cellAddress, '='), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -929,8 +936,15 @@ class ReferenceHelper
|
||||
private function updateNamedFormula(DefinedName $definedName, Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): void
|
||||
{
|
||||
if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) {
|
||||
/**
|
||||
* If we delete the entire range that is referenced by a Named Formula, MS Excel sets the value to #REF!
|
||||
* PhpSpreadsheet still only does a basic adjustment, so the Named Formula will still reference Cells.
|
||||
* Note that this applies only when deleting columns/rows; subsequent insertion won't fix the #REF!
|
||||
* TODO Can we work out a method to identify Named Ranges that cease to be valid, so that we can replace
|
||||
* them with a #REF!
|
||||
*/
|
||||
$formula = $definedName->getValue();
|
||||
$formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle());
|
||||
$formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true);
|
||||
$definedName->setValue($formula);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user