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.
This commit is contained in:
oleibman
2026-01-23 14:56:16 -08:00
parent 7758d917ba
commit 7aef8b24cc
2 changed files with 54 additions and 11 deletions
+26 -11
View File
@@ -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<array<mixed>>
*/
@@ -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);
}
/**
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
class ToArrayOldCalculatedValueTest extends AbstractFunctional
{
public function testOldCalculatedValue(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->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();
}
}