Modifications to FORMULATEXT() to return correct values for cells in array formula (wrapped in {} braces) and for cells within the spillage area of an array formula that should return the array formula even though they're not the actual formula cell

This commit is contained in:
MarkBaker
2022-03-09 18:01:32 +01:00
parent 5f79b74bc8
commit 5ea78ae834
2 changed files with 39 additions and 5 deletions
@@ -5,6 +5,8 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class Formula
{
@@ -30,14 +32,29 @@ class Formula
? $cell->getWorksheet()->getParent()->getSheetByName($worksheetName)
: $cell->getWorksheet();
if (
$worksheet === null ||
!$worksheet->cellExists($cellReference) ||
!$worksheet->getCell($cellReference)->isFormula()
) {
if ($worksheet === null || $worksheet->cellExists($cellReference) === false) {
return ExcelError::NA();
}
$arrayFormulaRange = $worksheet->getCell($cellReference)->arrayFormulaRange();
if ($arrayFormulaRange !== null) {
return self::arrayFormula($worksheet, $arrayFormulaRange);
}
if ($worksheet->getCell($cellReference)->isFormula() === false) {
return ExcelError::NA();
}
return $worksheet->getCell($cellReference)->getValue();
}
private static function arrayFormula(Worksheet $worksheet, string $arrayFormulaRange): string
{
[$arrayFormulaRange] = Coordinate::splitRange($arrayFormulaRange);
[$arrayFormulaCell] = $arrayFormulaRange;
$arrayFormula = $worksheet->getCell($arrayFormulaCell)->getValue();
return "{{$arrayFormula}}";
}
}
@@ -34,4 +34,21 @@ class FormulaTextTest extends AllSetupTeardown
{
self::assertSame('#REF!', Formula::text('B5'));
}
public function testArrayFormula(): void
{
$sheet = $this->getSheet();
$sheet->setCellValue('B2', '=SEQUENCE(3,3)', true, 'B2:D4');
// Execute the calculation to populate the spillage cells
$sheet->getCell('B2')->getCalculatedValue(true);
$sheet->setCellValue('A1', '=FORMULATEXT(B2)');
$sheet->setCellValue('E5', '=FORMULATEXT(D4)');
$result1 = $sheet->getCell('A1')->getCalculatedValue();
self::assertSame('{=SEQUENCE(3,3)}', $result1, 'Formula Cell');
$result2 = $sheet->getCell('E5')->getCalculatedValue();
self::assertSame('{=SEQUENCE(3,3)}', $result2, 'Spill Range Cell');
}
}