会議の議題を作成する

コーディング レベル: 初級
所要時間: 15 分
プロジェクトの種類: イベント ドリブン トリガーを使用した自動化

目標

  • ソリューションの機能を理解します。
  • Apps Script サービスがソリューション内でどのように機能するかを理解する。
  • スクリプトを設定します。
  • スクリプトを実行します。

このソリューションについて

Google ドキュメントで議題のドキュメントを自動的に作成し、Google カレンダーの会議に添付する。

カレンダーの予定に追加された予定リストのスクリーンショット

仕組み

このスクリプトは、議題のドキュメント テンプレートを作成します。カレンダーを更新すると、あなたがオーナーの予定の説明に「#agenda」が含まれているかどうかがチェックされます。タグが存在する場合、スクリプトはテンプレートのコピーを作成してカレンダーの予定に追加し、イベントの参加者と共有します。

Apps Script サービス

このソリューションでは、次のサービスを使用します。

  • ドライブ サービス - テンプレート ドキュメントが存在するかどうかを確認し、存在しない場合は、テンプレート ドキュメント用の新しいフォルダを作成します。新しい議題ごとにテンプレート ドキュメントのコピーを作成します。
  • Document サービス - 予定リストのテンプレートを作成します。
  • カレンダー サービス - 「#agenda」タグの付いた予定を確認し、予定リストへのリンクで予定の説明を更新します。
  • 基本サービス - Session クラスを使用して、ユーザーのメールアドレスを取得します。これにより、現在のユーザーのトリガーを作成できます。
  • スクリプト サービス - ユーザーのカレンダーが変更されるたびに配信されるトリガーを作成します。

前提条件

このサンプルを使用するには、次の前提条件を満たす必要があります。

  • Google アカウント(Google Workspace アカウントには管理者の承認が必要になる場合があります)。
  • インターネットにアクセスできるウェブブラウザ。

スクリプトを設定する

  1. 下のボタンをクリックすると、Apps Script のサンプル「会議の議題を作成する」プロジェクトが開きます。
    プロジェクトを開く
  2. [概要] をクリックします。
  3. 概要ページでコピーを作成 コピー作成のアイコン をクリックします。
  4. コピーしたプロジェクトの関数プルダウンで、[setUp] を選択します。
  5. [実行] をクリックします。
  6. プロンプトが表示されたら、スクリプトを承認します。 OAuth 同意画面に「このアプリは確認されていません」という警告が表示された場合は、[詳細設定] > [{プロジェクト名} に移動(安全でない)] を選択します。

スクリプトを実行する

  1. Google カレンダーを開きます。
  2. 新しい予定を作成するか、既存の予定を編集します。
  3. 説明に #agenda を追加して、予定を保存します。
  4. ドキュメントが共有されたことを知らせるメール通知が届くか、 カレンダーを更新して予定をもう一度クリックすると、予定リストドキュメントへのリンクが表示されます。

すべての参加者に、アジェンダを表示するためのメール通知が送信されます。このスクリプトは参加者に編集権限を付与しますが、スクリプトを編集して参加者のアジェンダ ドキュメント権限を更新することもできます。

コードを確認する

このソリューションの Apps Script コードを確認するには、下の [ソースコードを表示] をクリックします。

ソースコードを表示

Code.gs

solutions/automations/agenda-maker/Code.js
// To learn how to use this script, refer to the documentation:
// https://developers.google.com/apps-script/samples/automations/agenda-maker

/*
Copyright 2022 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
 * Checks if the folder for Agenda docs exists, and creates it if it doesn't.
 *
 * @return {*} Drive folder ID for the app.
 */
function checkFolder() {
  const folders = DriveApp.getFoldersByName('Agenda Maker - App');
  // Finds the folder if it exists
  while (folders.hasNext()) {
    let folder = folders.next();
    if (
      folder.getDescription() ==
        'Apps Script App - Do not change this description' &&
      folder.getOwner().getEmail() == Session.getActiveUser().getEmail()
    ) {
      return folder.getId();
    }
  }
  // If the folder doesn't exist, creates one
  let folder = DriveApp.createFolder('Agenda Maker - App');
  folder.setDescription('Apps Script App - Do not change this description');
  return folder.getId();
}

/**
 * Finds the template agenda doc, or creates one if it doesn't exist.
 */
