【问题标题】:Google Sheets Creates Random Cell Border with onEdit FunctionGoogle Sheets 使用 onEdit 函数创建随机单元格边框
【发布时间】:2021-07-13 00:02:24
【问题描述】:

所以我遇到了一个奇怪的问题,即 Google 表格在调用 onEdit 函数时一遍又一遍地在同一范围内绘制一个神秘的、看似随机的单元格边框。我终其一生都无法弄清楚发生了什么。

详情

如果编辑了特定范围(选择框),则会调用 onEdit 函数对其他几个范围进行一些基本的背景颜色更改。所有这些颜色变化都在起作用。但是,还会在另一个范围内绘制额外的垂直边框(Range With Problem)。

在此示例中要记住的一件事是,脚本中没有任何地方使用 setBorder。您看到正在创建的边框是 Google 表格正在做的事情,它不是由于代码而发生的。

这显示了在选择之前以蓝色突出显示的问题范围:

这显示了选择后绘制的垂直边框:

    ////////////////////////////////////////////   Sheet Variables

var app = SpreadsheetApp; 
var ss = app.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();

////////////////////////////////////////////  Top Box Variables 

var bigBox = sheet.getRange("B2");
var selectionBox = sheet.getRange("E3");
var top_Headers = sheet.getRange("E2:AI2");
var top_Stats = sheet.getRange("M3:AI3");

////////////////////////////////////////////   Bottom Box Variables

var statArray_Range = sheet.getRange("E6:J11");
var stat1_Range = sheet.getRange("E6:E11");
var stat2_Range = sheet.getRange("H6:H11");
var stat3_Range = sheet.getRange("J6:J11");
var last_Cell = "AI11";
var all_Cells = sheet.getRange("C6:"+last_Cell);

////////////////////////////////////////////   Arrays

var array_1 = ["FOO_green","BAR_green"];
var array_2 = ["FOO_red","BAR_red"];

////////////////////////////////////////////   Colors

var darkGreen = "#b6d7a8";
var lightGreen = "#d9ead3";
var darkRed = "#ea9999";
var lightRed = "#f4cccc";
var darkBlue = "#9fc5e8";
var lightBlue = "#cfe2f3";
var gray = "#efefef";
var lightGray = "#f3f3f3";

////////////////////////////////////////////   Data Validation

// --------------------------------------------------------- 
//    Create dropdown based on values in the sheet 'Data'
// ---------------------------------------------------------

var rule = app.newDataValidation().requireValueInRange(ss.getSheetByName("Data").getRange("A1:A4"),false).build();
selectionBox.setDataValidation(rule);

////////////////////////////////////////////   Stored Variables

// --------------------------------------------------------- 
//    Create variable to track the last selection made
// ---------------------------------------------------------

