Google Sheet: DoRangesHaveOverlap() = do all of these ranges have shared overlap points? GetRangeUnion() = return the union of any number of ranges
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* @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