chengkun
2025-09-15 3c9050e82e582414dc7b208c8283fe47be37eeba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php
 
namespace PhpOffice\PhpSpreadsheet\Cell;
 
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Exception;
 
/**
 * Validate a cell value according to its validation rules.
 */
class DataValidator
{
    /**
     * Does this cell contain valid value?
     *
     * @param Cell $cell Cell to check the value
     */
    public function isValid(Cell $cell): bool
    {
        if (!$cell->hasDataValidation() || $cell->getDataValidation()->getType() === DataValidation::TYPE_NONE) {
            return true;
        }
 
        $cellValue = $cell->getValue();
        $dataValidation = $cell->getDataValidation();
 
        if (!$dataValidation->getAllowBlank() && ($cellValue === null || $cellValue === '')) {
            return false;
        }
 
        $returnValue = false;
        $type = $dataValidation->getType();
        if ($type === DataValidation::TYPE_LIST) {
            $returnValue = $this->isValueInList($cell);
        } elseif ($type === DataValidation::TYPE_WHOLE) {
            if (!is_numeric($cellValue) || fmod((float) $cellValue, 1) != 0) {
                $returnValue = false;
            } else {
                $returnValue = $this->numericOperator($dataValidation, (int) $cellValue);
            }
        } 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);
            }
        } elseif ($type === DataValidation::TYPE_TEXTLENGTH) {
            $returnValue = $this->numericOperator($dataValidation, mb_strlen((string) $cellValue));
        }
 
        return $returnValue;
    }
 
    private function numericOperator(DataValidation $dataValidation, int|float $cellValue): bool
    {
        $operator = $dataValidation->getOperator();
        $formula1 = $dataValidation->getFormula1();
        $formula2 = $dataValidation->getFormula2();
        $returnValue = false;
        if ($operator === DataValidation::OPERATOR_BETWEEN) {
            $returnValue = $cellValue >= $formula1 && $cellValue <= $formula2;
        } elseif ($operator === DataValidation::OPERATOR_NOTBETWEEN) {
            $returnValue = $cellValue < $formula1 || $cellValue > $formula2;
        } elseif ($operator === DataValidation::OPERATOR_EQUAL) {
            $returnValue = $cellValue == $formula1;
        } elseif ($operator === DataValidation::OPERATOR_NOTEQUAL) {
            $returnValue = $cellValue != $formula1;
        } elseif ($operator === DataValidation::OPERATOR_LESSTHAN) {
            $returnValue = $cellValue < $formula1;
        } elseif ($operator === DataValidation::OPERATOR_LESSTHANOREQUAL) {
            $returnValue = $cellValue <= $formula1;
        } elseif ($operator === DataValidation::OPERATOR_GREATERTHAN) {
            $returnValue = $cellValue > $formula1;
        } elseif ($operator === DataValidation::OPERATOR_GREATERTHANOREQUAL) {
            $returnValue = $cellValue >= $formula1;
        }
 
        return $returnValue;
    }
 
    /**
     * Does this cell contain valid value, based on list?
     *
     * @param Cell $cell Cell to check the value
     */
    private function isValueInList(Cell $cell): bool
    {
        $cellValue = $cell->getValue();
        $dataValidation = $cell->getDataValidation();
 
        $formula1 = $dataValidation->getFormula1();
        if (!empty($formula1)) {
            // inline values list
            if ($formula1[0] === '"') {
                return in_array(strtolower($cellValue), 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);
                    }
 
                    return $result !== ExcelError::NA();
                } catch (Exception) {
                    return false;
                }
            }
        }
 
        return true;
    }
}