VLookup.php
3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php
namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
class VLookup extends LookupBase
{
/**
* VLOOKUP
* The VLOOKUP function searches for value in the left-most column of lookup_array and returns the value
* in the same row based on the index_number.
*
* @param mixed $lookupValue The value that you want to match in lookup_array
* @param mixed $lookupArray The range of cells being searched
* @param mixed $indexNumber The column number in table_array from which the matching value must be returned.
* The first column is 1.
* @param mixed $notExactMatch determines if you are looking for an exact match based on lookup_value
*
* @return mixed The value of the found cell
*/
public static function lookup($lookupValue, $lookupArray, $indexNumber, $notExactMatch = true)
{
$lookupValue = Functions::flattenSingleValue($lookupValue);
$indexNumber = Functions::flattenSingleValue($indexNumber);
$notExactMatch = ($notExactMatch === null) ? true : Functions::flattenSingleValue($notExactMatch);
try {
$indexNumber = self::validateIndexLookup($lookupArray, $indexNumber);
} catch (Exception $e) {
return $e->getMessage();
}
$f = array_keys($lookupArray);
$firstRow = array_pop($f);
if ((!is_array($lookupArray[$firstRow])) || ($indexNumber > count($lookupArray[$firstRow]))) {
return Functions::REF();
}
$columnKeys = array_keys($lookupArray[$firstRow]);
$returnColumn = $columnKeys[--$indexNumber];
$firstColumn = array_shift($columnKeys);
if (!$notExactMatch) {
uasort($lookupArray, ['self', 'vlookupSort']);
}
$rowNumber = self::vLookupSearch($lookupValue, $lookupArray, $firstColumn, $notExactMatch);
if ($rowNumber !== null) {
// return the appropriate value
return $lookupArray[$rowNumber][$returnColumn];
}
return Functions::NA();
}
private static function vlookupSort($a, $b)
{
reset($a);
$firstColumn = key($a);
$aLower = StringHelper::strToLower($a[$firstColumn]);
$bLower = StringHelper::strToLower($b[$firstColumn]);
if ($aLower == $bLower) {
return 0;
}
return ($aLower < $bLower) ? -1 : 1;
}
private static function vLookupSearch($lookupValue, $lookupArray, $column, $notExactMatch)
{
$lookupLower = StringHelper::strToLower($lookupValue);
$rowNumber = null;
foreach ($lookupArray as $rowKey => $rowData) {
$bothNumeric = is_numeric($lookupValue) && is_numeric($rowData[$column]);
$bothNotNumeric = !is_numeric($lookupValue) && !is_numeric($rowData[$column]);
$cellDataLower = StringHelper::strToLower($rowData[$column]);
// break if we have passed possible keys
if (
$notExactMatch &&
(($bothNumeric && ($rowData[$column] > $lookupValue)) ||
($bothNotNumeric && ($cellDataLower > $lookupLower)))
) {
break;
}
$rowNumber = self::checkMatch(
$bothNumeric,
$bothNotNumeric,
$notExactMatch,
$rowKey,
$cellDataLower,
$lookupLower,
$rowNumber
);
}
return $rowNumber;
}
}