Google Workspace 文档中的对话框和边栏

绑定到 Google 文档、表格或表单的脚本可以显示多种类型的界面元素,包括预构建的提醒和提示,以及包含自定义 HTML 服务页面的对话框和边栏。通常,这些元素从菜单项打开。(请注意,在 Google 表单中,只有打开表单进行修改的编辑者才能看到界面元素,打开表单进行回复的用户看不到。)

提醒对话框

提醒是一种在 Google 文档、表格、幻灯片或表单编辑器中打开的预构建对话框。它会显示一条消息和一个“确定”按钮;标题和备用按钮是可选的。这类似于在网络浏览器内的客户端 JavaScript 中调用 window.alert()

当对话框打开时,提醒会暂停服务器端脚本。脚本在用户关闭对话框后恢复,但 JDBC 连接在暂停期间不会保留。

如下例所示,Google 文档、表单、幻灯片和表格都使用 Ui.alert() 方法,该方法有三种变体。如需替换默认的“确定”按钮,请传递 Ui.ButtonSet 枚举中的值作为 buttons 参数。如需评估用户点击的是哪个按钮,请将 alert() 的返回值与 Ui.Button 枚举进行比较。

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show alert', 'showAlert')
      .addToUi();
}

function showAlert() {
  var ui = SpreadsheetApp.getUi(); // Same variations.

  var result = ui.alert(
     'Please confirm',
     'Are you sure you want to continue?',
      ui.ButtonSet.YES_NO);

  // Process the user's response.
  if (result == ui.Button.YES) {
    // User clicked "Yes".
    ui.alert('Confirmation received.');
  } else {
    // User clicked "No" or X in the title bar.
    ui.alert('Permission denied.');
  }
}

提示对话框

提示是在 Google 文档、表格、幻灯片或表单编辑器中打开的预构建对话框。它显示了一条消息、一个文本输入字段和一个“确定”按钮;标题和备用按钮是可选的。这类似于在网络浏览器内的客户端 JavaScript 中调用 window.prompt()

提示在对话框打开时暂停服务器端脚本。脚本在用户关闭对话框后恢复,但 JDBC 连接在暂停期间不会保留。

如下例所示,Google 文档、表单、幻灯片和表格都使用 Ui.prompt() 方法,该方法有三种变体。如需替换默认的“确定”按钮,请将 Ui.ButtonSet 枚举中的值作为 buttons 参数传递。如需评估用户的响应,请捕获 prompt() 的返回值,然后调用 PromptResponse.getResponseText() 来检索用户的输入,并将 PromptResponse.getSelectedButton() 的返回值与 Ui.Button 枚举进行比较。

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show prompt', 'showPrompt')
      .addToUi();
}

function showPrompt() {
  var ui = SpreadsheetApp.getUi(); // Same variations.

  var result = ui.prompt(
      'Let\'s get to know each other!',
      'Please enter your name:',
      ui.ButtonSet.OK_CANCEL);

  // Process the user's response.
  var button = result.getSelectedButton();
  var text = result.getResponseText();
  if (button == ui.Button.OK) {
    // User clicked "OK".
    ui.alert('Your name is ' + text + '.');
  } else if (button == ui.Button.CANCEL) {
    // User clicked "Cancel".
    ui.alert('I didn\'t get your name.');
  } else if (button == ui.Button.CLOSE) {
    // User clicked X in the title bar.
    ui.alert('You closed the dialog.');
  }
}

自定义对话框

自定义对话框可以在 Google 文档、表格、幻灯片或表单编辑器中显示 HTML 服务界面。

当对话框打开时,自定义对话框不会暂停服务器端脚本。 客户端组件可以使用适用于 HTML 服务接口的 google.script API 对服务器端脚本进行异步调用。

该对话框可以通过在 HTML 服务接口的客户端中调用 google.script.host.close() 来自行关闭。该对话框不能由其他界面关闭,只能由用户或自身关闭。

如下例所示,Google 文档、表单、幻灯片和表格都使用 Ui.showModalDialog() 方法打开对话框。