function initializeProperties(){

  var script_Properties = PropertiesService.getScriptProperties();

  if(selectionBox.isBlank())
  {
      script_Properties.setProperty("option_Selected","EMPTY");
  }
  else if(selectionBox.getValue().includes("FOO"))
  {
      script_Properties.setProperty("option_Selected","FOO");
  }
  else
  {
      script_Properties.setProperty("option_Selected","BAR");
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function onEdit(event){                                                   //           ON EDIT             //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    script_Properties = PropertiesService.getScriptProperties();
    oldValue = script_Properties.getProperty("option_Selected");

    // --------------------------------------------------------- 
    //    Define onEdit Event Variables
    // ---------------------------------------------------------

    range = event.range;
    inputValue = event.value;
    cell = range.getA1Notation();
    row = range.getRow();
    col = range.getColumn();

    // --------------------------------------------------------- 
    //    If Selection drop down is range edited
    // ---------------------------------------------------------

    if(col == "5" && row == "3")
    {      
    updateBGColor(inputValue);

    // --------------------------------------------------------- 
    //    Reset entire sheet - clear backgrounds and values
    // --------------------------------------------------------- 

    if(inputValue == null)
    {
      oldValue = script_Properties.setProperty("option_Selected","EMPTY");
      resetAll();
    }

    // --------------------------------------------------------- 
    //    If Selection made is 'BAR_green' or 'BAR_red'
    // --------------------------------------------------------- 

    else if(inputValue.includes("BAR"))
    {
      statArray_Range.setValue(null);
      statArray_Range.setBackground(null);

      if(oldValue != "BAR")
      {
        oldValue = script_Properties.setProperty("option_Selected","BAR");
        statArray_Range.setValue(null);
      }
    }

    // --------------------------------------------------------- 
    //    If Selection made is 'FOO_green' or 'FOO_red'
    // --------------------------------------------------------- 

    else if(inputValue.includes("FOO"))
    {
      statArray_Range.setValue("---");
      stat2_Range.setscript_PropertiesValidation(null);
      stat3_Range.setscript_PropertiesValidation(null);
      statArray_Range.setValue("---");
      statArray_Range.setBackground(lightGray);
      
      if(oldValue != "FOO")
      {
        oldValue = script_Properties.setProperty("option_Selected","FOO");
      }
    }
  }
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function updateBGColor(x){                                        //        UPDATE BACKGROUND COLOR          //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // --------------------------------------------------------- 
    //    If Selection made is "FOO_green" or "BAR_green"
    // --------------------------------------------------------- 

    if(array_1.includes(x))
    {   
        bigBox.setBackground(darkGreen);
        top_Headers.setBackground(lightGreen);
    }

    // --------------------------------------------------------- 
    //    If Selection made is "FOO_red" or"BAR_red"
    // --------------------------------------------------------- 

    else if(array_2.includes(x))
    {
        bigBox.setBackground(darkRed);
        top_Headers.setBackground(lightRed);      
    }

    // --------------------------------------------------------- 
    //    If Selection is Deleted
    // --------------------------------------------------------- 

    else if(x == undefined)
    {   
        bigBox.setBackground(gray);
        top_Headers.setBackground(gray);      
    }
    else{
        bigBox.setBackground(darkBlue);
        top_Headers.setBackground(lightBlue);
    }
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function resetAll(){                                                     //         RESET ALL          //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    top_Stats.setValue(null);
    all_Cells.setValue(null);
    all_Cells.setBackground(null);
}

希望有更多经验的 Javascript 大师能解开这个谜。

感谢您的宝贵时间...非常感谢您的帮助!!!

【问题讨论】:

  • 我更新了原始帖子,更准确地解释了脚本应该做什么。希望这可以帮助。让我知道是否还有什么可以让您更轻松地为您提供帮助。
  • 嗨。在 requireValueInRange() 中 showDropdown 为假有点令人困惑。因此,在进行更改时,单元格中的下拉列表消失了。我不得不一直重新选择数据验证中的复选框。我注意到,如果您取消 T5:V11 中的单元格合并,问题就会消失。
  • 在我的浏览器中,我只需在范围内双击,就会出现下拉菜单。将 showDropdown 设置为 false 只会隐藏三角形,但如果您双击范围,下拉菜单仍然可以正常工作。我还注意到一些奇怪的事情,就像你在取消合并范围时指出的那样。例如,如果您将 top_Headers 范围的最后一列更改为 AI2 之前的值,则该随机边框将绘制在不同的位置。
  • 还注意到注释掉一些事情,比如对 updateBGColor 的调用也会停止绘制边框,但这些都是无关紧要的,绝对不应该绘制一些随机边框。我想认为有一个合乎逻辑的解释,但到目前为止我找不到。

标签: javascript google-apps-script google-sheets


【解决方案1】:

问题在于合并的单元格

如果你有一个合并的范围,比如A1:B2,那么如果你是getRange('B2'),它实际上会选择A1。同样,电子表格服务会将这个合并范围视为 4 个不同的单元格。您可以将它们的合并方面更多地视为 UI 事物,在后端,它们仍然被视为 4 个单独的单元格。

如果您需要在合并范围周围放置边框,则需要仔细选择合并单元格覆盖的整个范围并设置 outside 边框。

// setBorder(top, left, bottom, right, vertical, horizontal, color, style)
range.setBorder(true, true, true, true, false, false, "black", SpreadsheetApp.BorderStyle.SOLID)

参考

编辑

96号线附近

    if(col == "5" && row == "3")
    {      
      updateBGColor(inputValue);
      SpreadsheetApp.flush() // ADD THIS LINE

Flush 确保在继续之前应用所有编辑。 Apps 脚本会尝试将它们批处理在一起以提高性能,但有时,尤其是在处理合并的范围和格式时,这可能会导致问题。

我通常尽可能远离合并范围!虽然添加这一行确实为我解决了这个问题。

【讨论】:

  • 感谢您的想法,但我确信这是不正确的。我一直在使用合并的单元格,没有任何问题。我刚刚更新了合并单元格的所有代码,使用所有单元格定义它们,问题仍然存在。所以这不是问题所在。在此示例中要记住的一件事是,脚本中没有任何地方定义 setBorder 或边框样式。您看到正在创建的边框是 Google 表格正在做的事情,它不是由于代码而发生的。这是真正的问题。试图找出导致表格在未定义边框时绘制边框的原因。
  • 我不知道 Flush 甚至是一个令人惊叹的东西。是的,这很好用。我什至将该行添加到真实脚本中,并且运行良好。非常感谢。在什么情况下你觉得通常需要使用 Flush?
  • 经过一些调试后,我无法确定导致问题的确切代码行,这似乎是综合操作的结果。这让我觉得也许flush 可以解决它。如果您必须在工作表中写入很多不同的内容,很多次,以及从工作表中读取的后续操作(即不在内存中),那么有时您需要flush。有时只是为了提高可靠性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多