function getTemplateId(folderId) {
  const folder = DriveApp.getFolderById(folderId);
  const files = folder.getFilesByName('Agenda TEMPLATE##');

  // If there is a file, returns the ID.
  while (files.hasNext()) {
    const file = files.next();
    return file.getId();
  }

  // Otherwise, creates the agenda template.
  // You can adjust the default template here
  const doc = DocumentApp.create('Agenda TEMPLATE##');
  const body = doc.getBody();

  body
      .appendParagraph('##Attendees##')
      .setHeading(DocumentApp.ParagraphHeading.HEADING1)
      .editAsText()
      .setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);

  body
      .appendParagraph('Overview')
      .setHeading(DocumentApp.ParagraphHeading.HEADING1)
      .editAsText()
      .setBold(true);
  body.appendParagraph(' ');
  body.appendParagraph('- Topic 1: ').editAsText().setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);
  body.appendParagraph('- Topic 2: ').editAsText().setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);
  body.appendParagraph('- Topic 3: ').editAsText().setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);

  body
      .appendParagraph('Next Steps')
      .setHeading(DocumentApp.ParagraphHeading.HEADING1)
      .editAsText()
      .setBold(true);
  body.appendParagraph('- Takeaway 1: ').editAsText().setBold(true);
  body.appendParagraph('- Responsible: ').editAsText().setBold(false);
  body.appendParagraph('- Accountable: ');
  body.appendParagraph('- Consult: ');
  body.appendParagraph('- Inform: ');
  body.appendParagraph(' ');
  body.appendParagraph('- Takeaway 2: ').editAsText().setBold(true);
  body.appendParagraph('- Responsible: ').editAsText().setBold(false);
  body.appendParagraph('- Accountable: ');
  body.appendParagraph('- Consult: ');
  body.appendParagraph('- Inform: ');
  body.appendParagraph(' ');
  body.appendParagraph('- Takeaway 3: ').editAsText().setBold(true);
  body.appendParagraph('- Responsible: ').editAsText().setBold(false);
  body.appendParagraph('- Accountable: ');
  body.appendParagraph('- Consult: ');
  body.appendParagraph('- Inform: ');

  doc.saveAndClose();

  folder.addFile(DriveApp.getFileById(doc.getId()));

  return doc.getId();
}

/**
 * When there is a change to the calendar, searches for events that include "#agenda"
 * in the decrisption.
 *
 */
function onCalendarChange() {
  // Gets recent events with the #agenda tag
  const now = new Date();
  const events = CalendarApp.getEvents(
      now,
      new Date(now.getTime() + 2 * 60 * 60 * 1000000),
      {search: '#agenda'},
  );

  const folderId = checkFolder();
  const templateId = getTemplateId(folderId);

  const folder = DriveApp.getFolderById(folderId);

  // Loops through any events found
  for (i = 0; i < events.length; i++) {
    const event = events[i];

    // Confirms whether the event has the #agenda tag
    let description = event.getDescription();
    if (description.search('#agenda') == -1) continue;

    // Only works with events created by the owner of this calendar
    if (event.isOwnedByMe()) {
      // Creates a new document from the template for an agenda for this event
      const newDoc = DriveApp.getFileById(templateId).makeCopy();
      newDoc.setName('Agenda for ' + event.getTitle());

      const file = DriveApp.getFileById(newDoc.getId());
      folder.addFile(file);

      const doc = DocumentApp.openById(newDoc.getId());
      const body = doc.getBody();

      // Fills in the template with information about the attendees from the
      // calendar event
      const conf = body.findText('##Attendees##');
      if (conf) {
        const ref = conf.getStartOffset();

        for (let i in event.getGuestList()) {
          let guest = event.getGuestList()[i];

          body.insertParagraph(ref + 2, guest.getEmail());
        }
        body.replaceText('##Attendees##', 'Attendees');
      }

      // Replaces the tag with a link to the agenda document
      const agendaUrl = 'https://docs.google.com/document/d/' + newDoc.getId();
      description = description.replace(
          '#agenda',
          '<a href=' + agendaUrl + '>Agenda Doc</a>',
      );
      event.setDescription(description);

      // Invites attendees to the Google doc so they automatically receive access to the agenda
      newDoc.addEditor(newDoc.getOwner());

      for (let i in event.getGuestList()) {
        let guest = event.getGuestList()[i];

        newDoc.addEditor(guest.getEmail());
      }
    }
  }
  return;
}

/**
 * Creates an event-driven trigger that fires whenever there's a change to the calendar.
 */
function setUp() {
  let email = Session.getActiveUser().getEmail();
  ScriptApp.newTrigger("onCalendarChange").forUserCalendar(email).onEventUpdated().create();
}

改造

サンプルは、必要に応じて何度でも編集できます。以下に、必要に応じて変更を加えることができます。

参加者のアジェンダ ドキュメントの権限を更新する

スクリプトにより、参加者に編集権限が付与されます。権限を表示のみに制限する場合は、コードの次の部分で addEditor メソッドを addViewer メソッドに置き換えます。

     for (let i in event.getGuestList()) {
       let guest = event.getGuestList()[i];

       newDoc.addEditor(guest.getEmail());

アジェンダ ドキュメントのテンプレートを編集する

アジェンダ ドキュメントのテンプレートを更新する方法は次のとおりです。

  1. カレンダーの予定に最初の予定リストを作成したら、Google ドライブを開きます。
  2. Agenda Maker - App というフォルダを開きます。
  3. Agenda TEMPLATE## ドキュメントを開き、編集します。

作成・変更者

このサンプルは、プロダクト管理およびプラットフォーム戦略コンサルタントの Jeremy Glassenberg によって作成されました。Jeremy を Twitter(@jGlassenberg)で見つけてください。

このサンプルは、Google Developer Experts の支援により Google によって管理されています。

次のステップ