Code.gs

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show dialog', 'showDialog')
      .addToUi();
}

function showDialog() {
  var html = HtmlService.createHtmlOutputFromFile('Page')
      .setWidth(400)
      .setHeight(300);
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .showModalDialog(html, 'My custom dialog');
}

Page.html

Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />

自定义边栏

边栏可以在 Google 文档、表单、幻灯片和表格编辑器中显示 HTML 服务界面。

当对话框打开时,边栏不会暂停服务器端脚本。客户端组件可以使用适用于 HTML 服务接口的 google.script API 对服务器端脚本进行异步调用。

通过在 HTML 服务接口的客户端调用 google.script.host.close(),边栏可以自行关闭。边栏不能由其他界面关闭,只能由用户或自身关闭。

如下例所示,Google 文档、表单、幻灯片和表格都使用 Ui.showSidebar() 方法打开边栏。

Code.gs

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show sidebar', 'showSidebar')
      .addToUi();
}

function showSidebar() {
  var html = HtmlService.createHtmlOutputFromFile('Page')
      .setTitle('My custom sidebar');
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .showSidebar(html);
}

Page.html

Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />

文件打开对话框

Google 选择器是一种“文件打开”对话框,适用于存储在 Google 服务器(包括 Google 云端硬盘、Google 图片搜索、Google 视频搜索等)中的信息。

如下例所示,可以在 HTML 服务中使用 Picker 的客户端 JavaScript API 来创建自定义对话框,让用户选择现有文件或上传新文件,然后将所选内容传回您的脚本以供进一步使用。

如需启用选择器并获取 API 密钥,请按照以下说明操作:

  1. 验证您的脚本项目使用的是标准 GCP 项目
  2. 在 Google Cloud 项目中启用“Google Picker API”
  3. 在 Google Cloud 项目仍处于打开状态期间,选择 API 和服务,然后点击凭据
  4. 点击创建凭据 > API 密钥。此操作会创建密钥,但您应修改密钥,以便向密钥同时添加应用限制和 API 限制。
  5. 在 API 密钥对话框中,点击关闭
  6. 在您创建的 API 密钥旁边,依次点击“更多”图标 “更多”图标> 修改 API 密钥
  7. 应用限制下,完成以下步骤:

    1. 选择 HTTP 引荐来源网址(网站)
    2. 网站限制下,点击添加一项
    3. 点击引荐来源网址,然后输入 *.google.com
    4. 再添加一项,并输入 *.googleusercontent.com 作为引荐来源网址。
    5. 点击完成
  8. API 限制下,完成以下步骤:

    1. 选择限制密钥
    2. 选择 API 部分中,选择 Google Picker API,然后点击确定

      注意:除非您已启用 Google Picker API,否则系统不会显示该 API,因为此列表仅显示已针对 Cloud 项目启用的 API。

  9. API 密钥下,点击“复制到剪贴板”图标 “复制到剪贴板”图标

  10. 点击底部的保存

code.gs

picker/code.gs
/**
 * Creates a custom menu in Google Sheets when the spreadsheet opens.
 */
function onOpen() {
  try {
    SpreadsheetApp.getUi().createMenu('Picker')
        .addItem('Start', 'showPicker')
        .addToUi();
  } catch (e) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', e.error);
  }
}

/**
 * Displays an HTML-service dialog in Google Sheets that contains client-side
 * JavaScript code for the Google Picker API.
 */
function showPicker() {
  try {
    const html = HtmlService.createHtmlOutputFromFile('dialog.html')
        .setWidth(600)
        .setHeight(425)
        .setSandboxMode(HtmlService.SandboxMode.IFRAME);
    SpreadsheetApp.getUi().showModalDialog(html, 'Select a file');
  } catch (e) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', e.error);
  }
}

