登記參加會議

程式設計層級:新手
時間長度:5 分鐘
專案類型:透過自訂選單事件導向的觸發條件

目標

  • 瞭解解決方案的功能。
  • 瞭解 Apps Script 服務在 解決方案
  • 設定指令碼。
  • 執行指令碼。

認識這項解決方案

建立端對端活動報名系統。如果你舉辦了活動 你也可以為會議等新日曆設定新的會議日曆 建立報名表單,並自動傳送電子郵件給參加者 行程。

從試算表轉移至表單和日曆的資訊

運作方式

這項解決方案會使用 Google 試算表中的自訂選單,導入 事件註冊系統。指令碼會建立會議日曆 事件。接著,指令碼會 一份表單,內含活動參加者可報名的活動清單。參與者之後 填寫表單,指令碼會將參與者新增至日曆活動, 透過電子郵件將行程傳送給他們

Apps Script 服務

這項解決方案使用下列服務:

  • 試算表服務:提供 將活動資訊提供給其他服務。
  • 日曆服務:建立 新增活動日曆、將活動新增至日曆,以及新增與會者 使用者註冊的活動
  • 房源服務:儲存 日曆服務所建立日曆的 ID。當使用者 按一下自訂 [會議] 選單中的 [設定會議], 屬性服務會檢查事件登錄系統是否已 方法是檢查日曆 ID 屬性是否存在。這麼做很有幫助 避免建立重複的表單和日曆。
  • 表單服務:建立表單 透過試算表連結報名 工作階段。
  • 指令碼服務:建立會啟動的觸發條件 參與者填寫表單時。
  • 文件服務:取得事件 與會者報名的活動資訊,並加入一份 事件計入新文件指令碼會授權與會者進行編輯 文件。
  • Mail 服務:以電子郵件將行程文件傳送至 參與者。

必要條件

如要使用這個範例,您必須具備下列先決條件:

  • Google 帳戶 (Google Workspace 帳戶可能會 需要管理員核准)。
  • 可存取網際網路的網路瀏覽器。

設定指令碼

  1. 按一下下方按鈕,即可複製「建立註冊編號」 研討會範例試算表。Apps Script 這個解決方案的專案已附加至試算表。
    建立副本
  2. 依序按一下「會議」>「設定」 會議。您可能需要重新整理這個自訂選單的頁面,才能 顯示。
  3. 出現提示時,請授權指令碼。 如果 OAuth 同意畫面顯示「這個應用程式未經驗證」警告, 如要繼續,請選取「進階」圖示 > 前往 {Project Name} (不安全)

  4. 依序按一下「會議」>「設定」 會議

執行指令碼

  1. 依序點選「工具」>「管理表單」> 前往即時表單
  2. 填寫並提交表單。
  3. 前往 calendar.google.com
  4. 在左側確認已勾選「會議日曆」旁的方塊。
  5. 前往報名活動的日期,確認你已報名 。

(選用) 重設解決方案

如要繼續試用這項解決方案,或自訂解決方案 您必須重設先前設定的部分項目,才顯示您自己的事件資訊 輸入的程式碼如要查看重設解決方案的步驟,請按一下 請在下方重設解決方案

重設解決方案

步驟 1:重設已儲存的指令碼屬性

如果您多次嘗試執行指令碼,系統會顯示 會議已設定完成。在 Google 雲端硬碟中尋找報名表單! 這是因為會議日曆建立後,日曆 ID 就會是日曆 ID 會儲存為指令碼屬性指令碼執行時,會檢查 日曆 ID 屬性已存在,如果存在,就會停止執行。

如要移除現有的日曆 ID 屬性,請按照下列步驟操作:

  1. 按一下試算表中的「擴充功能」 >>「Apps Script」
  2. 在 Apps Script 編輯器中,從以下位置選取 resetProperties: 函式下拉式選單,然後點選「執行」

步驟 2:刪除會議日曆

每次執行指令碼時,都會建立新的日曆。如果您不想 保留建立的原始日曆,請按照下列步驟進行:

  1. 前往 calendar.google.com
  2. 按一下會議日曆旁邊的 [會議日曆的選項] > 設定和共用
  3. 捲動至設定底部,然後按一下「刪除」

