很多时候我们会需要搜集些不同的资料。像是 Marketing 在做大规模但针对不同组织的调查问卷。如果只是三份、五份的问卷要做客制化、统整算还好;但如果是一百份、甚至上千份时,总不能一个个复制了吧。此时就会遇到个问题——
因为篇幅关系,这边会分成三篇来写,第一篇与第二篇回应第一题;第三篇回应第二题。但一样先讲结论,如果你很急着用,可以直接使用这份 Add-On: Form Publisher,功能非常强大。自己写的好处是,如果你一天突然要做些客制化,那就可以持续阅读阅读此篇,那让我们开始吧!
答案会在今天的文章中!
复制表单有两种方式。一种是比较简单的「复制范本」,简单来说就是针对一个表单复制,然後再行更改其中的元素。第二种是「从零制作」,这种就比较复杂,因为会是透过 GAS 完整制作表单,会需要比较熟悉 GAS。我们今天会先讲方式一,方式二会在明天讲。
等等,不是要讲 Google Form 吗,怎麽又是先开启 Google Sheet?那是因为我们想要开很多个创客制化表单的话,总要先有个表先设定说,需要设定哪些参数,而这就是 Google Sheet 派上场的地方。方式一我们先简单地示范如何复制并客制表单表单,简单的会用下图左侧绿色的参数,来生成右侧橙色的参数。白话文就是,我期待在创造完後後它会告诉我各表单的连结。
好,那因为我们要用到 Google Sheet ,所以一样用其作为开启的管道。一样借用 D8 的影片。
一样执行时会有「需要验证」出现,借用一下 D2 的影片:Google Apps Script (GAS) 的环境设定、专案结构(Trigger)与四种打包方式。
这边我们就直接取得 ID,那可以在 GAS 的後台用直接设定参数,也可以像这样写在 Google Sheet 上。考量到有些人会用不同的范本来生成表单,这边就直接写在 Google Sheet 上。
完整取得 ID 的方式在 D9 有详细的介绍可参考:如何用 Google Apps Script 自动化对 Google Drive 的操作?(一)列出所有档案 ID 与相关资讯
那我们之前从 D4 (如何透过 Google Apps Script 来整合 Google Form / Google Sheet 并自动寄出客制的 Email?)起介绍的抓「栏数」与「列数」,都是直接设定好要抓多少行与列,今天介绍比较弹性地设定的两个手法:
getLastRow()
:抓出表单中最下面有数值的「那一列」getLastColumn()
:抓出表单中最右侧有数值的「那一栏」。所以以我们的范围来说,就会是「列」抓到第 10 列,「行」抓到第 4(D) 行。但,如果我们要搭配之前常用的 getRange(start_row, start_col, numRows, numCols)
来取得范围的话,我们会需要将 numRows
和 numCols
写成——
let numRows = sheet.getLastRow() - start_row +1;
let numCols = sheet.getLastColumn() - start_col +1;
之所以最後还要有一个 +1
,原因是因为如果一开始的 start_row
和 start_col
本身也要算进去,如果单纯用最後一栏有资料的 index 值去减掉最一开始的 index 值,那跟我们想要的结果就会差了 1 如下图。这也是我们最一开始题目的答案。
所以完整的读档程序码长这样——
function readData(){
let ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getActiveSheet();
let start_row = 3;
let start_col = 1;
let numRows = sheet.getLastRow() - start_row +1;
let numCols = sheet.getLastColumn() - start_col +1;
let values = sheet.getRange(start_row,start_col,numRows,numCols).getValues();
Logger.log(values)
return values;
}
跑起来长这样——
读出来後会以 Array in array 的形式操作,我们待会会直接进入操作,想补概念可以回到 D4 ~
makeCopy()
复制好的,那我们现在将 Google Sheet 中的资料读到 GAS 当中後,我们要依据 ID 抓出档案并将其复制。我们先来快速看一下 makeCopy(name, destination)
怎麽用。
function copyForm(){
let target_id = template_id;
let form_file = DriveApp.getFileById(target_id);
let new_form_Id = form_file.makeCopy("D11 Test").getId()
Logger.log(new_form_Id)
}
跑起来会长这样——
补充的是,在上面的程序码中,我们用的是 makeCopy(name)
,也就是只填一个参数的话,那个参数就会是新档案的名称。如果填入两个,就会是 makeCopy(name, destination)
,也就是目的地的位置(要是个 folder object,需要用 DriveApp.getFolderById()
等方式来取得。那如果我们用的是没有参数,也就是直接输入 makeCopy()
的话,就会是在原地用预设的名称复制(通常会是「____的副本」或「Copy of ____」)
好,那我们复制完档案後,它现在仍是个一模一样的表单,我们要怎麽样放入客制的部分?这就到了 FormApp
的主场了。
FormApp()
的功能改写好,那将这 makeCopy
和 Step 3 整合起来,就会变成下列这段程序码。
function copyForm(){
let target_id = template_id;
let form_file = DriveApp.getFileById(target_id);
let new_form_Id = form_file.makeCopy("D11 Test").getId()
let new_form = FormApp.openById(new_form_Id);
new_form.setDescription('Hello, new form!')
.setConfirmationMessage('Thanks for responding!')
.setAcceptingResponses(false);
}
这边主要是对 form
Object 进行操作,就简单地运以下三个功能。
setAcceptingResponses()
)跑起来长这样——
整个 FormApp()
也正是「如何操作」 Google Form 的精髓所在,明天我们会大版面介绍如何完整使用其中的功能们。好,那这样我们接着就要整合 Step 3 的读取资料,和 Step 4 与 Step 5 了。
而完整整合起来会长这样。
function copyForm(){
let full_table_data = readData();
for (row_data of full_table_data){
let target_id = row_data[0];
let form_file = DriveApp.getFileById(target_id);
let new_form_name = row_data[1];
let new_form_Id = form_file.makeCopy(new_form_name).getId()
let new_form_description = row_data[2];
let new_form = FormApp.openById(new_form_Id);
new_form.setDescription(new_form_description)
.setConfirmationMessage('Thanks for responding!')
.setAcceptingResponses(false);
}
}
让我们来试跑看看——
好,那我们最後当然会希望能追踪我们所产生的表单,这就到了 Step 7 的写入表单。
那一样搭配我们从 D8( 如何用 Google Apps Script 将 Google Calendar 上的事件与更新全部列出到 Google Sheet 上?)开始每天见面的老朋友 writeData()
将 ID 写回 Google Sheet。
function writeData(data){
let starting_row = 3;
let starting_col = 4;
let num_row = data.length;
let num_col = data[0].length;
let sheet = SpreadsheetApp.getActiveSheet();
let range = sheet.getRange(starting_row,
starting_col, num_row, num_col);
range.setValues(data);
}
并将其与 copyForm()
结合即可。
function copyForm(){
let full_table_data = readData();
let new_form_id_arr = []
for (row_data of full_table_data){
let target_id = row_data[0];
let form_file = DriveApp.getFileById(target_id);
let new_form_name = row_data[1];
let new_form_Id = form_file.makeCopy(new_form_name).getId()
let new_form_description = row_data[2];
let new_form = FormApp.openById(new_form_Id);
new_form.setDescription(new_form_description)
.setConfirmationMessage('Thanks for responding!')
.setAcceptingResponses(false);
new_form_id_arr.push([new_form_Id]);
}
writeData(new_form_id_arr)
}
最後结果会长这样——
今天主要讲了下列功能:
getLastRow()
和 getLastColumn()
makeCopy()
的细节使用差异FormApp
来基础地调整表单的内容好,那看完今天的教学,至少知道如何将 Google 复制并调整基本的元素了(撒花)
好,那基本上我们就搞定了。但如果今天我们是想要高度客制化的表单怎麽办?像是不同人要设定不同的照片,甚至是有些人不要某些题目怎麽办?那就会到我们的方法二。也就是明天的主题。
一样提醒,用FormApp.create()
来创造表单是有 Quota 限制——每天不超过 250 份。如果还有问题,透过留言之外,也可以到 Facebook Group,想开很久这次铁人赛才真的开起来哈哈哈,欢迎来当 Founding Member。如果不想错过可以订阅按赞小铃铛(?),也欢迎留言跟我说你还想知道什麽做法/主题。我们明天见。
虽然昨天已经介绍了如何在你的网页中实作 Color System,但严格上来说今天才算是这系列第一...
ifconfig命令是设置或显示网络接口的程序,可以显示出我们机器的网卡信息, 可是有些时候最小化安...
你以为JS拿来就乖乖照着我们打的一行一行跑吗?太天真了,我说我~~ 变数怎麽存,存哪里,在哪里叫得到...
《30天带你上完 Google Data Analytics Certificate 课程》系列将...
Background 在前後端分离的专案维护一份完整且及时更新的api文件会极大的提高我们的工作效率...