我做了什么:
如果M列中的任何单元格已更改,则已发送电子邮件通知以指定同一行中N列的地址。但我还需要在同一行的其他列中指定一些正文文本。我做了一些有效的工作,但它也导致如果其他声明的列(例如项目,客户,任务,执行程序)已被更改,则已将emil发送给。
我需要什么:
只需跟踪一个“M”列中的更改,并将来自其他列但来自同一行的其他数据放入电子邮件正文中。并且(这就是重点)没有跟踪其他列的更改,只有在更改M列时才会发送电子邮件。
可能这很容易,但我扭曲了......
我根据以下内容制作了这个脚本:
我的剧本:
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var sendto = '';
if(cell.indexOf('M')!=-1){
sendto = sheet.getRange('N'+ sheet.getActiveCell().getRowIndex()).getValue()
}
var project = '';
project = sheet.getRange('C'+ sheet.getActiveCell().getRowIndex()).getValue()
var customer = '';
customer = sheet.getRange('D'+ sheet.getActiveCell().getRowIndex()).getValue()
var task = '';
task = sheet.getRange('E'+ sheet.getActiveCell().getRowIndex()).getValue()
var executor = '';
executor = sheet.getRange('F'+ sheet.getActiveCell().getRowIndex()).getValue()
var deadline = '';
deadline = LanguageApp.translate(Utilities.formatDate(sheet.getRange('I'+ sheet.getActiveCell().getRowIndex()).getValue() , "GMT" , "EEEE, dd MMMM YYYY" ),'en','pl')
var status = '';
status = sheet.getRange('M'+ sheet.getActiveCell().getRowIndex()).getValue()
var mysubject = status + ' | ' + project + ': ' + task + ' - ' + ss.getName() + ' update';
var mybody = '\nStatus: ' + status + '\n\nproject: ' + project + '\ncustomer: ' + customer + '\ntask: ' + task + '\nexecutor: ' + executor + '\nDeadline: ' + deadline + '\n\n' + ss.getName() + ': \n' + ss.getUrl();
MailApp.sendEmail({
to:sendto,
subject:mysubject,
body:mybody});
};
答案 0 :(得分:0)
我制作了一个示例脚本,您应该可以在https://docs.google.com/spreadsheets/d/11u0xkdtPlQsnVppCnPYM0CHuCTPLdmN8PcFlaW08lNw/edit#gid=0
看到你必须制作副本才能真正用它做点什么。
但是 ...复制不会给你我设置的触发器。如果您编辑脚本,请转到菜单资源 - > 当前项目的触发器,并使自己成为 checkForChanges()函数的基于时间的触发器。我将其设置为“每分钟”用于测试目的。
在我的专栏中,我添加了四个新的:
所以......周期性地,函数 checkForChanges()在 ChangeDetector 范围内运行,寻找 true 。如果它什么也没找到,它会立即退出。
每次发现更改时,它都会收集该行的数据并通过电子邮件发送。 (实际上,为了简单起见,我只是记录它。)
关键技巧是这对线:
lastEdits[row_][0] = currentHashCodes[row_][0];
ss_.getRangeByName("LastEdit").setValues(lastEdits);
请注意,如果您尽可能使用命名范围,您的代码会有多清晰。
以下是代码在将来某天丢失的代码:
/* Called from cells in column "Current Hash" */
function strHash(valCell) {
var hash = 0;
if (valCell.length == 0) return hash;
for (i = 0; i < valCell.length; i++) {
char = valCell.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
}
/* Called periodically from a timed trigger. */
function checkForChanges() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var changeDetector = ss.getRangeByName("ChangeDetector").getValues();
for (row in changeDetector) {
if (row > 0) {
changed = changeDetector[row][0];
if (changed) notify(ss, row);
}
}
}
/* Called by checkForChanges(). */
function notify(ss_, row_) {
initializeRangeArrays(ss_);
status = statii[row_][0];
project = projects[row_][0];
task = tasks[row_][0];
customer = customers[row_][0];
executor = executors[row_][0];
deadline = deadlines[row_][0];
sendto = recipients[row_][0];
var mysubject = status + ' | ' + project + ': ' + task + ' - ' + ss_.getName() + ' update';
var mybody = '\nStatus: ' + status
+ '\n\nproject: ' + project
+ '\ncustomer: ' + customer
+ '\ntask: ' + task
+ '\nexecutor: ' + executor
+ '\nDeadline: ' + deadline
+ '\n\n' + ss_.getName()
+ ': \n' + ss_.getUrl();
Logger.log("to: " + sendto);
Logger.log("subject: " + mysubject);
Logger.log("body: " + mybody);
Logger.log("");
lastEdits[row_][0] = currentHashCodes[row_][0];
ss_.getRangeByName("LastEdit").setValues(lastEdits);
};
var recipients = null;
var projects = null;
var customers = null;
var tasks = null;
var deadlines = null;
var executors = null;
var statii = null;
var lastEdits = null;
var currentHashCodes = null;
var rangeArraysInitialized = false;
/* Called by notify(). */
function initializeRangeArrays(ss_) {
if ( ! rangeArraysInitialized ) {
recipients = ss_.getRangeByName("Recipient").getValues();
projects = ss_.getRangeByName("Project").getValues();
customers = ss_.getRangeByName("Customer").getValues();
tasks = ss_.getRangeByName("Task").getValues();
deadlines = ss_.getRangeByName("Date").getValues();
statii = ss_.getRangeByName("Status").getValues();
executors = ss_.getRangeByName("Executor").getValues();
lastEdits = ss_.getRangeByName("LastEdit").getValues();
currentHashCodes = ss_.getRangeByName("CurrentHash").getValues();
rangeArraysInitialized = false;
}
}
更新2014/09/22:
我在演示电子表格中做了一些更改。请看一看。
我添加的脚本。 。 。
function strArrayHash(range) {
var ret = new Array();
var str = "";
for (item in range) {
str = range[item].toString();
if (str.length > 0) {
ret[item] = strHash(str);
Utilities.sleep(50); // play with this to reduce "internal execution error"s
} else {
ret[item] = "";
}
};
return ret;
}
在“P”栏中,我换了。 。 。
=if( M2 = "", "", strHash(R2)))
=if( M3 = "", "", strHash(R3)))
:
:
=if( M22 = "", "", strHash(R22)))
。 。 。与。 。 。
=ARRAYFORMULA(if( M2:M514 = "", "", strArrayHash(R2:R514)))
。 。 。在单元格“P2”中仅。我还删除了“P3:P22”
范围内所有单元格的内容我将总行数增加到1026
在P列中出现值后,我使用[选择性粘贴]»[仅粘贴值]将单元格P2:P1026复制到M2:M1026中。
在我的i7笔记本电脑中,它需要30秒才能重新计算并检测第500行的变化。
如果我尝试执行所有1024行,则会出现内部执行错误。
可能你需要使“if”子句复杂化,以致它只对真正需要它的行进行哈希计算。
更新:: 2017/02/24没有人对此感兴趣所以我停止了运行脚本的触发器。