File "Unique.php"
Full Path: /home/clickysoft/public_html/jmapi5.clickysoft.net/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Unique.php
File size: 4.32 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
class Unique
{
/**
* UNIQUE
* The UNIQUE function searches for value either from a one-row or one-column range or from an array.
*
* @param mixed $lookupVector The range of cells being searched
* @param mixed $byColumn Whether the uniqueness should be determined by row (the default) or by column
* @param mixed $exactlyOnce Whether the function should return only entries that occur just once in the list
*
* @return mixed The unique values from the search range
*/
public static function unique($lookupVector, $byColumn = false, $exactlyOnce = false)
{
if (!is_array($lookupVector)) {
// Scalars are always returned "as is"
return $lookupVector;
}
$byColumn = (bool) $byColumn;
$exactlyOnce = (bool) $exactlyOnce;
return ($byColumn === true)
? self::uniqueByColumn($lookupVector, $exactlyOnce)
: self::uniqueByRow($lookupVector, $exactlyOnce);
}
/**
* @return mixed
*/
private static function uniqueByRow(array $lookupVector, bool $exactlyOnce)
{
// When not $byColumn, we count whole rows or values, not individual values
// so implode each row into a single string value
array_walk(
$lookupVector,
function (array &$value): void {
$value = implode(chr(0x00), $value);
}
);
$result = self::countValuesCaseInsensitive($lookupVector);
if ($exactlyOnce === true) {
$result = self::exactlyOnceFilter($result);
}
if (count($result) === 0) {
return ExcelError::CALC();
}
$result = array_keys($result);
// restore rows from their strings
array_walk(
$result,
function (string &$value): void {
$value = explode(chr(0x00), $value);
}
);
return (count($result) === 1) ? array_pop($result) : $result;
}
/**
* @return mixed
*/
private static function uniqueByColumn(array $lookupVector, bool $exactlyOnce)
{
$flattenedLookupVector = Functions::flattenArray($lookupVector);
if (count($lookupVector, COUNT_RECURSIVE) > count($flattenedLookupVector, COUNT_RECURSIVE) + 1) {
// We're looking at a full column check (multiple rows)
$transpose = Matrix::transpose($lookupVector);
$result = self::uniqueByRow($transpose, $exactlyOnce);
return (is_array($result)) ? Matrix::transpose($result) : $result;
}
$result = self::countValuesCaseInsensitive($flattenedLookupVector);
if ($exactlyOnce === true) {
$result = self::exactlyOnceFilter($result);
}
if (count($result) === 0) {
return ExcelError::CALC();
}
$result = array_keys($result);
return $result;
}
private static function countValuesCaseInsensitive(array $caseSensitiveLookupValues): array
{
$caseInsensitiveCounts = array_count_values(
array_map(
function (string $value) {
return StringHelper::strToUpper($value);
},
$caseSensitiveLookupValues
)
);
$caseSensitiveCounts = [];
foreach ($caseInsensitiveCounts as $caseInsensitiveKey => $count) {
if (is_numeric($caseInsensitiveKey)) {
$caseSensitiveCounts[$caseInsensitiveKey] = $count;
} else {
foreach ($caseSensitiveLookupValues as $caseSensitiveValue) {
if ($caseInsensitiveKey === StringHelper::strToUpper($caseSensitiveValue)) {
$caseSensitiveCounts[$caseSensitiveValue] = $count;
break;
}
}
}
}
return $caseSensitiveCounts;
}
private static function exactlyOnceFilter(array $values): array
{
return array_filter(
$values,
function ($value) {
return $value === 1;
}
);
}
}