Skip to content

Instantly share code, notes, and snippets.

@emmaly
Last active March 4, 2023 02:57
Embed
What would you like to do?
Google Sheet: DoRangesHaveOverlap() = do all of these ranges have shared overlap points? GetRangeUnion() = return the union of any number of ranges
/**
* @param {SpreadsheetApp.Range} ranges
* @returns {boolean}
* - `true` indicates all ranges share the same overlapping point(s) with all others
* - `false` indicates no shared overlap point, even if they all overlap individually
*/
function DoRangesHaveOverlap(...ranges) {
return GetRangeUnion(...ranges) !== null;
}
function Example_IsUnion() {
const sheet = SpreadsheetApp.getActiveSheet();
const ranges = [
sheet.getRange(5, 5, 4, 4),
sheet.getRange(6, 6, 4, 4),
sheet.getRange(7, 7, 4, 4),
];
// ranges.forEach((range) => Logger.log("range: %s", range.getA1Notation()));
const sharedOverlap = DoRangesHaveOverlap(...ranges);
Logger.log("sharedOverlap: %s", sharedOverlap);
const union = GetRangeUnion(...ranges);
Logger.log("union: %s", union?.getA1Notation());
}
// sharedOverlap: true
// union: G7:H8
function Example_NoUnion() {
const sheet = SpreadsheetApp.getActiveSheet();
const ranges = [
sheet.getRange(4, 4, 4, 4),
sheet.getRange(5, 5, 4, 4),
sheet.getRange(6, 6, 4, 4),
sheet.getRange(7, 7, 4, 4),
sheet.getRange(8, 8, 4, 4),
];
// ranges.forEach((range) => Logger.log("range: %s", range.getA1Notation()));
const sharedOverlap = DoRangesHaveOverlap(...ranges);
Logger.log("sharedOverlap: %s", sharedOverlap);
const union = GetRangeUnion(...ranges);
Logger.log("union: %s", union?.getA1Notation());
}
// sharedOverlap: false
// union: null
* @param {SpreadsheetApp.Range[]} ranges
* @returns {SpreadsheetApp.Range}
*/
function GetRangeUnion(...ranges) {
const unionPair = (rangeA, rangeB) => {
const union = {
left: -1,
right: -1,
top: -1,
bottom: -1,
};
// if
// both range's left edge is at/before both range's right edge
// then
// union.left is the rightest left side
// union.right is the leftest right side
if (
rangeA.getColumn() <= rangeB.getLastColumn() && // rangeA's left edge is at/before rangeB's right edge
rangeB.getColumn() <= rangeA.getLastColumn() // rangeB's left edge is at/before rangeA's right edge
) {
union.left = Math.max(rangeA.getColumn() , rangeB.getColumn() ); // left is the rightest left side
union.right = Math.min(rangeA.getLastColumn(), rangeB.getLastColumn()); // right is the leftest right side
}
// if
// both range's top edge is at/above both range's bottom edge
// then
// union.top is the bottomest top side
// union.bottom is the toppest bottom side
if (
rangeA.getRow() <= rangeB.getLastRow() && // rangeA's top edge is at/before rangeB's bottom edge
rangeB.getRow() <= rangeA.getLastRow() // rangeB's top edge is at/before rangeA's bottom edge
) {
union.top = Math.max(rangeA.getRow() , rangeB.getRow() ); // top is the bottomest top side
union.bottom = Math.min(rangeA.getLastRow(), rangeB.getLastRow()); // bottom is the toppest bottom side
}
if (
union.left < 0 ||
union.right < 0 ||
union.top < 0 ||
union.bottom < 0
) return null; // no union occurred.
return rangeA.getSheet().getRange(union.top, union.left, union.bottom-union.top+1, union.right-union.left+1);
};
return ranges.reduce((rangeA, rangeB) => unionPair(rangeA, rangeB));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment