From 7aef8b24ccd24b90b7cdb166c4584cb78fecff7b Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:56:16 -0800 Subject: [PATCH] Option To Use OldCalculatedValue in ToArray and its Relatives Fix #1810, just before it turns 6 years old. Reporter thinks it can save time. Easy to implement, especially with the advent of named parameters which were not available when issue was opened. --- src/PhpSpreadsheet/Worksheet/Worksheet.php | 37 +++++++++++++------ .../ToArrayOldCalculatedValueTest.php | 28 ++++++++++++++ 2 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Worksheet/ToArrayOldCalculatedValueTest.php diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index d6cf0a9df..657216d97 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -2985,19 +2985,24 @@ class Worksheet * @param null|bool|float|int|RichText|string $nullValue value to use when null * @param bool $formatData Whether to format data according to cell's style. * @param bool $lessFloatPrecision If true, formatting unstyled floats will convert them to a more human-friendly but less computationally accurate value + * @param bool $oldCalculatedValue If calculateFormulas is false and this is true, use oldCalculatedFormula instead. * * @throws Exception * @throws \PhpOffice\PhpSpreadsheet\Calculation\Exception */ - protected function cellToArray(Cell $cell, bool $calculateFormulas, bool $formatData, mixed $nullValue, bool $lessFloatPrecision = false): mixed + protected function cellToArray(Cell $cell, bool $calculateFormulas, bool $formatData, mixed $nullValue, bool $lessFloatPrecision = false, $oldCalculatedValue = false): mixed { $returnValue = $nullValue; if ($cell->getValue() !== null) { if ($cell->getValue() instanceof RichText) { $returnValue = $cell->getValue()->getPlainText(); + } elseif ($calculateFormulas) { + $returnValue = $cell->getCalculatedValue(); + } elseif ($oldCalculatedValue && ($cell->getDataType() === DataType::TYPE_FORMULA)) { + $returnValue = $cell->getOldCalculatedValue(); } else { - $returnValue = ($calculateFormulas) ? $cell->getCalculatedValue() : $cell->getValue(); + $returnValue = $cell->getValue(); } if ($formatData) { @@ -3027,6 +3032,7 @@ class Worksheet * True - Don't return values for rows/columns that are defined as hidden. * @param bool $reduceArrays If true and result is a formula which evaluates to an array, reduce it to the top leftmost value. * @param bool $lessFloatPrecision If true, formatting unstyled floats will convert them to a more human-friendly but less computationally accurate value + * @param bool $oldCalculatedValue If calculateFormulas is false and this is true, use oldCalculatedFormula instead. * * @return mixed[][] */ @@ -3038,12 +3044,13 @@ class Worksheet bool $returnCellRef = false, bool $ignoreHidden = false, bool $reduceArrays = false, - bool $lessFloatPrecision = false + bool $lessFloatPrecision = false, + bool $oldCalculatedValue = false, ): array { $returnValue = []; // Loop through rows - foreach ($this->rangeToArrayYieldRows($range, $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision) as $rowRef => $rowArray) { + foreach ($this->rangeToArrayYieldRows($range, $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision, $oldCalculatedValue) as $rowRef => $rowArray) { /** @var int $rowRef */ $returnValue[$rowRef] = $rowArray; } @@ -3064,6 +3071,7 @@ class Worksheet * True - Don't return values for rows/columns that are defined as hidden. * @param bool $reduceArrays If true and result is a formula which evaluates to an array, reduce it to the top leftmost value. * @param bool $lessFloatPrecision If true, formatting unstyled floats will convert them to a more human-friendly but less computationally accurate value + * @param bool $oldCalculatedValue If calculateFormulas is false and this is true, use oldCalculatedFormula instead. * * @return mixed[][] */ @@ -3076,13 +3084,14 @@ class Worksheet bool $ignoreHidden = false, bool $reduceArrays = false, bool $lessFloatPrecision = false, + bool $oldCalculatedValue = false, ): array { $returnValue = []; $parts = explode(',', $ranges); foreach ($parts as $part) { // Loop through rows - foreach ($this->rangeToArrayYieldRows($part, $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision) as $rowRef => $rowArray) { + foreach ($this->rangeToArrayYieldRows($part, $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision, $oldCalculatedValue) as $rowRef => $rowArray) { /** @var int $rowRef */ $returnValue[$rowRef] = $rowArray; } @@ -3104,6 +3113,7 @@ class Worksheet * True - Don't return values for rows/columns that are defined as hidden. * @param bool $reduceArrays If true and result is a formula which evaluates to an array, reduce it to the top leftmost value. * @param bool $lessFloatPrecision If true, formatting unstyled floats will convert them to a more human-friendly but less computationally accurate value + * @param bool $oldCalculatedValue If calculateFormulas is false and this is true, use oldCalculatedFormula instead. * * @return Generator> */ @@ -3115,7 +3125,8 @@ class Worksheet bool $returnCellRef = false, bool $ignoreHidden = false, bool $reduceArrays = false, - bool $lessFloatPrecision = false + bool $lessFloatPrecision = false, + bool $oldCalculatedValue = false, ) { $range = Validations::validateCellOrCellRange($range); @@ -3181,7 +3192,7 @@ class Worksheet $columnRef = $returnCellRef ? $col : ($thisCol - $minColInt); $cell = $this->cellCollection->get("{$col}{$thisRow}"); if ($cell !== null) { - $value = $this->cellToArray($cell, $calculateFormulas, $formatData, $nullValue, lessFloatPrecision: $lessFloatPrecision); + $value = $this->cellToArray($cell, $calculateFormulas, $formatData, $nullValue, lessFloatPrecision: $lessFloatPrecision, oldCalculatedValue: $oldCalculatedValue); if ($reduceArrays) { while (is_array($value)) { $value = array_shift($value); @@ -3284,6 +3295,7 @@ class Worksheet * True - Don't return values for rows/columns that are defined as hidden. * @param bool $reduceArrays If true and result is a formula which evaluates to an array, reduce it to the top leftmost value. * @param bool $lessFloatPrecision If true, formatting unstyled floats will convert them to a more human-friendly but less computationally accurate value + * @param bool $oldCalculatedValue If calculateFormulas is false and this is true, use oldCalculatedFormula instead. * * @return mixed[][] */ @@ -3295,7 +3307,8 @@ class Worksheet bool $returnCellRef = false, bool $ignoreHidden = false, bool $reduceArrays = false, - bool $lessFloatPrecision = false + bool $lessFloatPrecision = false, + bool $oldCalculatedValue = false, ): array { $retVal = []; $namedRange = $this->validateNamedRange($definedName); @@ -3304,7 +3317,7 @@ class Worksheet $cellRange = str_replace('$', '', $cellRange); $workSheet = $namedRange->getWorksheet(); if ($workSheet !== null) { - $retVal = $workSheet->rangeToArray($cellRange, $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision); + $retVal = $workSheet->rangeToArray($cellRange, $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision, $oldCalculatedValue); } } @@ -3323,6 +3336,7 @@ class Worksheet * True - Don't return values for rows/columns that are defined as hidden. * @param bool $reduceArrays If true and result is a formula which evaluates to an array, reduce it to the top leftmost value. * @param bool $lessFloatPrecision If true, formatting unstyled floats will convert them to a more human-friendly but less computationally accurate value + * @param bool $oldCalculatedValue If calculateFormulas is false and this is true, use oldCalculatedFormula instead. * * @return mixed[][] */ @@ -3333,7 +3347,8 @@ class Worksheet bool $returnCellRef = false, bool $ignoreHidden = false, bool $reduceArrays = false, - bool $lessFloatPrecision = false + bool $lessFloatPrecision = false, + bool $oldCalculatedValue = false, ): array { // Garbage collect... $this->garbageCollect(); @@ -3344,7 +3359,7 @@ class Worksheet $maxRow = $this->getHighestRow(); // Return - return $this->rangeToArray("A1:{$maxCol}{$maxRow}", $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision); + return $this->rangeToArray("A1:{$maxCol}{$maxRow}", $nullValue, $calculateFormulas, $formatData, $returnCellRef, $ignoreHidden, $reduceArrays, $lessFloatPrecision, $oldCalculatedValue); } /** diff --git a/tests/PhpSpreadsheetTests/Worksheet/ToArrayOldCalculatedValueTest.php b/tests/PhpSpreadsheetTests/Worksheet/ToArrayOldCalculatedValueTest.php new file mode 100644 index 000000000..4ccb48028 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Worksheet/ToArrayOldCalculatedValueTest.php @@ -0,0 +1,28 @@ +getActiveSheet(); + $sheet->fromArray([['A', 'B', 'C', '=1+2']]); + $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx'); + $spreadsheet->disconnectWorksheets(); + $rsheet = $reloadedSpreadsheet->getActiveSheet(); + $rsheet->setCellValue('D1', '=1+3'); + $array1 = $rsheet->toArray(formatData: false, calculateFormulas: false, oldCalculatedValue: true); + self::assertSame([['A', 'B', 'C', 3]], $array1, 'uses value as read from spreadsheet'); + $array2 = $rsheet->toArray(formatData: false); + self::assertSame([['A', 'B', 'C', 4]], $array2, 'uses newly calculated value'); + + $reloadedSpreadsheet->disconnectWorksheets(); + } +}