Программно проверить, находится ли ячейка Google Sheet в именованном диапазоне - PullRequest
1 голос
/ 01 апреля 2020

Я пишу триггер Google Sheets onEdit(), и он должен что-то делать, только если отредактированная ячейка находится в именованном диапазоне в электронной таблице.

У меня есть это:

function onEdit(e) {
  var editRange = e.range;

  var numRows = editRange.getNumRows();
  var numCols = editRange.getNumColumns();

  for (var i = 1; i <= numRows; i++) {
    for (var j = 1; j <= numCols; j++) {
      var cell = editRange.getCell(i,j);

      if (isInRange(cell, myNamedRange)) {
         /* Do something clever */
      }
    }
  }
}

Но у меня проблемы с написанием функции isInRange(). Такое ощущение, что это должна быть встроенная функция работы с электронными таблицами, но я не могу найти ничего похожего.

Обновление: В одночасье меня поразило, что может быть более простой подход. Что мне действительно нужно, так это пересечение двух диапазонов.

Ответы [ 2 ]

2 голосов
/ 02 апреля 2020
  • Вы хотите проверить, включена ли ячейка в названный диапазон.
  • Вы хотите создать функцию isInRange.
  • Вы хотите добиться этого с помощью Google Apps Script.

Если мое понимание верно, как насчет этого ответа? Пожалуйста, подумайте об этом как об одном из нескольких возможных ответов.

Поток:

Поток isInRange выглядит следующим образом.

  1. Получите именованные диапазоны в активный лист.
  2. Получить именованный диапазон, используя myNamedRange.
  3. Возврат true, когда cell находится в именованном диапазоне myNamedRange.
  4. Возврат false, когда cell НЕ находится в именованном диапазоне myNamedRange.
  5. Ошибка возникает, когда myNamedRange не был найден.

Пример сценария:

function isInRange(cell, myNamedRange) {
  var sheet = SpreadsheetApp.getActiveSheet();
  var namedRanges = sheet.getNamedRanges();
  for (var i = 0; i < namedRanges.length; i++) {
    var nr = namedRanges[i];
    if (nr.getName() == myNamedRange) {
      var range = nr.getRange();
      var startRow = range.getRow();
      var endRow = startRow + range.getNumRows() - 1;
      var startColumn = range.getColumn();
      var endColumn = startColumn + range.getNumColumns() - 1;
      return cell.getRow() >= startRow && cell.getRow() <= endRow && cell.getColumn() >= startColumn && cell.getColumn() <= endColumn;
    }
  }
  throw new Error(myNamedRange + " was not found.");
}
  • Когда этот пример сценария isInRange используется для вашего onEdit, когда cell находится в именованном диапазоне myNamedRange, оператор if if (isInRange(cell, myNamedRange)) {} равен true.

Примечание:

  • В этом примере сценария именованные диапазоны извлекаются из активного листа. Если вы хотите изменить это, пожалуйста, измените скрипт.

Ссылки:

Если я неправильно понял ваш вопрос, и это не то направление, в котором вы хотите, я приношу свои извинения.

Добавлено:

  • Вы хотите чтобы получить диапазоны пересечения двух диапазонов.
    • Например, когда именованный диапазон и введенный диапазон равны «A1: B3» и «B3: C4» соответственно, вы хотите получить «B3» в качестве диапазона пересечения.

Если мое понимание верно, как насчет этого примера сценария? Этот пример сценария выглядит следующим образом.

Поток:

  1. Извлечение a1Notations из «inputRange».
  2. Извлечение a1Notations из «myNamedRange».
  3. Извлечение диапазонов пересечения.

В этом примере сценария возвращаемое значение возвращает массив, включающий a1Notations. Поскольку диапазон ввода может быть не продолжен, и когда массив a1Notations можно также использовать для RangeList .

Пример сценария:

function myFunction() {
  var myNamedRange = "sampleNamedRange";  // Please set the name of the named range.
  var inputRange = SpreadsheetApp.getActiveSheet().getRange("B3:C4");  // Please set the range.


  var columnToLetter = function(column) { // <--- https://stackoverflow.com/a/21231012/7108653
    var temp, letter = '';
    while (column > 0) {
      temp = (column - 1) % 26;
      letter = String.fromCharCode(temp + 65) + letter;
      column = (column - temp - 1) / 26;
    }
    return letter;
  };

  var result = [];
  var sheet = SpreadsheetApp.getActiveSheet();
  var namedRanges = sheet.getNamedRanges();
  for (var i = 0; i < namedRanges.length; i++) {
    var nr = namedRanges[i];
    if (nr.getName() == myNamedRange) {
      // Retrieve a1Notations from "inputRange".
      var iStartRow = inputRange.getRow();
      var iEndRow = iStartRow + inputRange.getNumRows() - 1;
      var iStartColumn = inputRange.getColumn();
      var iEndColumn = iStartColumn + inputRange.getNumColumns() - 1;
      var irA1Notations = [];
      for (var j = iStartRow; j <= iEndRow; j++) {
        var temp = [];
        for (var k = iStartColumn; k <= iEndColumn; k++) {
          temp.push(columnToLetter(k) + j);
        }
        Array.prototype.push.apply(irA1Notations, temp);
      }

      // Retrieve a1Notations from "myNamedRange".
      var namedRange = nr.getRange();
      var nStartRow = namedRange.getRow();
      var nEndRow = nStartRow + namedRange.getNumRows() - 1;
      var nStartColumn = namedRange.getColumn();
      var nEndColumn = nStartColumn + namedRange.getNumColumns() - 1;
      var nrA1Notations = {};
      for (var j = nStartRow; j <= nEndRow; j++) {
        for (var k = nStartColumn; k <= nEndColumn; k++) {
          nrA1Notations[columnToLetter(k) + j] = null;
        }
      }

      // Retrieve intersection ranges.
      result = irA1Notations.filter(function(e) {return nrA1Notations.hasOwnProperty(e)});
    }
  }

  Logger.log(result)
}
0 голосов
/ 02 апреля 2020

Я принял ответ Танаике , так как он дал мне много подсказок, которые я нашел полезными, работая над этим. Но на самом деле я написал rangeIntersection() функцию, как я упоминал в сегодняшнем утреннем обновлении моего вопроса.

Код приведен на тот случай, если кто-то еще может найти его полезным.

function rangeIntersection(range1, range2) {
  var sheet1 = range1.getSheet();
  var sheet2 = range2.getSheet();

  if (sheet1.getSheetId() !== sheet2.getSheetId()) {
    return false;
  }

  if (range1.getLastColumn() < range2.getColumn() ||
      range1.getColumn() > range2.getLastColumn() ||
      range1.getLastRow() < range2.getRow() ||
      range1.getRow() > range2.getLastRow()) {
    return false;
  }

  var intersectRange = sheet1.getRange(
    Math.max(range1.getRow(), range2.getRow()),
    Math.max(range1.getColumn(), range2.getColumn()),
    Math.min(range1.getLastRow(), range2.getLastRow()) - Math.max(range1.getRow(), range2.getRow()) + 1,
    Math.min(range1.getLastColumn(), range2.getLastColumn()) - Math.max(range1.getColumn(), range2.getColumn()) + 1,
  );

  return intersectRange;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...