在“电子表格”的“应用程序”脚本中选择连续范围

时间:2013-03-03 16:17:32

标签: google-apps-script google-sheets

是否可以获取特定单元格的范围,类似于电子表格中的Ctrl + A?

2 个答案:

答案 0 :(得分: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

我希望有所帮助!

答案 1 :(得分:2)

我尝试了以上内容,由于缺乏声誉,我无法评论,在一张包含多张工作表的工作表中,发现如果更改该行,它会更好用: var contiguousRange = SpreadsheetApp.getActiveSheet()。getRange(cellA1); 同 var contiguousRange = sheet.getRange(cellA1);