2013-03-03 2 views
1

Возможно ли получить диапазон, окружающий определенную ячейку, аналогичную Ctrl + A в электронной таблице?Выберите смежный диапазон в скрипте приложения для таблицы

+0

Вы имеете в виду получить весь лист в диапазоне? –

+0

@Sergeinsas Нет, это смежный регион. Возможно, в одной таблице есть два отдельных региона, я хочу выбрать один из них. –

+1

Вы должны быть более понятны в своем вопросе. Вы говорите об именованных диапазонах? Ctrl-A в таблице, как сказал Серж, выбирает весь лист. – Srik

ответ

6

У меня есть несколько таблиц, где таблицы создаются функциями QUERY(), поэтому границы гибкие. В прошлом я прибегал к настройке именованных диапазонов, размер которых, как я ожидаю, является самым большим, что потребует результатов QUERY, и используя эти диапазоны имен для других операций.

Больше не нужно!

Вот функцию полезности, getContiguousRange(), которая принимает расположение клеток в A1 нотации, и возвращает Range смежных ячеек, которые содержат его. Этот код доступен in a gist.

/** 
* 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)) 
} 

В качестве теста рассмотрите эту таблицу. Он имеет два смежных диапазона, оба с оборванными краями. Spreadsheet screenshot

Вот наша тестовая функция:

function testRanges() { 
    var range1 = getContiguousRange("C3").getA1Notation(); 
    var range2 = getContiguousRange("B8").getA1Notation(); 
    debugger; // Pause if running in debugger 
} 

И это то, что мы получаем:

Debugger Results

Я надеюсь, что помогает!

+0

Очень умный! Спасибо за обмен, +1. –

2

Я пробовал выше, что я не могу прокомментировать из-за отсутствия репутации, на листе с несколькими листами и нашел, что он работает лучше, если вы меняете строку: var contiguousRange = SpreadsheetApp.getActiveSheet() .getRange (cellA1); с var contiguousRange = sheet.getRange (cellA1);

Смежные вопросы