/**
 * Gets the user's OAuth 2.0 access token so that it can be passed to Picker.
 * This technique keeps Picker from needing to show its own authorization
 * dialog, but is only possible if the OAuth scope that Picker needs is
 * available in Apps Script. In this case, the function includes an unused call
 * to a DriveApp method to ensure that Apps Script requests access to all files
 * in the user's Drive.
 *
 * @return {string} The user's OAuth 2.0 access token.
 */
function getOAuthToken() {
  try {
    DriveApp.getRootFolder();
    return ScriptApp.getOAuthToken();
  } catch (e) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', e.error);
  }
}

dialog.html

picker/dialog.html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
  <script>
    // IMPORTANT: Replace the value for DEVELOPER_KEY with the API key obtained
    // from the Google Developers Console.
    var DEVELOPER_KEY = 'ABC123 ... ';
    var DIALOG_DIMENSIONS = {width: 600, height: 425};
    var pickerApiLoaded = false;

    /**
     * Loads the Google Picker API.
     */
    function onApiLoad() {
      gapi.load('picker', {'callback': function() {
        pickerApiLoaded = true;
      }});
     }

    /**
     * Gets the user's OAuth 2.0 access token from the server-side script so that
     * it can be passed to Picker. This technique keeps Picker from needing to
     * show its own authorization dialog, but is only possible if the OAuth scope
     * that Picker needs is available in Apps Script. Otherwise, your Picker code
     * will need to declare its own OAuth scopes.
     */
    function getOAuthToken() {
      google.script.run.withSuccessHandler(createPicker)
          .withFailureHandler(showError).getOAuthToken();
    }

    /**
     * Creates a Picker that can access the user's spreadsheets. This function
     * uses advanced options to hide the Picker's left navigation panel and
     * default title bar.
     *
     * @param {string} token An OAuth 2.0 access token that lets Picker access the
     *     file type specified in the addView call.
     */
    function createPicker(token) {
      if (pickerApiLoaded && token) {
        var picker = new google.picker.PickerBuilder()
            // Instruct Picker to display only spreadsheets in Drive. For other
            // views, see https://developers.google.com/picker/docs/#otherviews
            .addView(google.picker.ViewId.SPREADSHEETS)
            // Hide the navigation panel so that Picker fills more of the dialog.
            .enableFeature(google.picker.Feature.NAV_HIDDEN)
            // Hide the title bar since an Apps Script dialog already has a title.
            .hideTitleBar()
            .setOAuthToken(token)
            .setDeveloperKey(DEVELOPER_KEY)
            .setCallback(pickerCallback)
            .setOrigin(google.script.host.origin)
            // Instruct Picker to fill the dialog, minus 2 pixels for the border.
            .setSize(DIALOG_DIMENSIONS.width - 2,
                DIALOG_DIMENSIONS.height - 2)
            .build();
        picker.setVisible(true);
      } else {
        showError('Unable to load the file picker.');
      }
    }

    /**
     * A callback function that extracts the chosen document's metadata from the
     * response object. For details on the response object, see
     * https://developers.google.com/picker/docs/result
     *
     * @param {object} data The response object.
     */
    function pickerCallback(data) {
      var action = data[google.picker.Response.ACTION];
      if (action == google.picker.Action.PICKED) {
        var doc = data[google.picker.Response.DOCUMENTS][0];
        var id = doc[google.picker.Document.ID];
        var url = doc[google.picker.Document.URL];
        var title = doc[google.picker.Document.NAME];
        document.getElementById('result').innerHTML =
            '<b>You chose:</b><br>Name: <a href="' + url + '">' + title +
            '</a><br>ID: ' + id;
      } else if (action == google.picker.Action.CANCEL) {
        document.getElementById('result').innerHTML = 'Picker canceled.';
      }
    }

    /**
     * Displays an error message within the #result element.
     *
     * @param {string} message The error message to display.
     */
    function showError(message) {
      document.getElementById('result').innerHTML = 'Error: ' + message;
    }
  </script>
</head>
<body>
  <div>
    <button onclick="getOAuthToken()">Select a file</button>
    <p id="result"></p>
  </div>
  <script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>