Update cells that use structured references in formula, and defined names, when a table column heading is changed

This commit is contained in:
MarkBaker
2022-12-10 13:17:55 +01:00
parent 7b4ba98081
commit 873ea0b503
2 changed files with 84 additions and 2 deletions
+33 -2
View File
@@ -8,9 +8,11 @@ use PhpOffice\PhpSpreadsheet\Collection\Cells;
use PhpOffice\PhpSpreadsheet\Exception;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDate;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\CellStyleAssessor;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Style\Style;
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class Cell
@@ -190,6 +192,29 @@ class Cell
);
}
/**
* @param mixed $oldValue
* @param mixed $newValue
*/
protected static function updateIfCellIsTableHeader(Worksheet $workSheet, self $cell, $oldValue, $newValue): void
{
if (StringHelper::strToLower($oldValue ?? '') === StringHelper::strToLower($newValue ?? '')) {
return;
}
foreach ($workSheet->getTableCollection() as $table) {
/** @var Table $table */
if ($cell->isInRange($table->getRange())) {
$rangeRowsColumns = Coordinate::getRangeBoundaries($table->getRange());
if ($cell->getRow() === (int) $rangeRowsColumns[0][1]) {
Table\Column::updateStructuredReferences($workSheet, $oldValue, $newValue);
}
return;
}
}
}
/**
* Set cell value.
*
@@ -221,8 +246,10 @@ class Cell
*
* @return Cell
*/
public function setValueExplicit($value, $dataType)
public function setValueExplicit($value, string $dataType = DataType::TYPE_STRING)
{
$oldValue = $this->value;
// set the value according to data type
switch ($dataType) {
case DataType::TYPE_NULL:
@@ -270,7 +297,11 @@ class Cell
// set the datatype
$this->dataType = $dataType;
return $this->updateInCollection();
$this->updateInCollection();
$cellCoordinate = $this->getCoordinate();
self::updateIfCellIsTableHeader($this->getParent()->getParent(), $this, $oldValue, $value); // @phpstan-ignore-line
return $this->getParent()->get($cellCoordinate); // @phpstan-ignore-line
}
public const CALCULATE_DATE_TIME_ASIS = 0;
@@ -2,7 +2,11 @@
namespace PhpOffice\PhpSpreadsheet\Worksheet\Table;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class Column
{
@@ -200,4 +204,51 @@ class Column
return $this;
}
public static function updateStructuredReferences(?Worksheet $workSheet, ?string $oldTitle, string $newTitle): void
{
if ($workSheet === null || $oldTitle === null || $oldTitle === '') {
return;
}
// Remember that table headings are case-insensitive
if (StringHelper::strToLower($oldTitle) !== StringHelper::strToLower($newTitle)) {
// We need to check all formula cells that might contain Structured References that refer
// to this column, and update those formulae to reference the new column text
$spreadsheet = $workSheet->getParent();
foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
self::updateStructuredReferencesInCells($sheet, $oldTitle, $newTitle);
}
self::updateStructuredReferencesInNamedFormulae($spreadsheet, $oldTitle, $newTitle);
}
}
private static function updateStructuredReferencesInCells(Worksheet $worksheet, string $oldTitle, string $newTitle): void
{
$pattern = '/\[(@?)' . preg_quote($oldTitle) . '\]/mui';
foreach ($worksheet->getCoordinates(false) as $coordinate) {
$cell = $worksheet->getCell($coordinate);
if ($cell->getDataType() === DataType::TYPE_FORMULA) {
$formula = $cell->getValue();
if (preg_match($pattern, $formula) === 1) {
$formula = preg_replace($pattern, "[$1{$newTitle}]", $formula);
$cell->setValueExplicit($formula, DataType::TYPE_FORMULA);
}
}
}
}
private static function updateStructuredReferencesInNamedFormulae(Spreadsheet $spreadsheet, string $oldTitle, string $newTitle): void
{
$pattern = '/\[(@?)' . preg_quote($oldTitle) . '\]/mui';
foreach ($spreadsheet->getNamedFormulae() as $namedFormula) {
$formula = $namedFormula->getValue();
if (preg_match($pattern, $formula) === 1) {
$formula = preg_replace($pattern, "[$1{$newTitle}]", $formula);
$namedFormula->setValue($formula); // @phpstan-ignore-line
}
}
}
}