Javascript 谷歌应用程序脚本双重删除电子表格中的行
} 我已经设置了运行onEdit的触发器。它所做的是检查一个名为Closed的列,看它是否回答Yes。“关闭”列有一个数据验证下拉菜单,其中的值为“是” 因此,当我单击下拉菜单并选择“是”时,它应该将整行复制到另一个名为“关闭请求”的工作表中,然后从名为“打开请求”的电子表格中删除该行 我遇到的问题是,大约有50%的时间,它会删除我选择“是”的行,但它也会删除它下面的行,大约有50%的时间,当这种情况发生时,只有在某些时候,第二个删除的行会在关闭的请求中显示,其他时候,除非我撤消,否则整行将永远消失Javascript 谷歌应用程序脚本双重删除电子表格中的行,javascript,google-apps-script,google-sheets,Javascript,Google Apps Script,Google Sheets,} 我已经设置了运行onEdit的触发器。它所做的是检查一个名为Closed的列,看它是否回答Yes。“关闭”列有一个数据验证下拉菜单,其中的值为“是” 因此,当我单击下拉菜单并选择“是”时,它应该将整行复制到另一个名为“关闭请求”的工作表中,然后从名为“打开请求”的电子表格中删除该行 我遇到的问题是,大约有50%的时间,它会删除我选择“是”的行,但它也会删除它下面的行,大约有50%的时间,当这种情况发生时,只有在某些时候,第二个删除的行会在关闭的请求中显示,其他时候,除非我撤消,否则整行将永远
从我可以看出,DelutoFor函数删除整个行,并将它下面的所有行移到一行,以填入空白。因此,要删除的行下面的行被上移到同一行,并且也被删除。我不知道为什么函数会被调用两次
我尝试添加一些延迟,但它似乎不起作用。可以尝试按原样向后迭代。删除后插入SpreadsheetApp.flush也会有所帮助 @杰克,我有一个与你类似的用例。我的代码是BryanP讨论的反向代码。我的代码大致在此处:。这是因为我在一批中删除了它们,所以我使用了向后的方法,即删除具有较高行号的行不会干扰具有较低行号的任何行的行号
function onEdit() {
var openRequests = SpreadsheetApp.getActive().getSheetByName('Open Requests');
var lastRowOpen = openRequests.getLastRow();
var closedRequests = SpreadsheetApp.getActive().getSheetByName('Closed Requests');
var lastRowClose = closedRequests.getLastRow();
var closed = openRequests.getRange(2,8,lastRowOpen,1).getValues();
for (var i = 0; i < lastRowOpen; i++)
{
if (closed[i][0].toString() == 'Yes')
{
var line = i+2;
if (closedRequests.getLastRow() == 1)
{
openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(2,1,1,9));
closedRequests.getRange(2,9,1,1).setValue(new Date());
openRequests.deleteRow(line);
}
else
{
openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(lastRowClose+1,1,1,9));
closedRequests.getRange(lastRowClose+1,9,1,1).setValue(new Date());
openRequests.deleteRow(line);
}
}
}
但是您并不是在批处理模式下删除行,所以向后可能不会有什么区别,除非两个用户同时使用工作表和删除
所以我想试试你的代码。我将您的代码插入到我的电子表格中已经存在的onedit函数中,该函数用于在一段时间不活动后将行涂成红色,并在任务实际完成后添加时间戳
然后为了测试,我使用了一份电子表格的副本,其中已经有50行/任务。我手动在一行中填写所需的单元格,并使用下拉列表从单元格中选择“完成”,我将您的代码更改为“完成”,而不是“是”。我重复了20行
结果是:您的代码成功了,正如您预期的那样,20次中的每一次都成功了。。。无双重删除,始终跨多个服务器复制数据。它对我有效,没有引入延迟,也没有引入SpreadsheetApp.flush
恐怕我没有可靠的建议。顺便说一下,我提到了一个已知的错误,即电子表格本身没有正确刷新,因此没有显示删除的行;出现此故障时,可以通过手动刷新电子表格来检查是否存在此问题。但是,此故障的指示在逻辑上似乎与您关于两个连续行的双重复制的报告不符。线程锁定?听起来像是线程锁定问题。尝试:
function onEdit(e) {
var eRange = e.source.getActiveRange();
var openRequests = SpreadsheetApp.getActive().getSheetByName('Open Requests');
var closedRequests = SpreadsheetApp.getActive().getSheetByName('Closed Requests');
var nextRowClose = (closedRequests.getLastRow()?closedRequests.getLastRow()+1:2);
if(eRange.getSheet().getName()=="Open Requests" && eRange.getColumn()==8 && eRange.getValue()=="Yes") {
openRequests.getRange(eRange.getRow(), 1, 1, 9)
.copyTo(closedRequests.getRange(nextRowClose, 1));
closedRequests.getRange(nextRowClose, 9).setValue(new Date());
openRequests.deleteRow(eRange.getRow());
}
}
问题:
1当时有多少人在使用电子表格
2这种情况多久发生一次。你有同样的问题吗?不完全一样。切换到向后有什么不同吗?一个人正在使用它。当它发生时,它会连续发生几次。有时甚至根本不会发生这种情况。您可以删除单元格样式下拉菜单-听起来这似乎是编辑被调用两次的原因。到目前为止,这似乎是可行的。你能告诉我是什么导致了双重删除吗?嗨,杰克,我不知道为什么你的剧本出了问题。我以前在循环中修改文档时见过类似的情况。我提出的解决方案直接指向源代码,而无需循环之前的响应,因为从下拉列表中选择“是”将表明不需要这样做。希望这能满足您的需要。你好,MichaelP.S。如果您希望继续研究该问题,可能会在Google Apps脚本问题跟踪程序中获得更明确的答案:I get this error TypeError:Cannot call method getActiveRange of undefined。从应用程序脚本摘要电子邮件中,引用行var eRange=e.source.getActiveRange;。它仍然有效,但每次删除电子邮件中的内容时,我都会遇到一个错误。我不明白发生这种情况时,您要删除的是哪张表和单元格?
function onEdit() {
// ****** add lock code
var lock = LockService.getPublicLock();
var hasMutex = lock.tryLock(100);
if(hasMutex==false) {
return;
}
// *** end
var openRequests = SpreadsheetApp.getActive().getSheetByName('Open Requests');
var lastRowOpen = openRequests.getLastRow();
var closedRequests = SpreadsheetApp.getActive().getSheetByName('Closed Requests');
var lastRowClose = closedRequests.getLastRow();
var closed = openRequests.getRange(2,8,lastRowOpen,1).getValues();
for (var i = 0; i < lastRowOpen; i++)
{
if (closed[i][0].toString() == 'Yes')
{
var line = i+2;
if (closedRequests.getLastRow() == 1)
{
openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(2,1,1,9));
closedRequests.getRange(2,9,1,1).setValue(new Date());
openRequests.deleteRow(line);
}
else
{
openRequests.getRange(line,1,1,9).copyTo(closedRequests.getRange(lastRowClose+1,1,1,9));
closedRequests.getRange(lastRowClose+1,9,1,1).setValue(new Date());
openRequests.deleteRow(line);
}
}
}
// ****** add lock code
lock.releaseLock();
// *** end
}