每当我尝试显示UI对话框(例如msgBox或alert)时,通过菜单项(例如,从Google表格中)进行调用时,它都可以正常工作,但是如果我尝试显示该对话框,则会挂起脚本从Google Apps脚本编辑器调用它(例如,通过运行>运行功能)。
我的猜测是,因为Google Apps脚本编辑器无法显示任何用户界面。为了解决这个问题,我想创建一个包装函数来检查脚本的运行方式,而不是根据源来显示UI。
“执行”屏幕具有类型(编辑器,独立,触发器)的概念:
这使我认为有某种方法可以某种方式在代码中获取此类型。
该函数的伪代码:
function showMessage(message) {
var scriptSource = ???;
if (scriptSource === "Standalone") {
Browser.msgBox(message);
} else {
console.log(message);
}
}
我将如何获得scriptSource
?
我能找到的最接近的东西是TriggerSource,但是缺少枚举值'Editor'和'Trigger'。此外,它是仅在Trigger上可用的属性。我不知道如何访问当前触发器。据我了解,只有在充当触发器的函数上,才能通过event object(例如,通过triggerUid
)使用该功能。我在应用脚本编辑器中运行的此方法无权访问事件对象。
答案 0 :(得分:1)
Browser.msgBox()
。我可以理解您的上述问题。为了解决这个问题,我想建议使用Apps Script API。示例脚本的流程如下。我认为针对您的情况有几种解决方法。因此,请将此视为其中之一。
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");
}
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/script.external_request
https://www.googleapis.com/auth/script.projects.readonly
如果我误解了你的问题,对不起。
如果我的理解是正确的,那么该示例脚本如何?这是一个示例脚本。可以通过提供脚本ID和函数名称来检索过程列表。在此示例脚本中,使用Apps Script API中的process.listScriptProcesses的“ ProcessType”,可以确认是否从脚本编辑器或自定义菜单中调用了该函数。
这是一个示例脚本。可以通过提供脚本ID和函数名称来检索过程列表。
使用此脚本时,请在API控制台上启用Apps Script API,并在清单中添加https://www.googleapis.com/auth/script.processes
范围。
此脚本的使用方法如下。
addCustomMenu()
。sampleFunction
。
Call from custom menu
将显示在日志中。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>
如果您从此处运行脚本:
您必须去这里查看它: