AutorÃa | Ultima modificación | Ver Log |
<?phpnamespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;use PhpOffice\PhpSpreadsheet\Calculation\Functions;use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;class ChooseRowsEtc{/*** Transpose 2-dimensional array.* See https://stackoverflow.com/questions/797251/transposing-multidimensional-arrays-in-php* especially the comment from user17994717.** @param mixed[] $array** @return mixed[]*/public static function transpose(array $array): array{return empty($array) ? [] : (array_map((count($array) === 1) ? (fn ($x) => [$x]) : null, ...$array)); // @phpstan-ignore-line}/** @return mixed[] */private static function arrayValues(mixed $array): array{return is_array($array) ? array_values($array) : [$array];}/*** CHOOSECOLS.** @param mixed $input expecting two-dimensional array** @return mixed[]|string*/public static function chooseCols(mixed $input, mixed ...$args): array|string{if (!is_array($input)) {$input = [[$input]];}$retval = self::chooseRows(self::transpose($input), ...$args);return is_array($retval) ? self::transpose($retval) : $retval;}/*** CHOOSEROWS.** @param mixed $input expecting two-dimensional array** @return mixed[]|string*/public static function chooseRows(mixed $input, mixed ...$args): array|string{if (!is_array($input)) {$input = [[$input]];}$inputArray = [[]]; // no row 0$numRows = 0;foreach ($input as $inputRow) {$inputArray[] = self::arrayValues($inputRow);++$numRows;}$outputArray = [];foreach (Functions::flattenArray2(...$args) as $arg) {if (!is_numeric($arg)) {return ExcelError::VALUE();}$index = (int) $arg;if ($index < 0) {$index += $numRows + 1;}if ($index <= 0 || $index > $numRows) {return ExcelError::VALUE();}$outputArray[] = $inputArray[$index];}return $outputArray;}private static function dropRows(array $array, mixed $offset): array|string{if ($offset === null) {return $array;}if (!is_numeric($offset)) {return ExcelError::VALUE();}$offset = (int) $offset;$count = count($array);if (abs($offset) >= $count) {// In theory, this should be #CALC!, but Excel treats// #CALC! as corrupt, and it's not worth figuring out whyreturn ExcelError::VALUE();}if ($offset === 0) {return $array;}if ($offset > 0) {return array_slice($array, $offset);}return array_slice($array, 0, $count + $offset);}/*** DROP.** @param mixed $input expect two-dimensional array** @return mixed[]|string*/public static function drop(mixed $input, mixed $rows = null, mixed $columns = null): array|string{if (!is_array($input)) {$input = [[$input]];}$inputArray = []; // no row 0foreach ($input as $inputRow) {$inputArray[] = self::arrayValues($inputRow);}$outputArray1 = self::dropRows($inputArray, $rows);if (is_string($outputArray1)) {return $outputArray1;}$outputArray2 = self::transpose($outputArray1);$outputArray3 = self::dropRows($outputArray2, $columns);if (is_string($outputArray3)) {return $outputArray3;}return self::transpose($outputArray3);}private static function takeRows(array $array, mixed $offset): array|string{if ($offset === null) {return $array;}if (!is_numeric($offset)) {return ExcelError::VALUE();}$offset = (int) $offset;if ($offset === 0) {// should be #CALC! - see abovereturn ExcelError::VALUE();}$count = count($array);if (abs($offset) >= $count) {return $array;}if ($offset > 0) {return array_slice($array, 0, $offset);}return array_slice($array, $count + $offset);}/*** TAKE.** @param mixed $input expecting two-dimensional array** @return mixed[]|string*/public static function take(mixed $input, mixed $rows, mixed $columns = null): array|string{if (!is_array($input)) {$input = [[$input]];}if ($rows === null && $columns === null) {return $input;}$inputArray = [];foreach ($input as $inputRow) {$inputArray[] = self::arrayValues($inputRow);}$outputArray1 = self::takeRows($inputArray, $rows);if (is_string($outputArray1)) {return $outputArray1;}$outputArray2 = self::transpose($outputArray1);$outputArray3 = self::takeRows($outputArray2, $columns);if (is_string($outputArray3)) {return $outputArray3;}return self::transpose($outputArray3);}/*** EXPAND.** @param mixed $input expecting two-dimensional array** @return mixed[]|string*/public static function expand(mixed $input, mixed $rows, mixed $columns = null, mixed $pad = '#N/A'): array|string{if (!is_array($input)) {$input = [[$input]];}if ($rows === null && $columns === null) {return $input;}$numRows = count($input);$rows ??= $numRows;if (!is_numeric($rows)) {return ExcelError::VALUE();}$rows = (int) $rows;if ($rows < count($input)) {return ExcelError::VALUE();}$numCols = 0;foreach ($input as $inputRow) {$numCols = max($numCols, is_array($inputRow) ? count($inputRow) : 1);}$columns ??= $numCols;if (!is_numeric($columns)) {return ExcelError::VALUE();}$columns = (int) $columns;if ($columns < $numCols) {return ExcelError::VALUE();}$inputArray = [];foreach ($input as $inputRow) {$inputArray[] = array_pad(self::arrayValues($inputRow), $columns, $pad);}$outputArray = [];$padRow = array_pad([], $columns, $pad);for ($count = 0; $count < $rows; ++$count) {$outputArray[] = ($count >= $numRows) ? $padRow : $inputArray[$count];}return $outputArray;}}