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 服務使用者介面。

自訂對話方塊不會在對話方塊開啟時暫停伺服器端指令碼。 用戶端元件可以使用 google.script API,對 HTML 服務介面進行非同步呼叫,藉此呼叫伺服器端指令碼。

對話方塊可以透過在 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 服務使用者介面。

對話方塊開啟時,側欄不會暫停伺服器端指令碼。用戶端元件可以使用 google.script API,對 HTML 服務介面進行非同步呼叫,藉此呼叫伺服器端指令碼。

側欄可以在 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 Picker 是一種 JavaScript API,可讓使用者選取或上傳 Google 雲端硬碟檔案。您可以在 HTML 服務中使用 Google Picker 程式庫建立自訂對話方塊,讓使用者選取現有檔案或上傳新檔案,然後將選取項目傳回指令碼以供進一步使用。

需求條件

如要透過 Apps Script 使用 Google Picker,必須符合幾項規定。

範例

以下範例顯示 Apps Script 中的 Google Picker。

code.gs

picker/code.gs
/**  * Creates a custom menu in Google Sheets when the spreadsheet opens.  */ function onOpen() {   SpreadsheetApp.getUi()     .createMenu("Picker")     .addItem("Start", "showPicker")     .addToUi(); }  /**  * Displays an HTML-service dialog in Google Sheets that contains client-side  * JavaScript code for the Google Picker API.  */ function showPicker() {   const html = HtmlService.createHtmlOutputFromFile("dialog.html")     .setWidth(800)     .setHeight(600)     .setSandboxMode(HtmlService.SandboxMode.IFRAME);   SpreadsheetApp.getUi().showModalDialog(html, "Select a file"); } /**  * Checks that the file can be accessed.  */ function getFile(fileId) {   return Drive.Files.get(fileId, { fields: "*" }); }  /**  * 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() {   return ScriptApp.getOAuthToken(); }

dialog.html

picker/dialog.html
<!DOCTYPE html> <html>   <head>     <link       rel="stylesheet"       href="https://ssl.gstatic.com/docs/script/css/add-ons.css"     />     <style>       #result {         display: flex;         flex-direction: column;         gap: 0.25em;       }        pre {         font-size: x-small;         max-height: 25vh;         overflow-y: scroll;         background: #eeeeee;         padding: 1em;         border: 1px solid #cccccc;       }     </style>     <script>       // TODO: Replace the value for DEVELOPER_KEY with the API key obtained       // from the Google Developers Console.       const DEVELOPER_KEY = "AIza...";       // TODO: Replace the value for CLOUD_PROJECT_NUMBER with the project       // number obtained from the Google Developers Console.       const CLOUD_PROJECT_NUMBER = "1234567890";        let pickerApiLoaded = false;       let oauthToken;        /**        * 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((token) => {             oauthToken = token;             createPicker(token);           })           .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) {         document.getElementById("result").innerHTML = "";          if (pickerApiLoaded && token) {           const picker = new google.picker.PickerBuilder()             // Instruct Picker to display only spreadsheets in Drive. For other             // views, see https://developers.google.com/picker/reference/picker.viewid             .addView(               new google.picker.DocsView(                 google.picker.ViewId.SPREADSHEETS               ).setOwnedByMe(true)             )             // 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)             .setAppId(CLOUD_PROJECT_NUMBER)             .setCallback(pickerCallback)             .setOrigin(google.script.host.origin)             .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/reference/picker.responseobject        *        * @param {object} data The response object.        */       function pickerCallback(data) {         const action = data[google.picker.Response.ACTION];         if (action == google.picker.Action.PICKED) {           handlePicked(data);         } else if (action == google.picker.Action.CANCEL) {           document.getElementById("result").innerHTML = "Picker canceled.";         }       }        /**        * Handles `"PICKED"` responsed from the Google Picker.        *        * @param {object} data The response object.        */       function handlePicked(data) {         const doc = data[google.picker.Response.DOCUMENTS][0];         const id = doc[google.picker.Document.ID];          google.script.run           .withSuccessHandler((driveFilesGetResponse) => {             // Render the response from Picker and the Drive.Files.Get API.             const resultElement = document.getElementById("result");             resultElement.innerHTML = "";              for (const response of [               {                 title: "Picker response",                 content: JSON.stringify(data, null, 2),               },               {                 title: "Drive.Files.Get response",                 content: JSON.stringify(driveFilesGetResponse, null, 2),               },             ]) {               const titleElement = document.createElement("h3");               titleElement.appendChild(document.createTextNode(response.title));               resultElement.appendChild(titleElement);                const contentElement = document.createElement("pre");               contentElement.appendChild(                 document.createTextNode(response.content)               );               resultElement.appendChild(contentElement);             }           })           .withFailureHandler(showError)           .getFile(data[google.picker.Response.DOCUMENTS][0].id);       }        /**        * 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>       <div id="result"></div>     </div>     <script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>   </body> </html>

appsscript.json

picker/appsscript.json
{     "timeZone": "America/Los_Angeles",     "exceptionLogging": "STACKDRIVER",     "runtimeVersion": "V8",     "oauthScopes": [       "https://www.googleapis.com/auth/script.container.ui",       "https://www.googleapis.com/auth/drive.file"     ],     "dependencies": {       "enabledAdvancedServices": [         {           "userSymbol": "Drive",           "version": "v3",           "serviceId": "drive"         }       ]     }   }