Logical.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <?php
  2. namespace PhpOffice\PhpSpreadsheet\Calculation;
  3. class Logical
  4. {
  5. /**
  6. * TRUE.
  7. *
  8. * Returns the boolean TRUE.
  9. *
  10. * Excel Function:
  11. * =TRUE()
  12. *
  13. * @category Logical Functions
  14. *
  15. * @return bool True
  16. */
  17. public static function true()
  18. {
  19. return true;
  20. }
  21. /**
  22. * FALSE.
  23. *
  24. * Returns the boolean FALSE.
  25. *
  26. * Excel Function:
  27. * =FALSE()
  28. *
  29. * @category Logical Functions
  30. *
  31. * @return bool False
  32. */
  33. public static function false()
  34. {
  35. return false;
  36. }
  37. private static function countTrueValues(array $args)
  38. {
  39. $returnValue = 0;
  40. foreach ($args as $arg) {
  41. // Is it a boolean value?
  42. if (is_bool($arg)) {
  43. $returnValue += $arg;
  44. } elseif ((is_numeric($arg)) && (!is_string($arg))) {
  45. $returnValue += ((int) $arg != 0);
  46. } elseif (is_string($arg)) {
  47. $arg = strtoupper($arg);
  48. if (($arg == 'TRUE') || ($arg == Calculation::getTRUE())) {
  49. $arg = true;
  50. } elseif (($arg == 'FALSE') || ($arg == Calculation::getFALSE())) {
  51. $arg = false;
  52. } else {
  53. return Functions::VALUE();
  54. }
  55. $returnValue += ($arg != 0);
  56. }
  57. }
  58. return $returnValue;
  59. }
  60. /**
  61. * LOGICAL_AND.
  62. *
  63. * Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE.
  64. *
  65. * Excel Function:
  66. * =AND(logical1[,logical2[, ...]])
  67. *
  68. * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays
  69. * or references that contain logical values.
  70. *
  71. * Boolean arguments are treated as True or False as appropriate
  72. * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
  73. * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
  74. * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value
  75. *
  76. * @category Logical Functions
  77. *
  78. * @param mixed ...$args Data values
  79. *
  80. * @return bool|string the logical AND of the arguments
  81. */
  82. public static function logicalAnd(...$args)
  83. {
  84. $args = Functions::flattenArray($args);
  85. if (count($args) == 0) {
  86. return Functions::VALUE();
  87. }
  88. $args = array_filter($args, function ($value) {
  89. return $value !== null || (is_string($value) && trim($value) == '');
  90. });
  91. $argCount = count($args);
  92. $returnValue = self::countTrueValues($args);
  93. if (is_string($returnValue)) {
  94. return $returnValue;
  95. }
  96. return ($returnValue > 0) && ($returnValue == $argCount);
  97. }
  98. /**
  99. * LOGICAL_OR.
  100. *
  101. * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE.
  102. *
  103. * Excel Function:
  104. * =OR(logical1[,logical2[, ...]])
  105. *
  106. * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays
  107. * or references that contain logical values.
  108. *
  109. * Boolean arguments are treated as True or False as appropriate
  110. * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
  111. * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
  112. * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value
  113. *
  114. * @category Logical Functions
  115. *
  116. * @param mixed $args Data values
  117. *
  118. * @return bool|string the logical OR of the arguments
  119. */
  120. public static function logicalOr(...$args)
  121. {
  122. $args = Functions::flattenArray($args);
  123. if (count($args) == 0) {
  124. return Functions::VALUE();
  125. }
  126. $args = array_filter($args, function ($value) {
  127. return $value !== null || (is_string($value) && trim($value) == '');
  128. });
  129. $returnValue = self::countTrueValues($args);
  130. if (is_string($returnValue)) {
  131. return $returnValue;
  132. }
  133. return $returnValue > 0;
  134. }
  135. /**
  136. * LOGICAL_XOR.
  137. *
  138. * Returns the Exclusive Or logical operation for one or more supplied conditions.
  139. * i.e. the Xor function returns TRUE if an odd number of the supplied conditions evaluate to TRUE, and FALSE otherwise.
  140. *
  141. * Excel Function:
  142. * =XOR(logical1[,logical2[, ...]])
  143. *
  144. * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays
  145. * or references that contain logical values.
  146. *
  147. * Boolean arguments are treated as True or False as appropriate
  148. * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
  149. * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
  150. * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value
  151. *
  152. * @category Logical Functions
  153. *
  154. * @param mixed $args Data values
  155. *
  156. * @return bool|string the logical XOR of the arguments
  157. */
  158. public static function logicalXor(...$args)
  159. {
  160. $args = Functions::flattenArray($args);
  161. if (count($args) == 0) {
  162. return Functions::VALUE();
  163. }
  164. $args = array_filter($args, function ($value) {
  165. return $value !== null || (is_string($value) && trim($value) == '');
  166. });
  167. $returnValue = self::countTrueValues($args);
  168. if (is_string($returnValue)) {
  169. return $returnValue;
  170. }
  171. return $returnValue % 2 == 1;
  172. }
  173. /**
  174. * NOT.
  175. *
  176. * Returns the boolean inverse of the argument.
  177. *
  178. * Excel Function:
  179. * =NOT(logical)
  180. *
  181. * The argument must evaluate to a logical value such as TRUE or FALSE
  182. *
  183. * Boolean arguments are treated as True or False as appropriate
  184. * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
  185. * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
  186. * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value
  187. *
  188. * @category Logical Functions
  189. *
  190. * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE
  191. *
  192. * @return bool|string the boolean inverse of the argument
  193. */
  194. public static function NOT($logical = false)
  195. {
  196. $logical = Functions::flattenSingleValue($logical);
  197. if (is_string($logical)) {
  198. $logical = strtoupper($logical);
  199. if (($logical == 'TRUE') || ($logical == Calculation::getTRUE())) {
  200. return false;
  201. } elseif (($logical == 'FALSE') || ($logical == Calculation::getFALSE())) {
  202. return true;
  203. }
  204. return Functions::VALUE();
  205. }
  206. return !$logical;
  207. }
  208. /**
  209. * STATEMENT_IF.
  210. *
  211. * Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE.
  212. *
  213. * Excel Function:
  214. * =IF(condition[,returnIfTrue[,returnIfFalse]])
  215. *
  216. * Condition is any value or expression that can be evaluated to TRUE or FALSE.
  217. * For example, A10=100 is a logical expression; if the value in cell A10 is equal to 100,
  218. * the expression evaluates to TRUE. Otherwise, the expression evaluates to FALSE.
  219. * This argument can use any comparison calculation operator.
  220. * ReturnIfTrue is the value that is returned if condition evaluates to TRUE.
  221. * For example, if this argument is the text string "Within budget" and the condition argument evaluates to TRUE,
  222. * then the IF function returns the text "Within budget"
  223. * If condition is TRUE and ReturnIfTrue is blank, this argument returns 0 (zero). To display the word TRUE, use
  224. * the logical value TRUE for this argument.
  225. * ReturnIfTrue can be another formula.
  226. * ReturnIfFalse is the value that is returned if condition evaluates to FALSE.
  227. * For example, if this argument is the text string "Over budget" and the condition argument evaluates to FALSE,
  228. * then the IF function returns the text "Over budget".
  229. * If condition is FALSE and ReturnIfFalse is omitted, then the logical value FALSE is returned.
  230. * If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned.
  231. * ReturnIfFalse can be another formula.
  232. *
  233. * @category Logical Functions
  234. *
  235. * @param mixed $condition Condition to evaluate
  236. * @param mixed $returnIfTrue Value to return when condition is true
  237. * @param mixed $returnIfFalse Optional value to return when condition is false
  238. *
  239. * @return mixed The value of returnIfTrue or returnIfFalse determined by condition
  240. */
  241. public static function statementIf($condition = true, $returnIfTrue = 0, $returnIfFalse = false)
  242. {
  243. $condition = ($condition === null) ? true : (bool) Functions::flattenSingleValue($condition);
  244. $returnIfTrue = ($returnIfTrue === null) ? 0 : Functions::flattenSingleValue($returnIfTrue);
  245. $returnIfFalse = ($returnIfFalse === null) ? false : Functions::flattenSingleValue($returnIfFalse);
  246. return ($condition) ? $returnIfTrue : $returnIfFalse;
  247. }
  248. /**
  249. * IFERROR.
  250. *
  251. * Excel Function:
  252. * =IFERROR(testValue,errorpart)
  253. *
  254. * @category Logical Functions
  255. *
  256. * @param mixed $testValue Value to check, is also the value returned when no error
  257. * @param mixed $errorpart Value to return when testValue is an error condition
  258. *
  259. * @return mixed The value of errorpart or testValue determined by error condition
  260. */
  261. public static function IFERROR($testValue = '', $errorpart = '')
  262. {
  263. $testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue);
  264. $errorpart = ($errorpart === null) ? '' : Functions::flattenSingleValue($errorpart);
  265. return self::statementIf(Functions::isError($testValue), $errorpart, $testValue);
  266. }
  267. }