Javascript 谷歌应用程序脚本。检查Range1是否与Range2相交
大家好 我想要一个类似于Google Sheets脚本中VBA的Javascript 谷歌应用程序脚本。检查Range1是否与Range2相交,javascript,google-apps-script,google-sheets,Javascript,Google Apps Script,Google Sheets,大家好 我想要一个类似于Google Sheets脚本中VBA的intersect的函数。有什么好办法吗?函数必须返回: RangeIntersect(R1,R2)=true如果R1与R2有公共单元格 RangeIntersect(R1,R2)=false如果R1与R2没有公共单元格 先谢谢你 速度测试 我希望函数能尽快工作。这是因为它将在onEdit函数内的循环中使用。如果愿意,请使用以下脚本测试提供的函数: function speedtest () { var sheet;
intersect
的函数。有什么好办法吗?函数必须返回:
如果R1与R2有公共单元格RangeIntersect(R1,R2)=true
如果R1与R2没有公共单元格RangeIntersect(R1,R2)=false
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);
}
}
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;
}
功能速度测试(){
var表;
sheet=SpreadsheetApp.getActiveSheet();
变量rr1=['A1:C16','B2:B88','D1:D8','E1:E17','A18:B51','A13:A14','A17:C17'];
变量r1,r2;
r1=sheet.getRange(rr1[0]);
风险值rr2=[];
//定义一些范围
对于(变量x=0;x<30;x++){
对于(变量i=0;i
首先,您需要获取范围坐标:
function Coordinates (range) {
var self = this
;
self.x1 = range.getColumn();
self.y1 = range.getRow();
self.x2 = range.getLastColumn();
self.y2 = range.getLastRow();
}
其次,您需要知道列边界和行边界是否重叠:
function Overlaps (a, b, c, d) {
return (a >= c && a <= d) || (b >= c && b <= d) || (c >= a && c <= b) || (d >= a && d <= b);
}
下面是一个快速测试:
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;
}
请注意,这只是一个快速解决方案。还请注意,getActiveRange将包括通过隐藏或筛选隐藏的任何行和列,否则将包括在所选范围中
增加了2016-05-04
Max快速解决方案的缩短版,带有一个返回点(我更喜欢一个退出点):
我制作了自己版本的脚本:
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);
}
}
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;
}
函数范围相交(R1、R2){
var LR1=R1.getLastRow();
var Ro2=R2.getRow();
如果(LR1
此脚本的运行速度快了约1.4倍,因为它每次在两个范围不相交时返回
更新使用v8发动机测试。所有建议解决方案的速度几乎相同:
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);
}
我没有检查我的代码是否比其他选项快。我知道谷歌建议尽量减少读写次数,所以我自己这样做是为了检查范围和工作表:
function rgInter(r1,r2){
let a1 = rgNum(r1),a2 = rgNum(r2);
return ((a1[1] === a2[1]) && (a2[5] >= a1[3] && a2[3] <= a1[5]) && ( a2[4] >= a1[2] && a2[2] <= a1[4]));
}
function rgNum(rg){ //0.text, 1.gid, 2.colI, 3.rowI, 4.colF, 5.rowF
const re = /gid=(\d+)&range=([A-Z]+)(\d+):?([A-Z]*)(\d*)/g;
let trg = rg.getDataSourceUrl();
let ma = Array.from(trg.matchAll(re))[0];
ma[2] = lTcol(ma[2]);ma[3] = parseInt(ma[3]);
if (ma[4].length === 0) { ma[4] = ma[2]; ma[5] = ma[3];}
else { ma[4] = lTcol(ma[4]); ma[5] = parseInt(ma[5]);}
return ma;
}
function lTcol(tcol)//number of the col from text {
const a = "A".charCodeAt(0)-1;
let n = 0, tl = tcol.length;
for (let i =0; i < tl; i++) {
n+= Math.pow(26,i);
n+= (tcol.charCodeAt(i)-a -1) * Math.pow(26,tl-1-i); }
return n;
}
功能rgInter(r1、r2){
设a1=rgNum(r1),a2=rgNum(r2);
返回((a1[1]===a2[1])&&&(a2[5]>=a1[3]&&a2[3]=a1[2]&&a2[2]检查工作表是否相同。我认为这是最快的速度:
function rangesIntersect(r1, r2)
{
if (r1.getSheet().getIndex() != r2.getSheet().getIndex()) return false;
if (r1.getLastRow() < r2.getRow()) return false;
if (r2.getLastRow() < r1.getRow()) return false;
if (r1.getLastColumn() < r2.getColumn()) return false;
if (r2.getLastColumn() < r1.getColumn()) return false;
return true;
}
功能范围选择(r1、r2)
{
如果(r1.getSheet().getIndex()!=r2.getSheet().getIndex())返回false;
if(r1.getLastRow()
做得很好!我不知道range对象上的getLastColumn/Row方法。你可能应该检查范围是否在同一张表上。重复这个好主意!我用速度测试脚本更新了我的答案。你的解决方案类似于@tanaike的范围解决方案:如果范围在不同的表上怎么办?这将说明Sheet1!A1:B2
重叠Sheet2!A1:B2
时,它们不重叠。