【问题标题】:Google Sheets Add-On onOpen() only running once but onEdit() is fine谷歌表格插件 onOpen() 只运行一次,但 onEdit() 很好
【发布时间】:2015-02-21 19:41:28
【问题描述】:

我正在开发一个名为 LastEdit 的表格插件。我遇到的问题是 onOpen() 仅在第一次安装附加组件时运行:

  • 代码作为绑定脚本运行到我编写插件的原始工作表中运行良好;只有已发布的插件(安装到不同的 Google 云端硬盘帐户)才会出现问题
  • 如果我从 Chrome 网上应用店安装插件:
  • 安装了插件后会自动打开一个新的无标题工作表。
  • 第一次一切正常:弹出帮助提示、填充 AddonMenu 等。
  • 如果我刷新页面 onOpen() 将停止工作。我仍然看到名为 LastEdit 的附加菜单,但它是空的,除了默认的帮助按钮;我的所有自定义菜单项都丢失了。
  • 如果我打开一个新工作表,我也会遇到同样的问题。
  • 如果我转到加载项 -> 管理加载项并单击管理 -> 在此文档中使用,则没有任何更改。我可以任意组合选中、取消选中和刷新页面。
  • 脚本在其他方面工作正常:调用 onEdit() 没有问题。
  • 我在 onOpen() 的开头偷偷添加了一个 ui.alert();在自动打开的第一个工作表中,我只看到一次此警报。
  • 我尝试从 onOpen() 中删除除 ui.alert() 之外的所有代码,但它甚至无法管理。

那么,为什么 onOpen() 不再运行了?

这是代码顺便说一句:

var documentProperties = PropertiesService.getDocumentProperties();
var ui = SpreadsheetApp.getUi();
var sheet = SpreadsheetApp.getActive();
var editCell;

// This function runs whenever cells are edited
function onEdit() {
  updateLastEdit();
}

// This function updates the editCell contents
function updateLastEdit() {
  // Fetch the coordinate of the designated LastEdit cell
  editCell = documentProperties.getProperty('editCell');
  // If our docProp editCell is 0 then we don't have a LastEdit to update
  if (editCell != 0.0) {
    sheet.getRange(editCell).setValue(new Date() + '');
  }
}

// This function will be used to designate the new LastEdit cell
function lastEdit() {
  editCell =  sheet.getActiveCell()
  SpreadsheetApp.getUi().alert("LastEdit cell added at: " + editCell.getA1Notation());
  documentProperties.setProperty('editCell', editCell.getA1Notation());
  // Once we've stashed the location of the LastEdit cell we move to update the LastEdit cell contents
  updateLastEdit();
}

// When the Sheet opens add a new custom menu
function onOpen(e) {

  // This is the alert for testing purposes
  ui.alert("onOpen() has run!");

  // Contingency strategy; set an Installable Trigger to perform the onOpen tasks
  //ScriptApp.newTrigger("openTrigger").forSpreadsheet(sheet).onOpen().create();

  // Creating custom menu for this app
  newMenu = ui.createAddonMenu();
  newMenu.addItem('Insert LastEdit Cell', 'insertLastEdit');
  newMenu.addItem('Disable LastEdit Cell', 'disableLastEdit');
  newMenu.addItem('LastEdit Cell Location', 'locateLastEdit');
  newMenu.addSeparator();
  newMenu.addItem('About', 'aboutLastEdit');
  newMenu.addToUi();
  // I know this can be shortened, but I removed/tested each individual
  // item to see if any of these were derailing onOpen()
}

// Insert LastEdit Cell
function insertLastEdit() {
  lastEdit();
}

// Disable LastEdit Cell
function disableLastEdit() {
  documentProperties.setProperty('editCell', 0);
  SpreadsheetApp.getUi().alert("LastEdit cell disabled");
}

// Fetch and display the LastEdit cell location via popup
function locateLastEdit() {
  editCell = documentProperties.getProperty('editCell');
  if (editCell != 0) {
    SpreadsheetApp.getUi().alert("LastEdit cell is located at: " + editCell);
  } else {
    SpreadsheetApp.getUi().alert("No LastEdit cell is active ");
  }
}

// About! 
function aboutLastEdit() {
  ui.alert("About LastEdit", SpreadsheetApp.getUi().ButtonSet.OK);
}

// After installation just run the onOpen function
function onInstall(e) {
  onOpen(e);
}

// If an Installable Trigger is required...
function openTrigger() {
    // I had a duplicate of onOpen() in here, but have abandoned this strategy
}

我在这里缺少什么?附加组件授权似乎有很多移动部分(绑定脚本、简单触发器、在文档中启用、authMode.LIMITED 与 FULL 等)我查看了附加组件授权生命周期页面,但它似乎指向这个过程在很大程度上是自动处理的。

提前感谢您的帮助!

【问题讨论】:

    标签: google-apps-script google-sheets add-on chrome-web-store


    【解决方案1】:

    "如果为用户安装了插件但在当前文档中未启用,onOpen(e) 运行在 AuthMode.NONE;如果插件在当前文档中启用,onOpen(e) 运行在AuthMode.LIMITED。如果插件已安装并启用,则启用状态优先,因为 LIMITED 允许访问更多 Apps 脚本服务。"

    当脚本在 AuthMode.NONE 上时,它无权访问属性服务。由于您有调用此服务的全局代码,因此如果 onOpen() 执行失败,则加载项。

    您需要将此全局代码移动到函数内。

    在此处查看更多信息https://developers.google.com/apps-script/add-ons/lifecycle#authorization_modes

    【讨论】:

    • 那么我可以将 PropertiesService 移动到它自己的函数中...function preparation() { var documentProperties = PropertiesService.getDocumentProperties(); } ...然后在 onOpen() 中调用此函数preparation() 吗?
    • 是的,你可以。但是您没有在 onOpen 函数中使用任何文档属性,所以我不明白您为什么要这样做。此外,如果您在 onOpen 中调用此函数,代码仍然会失败,因为 Authmode 将是 NONE 直到用户与您的插件交互
    • 知道了!现在一切正常。我为附加组件创建了一个动态菜单,其中包含有关在 Authmode 为 NONE 时如何在文档中启用的说明。谢谢!
    • 您好,请您发布您的解决方案代码。我有一个非常相似的问题,但一直无法解决。提前致谢
    猜你喜欢
    • 1970-01-01
    • 2020-11-07
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多