Google 脚本:当复选框为真时,将行从 sheet A 复制到 sheet B。当复选框为假时,从 sheet B 中删除复制的行

Google Scripts: When checkbox true, copy row from sheet A to sheet B. When checkbox false, delete copied row from sheet B

我是 Google 脚本的新手,真的应该先学习基础知识,但直接跳到试图为朋友解决问题。在网上找到了这段代码,它是我想要实现的完美解决方案,但是,以下代码片段似乎导致了问题并且没有执行其预期的功能:

} else if (s.getName() == "Tab1" && r.getColumn() == 1 && r.getValue() == "") {
    // Remove the row from "Tab2" when the checkbox in "Tab1" is unchecked 
    var prop = PropertiesService.getDocumentProperties();
    var targetRow = prop.getProperty(row);
    ss.getSheetByName("Tab2").deleteRow(targetRow);
    Logger.log("Deleted the " + targetRow + "row from " + s.getName());
    prop.deleteProperty(row);

完整代码见下:

function onEdit(event) {
// assumes source data in sheet named "Tab1"
// target sheet of move to named "Tab2"
// getColumn with check-boxes is currently set to colu 1 or C
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
var row = r.getRow();
var numColumns = s.getLastColumn();
Logger.log(r.getValue());

if (s.getName() == "Tab1" && r.getColumn() == 1 && r.getValue() == true) {
    // Create the record in "Tab2"
    var prop = PropertiesService.getDocumentProperties();
    var targetSheet = ss.getSheetByName("Tab2");
    var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 2);
    s.getRange(row, 2, 1, numColumns).copyTo(target, { contentsOnly: true });
    // Insert checkbox cell (already checked)
    targetSheet.getRange(target.getRow(), 1).insertCheckboxes().check();
    prop.setProperty(row, target.getRow());
} else if (s.getName() == "Tab1" && r.getColumn() == 1 && r.getValue() == "") {
    // Remove the row from "Tab2" when the checkbox in "Tab1" is unchecked 
    var prop = PropertiesService.getDocumentProperties();
    var targetRow = prop.getProperty(row);
    ss.getSheetByName("Tab2").deleteRow(targetRow);
    Logger.log("Deleted the " + targetRow + "row from " + s.getName());
    prop.deleteProperty(row);
} else if (s.getName() == "Tab2" && r.getColumn() == 1 && r.getValue() == false) {
    // Remove the row from "Tab2" when the checkbox is unchecked and unchecks in "Tab1"
    var prop = PropertiesService.getDocumentProperties();
    s.deleteRow(row);

    // Look the corresponding row in "Tab1"
    var keys = prop.getKeys();
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if (prop.getProperty(key) == row) {
            ss.getSheetByName("Tab1").getRange(key, 1).setValue(false);
            prop.deleteProperty(key)
            break;
        }
    }
}

}

一切都完全按照我的预期工作(请参阅下面的用例),除了当 Tab1 中的复选框在第 X 行上未选中并且 Tab2 中的关联行(通过 PropertiesService)未被删除时...但它应该是。

用例:

  1. Tab1 中第 X 行的复选框为真 - 将行复制到下一个可用行的 Tab2 [在上面的代码中工作]
  2. 然后将 Tab1 中第 X 行的复选框设置为假(该行已被复制到 Tab2 中)- 删除 Tab2 中的关联行[在上面的代码中不起作用]
  3. Tab2 中第 X 行的复选框设为 false - 删除 Tab2 中的行并将 Tab1 中关联行的复选框设为 false [在上面的代码中工作]

理想情况下,上面的代码会更聪明,每一行都有一个唯一的标识符(例如,这可以添加到 A 列中)并且更像关系数据库,因此代码不依赖于顺序维护的行数,例如如果用户将来想在现有行之间插入新行。

提前感谢您的帮助!

我正在尝试重现该问题,是的,我也遇到了您所指的问题。现在,在对代码进行了一些修改之后,我似乎无法修改它并使其工作。甚至修改最后一个条件并将其作为您的第二个条件。

对我有用的是:

  } else if (s.getName() == "Tab1" && r.getColumn() == 1 && r.getValue() == false) {
    sourceRow = ss.getSheetByName("Tab1").getRange(r.getRow(), 1, 1, ss.getSheetByName("Tab1").getLastColumn()).getValues();
    destData = ss.getSheetByName("Tab2").getDataRange().getValues();    
    destData.forEach(function(item, index){
      tempRow = sourceRow[0];
      tempRow[0] = true;
      if(JSON.stringify(tempRow) === JSON.stringify(item)) {
        ss.getSheetByName("Tab2").deleteRow(index + 1);
      }
    });

所以我确实手动访问了两张纸上的数据。将 Tab2 中的所有行与 Tab1 中的选定行进行比较。

而且由于选中的行在捕获后已经取消选中,所以我确实创建了一个临时变量来存储勾选的行值。然后在 Tab2 中查找。如果相同则删除Tab2中的行

另外,请注意上面的 r.getValue() 条件已更新为与 false 值而不是空白进行比较。