Skip to content

Commit

Permalink
Evaluate NamedRange and ArrayFunction in DataValidator
Browse files Browse the repository at this point in the history
Fix #4206.
  • Loading branch information
oleibman committed Jan 3, 2025
1 parent 441abf0 commit fb29a76
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 15 deletions.
28 changes: 14 additions & 14 deletions src/PhpSpreadsheet/Cell/DataValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace PhpOffice\PhpSpreadsheet\Cell;

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Exception;

/**
Expand Down Expand Up @@ -118,22 +118,22 @@ private function isValueInList(Cell $cell): bool
// inline values list
if ($formula1[0] === '"') {
return in_array(strtolower($cellValueString), explode(',', strtolower(trim($formula1, '"'))), true);
} elseif (strpos($formula1, ':') > 0) {
// values list cells
$matchFormula = '=MATCH(' . $cell->getCoordinate() . ', ' . $formula1 . ', 0)';
$calculation = Calculation::getInstance($cell->getWorksheet()->getParent());

try {
$result = $calculation->calculateFormula($matchFormula, $cell->getCoordinate(), $cell);
while (is_array($result)) {
$result = array_pop($result);
}
}
$calculation = Calculation::getInstance($cell->getWorksheet()->getParent());

return $result !== ExcelError::NA();
} catch (Exception) {
return false;
try {
$result = $calculation->calculateFormula("=$formula1", $cell->getCoordinate(), $cell);
$result = is_array($result) ? Functions::flattenArray($result) : [$result];
foreach ($result as $oneResult) {
if (is_scalar($oneResult) && strcasecmp((string) $oneResult, $cellValueString) === 0) {
return true;
}
}
} catch (Exception) {
// do nothing
}

return false;
}

return true;
Expand Down
38 changes: 38 additions & 0 deletions tests/PhpSpreadsheetTests/Cell/DataValidator3Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace PhpOffice\PhpSpreadsheetTests\Cell;

use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase;

class DataValidator3Test extends TestCase
{
public function testArrayFunctionAsList(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue(1);
$sheet->getCell('A2')->setValue(3);
$sheet->getCell('A3')->setValue(5);
$sheet->getCell('A4')->setValue(7);
Calculation::getInstance($spreadsheet)
->setInstanceArrayReturnType(
Calculation::RETURN_ARRAY_AS_ARRAY
);

$sheet->getCell('G1')->setValue('=UNIQUE(A1:A4)');
$validation = $sheet->getCell('H4')->getDataValidation();
$validation->setType(DataValidation::TYPE_LIST)
->setFormula1('ANCHORARRAY(G1)');
$sheet->getCell('H4')->setValue(2);
self::assertFalse($sheet->getCell('H4')->hasValidValue());
$sheet->getCell('H4')->setValue(3);
self::assertTrue($sheet->getCell('H4')->hasValidValue());

$spreadsheet->disconnectWorksheets();
}
}
24 changes: 23 additions & 1 deletion tests/PhpSpreadsheetTests/Cell/DataValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Cell;

use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
use PhpOffice\PhpSpreadsheet\NamedRange;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -62,7 +63,7 @@ public function testList(): void
$sheet->getCell('B2')->setValue(6);
$sheet->getCell('B3')->setValue(7);
$testCell = $sheet->getCell('A1'); // redefine $testCell, because it has broken coordinates after using other cells
$validation->setFormula1('B1:B3');
$validation->setFormula1('$B$1:$B$3');
$testCell->setValue('10');
self::assertFalse($testCell->hasValidValue(), "cell value ('10') is not allowed");
$testCell = $sheet->getCell('A1'); // redefine $testCell, because it has broken coordinates after using other cells
Expand Down Expand Up @@ -93,4 +94,25 @@ public function testInvalidNumeric(): void

$spreadsheet->disconnectWorksheets();
}

public function testDefinedNameAsList(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue(1);
$sheet->getCell('A2')->setValue(3);
$sheet->getCell('A3')->setValue(5);
$sheet->getCell('A4')->setValue(7);
$spreadsheet->addNamedRange(new NamedRange('listvalues', $sheet, '$A$1:$A$4'));

$validation = $sheet->getCell('D4')->getDataValidation();
$validation->setType(DataValidation::TYPE_LIST)
->setFormula1('listvalues');
$sheet->getCell('D4')->setValue(2);
self::assertFalse($sheet->getCell('D4')->hasValidValue());
$sheet->getCell('D4')->setValue(3);
self::assertTrue($sheet->getCell('D4')->hasValidValue());

$spreadsheet->disconnectWorksheets();
}
}

0 comments on commit fb29a76

Please sign in to comment.