步驟 3:刪除表單提交觸發條件

每次執行指令碼時,指令碼都會建立表單提交觸發條件。目的地: 避免因觸發多個觸發事件而產生重複電子郵件的觸發條件,請移除原始檔案 觸發。步驟如下:

  1. 按一下試算表中的「擴充功能」 >>「Apps Script」
  2. 在 Apps Script 專案中,按一下左側的「觸發條件」
  3. 按一下觸發條件旁邊的「更多」圖示 >「刪除觸發條件」

每次執行指令碼時,系統都會建立新表單。請按照以下步驟 取消表單與試算表的連結,然後予以刪除:

  1. 在試算表中,在「表單回覆」工作表上按一下滑鼠右鍵,然後按一下 取消表單連結 > 確定
  2. 再次在「表單回覆」工作表上按一下滑鼠右鍵,然後按一下「刪除」> 確定
  3. 前往 forms.google.com
  4. 在「會議表單」上按一下滑鼠右鍵,然後點選「移除」。 >「移至垃圾桶」>

重設解決方案後,您就可以自行新增資料,或是繼續 使用範例資料,然後再次執行指令碼。

查看程式碼

如要查看這個解決方案的 Apps Script 程式碼,請按一下 查看原始碼如下:

查看原始碼

Code.gs

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

/*
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.
*/

/**
 * Inserts a custom menu when the spreadsheet opens.
 */
function onOpen() {
  SpreadsheetApp.getUi().createMenu('Conference')
      .addItem('Set up conference', 'setUpConference_')
      .addToUi();
}

/**
 * Uses the conference data in the spreadsheet to create
 * Google Calendar events, a Google Form, and a trigger that allows the script
 * to react to form responses.
 */
function setUpConference_() {
  let scriptProperties = PropertiesService.getScriptProperties();
  if (scriptProperties.getProperty('calId')) {
    Browser.msgBox('Your conference is already set up. Look in Google Drive for your'
                   + ' sign-up form!');
                   return;
  }
  let ss = SpreadsheetApp.getActive();
  let sheet = ss.getSheetByName('Conference Setup');
  let range = sheet.getDataRange();
  let values = range.getValues();
  setUpCalendar_(values, range);
  setUpForm_(ss, values);
  ScriptApp.newTrigger('onFormSubmit').forSpreadsheet(ss).onFormSubmit()
      .create();
}

/**
 * Creates a Google Calendar with events for each conference session in the
 * spreadsheet, then writes the event IDs to the spreadsheet for future use.
 * @param {Array<string[]>} values Cell values for the spreadsheet range.
 * @param {Range} range A spreadsheet range that contains conference data.
 */
function setUpCalendar_(values, range) {
  let cal = CalendarApp.createCalendar('Conference Calendar');
  // Start at 1 to skip the header row.
  for (let i = 1; i < values.length; i++) {
    let session = values[i];
    let title = session[0];
    let start = joinDateAndTime_(session[1], session[2]);
    let end = joinDateAndTime_(session[1], session[3]);
    let options = {location: session[4], sendInvites: true};
    let event = cal.createEvent(title, start, end, options)
        .setGuestsCanSeeGuests(false);
    session[5] = event.getId();
  }
  range.setValues(values);

  // Stores the ID for the Calendar, which is needed to retrieve events by ID.
  let scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.setProperty('calId', cal.getId());
}

/**
 * Creates a single Date object from separate date and time cells.
 *
 * @param {Date} date A Date object from which to extract the date.
 * @param {Date} time A Date object from which to extract the time.
 * @return {Date} A Date object representing the combined date and time.
 */
function joinDateAndTime_(date, time) {
  date = new Date(date);
  date.setHours(time.getHours());
  date.setMinutes(time.getMinutes());
  return date;
}

/**
 * Creates a Google Form that allows respondents to select which conference
 * sessions they would like to attend, grouped by date and start time in the
 * caller's time zone.
 *
 * @param {Spreadsheet} ss The spreadsheet that contains the conference data.
 * @param {Array<String[]>} values Cell values for the spreadsheet range.
 */
function setUpForm_(ss, values) {
  // Group the sessions by date and time so that they can be passed to the form.
  let schedule = {};
  // Start at 1 to skip the header row.
  for (let i = 1; i < values.length; i++) {
    let session = values[i];
    let day = session[1].toLocaleDateString();
    let time = session[2].toLocaleTimeString();
    if (!schedule[day]) {
      schedule[day] = {};
    }
    if (!schedule[day][time]) {
      schedule[day][time] = [];
    }
    schedule[day][time].push(session[0]);
  }

  // Creates the form and adds a multiple-choice question for each timeslot.
  let form = FormApp.create('Conference Form');
  form.setDestination(FormApp.DestinationType.SPREADSHEET, ss.getId());
  form.addTextItem().setTitle('Name').setRequired(true);
  form.addTextItem().setTitle('Email').setRequired(true);
  Object.keys(schedule).forEach(function(day) {
    let header = form.addSectionHeaderItem().setTitle('Sessions for ' + day);
    Object.keys(schedule[day]).forEach(function(time) {
      let item = form.addMultipleChoiceItem().setTitle(time + ' ' + day)
          .setChoiceValues(schedule[day][time]);
    });
  });
}

/**
 * Sends out calendar invitations and a
 * personalized Google Docs itinerary after a user responds to the form.
 *
 * @param {Object} e The event parameter for form submission to a spreadsheet;
 *     see https://developers.google.com/apps-script/understanding_events
 */
function onFormSubmit(e) {
  let user = {name: e.namedValues['Name'][0], email: e.namedValues['Email'][0]};

  // Grab the session data again so that we can match it to the user's choices.
  let response = [];
  let values = SpreadsheetApp.getActive().getSheetByName('Conference Setup')
      .getDataRange().getValues();
  for (let i = 1; i < values.length; i++) {
    let session = values[i];
    let title = session[0];
    let day = session[1].toLocaleDateString();
    let time = session[2].toLocaleTimeString();
    let timeslot = time + ' ' + day;

    // For every selection in the response, find the matching timeslot and title
    // in the spreadsheet and add the session data to the response array.
    if (e.namedValues[timeslot] && e.namedValues[timeslot] == title) {
      response.push(session);
    }
  }
  sendInvites_(user, response);
  sendDoc_(user, response);
}

/**
 * Add the user as a guest for every session he or she selected.
 * @param {object} user An object that contains the user's name and email.
 * @param {Array<String[]>} response An array of data for the user's session choices.
 */
function sendInvites_(user, response) {
  let id = ScriptProperties.getProperty('calId');
  let cal = CalendarApp.getCalendarById(id);
  for (let i = 0; i < response.length; i++) {
    cal.getEventSeriesById(response[i][5]).addGuest(user.email);
  }
}

/**
 * Creates and shares a personalized Google Doc that shows the user's itinerary.
 * @param {object} user An object that contains the user's name and email.
 * @param {Array<string[]>} response An array of data for the user's session choices.
 */
function sendDoc_(user, response) {
  let doc = DocumentApp.create('Conference Itinerary for ' + user.name)
      .addEditor(user.email);
  let body = doc.getBody();
  let table = [['Session', 'Date', 'Time', 'Location']];
  for (let i = 0; i < response.length; i++) {
    table.push([response[i][0], response[i][1].toLocaleDateString(),
      response[i][2].toLocaleTimeString(), response[i][4]]);
  }
  body.insertParagraph(0, doc.getName())
      .setHeading(DocumentApp.ParagraphHeading.HEADING1);
  table = body.appendTable(table);
  table.getRow(0).editAsText().setBold(true);
  doc.saveAndClose();

  // Emails a link to the Doc as well as a PDF copy.
  MailApp.sendEmail({
    to: user.email,
    subject: doc.getName(),
    body: 'Thanks for registering! Here\'s your itinerary: ' + doc.getUrl(),
    attachments: doc.getAs(MimeType.PDF),
  });
}

/**
 * Removes the calId script property so that the 'setUpConference_()' can be run again.
 */
function resetProperties(){
  let scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.deleteAllProperties();
}

貢獻者

這個範例是由 Google 在 Google Developers 專家的協助下維護。

後續步驟