编码级别:初级
时长:5 分钟
项目类型:使用自定义菜单和
事件驱动的触发器
目标
- 了解此解决方案的用途。
- 了解 Apps 脚本服务在
解决方案。
- 设置脚本。
- 运行脚本。
关于此解决方案
建立端到端的活动登记系统。如果您有活动
例如会议,您可以为会议创建新日历
创建报名表单,并自动向参加者发送电子邮件,
行程安排。
![将 Google 表格中的信息转移到 Google 表单和日历](https://developers.google.cn/static/apps-script/samples/images/event-signup.jpeg?authuser=5&hl=sl)
工作原理
此解决方案使用 Google 表格中的自定义菜单来实现自动化
活动注册系统。脚本将创建一个包含会议的日历
Google 表格电子表格中列出的事件。然后,该脚本会创建
一个表单,列出参加者可以报名参加的活动。参加者之后
填写完表单后,脚本会将参加者添加到日历活动,
通过电子邮件将行程发送给他们
Apps 脚本服务
此解决方案使用以下服务:
- 电子表格服务 - 提供
向其他服务发送事件信息
- 日历服务 - 创建
为活动创建新日历、向日历中添加活动以及添加参加者
与自己报名参加的活动密切相关
- 房源服务 - 存储
日历服务创建的日历的 ID。当用户
点击自定义会议菜单中的设置会议,
Properties 服务会检查事件注册系统是否
通过检查日历 ID 属性是否存在进行设置。这样做很有帮助
避免创建重复的表单和日历。
- 表单服务 - 创建表单
从允许参加者注册
会话。
- 脚本服务 - 创建可触发的触发器
当参加者填写表单时触发。
- 文档服务 - 获取事件
参加者报名参加的活动的相关信息,并添加参加者列表
复制到一个新文档脚本向参加者授予编辑权限
文档。
- 邮件服务 - 通过电子邮件将行程文档发送至
参加者。
前提条件
如需使用此示例,您需要满足以下前提条件:
- Google 账号(Google Workspace 账号可能
需要管理员批准)。
- 可以访问互联网的网络浏览器。
设置脚本
- 点击以下按钮,复制创建
会议中的会议示例电子表格。Apps 脚本
已附加到该电子表格中。
复制
- 点击会议 > 设置
会议。您可能需要刷新此自定义菜单的页面
。
出现提示时,为脚本授权。
如果 OAuth 同意屏幕显示以下警告:“此应用未经验证”,
选择高级 > 以继续
前往“{Project Name}”(不安全)。
点击会议 > 设置
会议。
运行脚本
- 点击 Tools > Manage Form
> 转到实时表单。
- 填写并提交表单。
- 前往 calendar.google.com。
- 在左侧,确保会议日历旁边的复选框处于选中状态。
- 查看你报名参加活动的日期,并确认你已加入
以参加者身份加入
(可选)重置解决方案
如果您想再次尝试此解决方案,或对其进行自定义以便使用
您需要重置一些已设置的项目
。如需查看重置解决方案的步骤,请点击
按下面的步骤重置解决方案:
重置解决方案
第 1 步:重置存储的脚本属性
如果您尝试多次运行该脚本,系统将显示您的
已经设置好了。请在 Google 云端硬盘中查找您的注册表单!
这是因为创建会议日历后,日历 ID
存储为脚本属性。该脚本在运行时会检查
日历 ID 属性已存在,如果存在,则会停止运行。
请按照以下步骤移除现有的日历 ID 属性:
- 在电子表格中,点击附加信息
> Apps 脚本。
- 在 Apps 脚本编辑器中,选择
resetProperties
函数下拉列表,然后点击运行。
第 2 步:删除会议日历
每次该脚本运行时,都会创建一个新日历。如果您不想
保留创建的原始日历,请按照以下步骤操作:
- 前往 calendar.google.com。
- 点击“会议日历”旁边的“会议日历选项”
>
设置和共享。
- 滚动到设置的底部,然后点击删除。
每次运行该脚本时,该脚本都会为表单提交创建一个触发器。接收者
避免多个触发器导致重复发送电子邮件,移除原始邮件
触发。请按以下步骤操作:
- 在电子表格中,点击附加信息
> Apps 脚本。
- 在 Apps 脚本项目中,点击左侧的触发器
。
- 点击触发器旁边的“更多”图标
> 删除触发器。
每次运行该脚本时,它都会创建一个新表单。请按以下步骤操作
取消表单与电子表格的关联并将其删除:
- 在电子表格中,右键点击表单回复工作表,然后点击
取消关联表单 > 确定。
- 再次点击表单回复工作表,然后点击删除。
> 确定。
- 前往 forms.google.com。
- 右键点击会议表单,然后点击移除
> 移至回收站。
重置解决方案后,您可以添加自己的数据,也可以继续
请使用示例数据,然后再次运行脚本。
查看代码
如需查看此解决方案的 Apps 脚本代码,请点击
下面查看源代码:
查看源代码
Code.gs
// 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 开发者专家的帮助下进行维护。
后续步骤