Google App脚本.检查Range1是否与Range2相交

Max*_*rov 3 javascript google-sheets google-apps-script

今天是个好日子!

我想intersect在Google表格脚本中使用与VBA类似的功能.有一个很好的方法来做到这一点?该函数必须返回:

  • RangeIntersect(R1, R2) = true 如果R1与R2有共同的细胞,
  • RangeIntersect(R1, R2) = false 如果R1没有与R2共同的单元格

先感谢您.

速度测试

我希望功能尽可能快地运行.那是因为它将在onEdit函数内部的循环中使用.如果您愿意,可以使用此脚本测试提供的功能:

function speedtest () {
  var sheet;      
  sheet = SpreadsheetApp.getActiveSheet();      
  var rr1 = ['A1:C16', 'B2:B88', 'D1:D8', 'E1:E17', 'A18:B51', 'A13:A14', 'A17:C17'];

  var r1, r2;

  r1 = sheet.getRange(rr1[0]);      
  var rr2 = [];

  // define some ranges
  for (var x = 0; x < 30; x++) {
  for (var i = 0; i < rr1.length; i++) {
    r2 = sheet.getRange(rr1[i]);
    rr2.push(r2);
  }
  }

  var C;

  var start, end, time;
  // timer start     

    for (var t = 0; t < 10; t++) {
        start = new Date().getTime();

        for (var f = 0; f < rr2.length; f++) {
             C = RangeIntersect(r1, rr2[f]);               
        }

        end = new Date().getTime();
        time = end - start;
        Logger.log('Execution time = ' + time);    

    }            
}
Run Code Online (Sandbox Code Playgroud)

Ren*_*air 6

首先,您需要获取范围坐标:

function Coordinates (range) {
  var self = this
  ;
  self.x1 = range.getColumn();
  self.y1 = range.getRow();
  self.x2 = range.getLastColumn();
  self.y2 = range.getLastRow();
}
Run Code Online (Sandbox Code Playgroud)

其次,您需要知道列边界和行边界是否重叠:

function Overlaps (a, b, c, d) {
  return (a >= c && a <= d) || (b >= c && b <= d) || (c >= a && c <= b) || (d >= a && d <= b);
}
Run Code Online (Sandbox Code Playgroud)

您要求的比较两个范围的功能:

function RangeIntersect (R1, R2) {

  R1 = new Coordinates (R1);
  R2 = new Coordinates (R2);

  return (Overlaps(R1.x1, R1.x2, R2.x1, R2.x2) && Overlaps(R1.y1, R1.y2, R2.y1, R2.y2));
}
Run Code Online (Sandbox Code Playgroud)

这是一个快速测试:

function test () {
  var sheet, r1, r2, r3
  ;
  sheet = SpreadsheetApp.getActiveSheet();
  r1 = sheet.getRange(1, 1, 2, 2);
  r2 = sheet.getRange(2, 2, 2, 2);
  r3 = sheet.getRange(4, 4);

  Logger.log("%s %s overlap %s", r1.getA1Notation(), (RangeIntersect(r1, r2) ? "does" : "does not"), r2.getA1Notation());
  Logger.log("%s %s overlap %s", r2.getA1Notation(), (RangeIntersect(r2, r3) ? "does" : "does not"), r3.getA1Notation());
  Logger.log("%s %s overlap %s", r1.getA1Notation(), (RangeIntersect(r1, r3) ? "does" : "does not"), r3.getA1Notation());

  return;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这只是一个快速解决方案.另请注意,getActiveRange将包含通过隐藏或过滤隐藏的任何行和列,否则将包含在所选范围内.

新增2016-05-04

Max的快速解决方案缩短版,只需一次退货(我更喜欢单个退出点):

function RangeIntersect (R1, R2) {
  return (R1.getLastRow() >= R2.getRow()) && (R2.getLastRow() >= R1.getRow()) && (R1.getLastColumn() >= R2.getColumn()) && (R2.getLastColumn() >= R1.getColumn());
}
Run Code Online (Sandbox Code Playgroud)


Max*_*rov 5

我已经创建了自己的脚本版本:

function RangeIntersect(R1, R2) {

  var LR1 = R1.getLastRow();
  var Ro2 = R2.getRow();
  if (LR1 < Ro2) return false;


  var LR2 = R2.getLastRow();
  var Ro1 = R1.getRow();
  if (LR2 < Ro1) return false;

  var LC1 = R1.getLastColumn();
  var C2 = R2.getColumn();
  if (LC1 < C2) return false;

  var LC2 = R2.getLastColumn();
  var C1 = R1.getColumn();
  if (LC2 < C1) return false;

  return true;

}
Run Code Online (Sandbox Code Playgroud)

该脚本的运行速度约快1.4倍,因为每次2个范围不相交时它都会返回。


Eri*_*eda 5

如果您想要代表交点的范围,您可以使用以下代码:

function getIntersection(range1, range2) {
  if (range1.getSheet().getSheetId() != range2.getSheet().getSheetId()) {
    return null;
  }
  var sheet = range1.getSheet();
  var startRow = Math.max(range1.getRow(), range2.getRow());
  var endRow = Math.min(range1.getLastRow(), range2.getLastRow());
  var startColumn = Math.max(range1.getColumn(), range2.getColumn());
  var endColumn = Math.min(range1.getLastColumn(), range2.getLastColumn());
  if (startRow > endRow || startColumn > endColumn) {
    return null;
  }
  return sheet.getRange(startRow, startColumn, endRow - startRow + 1, endColumn - startColumn + 1);
}
Run Code Online (Sandbox Code Playgroud)