Skip to content

Instantly share code, notes, and snippets.

@JosephDomenici
Created June 22, 2019 18:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JosephDomenici/51d2555e5cd775b3a39482a98d483062 to your computer and use it in GitHub Desktop.
Save JosephDomenici/51d2555e5cd775b3a39482a98d483062 to your computer and use it in GitHub Desktop.
Custom Sheets function that finds an exact match on multiple columns and conditions
/**
* Finds an exact match on multiple columns and conditions. This function accepts an indefinite number of match parameters to search against.
*
* @param {"Foo"} value1 The first value to look up.
* @param {Sheet1!A:A} range1 The first range to match against.
* @param {"Bar"} value2 (optional, repeating) The second value to look up.
* @param {Sheet1!B:B} range2 (optional, repeating) The second range to match against.
* @return {Array} Row numbers of rows that exactly match on all conditions.
* @customfunction
*/
function MATCHES(value1, range1, value2, range2)
{
if (arguments.length < 2) { throw new Error("There must be at least one search term and one range to evaluate."); }
if (arguments.length % 2 != 0) { throw new Error("There must be an even number of parameters."); }
var matches = {};
for (var i = 1; i < arguments.length; i += 2)
{
var range = arguments[i];
var value = arguments[i - 1];
if (range[0].length > 1 && range.length > 1) { throw new Error("Search ranges must be a single column or row."); }
if (typeof(value) == "object" || typeof(value) == "undefined")
{
if (value[0].length > 1 || value.length > 1) { throw new Error("Match values must not span an array."); }
}
// Match over a column
if (range.length > 1)
{
for (var j = 0; j < range.length; j++)
{
if (range[j][0] == value)
{
if ((j + 1) in matches)
{
matches[j + 1]++;
}
else
{
matches[j + 1] = 1;
}
}
}
}
// Match over a row
else
{
for (var j = 0; j < range[0].length; j++)
{
if (range[0][j] == value)
{
if ((j + 1) in matches)
{
matches[j + 1]++;
}
else
{
matches[j + 1] = 1;
}
}
}
}
}
var keys = Object.keys(matches);
// Return the first result that matches across all search ranges
for (var i = 0; i < keys.length; i++)
{
var key = keys[i];
if (matches[key] == arguments.length / 2)
{
return key;
}
}
throw new Error("Did not find an exact match for all values in MATCHES evaluation.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment