Google Workspace ドキュメントのダイアログとサイドバー

Google ドキュメント、スプレッドシート、フォームにバインドされたスクリプトでは、さまざまなタイプのユーザー インターフェース要素を表示できます。たとえば、事前に構築されたアラートとプロンプトに加えて、カスタム HTML サービスページを含むダイアログとサイドバーを表示できます。通常、これらの要素はメニュー項目から開きます。(Google フォームでユーザー インターフェース要素を表示できるのは、そのフォームを開いて変更を行った編集者だけであり、回答するためにフォームを開いたユーザーには表示されません)。

アラート ダイアログ

アラートは、Google ドキュメント、スプレッドシート、スライド、フォームのエディタ内で開く事前作成済みのダイアログ ボックスです。メッセージと [OK] ボタンが表示されます。タイトルと代替ボタンは省略可能です。これは、ウェブブラウザ内のクライアントサイド JavaScript で window.alert() を呼び出す場合と似ています。

ダイアログが開いている間、サーバーサイド スクリプトが停止します。ユーザーがダイアログを閉じるとスクリプトが再開されますが、停止期間中は JDBC 接続は維持されません。

以下の例に示すように、Google ドキュメント、フォーム、スライド、スプレッドシートはすべて、メソッド Ui.alert() を使用します。このメソッドは 3 つのバリアントで使用できます。デフォルトの [OK] ボタンをオーバーライドするには、buttons 引数として Ui.ButtonSet 列挙型の値を渡します。ユーザーがクリックしたボタンを評価するには、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 ドキュメント、スプレッドシート、スライド、フォームのエディタ内で開く事前作成済みのダイアログ ボックスです。メッセージ、テキスト入力フィールド、「OK」ボタンが表示されます。タイトルと代替ボタンは省略可能です。これは、ウェブブラウザ内のクライアントサイド JavaScript で window.prompt() を呼び出す場合と似ています。

ダイアログが開いている間は、サーバーサイド スクリプトが一時停止されます。ユーザーがダイアログを閉じるとスクリプトが再開されますが、停止期間中は JDBC 接続は維持されません。

以下の例に示すように、Google ドキュメント(フォーム、スライド、スプレッドシート)はすべて、Ui.prompt() メソッドを使用します。このメソッドは 3 つのバリアントで使用できます。デフォルトの [OK] ボタンをオーバーライドするには、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 Picker は、Google ドライブ、Google 画像検索、Google ビデオ検索などの Google サーバーに保存されている情報を「ファイルを開く」ダイアログです。

以下の例に示すように、Picker のクライアントサイドの JavaScript API を HTML サービス内で使用してカスタム ダイアログを作成し、ユーザーが既存のファイルを選択したり、新しいファイルをアップロードしたりしてから、その選択内容をスクリプトに返してさらに使用できるようにします。

Picker を有効にして 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. さらにアイテムを追加し、参照 URL として「*.googleusercontent.com」と入力します。
    5. [完了] をクリックします。
  8. [API の制限] で、次の手順を完了します。

    1. [キーを制限] を選択します。
    2. [Select APIs] セクションで、[Google Picker API] を選択して [OK] をクリックします。

      注: Google Picker 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>