如何确定导致脚本运行的原因?

时间:2018-12-30 04:31:46

标签: google-apps-script

每当我尝试显示UI对话框(例如msgBoxalert)时,通过菜单项(例如,从Google表格中)进行调用时,它都可以正常工作,但是如果我尝试显示该对话框,则会挂起脚本从Google Apps脚本编辑器调用它(例如,通过运行>运行功能)。

  

enter image description here

我的猜测是,因为Google Apps脚本编辑器无法显示任何用户界面。为了解决这个问题,我想创建一个包装函数来检查脚本的运行方式,而不是根据源来显示UI。

“执行”屏幕具有类型(编辑器,独立,触发器)的概念:

  

enter image description here

这使我认为有某种方法可以某种方式在代码中获取此类型。

该函数的伪代码:

function showMessage(message) {
  var scriptSource = ???;
  if (scriptSource === "Standalone") {
    Browser.msgBox(message);
  } else {
    console.log(message);
  }
}

我将如何获得scriptSource

我能找到的最接近的东西是TriggerSource,但是缺少枚举值'Editor'和'Trigger'。此外,它是仅在Trigger上可用的属性。我不知道如何访问当前触发器。据我了解,只有在充当触发器的函数上,才能通过event object(例如,通过triggerUid)使用该功能。我在应用脚本编辑器中运行的此方法无权访问事件对象。

3 个答案:

答案 0 :(得分:1)

  • 您想知道当前项目是容器绑定脚本类型还是独立脚本类型。
  • 您要使用Browser.msgBox()

我可以理解您的上述问题。为了解决这个问题,我想建议使用Apps Script API。示例脚本的流程如下。我认为针对您的情况有几种解决方法。因此,请将此视为其中之一。

  1. 使用Apps Script API中的projects.get方法检索项目的父ID。父ID表示Google文档的文件ID。
    • 返回父ID后,发现该项目是容器绑定的脚本类型。
    • 未返回父ID时,发现该项目是独立脚本类型。
  2. 当父ID的mimeType为Google Form时,不能使用Browser.msgBox()。因此,使用if语句。

示例脚本:

这是一个示例脚本。在此示例脚本中,使用了当前项目的脚本ID。当然,您也可以手动提供脚本ID。

var id = ScriptApp.getScriptId(); // Retrieve scriptId of current project.
var url = "https://script.googleapis.com/v1/projects/" + id + "?fields=parentId";
var res = UrlFetchApp.fetch(url, {headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}});
res = JSON.parse(res.getContentText());
if ("parentId" in res) {
  Logger.log("Container-bound script type.")
  var mimeType = DriveApp.getFileById(res.parentId).getMimeType();
  if (mimeType === MimeType.GOOGLE_FORMS) {
    Logger.log("Browser.msgBox() cannot be used at Google Form.");
  } else {
    Browser.msgBox("Hello world");
  }
} else {
  Logger.log("Standalone script type.")
  Logger.log("Hello world");
}

注意:

  • 使用此脚本时,请执行以下流程。
    1. 在API控制台上启用Apps脚本API。
    2. 至少,将以下范围添加到清单。
      • https://www.googleapis.com/auth/drive
      • https://www.googleapis.com/auth/script.external_request
      • https://www.googleapis.com/auth/script.projects.readonly
  • 如果在脚本中需要添加其他范围,请添加它们。而且,如果要在脚本编辑器中使用范围的自动安装程序,则可以使用库来实现。您可以在here上查看详细信息。

参考文献:

如果我误解了你的问题,对不起。

编辑:

  • 您要确认是从脚本编辑器还是从自定义菜单调用该函数。

如果我的理解是正确的,那么该示例脚本如何?这是一个示例脚本。可以通过提供脚本ID和函数名称来检索过程列表。在此示例脚本中,使用Apps Script API中的process.listScriptProcesses的“ ProcessType”,可以确认是否从脚本编辑器或自定义菜单中调用了该函数。

示例脚本:

这是一个示例脚本。可以通过提供脚本ID和函数名称来检索过程列表。

使用此脚本时,请在API控制台上启用Apps Script API,并在清单中添加https://www.googleapis.com/auth/script.processes范围。

此脚本的使用方法如下。

  1. 运行addCustomMenu()
  2. 在自定义菜单上运行sampleFunction
    • 这样,Call from custom menu将显示在日志中。
  3. 在脚本编辑器中运行sampleFunction
    • 这样,Call from script editor将显示在日志中。
脚本:
function addCustomMenu() {
  SpreadsheetApp.getUi().createMenu('sampleCustomMenu').addItem('sample', 'sampleFunction').addToUi();
}

function sampleFunction() {
  var scriptId = ScriptApp.getScriptId();
  var functionName = "sampleFunction";
  var url = "https://script.googleapis.com/v1/processes:listScriptProcesses?scriptId=" + scriptId + "&scriptProcessFilter.functionName=" + functionName;
  var res = UrlFetchApp.fetch(url, {headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}, muteHttpExceptions: true});
  res = JSON.parse(res);
  if (!("processType" in res.processes[0])) {
    Logger.log("Call from custom menu")
  } else if (res.processes[0].processType == "EDITOR") {
    Logger.log("Call from script editor")
  }
}

参考文献:

答案 1 :(得分:1)

这不是最佳解决方案,但是我当前的解决方法是为每个函数创建3个版本,并将调用方式附加到名称中。

例如,如果有一个“ Hello World”功能:

function onOpen() {
  var menu = [
    {name: 'Hello World', functionName: 'helloWorldViaMenu_'},
  ];
  SpreadsheetApp.getActive().addMenu('Custom', menu);
}

function helloWorldViaMenu_() {
  helloWorld_(false);
}

function helloWorldViaEditor() {
  helloWorld_(true);
}

function helloWorld_(invokedFromEditor) {
  if (invokedFromEditor) {
    Logger.log("Hello world");
  } else {
    Browser.msgBox("Hello world");
  }
}

helloWorldViaEditor是唯一没有末尾_的,因此可以通过“选择功能”编辑器UI下拉菜单进行选择。

答案 2 :(得分:0)

制作对话框

您可以从菜单或脚本编辑器中运行它们。它们的工作原理相同。

<div id="dialog" title="Tab data">
  <form>
    <fieldset class="ui-helper-reset">
      <label for="tab_title">Title</label>
      <input type="text" name="tab_title" id="tab_title" value="Tab Title" class="ui-widget-content ui-corner-all">
      <label for="tab_content">Content</label>
      <textarea name="tab_content" id="tab_content" class="ui-widget-content ui-corner-all">Tab content</textarea>
    </fieldset>
  </form>
</div>

<a id="add_tab" href="#">Add Tab</a>

<div id="tabs">
  <ul>
    <li><a href="#tabs-1">Nunc tincidunt</a> <span class="ui-icon ui-icon-close" role="presentation">Remove Tab</span></li>
  </ul>
  <div id="tabs-1">
    <p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
  </div>
</div>

如果您从此处运行脚本:

enter image description here

您必须去这里查看它:

enter image description here