3
3
namespace PhpOffice \PhpSpreadsheet \Cell ;
4
4
5
5
use PhpOffice \PhpSpreadsheet \Calculation \Calculation ;
6
- use PhpOffice \PhpSpreadsheet \Calculation \Information \ ExcelError ;
6
+ use PhpOffice \PhpSpreadsheet \Calculation \Functions ;
7
7
use PhpOffice \PhpSpreadsheet \Exception ;
8
8
9
9
/**
@@ -37,46 +37,70 @@ public function isValid(Cell $cell): bool
37
37
if (!is_numeric ($ cellValue ) || fmod ((float ) $ cellValue , 1 ) != 0 ) {
38
38
$ returnValue = false ;
39
39
} else {
40
- $ returnValue = $ this ->numericOperator ($ dataValidation , (int ) $ cellValue );
40
+ $ returnValue = $ this ->numericOperator ($ dataValidation , (int ) $ cellValue, $ cell );
41
41
}
42
42
} elseif ($ type === DataValidation::TYPE_DECIMAL || $ type === DataValidation::TYPE_DATE || $ type === DataValidation::TYPE_TIME ) {
43
43
if (!is_numeric ($ cellValue )) {
44
44
$ returnValue = false ;
45
45
} else {
46
- $ returnValue = $ this ->numericOperator ($ dataValidation , (float ) $ cellValue );
46
+ $ returnValue = $ this ->numericOperator ($ dataValidation , (float ) $ cellValue, $ cell );
47
47
}
48
48
} elseif ($ type === DataValidation::TYPE_TEXTLENGTH ) {
49
- $ returnValue = $ this ->numericOperator ($ dataValidation , mb_strlen ($ cell ->getValueString ()));
49
+ $ returnValue = $ this ->numericOperator ($ dataValidation , mb_strlen ($ cell ->getValueString ()), $ cell );
50
50
}
51
51
52
52
return $ returnValue ;
53
53
}
54
54
55
- private function numericOperator (DataValidation $ dataValidation , int |float $ cellValue ): bool
55
+ private const TWO_FORMULAS = [DataValidation::OPERATOR_BETWEEN , DataValidation::OPERATOR_NOTBETWEEN ];
56
+
57
+ private static function evaluateNumericFormula (mixed $ formula , Cell $ cell ): mixed
58
+ {
59
+ if (!is_numeric ($ formula )) {
60
+ $ calculation = Calculation::getInstance ($ cell ->getWorksheet ()->getParent ());
61
+
62
+ try {
63
+ $ result = $ calculation
64
+ ->calculateFormula ("= $ formula " , $ cell ->getCoordinate (), $ cell );
65
+ while (is_array ($ result )) {
66
+ $ result = array_pop ($ result );
67
+ }
68
+ $ formula = $ result ;
69
+ } catch (Exception ) {
70
+ // do nothing
71
+ }
72
+ }
73
+
74
+ return $ formula ;
75
+ }
76
+
77
+ private function numericOperator (DataValidation $ dataValidation , int |float $ cellValue , Cell $ cell ): bool
56
78
{
57
79
$ operator = $ dataValidation ->getOperator ();
58
- $ formula1 = $ dataValidation ->getFormula1 ();
59
- $ formula2 = $ dataValidation ->getFormula2 ();
60
- $ returnValue = false ;
61
- if ($ operator === DataValidation::OPERATOR_BETWEEN ) {
62
- $ returnValue = $ cellValue >= $ formula1 && $ cellValue <= $ formula2 ;
63
- } elseif ($ operator === DataValidation::OPERATOR_NOTBETWEEN ) {
64
- $ returnValue = $ cellValue < $ formula1 || $ cellValue > $ formula2 ;
65
- } elseif ($ operator === DataValidation::OPERATOR_EQUAL ) {
66
- $ returnValue = $ cellValue == $ formula1 ;
67
- } elseif ($ operator === DataValidation::OPERATOR_NOTEQUAL ) {
68
- $ returnValue = $ cellValue != $ formula1 ;
69
- } elseif ($ operator === DataValidation::OPERATOR_LESSTHAN ) {
70
- $ returnValue = $ cellValue < $ formula1 ;
71
- } elseif ($ operator === DataValidation::OPERATOR_LESSTHANOREQUAL ) {
72
- $ returnValue = $ cellValue <= $ formula1 ;
73
- } elseif ($ operator === DataValidation::OPERATOR_GREATERTHAN ) {
74
- $ returnValue = $ cellValue > $ formula1 ;
75
- } elseif ($ operator === DataValidation::OPERATOR_GREATERTHANOREQUAL ) {
76
- $ returnValue = $ cellValue >= $ formula1 ;
80
+ $ formula1 = self ::evaluateNumericFormula (
81
+ $ dataValidation ->getFormula1 (),
82
+ $ cell
83
+ );
84
+
85
+ $ formula2 = 0 ;
86
+ if (in_array ($ operator , self ::TWO_FORMULAS , true )) {
87
+ $ formula2 = self ::evaluateNumericFormula (
88
+ $ dataValidation ->getFormula2 (),
89
+ $ cell
90
+ );
77
91
}
78
92
79
- return $ returnValue ;
93
+ return match ($ operator ) {
94
+ DataValidation::OPERATOR_BETWEEN => $ cellValue >= $ formula1 && $ cellValue <= $ formula2 ,
95
+ DataValidation::OPERATOR_NOTBETWEEN => $ cellValue < $ formula1 || $ cellValue > $ formula2 ,
96
+ DataValidation::OPERATOR_EQUAL => $ cellValue == $ formula1 ,
97
+ DataValidation::OPERATOR_NOTEQUAL => $ cellValue != $ formula1 ,
98
+ DataValidation::OPERATOR_LESSTHAN => $ cellValue < $ formula1 ,
99
+ DataValidation::OPERATOR_LESSTHANOREQUAL => $ cellValue <= $ formula1 ,
100
+ DataValidation::OPERATOR_GREATERTHAN => $ cellValue > $ formula1 ,
101
+ DataValidation::OPERATOR_GREATERTHANOREQUAL => $ cellValue >= $ formula1 ,
102
+ default => false ,
103
+ };
80
104
}
81
105
82
106
/**
@@ -94,22 +118,22 @@ private function isValueInList(Cell $cell): bool
94
118
// inline values list
95
119
if ($ formula1 [0 ] === '" ' ) {
96
120
return in_array (strtolower ($ cellValueString ), explode (', ' , strtolower (trim ($ formula1 , '" ' ))), true );
97
- } elseif (strpos ($ formula1 , ': ' ) > 0 ) {
98
- // values list cells
99
- $ matchFormula = '=MATCH( ' . $ cell ->getCoordinate () . ', ' . $ formula1 . ', 0) ' ;
100
- $ calculation = Calculation::getInstance ($ cell ->getWorksheet ()->getParent ());
101
-
102
- try {
103
- $ result = $ calculation ->calculateFormula ($ matchFormula , $ cell ->getCoordinate (), $ cell );
104
- while (is_array ($ result )) {
105
- $ result = array_pop ($ result );
106
- }
121
+ }
122
+ $ calculation = Calculation::getInstance ($ cell ->getWorksheet ()->getParent ());
107
123
108
- return $ result !== ExcelError::NA ();
109
- } catch (Exception ) {
110
- return false ;
124
+ try {
125
+ $ result = $ calculation ->calculateFormula ("= $ formula1 " , $ cell ->getCoordinate (), $ cell );
126
+ $ result = is_array ($ result ) ? Functions::flattenArray ($ result ) : [$ result ];
127
+ foreach ($ result as $ oneResult ) {
128
+ if (is_scalar ($ oneResult ) && strcasecmp ((string ) $ oneResult , $ cellValueString ) === 0 ) {
129
+ return true ;
130
+ }
111
131
}
132
+ } catch (Exception ) {
133
+ // do nothing
112
134
}
135
+
136
+ return false ;
113
137
}
114
138
115
139
return true ;
0 commit comments