AutorÃa | Ultima modificación | Ver Log |
<?phpnamespace PhpOffice\PhpSpreadsheet\Calculation\TextData;use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;use PhpOffice\PhpSpreadsheet\Calculation\Calculation;use PhpOffice\PhpSpreadsheet\Calculation\Functions;use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue;use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;use PhpOffice\PhpSpreadsheet\Cell\DataType;use PhpOffice\PhpSpreadsheet\Shared\StringHelper;class Concatenate{use ArrayEnabled;/*** This implements the CONCAT function, *not* CONCATENATE.** @param array $args*/public static function CONCATENATE(...$args): string{$returnValue = '';// Loop through arguments$aArgs = Functions::flattenArray($args);foreach ($aArgs as $arg) {$value = Helpers::extractString($arg);if (ErrorValue::isError($value, true)) {$returnValue = $value;break;}$returnValue .= Helpers::extractString($arg);if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {$returnValue = ExcelError::CALC();break;}}return $returnValue;}/*** This implements the CONCATENATE function.** @param array $args data to be concatenated*/public static function actualCONCATENATE(...$args): array|string{if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_GNUMERIC) {return self::CONCATENATE(...$args);}$result = '';foreach ($args as $operand2) {$result = self::concatenate2Args($result, $operand2);if (ErrorValue::isError($result, true) === true) {break;}}return $result;}private static function concatenate2Args(array|string $operand1, null|array|bool|float|int|string $operand2): array|string{if (is_array($operand1) || is_array($operand2)) {$operand1 = Calculation::boolToString($operand1);$operand2 = Calculation::boolToString($operand2);[$rows, $columns] = Calculation::checkMatrixOperands($operand1, $operand2, 2);$errorFound = false;for ($row = 0; $row < $rows && !$errorFound; ++$row) {for ($column = 0; $column < $columns; ++$column) {if (ErrorValue::isError($operand2[$row][$column])) {return $operand2[$row][$column];}$operand1[$row][$column]= Calculation::boolToString($operand1[$row][$column]). Calculation::boolToString($operand2[$row][$column]);if (mb_strlen($operand1[$row][$column]) > DataType::MAX_STRING_LENGTH) {$operand1 = ExcelError::CALC();$errorFound = true;break;}}}} elseif (ErrorValue::isError($operand2, true) === true) {$operand1 = (string) $operand2;} else {$operand1 .= (string) Calculation::boolToString($operand2);if (mb_strlen($operand1) > DataType::MAX_STRING_LENGTH) {$operand1 = ExcelError::CALC();}}return $operand1;}/*** TEXTJOIN.** @param mixed $delimiter The delimter to use between the joined arguments* Or can be an array of values* @param mixed $ignoreEmpty true/false Flag indicating whether empty arguments should be skipped* Or can be an array of values* @param mixed $args The values to join** @return array|string The joined string* If an array of values is passed for the $delimiter or $ignoreEmpty arguments, then the returned result* will also be an array with matching dimensions*/public static function TEXTJOIN(mixed $delimiter = '', mixed $ignoreEmpty = true, mixed ...$args): array|string{if (is_array($delimiter) || is_array($ignoreEmpty)) {return self::evaluateArrayArgumentsSubset([self::class, __FUNCTION__],2,$delimiter,$ignoreEmpty,...$args);}$delimiter ??= '';$ignoreEmpty ??= true;$aArgs = Functions::flattenArray($args);$returnValue = self::evaluateTextJoinArray($ignoreEmpty, $aArgs);$returnValue ??= implode($delimiter, $aArgs);if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {$returnValue = ExcelError::CALC();}return $returnValue;}private static function evaluateTextJoinArray(bool $ignoreEmpty, array &$aArgs): ?string{foreach ($aArgs as $key => &$arg) {$value = Helpers::extractString($arg);if (ErrorValue::isError($value, true)) {return $value;}if ($ignoreEmpty === true && ((is_string($arg) && trim($arg) === '') || $arg === null)) {unset($aArgs[$key]);} elseif (is_bool($arg)) {$arg = Helpers::convertBooleanValue($arg);}}return null;}/*** REPT.** Returns the result of builtin function round after validating args.** @param mixed $stringValue The value to repeat* Or can be an array of values* @param mixed $repeatCount The number of times the string value should be repeated* Or can be an array of values** @return array|string The repeated string* If an array of values is passed for the $stringValue or $repeatCount arguments, then the returned result* will also be an array with matching dimensions*/public static function builtinREPT(mixed $stringValue, mixed $repeatCount): array|string{if (is_array($stringValue) || is_array($repeatCount)) {return self::evaluateArrayArguments([self::class, __FUNCTION__], $stringValue, $repeatCount);}$stringValue = Helpers::extractString($stringValue);if (!is_numeric($repeatCount) || $repeatCount < 0) {$returnValue = ExcelError::VALUE();} elseif (ErrorValue::isError($stringValue, true)) {$returnValue = $stringValue;} else {$returnValue = str_repeat($stringValue, (int) $repeatCount);if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {$returnValue = ExcelError::VALUE(); // note VALUE not CALC}}return $returnValue;}}