Created
March 5, 2013 04:42
-
-
Save mogsdad/5088074 to your computer and use it in GitHub Desktop.
This snippet of Google Apps-Script was written in response to StackOverflow question 15187688, where the user was looking for a way to obtain a contiguous range of cells - a group of cells that contained values, but which was smaller than the range that would result from calling getDataRange().
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 testRanges() { | |
var range1 = getContiguousRange("C3").getA1Notation(); | |
var range2 = getContiguousRange("B8").getA1Notation(); | |
debugger; | |
} | |
/** | |
* Return the contiguous Range that contains the given cell. | |
* | |
* @param {String} cellA1 Location of a cell, in A1 notation. | |
* @param {Sheet} sheet (Optional) sheet to examine. Defaults | |
* to "active" sheet. | |
* | |
* @return {Range} A Spreadsheet service Range object. | |
*/ | |
function getContiguousRange(cellA1,sheet) { | |
// Check for parameters, handle defaults, throw error if required is missing | |
if (arguments.length < 2) | |
sheet = SpreadsheetApp.getActiveSheet(); | |
if (arguments.length < 1) | |
throw new Error("getContiguousRange(): missing required parameter."); | |
// A "contiguous" range is a rectangular group of cells whose "edge" contains | |
// cells with information, with all "past-edge" cells empty. | |
// The range will be no larger than that given by "getDataRange()", so we can | |
// use that range to limit our edge search. | |
var fullRange = sheet.getDataRange(); | |
var data = fullRange.getValues(); | |
// The data array is 0-based, but spreadsheet rows & columns are 1-based. | |
// We will make logic decisions based on rows & columns, and convert to | |
// 0-based values to reference the data. | |
var topLimit = fullRange.getRowIndex(); // always 1 | |
var leftLimit = fullRange.getColumnIndex(); // always 1 | |
var rightLimit = fullRange.getLastColumn(); | |
var bottomLimit = fullRange.getLastRow(); | |
// is there data in the target cell? If no, we're done. | |
var contiguousRange = SpreadsheetApp.getActiveSheet().getRange(cellA1); | |
var cellValue = contiguousRange.getValue(); | |
if (cellValue = "") return contiguousRange; | |
// Define the limits of our starting dance floor | |
var minRow = contiguousRange.getRow(); | |
var maxRow = minRow; | |
var minCol = contiguousRange.getColumn(); | |
var maxCol = minCol; | |
var chkCol, chkRow; // For checking if the edge is clear | |
// Now, expand our range in one direction at a time until we either reach | |
// the Limits, or our next expansion would have no filled cells. Repeat | |
// until no direction need expand. | |
var expanding; | |
do { | |
expanding = false; | |
// Move it to the left | |
if (minCol > leftLimit) { | |
chkCol = minCol - 1; | |
for (var row = minRow; row <= maxRow; row++) { | |
if (data[row-1][chkCol-1] != "") { | |
expanding = true; | |
minCol = chkCol; // expand left 1 column | |
break; | |
} | |
} | |
} | |
// Move it on up | |
if (minRow > topLimit) { | |
chkRow = minRow - 1; | |
for (var col = minCol; col <= maxCol; col++) { | |
if (data[chkRow-1][col-1] != "") { | |
expanding = true; | |
minRow = chkRow; // expand up 1 row | |
break; | |
} | |
} | |
} | |
// Move it to the right | |
if (maxCol < rightLimit) { | |
chkCol = maxCol + 1; | |
for (var row = minRow; row <= maxRow; row++) { | |
if (data[row-1][chkCol-1] != "") { | |
expanding = true; | |
maxCol = chkCol; // expand right 1 column | |
break; | |
} | |
} | |
} | |
// Then get on down | |
if (maxRow < bottomLimit) { | |
chkRow = maxRow + 1; | |
for (var col = minCol; col <= maxCol; col++) { | |
if (data[chkRow-1][col-1] != "") { | |
expanding = true; | |
maxRow = chkRow; // expand down 1 row | |
break; | |
} | |
} | |
} | |
} while (expanding); // Lather, rinse, repeat | |
// We've found the extent of our contiguous range - return a Range object. | |
return sheet.getRange(minRow, minCol, (maxRow - minRow + 1), (maxCol - minCol + 1)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment