当用户打开工作表或单击工作表中的链接时,Google Sheets 附加组件会自动打开

ang*_*okh 2 google-sheets google-apps-script

我创建了一个谷歌表格插件。然而,它有点隐藏在附加菜单中。有没有办法在用户打开工作表或单击工作表中的链接时自动启用附加组件?我搜索了 Google Sheets 文档,但一无所获。

编辑1:

由于自动打开插件侧边栏似乎是一种糟糕的用户体验,那么通过单击工作表中的链接来打开怎么样?让用户通过单击插件插入的工作表中的链接来选择打开侧边栏。

Mog*_*dad 5

当然,您可以获取一个 UI 组件,以便在打开文档时自动打开加载项。对于附加组件来说,这是可怕的行为,并且永远不应该发布它,因为它会干扰其他附加组件。但仍然可以做到。

但也有一些限制。

  • 必须为该文档启用该附加组件。请参阅附加授权生命周期
  • 根据附加组件执行的操作,它可能需要用户授权。例如,如果用户 A 和用户 B 共享一个文档,并且用户 A 安装并授权该附加组件,则用户 B 也会看到该附加组件已启用,但需要单独授权以允许其在其帐户上运行。

对于不需要任何类型授权的附加组件,它可以像showSidebar()在函数中添加调用一样简单。onOpen()

function onOpen(e) {
  var ui = SpreadsheetApp.getUi()
      .createAddonMenu()
      .addItem('Show sidebar', 'showSidebar')
      .addItem('Show dialog', 'showDialog')
      .addToUi();

    // Display sidebar
    showSidebar();
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们想要选择启用和禁用该行为怎么办?与其盲目地打开附加组件侧边栏,不如onOpen()使用菜单项来控制行为,并且仅在启用时打开附加组件。

/**
 * Adds a custom menu with items to show the sidebar and dialog.
 *
 * @param {Object} e The event parameter for a simple onOpen trigger.
 */
function onOpen(e) {
  var ui = SpreadsheetApp.getUi()
      .createAddonMenu()
      .addItem('Show sidebar', 'showSidebar')
      .addItem('Show dialog', 'showDialog')
      .addSeparator()
      .addItem(autoEnabled_()?"Disable auto-sidebar":"Enable auto-sidebar", "autoToggle_")
      .addToUi();

    // Display sidebar if auto-sidebar is enabled
    if (autoEnabled_()) showSidebar();
}
Run Code Online (Sandbox Code Playgroud)

现在我们介绍了两个与自动侧边栏控制相关的功能,autoEnabled_()以及autoToggle_()。第一个似乎告诉我们自动侧边栏的启用状态是什么,而第二个似乎改变状态,并作为菜单项中的字符串参数提供(...因此它不能接受参数)。

由于自动显示仅在打开文档时才起作用,因此我们需要某种方法来记住用户在使用文档之间的设置。可以使用 来解决这个问题PropertyService。不过,我们需要小心,因为该服务需要授权。由于这是一个在首次安装时将运行的附加组件ScriptApp.AuthMode.NONE,因此我们不能依赖能够访问该服务。因此,在这种情况下,请将其包装在一个try...catch块中。

为了使代码易于维护,最好将像 PropertyService 这样的“混乱”函数保留在一处。“混乱”,因为它依赖字符串映射来存储和检索数据,并且我们代码中的简单拼写错误会引入难以发现的错误。为了降低这种长期质量成本,我们可以通过将状态切换作为读取当前设置的子情况,将我们需要的两个功能合并为一个。这是生成的autoEnabled_()函数,autoToggle_()只需提供一个参数即可autoEnabled_()更改状态。

/**
 * Get status of auto-sidebar, and optionally change it.
 *
 * @var {any} optSet  (optional) Any truthy value will change the setting.
 *
 * @returns {Boolean} Returns true if enabled, false if not.
 *                    Always returns false if ScriptApp.AuthMode.NONE.
 */
function autoEnabled_(optSet) {
  try {
    var autoState = PropertiesService.getUserProperties().getProperty('autoState');
  }
  catch (e) {
    // Called with ScriptApp.AuthMode.NONE
    return false;
  }

  if (optSet) {
    autoState = (autoState == 'enabled')?'disabled':'enabled';
    PropertiesService.getUserProperties()
                     .setProperty('autoState',autoState);
    // Re-run the onOpen function to update menu
    onOpen({authMode:ScriptApp.AuthMode.LIMITED});
  }

  return autoState == 'enabled';
}

/**
 * Toggle state of auto-sidebar.
 */
function autoToggle_() {autoEnabled_('toggle');}  // remove underscore and call from debugger to enable logs w/o UI
Run Code Online (Sandbox Code Playgroud)

完整的代码片段如下所示。要尝试一下,请从编辑器中作为模板提供的通用“Add on”脚本开始,然后用代码onOpen()片段中的代码替换原始脚本。

/**
 * Adds a custom menu with items to show the sidebar and dialog.
 *
 * @param {Object} e The event parameter for a simple onOpen trigger.
 */
function onOpen(e) {
  var ui = SpreadsheetApp.getUi()
      .createAddonMenu()
      .addItem('Show sidebar', 'showSidebar')
      .addItem('Show dialog', 'showDialog')
      .addSeparator()
      .addItem(autoEnabled_()?"Disable auto-sidebar":"Enable auto-sidebar", "autoToggle_")
      .addToUi();

    // Display sidebar if auto-sidebar is enabled
    if (autoEnabled_()) showSidebar();
}

/**
 * Get status of auto-sidebar, and optionally change it.
 *
 * @var {any} optSet  (optional) Any truthy value will change the setting.
 *
 * @returns {Boolean} Returns true if enabled, false if not.
 *                    Always returns false if ScriptApp.AuthMode.NONE.
 */
function autoEnabled_(optSet) {
  try {
    var autoState = PropertiesService.getUserProperties().getProperty('autoState');
  }
  catch (e) {
    // Called with ScriptApp.AuthMode.NONE
    return false;
  }
  
  if (optSet) {
    autoState = (autoState == 'enabled')?'disabled':'enabled';
    PropertiesService.getUserProperties()
                     .setProperty('autoState',autoState);
    // Re-run the onOpen function to update menu
    onOpen({authMode:ScriptApp.AuthMode.LIMITED});
  }

  return autoState == 'enabled';
}

/**
 * Toggle state of auto-sidebar.
 */
function autoToggle_() {autoEnabled_('toggle');}  // remove underscore and call from debugger to enable logs w/o UI
Run Code Online (Sandbox Code Playgroud)

致谢

感谢 Serge 在我们第一次合作开发附加想法时向我提出了这个想法!