📝

情シスはGWSのユーザー情報でGoogleフォームを作りたい

2024/02/27に公開

背景

GWS利用している会社の情シスです。
社内に対してGoogleフォームでアンケートを作る際、社員名やメールアドレスを選択肢として選べるようにしたいことがあると思います。
フォーム回答者本人のメールアドレスなら自動で収集できますが、本人以外の情報を入れられるようにしたい。自由記述だと入力ミスがあるので、選択肢項目にしたい。

例えて言うなら、SlackワークフローでAnswer formatに Select a person を選んだときのようなUIです。
一人ずつ指定しなくても、現存する社員が勝手に一覧で出てきてほしい。

ほしいですよね。
しかしGoogleフォームにはそのような選択肢はありません。

どうするか

GWSならディレクトリに社員情報を持っています。
ディレクトリからデータを取ってくるならDirectory API
GASがあればすぐ使えますし、GASとフォームも連携が簡単です。これでやってみます。

流れを説明するために、例として以下のような状況を設定しました。

  • 社内利用するGoogleフォームを作る
  • フォームでは同僚のメールアドレスを選択し、メッセージを入力できるようにする

手順

以下、初めての方でも書いてある通りにやれば(たぶん)できる手順です。
自分でできる方は「コード」まで飛んでください。

フォームを作り、コードの雛形をコピペ

  1. まずGoogleフォームを作り、必要な項目を一通り設定します。
    メールアドレスも選択肢項目として作っておいてください。選択肢の中身(オプション1の部分)は何もしなくて大丈夫です。

    この状態でフォームをプレビューすると、もちろん「オプション1」しか表示されません。
  2. フォーム編集画面右上から「スクリプトエディタ」を選びます。
  3. スクリプトエディタが開いたら、以下「コード」にある内容をコピペし、**ここに自社ドメインを入れる(hoge.co.jpなど)** の部分に自社ドメインを入力します。

コードにフォーム固有の情報を埋める

  1. コード内のFORM_IDを埋めます。
    先ほど作ったフォームのURLは以下の形式になっています。
    https://docs.google.com/forms/d/hogehoge/edit
    hogehoge部分をコピーし、コード内の **ここにフォームIDを入れる** 部分に貼り付けてください。
  2. スクリプトエディタ画面で Ctrl+S キーを押してコードを保存します。すると画面上部「デバッグ」の横で処理名を選べるようになるので、 getAllItemsFromForm を選んで「実行」をクリックします。
  3. 権限の確認が表示されます。許可してください。

  4. 処理が実行され、以下のようなログが表示されます。
  5. 表示された内容から、メールアドレスの項目(例では「誰に対するメッセージですか?」)のIDをコピーし、コード内 **ここに項目IDを入れる** に貼り付けてください。
  6. スクリプトエディタ画面で Ctrl+S キーを押してコードを保存します。

Directory APIを使えるようにする

  1. このままではDirectory APIが使えません。
    スクリプトエディタ画面左側の「サービス」横の「+」をクリックします。
  2. Admin SDK API を選び、「追加」をクリックします。
  3. 「サービス」の下に AdminDirectory が表示されました。

実行!

  1. 画面上部「デバッグ」の横で addEmailAddressToForm を選んで「実行」をクリックします。
  2. 実行が無事完了したら、フォームを見てみます。
  3. 「オプション1」だけだったところに選択肢が入っています!

今後のために

単発のフォームならここまでで完了です。
長く使いたいフォームの場合、入退社でメンバーの変動がありえます。
その場合はトリガーを設定しておけば、フォームの選択肢を定期的に最新の状態にできます。
以下では毎月1日に実行するよう設定しています。
実行される時間は、フォームが使われていなそうな時間にします。

  1. スクリプトエディタの画面に戻り、画面左の「トリガー」をクリックします。
  2. 画面右下「トリガーを追加」をクリックします。
  3. 以下のように設定します。
    実行する関数 addEmailAddressToForm
    実行するデプロイを選択 デフォルト表示のまま
    イベントのソースを選択 時間主導型
    時間ベースのトリガーのタイプを選択 月ベースのタイマー
    日を選択 1日
    時間を選択 午前0時~1時

これで情報が新しい状態に保たれるようになりました。

フォームで回答されたあと、その選択肢が消えたらどうなるのか。

  • 回答の「概要」表示では、消えた選択肢でも表示されました。
  • 回答の「個別」表示では、メールアドレスのプルダウンが空白で表示されました。これは、UIがプルダウンであるためだと思います。

結論、退職者の選択肢が消えても問題はなさそうです。

コード

const DOMAIN = '**ここに自社ドメインを入れる(hoge.co.jpなど)**'
const FORM_ID = '**ここにフォームIDを入れる**'
const ITEM_ID = '**ここに項目IDを入れる**'

/**
 * フォームの選択肢項目にGoogleディレクトリから取得したアドレスを追加する
 * 
 * FormApp
 * https://developers.google.com/apps-script/reference/forms/form-app?hl=ja
 * Form
 * https://developers.google.com/apps-script/reference/forms/form?hl=ja
 */
function addEmailAddressToForm() {
  var form = FormApp.openById(FORM_ID);
  var item = form.getItemById(ITEM_ID);
  var formItems = form.getItems()

  // メールアドレス一覧を取得する
  var users = getEmailList();
  // フォームの項目にアドレスリストを設定する
  item.asListItem().setChoiceValues(users);
}

/**
 * Googleディレクトリからユーザー一覧を取得する
 */
function getUsersFromDirectory(){
  return AdminDirectory.Users.list({
    domain: DOMAIN,
    orderBy: 'EMAIL',
    maxResults: 500
  });
}

/**
 * ユーザーリストからprimaryEmailだけを取り出す
 */
function getEmailList() {
  var users = getUsersFromDirectory();
  return users.users.map(function(user) {
    return  user.primaryEmail;
  });
}

/**
 * フォームの項目とIDをすべて取得してログ出力する
 */
 function getAllItemsFromForm(){
  var form = FormApp.openById(FORM_ID)

  for(var item of form.getItems()){
    var itemName = item.getTitle();
    var itemId = item.getId();
    console.log(`項目名 ${itemName}, \nID ${itemId}`);
  }
 }

コード解説

  • getUsersFromDirectory()でディレクトリからユーザー情報を取得しています。この時点ではメール含むすべての情報が取得できています。
  • getEmailList() でユーザー情報からプライマリアドレスのみを取り出しています。メール以外の項目を取りたい場合は、primaryEmail の代わりに別の項目名を設定してください。 項目名はリファレンスにあります。
  • このコードでは、フォーム上の項目を操作する際、項目名ではなくIDを使っています。(getItemById)
    ネット上に出てくるサンプルだと項目IDを使っているものが多いのですが、これだと運用後に項目名を変更された場合に処理が動かなくなるためです。
  • APIで一度に取れる情報は500件までです。1回取って終わりにしているコードなので、GWSユーザー数が501以上の組織ではそのまま使えません。(そもそも選択肢が500以上あるプルダウンはどうなんだという話も…)

Discussion