Skip to content

Commit

Permalink
Numeric Data Validation Formats Only Worked for Constants
Browse files Browse the repository at this point in the history
Change to evaluate formulas when applicable.
  • Loading branch information
oleibman committed Jan 1, 2025
1 parent bbc069e commit 6938fcb
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
42 changes: 37 additions & 5 deletions src/PhpSpreadsheet/Cell/DataValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,58 @@ public function isValid(Cell $cell): bool
if (!is_numeric($cellValue) || fmod((float) $cellValue, 1) != 0) {
$returnValue = false;
} else {
$returnValue = $this->numericOperator($dataValidation, (int) $cellValue);
$returnValue = $this->numericOperator($dataValidation, (int) $cellValue, $cell);
}
} elseif ($type === DataValidation::TYPE_DECIMAL || $type === DataValidation::TYPE_DATE || $type === DataValidation::TYPE_TIME) {
if (!is_numeric($cellValue)) {
$returnValue = false;
} else {
$returnValue = $this->numericOperator($dataValidation, (float) $cellValue);
$returnValue = $this->numericOperator($dataValidation, (float) $cellValue, $cell);
}
} elseif ($type === DataValidation::TYPE_TEXTLENGTH) {
$returnValue = $this->numericOperator($dataValidation, mb_strlen($cell->getValueString()));
$returnValue = $this->numericOperator($dataValidation, mb_strlen($cell->getValueString()), $cell);
}

return $returnValue;
}

private function numericOperator(DataValidation $dataValidation, int|float $cellValue): bool
private function numericOperator(DataValidation $dataValidation, int|float $cellValue, Cell $cell): bool
{
$calculation = null;
$operator = $dataValidation->getOperator();
$formula1 = $dataValidation->getFormula1();
$formula2 = $dataValidation->getFormula2();
if (!is_numeric($formula1)) {
$calculation = Calculation::getInstance($cell->getWorksheet()->getParent());

try {
$result = $calculation
->calculateFormula("=$formula1", $cell->getCoordinate(), $cell);
while (is_array($result)) {
$result = array_pop($result);
}
$formula1 = $result;
} catch (Exception) {
// do nothing
}
}
$formula2 = 0;
if ($operator === DataValidation::OPERATOR_BETWEEN || $operator === DataValidation::OPERATOR_NOTBETWEEN) {
$formula2 = $dataValidation->getFormula2();
if (!is_numeric($formula2)) {
$calculation ??= Calculation::getInstance($cell->getWorksheet()->getParent());

try {
$result = $calculation
->calculateFormula("=$formula2", $cell->getCoordinate(), $cell);
while (is_array($result)) {
$result = array_pop($result);
}
$formula2 = $result;
} catch (Exception) {
// do nothing
}
}
}
$returnValue = false;
if ($operator === DataValidation::OPERATOR_BETWEEN) {
$returnValue = $cellValue >= $formula1 && $cellValue <= $formula2;
Expand Down
28 changes: 28 additions & 0 deletions tests/PhpSpreadsheetTests/ReferenceHelperDVTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,32 @@ public function testWholeRow(): void
self::assertSame(DataValidation::TYPE_NONE, $sheet->getDataValidation('H1')->getType());
$spreadsheet->disconnectWorksheets();
}

public function testFormula2(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getCell('A1')->setValue(5);
$sheet->getCell('A5')->setValue(9);
$dv = new DataValidation();
$dv->setType(DataValidation::TYPE_WHOLE)
->setOperator(DataValidation::OPERATOR_BETWEEN)
->setFormula1('$A$1')
->setFormula2('$A$5')
->setErrorStyle(DataValidation::STYLE_STOP)
->setShowErrorMessage(true)
->setErrorTitle('Input Error')
->setError('Value is not whole number within bounds');
$sheet->setDataValidation('B2', $dv);
$sheet->insertNewRowBefore(2);
$dv2 = $sheet->getCell('B3')->getDataValidation();
self::assertSame('$A$1', $dv2->getFormula1());
self::assertSame('$A$6', $dv2->getFormula2());

$sheet->getCell('B3')->setValue(7);
self::assertTrue($sheet->getCell('B3')->hasValidValue());
$sheet->getCell('B3')->setValue(1);
self::assertFalse($sheet->getCell('B3')->hasValidValue());
$spreadsheet->disconnectWorksheets();
}
}

0 comments on commit 6938fcb

Please sign in to comment.