33namespace PhpOffice \PhpSpreadsheet \Cell ;
44
55use PhpOffice \PhpSpreadsheet \Calculation \Calculation ;
6- use PhpOffice \PhpSpreadsheet \Calculation \Information \ ExcelError ;
6+ use PhpOffice \PhpSpreadsheet \Calculation \Functions ;
77use PhpOffice \PhpSpreadsheet \Exception ;
88
99/**
@@ -37,46 +37,70 @@ public function isValid(Cell $cell): bool
3737 if (!is_numeric ($ cellValue ) || fmod ((float ) $ cellValue , 1 ) != 0 ) {
3838 $ returnValue = false ;
3939 } else {
40- $ returnValue = $ this ->numericOperator ($ dataValidation , (int ) $ cellValue );
40+ $ returnValue = $ this ->numericOperator ($ dataValidation , (int ) $ cellValue, $ cell );
4141 }
4242 } elseif ($ type === DataValidation::TYPE_DECIMAL || $ type === DataValidation::TYPE_DATE || $ type === DataValidation::TYPE_TIME ) {
4343 if (!is_numeric ($ cellValue )) {
4444 $ returnValue = false ;
4545 } else {
46- $ returnValue = $ this ->numericOperator ($ dataValidation , (float ) $ cellValue );
46+ $ returnValue = $ this ->numericOperator ($ dataValidation , (float ) $ cellValue, $ cell );
4747 }
4848 } elseif ($ type === DataValidation::TYPE_TEXTLENGTH ) {
49- $ returnValue = $ this ->numericOperator ($ dataValidation , mb_strlen ($ cell ->getValueString ()));
49+ $ returnValue = $ this ->numericOperator ($ dataValidation , mb_strlen ($ cell ->getValueString ()), $ cell );
5050 }
5151
5252 return $ returnValue ;
5353 }
5454
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
5678 {
5779 $ 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+ );
7791 }
7892
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+ };
80104 }
81105
82106 /**
@@ -94,22 +118,22 @@ private function isValueInList(Cell $cell): bool
94118 // inline values list
95119 if ($ formula1 [0 ] === '" ' ) {
96120 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 ());
107123
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+ }
111131 }
132+ } catch (Exception ) {
133+ // do nothing
112134 }
135+
136+ return false ;
113137 }
114138
115139 return true ;
0 commit comments