2015年5月24日

[教學] 讓新版 Google 表單(試算表)能自動寄信﹍(2) 安裝程式碼

A+
google-spreadsheet-auto-send-email以下接續「第一篇」的步驟。



google-spreadsheet-auto-send-email-1

在試算表的畫面,按「工具」→「指令碼編輯器」


google-spreadsheet-auto-send-email-2

圖中紅框原本的程式碼請全部清除,置換為本文的安裝程式碼。



三、安裝程式碼



如果要修改參數的話,請參照以上程式碼行號。

B:紅色字串請務必改為自己的 email 地址

C:此行字串可改為自訂標題

D:如果你的 Google 表單供填寫 email 的項目名稱就是 "email",此項不必變動

E:每個 Google 帳號每日可寄信的額度為 100 封,可設定剩下多少額度時通知自己。

這個工具預設為寄信給填表者,如果要改為只通知自己的話,請將 W 行的 notifyEmail 置換為 adminEmail,那麼我們不必進入試算表,就能即時看到所有的填寫資訊,也是相當方便的功能。



四、設定寄信觸發程序


google-spreadsheet-auto-send-email-3

程式碼設定完畢後,如上圖,先按 A 處的圖示儲存,再按「資源」→「現有專案的啟動程序」,來設定觸發程序。


google-spreadsheet-auto-send-email-4

按下紅框的字串


google-spreadsheet-auto-send-email-5

按 A~C 的順序,依序調整為圖中的選項,便能在填寫者提交表單時,立即送出 email 通知。

最後按下「儲存」。


google-spreadsheet-auto-send-email-6

寄信功能會要求授權,應該會彈出上圖訊息,按下「繼續」,並依照後續畫面指示,完成授權動作即可。

過去曾有讀者表示,授權畫面不會出現,最後搞了很久才找出原因,原來是瀏覽器安裝了「擋廣告」之類的外掛。建議讀者不要安裝各種擋廣告的外掛,否則很多網頁異常的狀況會讓你花更多時間 debug,卻又找不出原因來。



五、測試自動寄信功能


google-spreadsheet-auto-send-email-7

回到試算表主畫面,我們來試試看能否自動寄信。如上圖按「表單」→「查看即時表單」,自行填寫表單測試。


google-spreadsheet-auto-send-email-8

隨意填寫,按「提交」送出資料。


google-spreadsheet-auto-send-email-9

回到試算表,立即看到新增的一筆資料,請看紅色底線標註的時間點。

如果有安裝「Checker Plus for Gmail™」這類的瀏覽器外掛,其實沒幾秒就會收到信件通知了。


google-spreadsheet-auto-send-email-10

檢視一下 Gmail 的畫面,果然馬上就收到了表單填寫通知。而且無論表單設計了幾個項目,這個工具都會取出所有項目及填寫資料,並在通知信件中列出,可說非常的實用!


2016.1.2 公告:本篇的寄信功能近來很多讀者留言尋求協助,由於本站的主題及業務為 Blogger 相關,目前無暇分身協助處理 Google 試算表的問題。若操作上遇到困難,請直接參考「六、常見 FAQ」、或其他讀者留言的案例處理。如果仍無法處理、有商業用途需要立即解決使用上的問題,那麼請付費交換 WFU 的時間,來幫您檢視 Google 試算表哪裡出了問題,請使用下面的表單與我聯繫。

聯絡表單:




六、常見 FAQ


日後若有常見問題,會持續補充在此。

Q1: 依照上面的方式後,跳出運算子之後遺漏名稱。 (第 1 行,檔案名稱:程式碼) -- 就無法繼續第四項之後的功能耶,是那裡有問題嗎?

Ans: 根據你提供的錯誤訊息測試了一下,應該是使用了非主流的瀏覽器,複製的的程式碼包含了行號 A、B、C...,這樣程式是無法執行的。請使用本站建議的瀏覽器 Chrome、Firefox、Opera 等複製程式碼,就沒問題了。


Q2: 留言 #12 詢問,貼上後執行,他跑出錯誤 TypeError: 無法讀取 undefined 的「namedValues」屬性。 (第 2 行,檔案名稱:)

Ans: 想要測試程式碼有無問題,請不要直接執行,必定會出現這些訊息。需要測試的話,請直接填寫表單,程式會自動執行,就可知道效果了。


Q3: 只需要寄信給自己的作法?

Ans: 如果只需要寄信給自己,不需要安裝這個工具,留言 #4 提供了寄信給自己的步驟:
  1. 點選「工具」
  2. 點選「通知規則」
  3. 新增通知規則
  4. 選擇「使用者提供表格
  5. 下方選擇電子郵件「 立即」


Q4: 留言 #14 詢問,為何沒有收到通知?

Ans: 這個工具的設計,是寄信給填表者。如果你只需要寄信給自己的話,那麼不需要安裝這個工具,請參考 Q3 的操作步驟即可。

補充一下,這個工具雖可填入自己 email 來通知自己,但通知的時機是 google 帳號的寄信額度超過的時候,系統才會寄給自己提醒訊息。如果一開始製作的試算表,沒有包含讓填表者填寫的 email 欄位,那麼程式碼 D 行在抓不到 email 欄位的情況下,執行到 I 行時程式就會當掉了。


更多 Google 試算表工具:

53 則留言:

  1. 這程式碼較我先前看過的簡短許多,而且可直接設定要收信的mail,不用多一道工
    感謝分享^^

    回覆刪除
    回覆
    1. 我也要來把過去裝 formemail 的表單都改成新的程式碼,不小的工程~~XD

      刪除
    2. Wayne的應該很多吧XD還好我現在只有兩個預約表
      不過,不換會有差嗎?新的跟舊的有其他差異嗎?

      刪除
    3. 舊的功能比較多, 已經裝了就沒必要改,怕你 code 不熟到時改壞了~ XD
      差異請見第一篇「一、自動寄信方案的抉擇」

      刪除
    4. okok瞭解了!看來我的應該暫時選擇不改(沒那麼多信,也避免出錯XDDD)

      刪除
  2. 版大好 我可以自動寄信了
    但是 我的問題是
    傳送到mail的問題順去亂跑
    一下Q1 一下Q5 並不是按照順去下來的
    請問該如何處理
    煩請版大指教

    回覆刪除
    回覆
    1. 已經修改了部分程式碼,請刪除原程式碼,重新安裝即可,現在可以按順序出現了。

      刪除
  3. 作者已經移除這則留言。

    回覆刪除
  4. Wayne 您好,很感謝您在網路上分享blogger 的訊息,今天剛好瀏覽到您這篇(自動寄信)的文章,想跟您分享試算表自己內建便有新增資料就自動寄信的功能,步驟如下:

    1.點選「工具」
    2.點選「通知規則」
    3.新增通知規則
    4.選擇「使用者提供表格
    5.下方選擇電子郵件「 立即」

    如此一來便可以即時收到使用者的表單,並且應該能減少建立新function的資源浪費
    提供給您參考:)

    回覆刪除
    回覆
    1. 謝謝您提供的技巧,對於寄信給自己的通知,這的確是比較方便的作法。

      本文提供的程式,主要是寄信給填表者。

      刪除
  5. 請問 我的表單寄出正常
    但是 收到的內容卻 重複好幾次
    是哪裡出錯了???

    回覆刪除
    回覆
    1. 程式碼有更新過,也許你重作表單、重新安裝看看。

      另外就是,看看你編輯表單時,是否有刪除題目、又重新新增同樣的題目過?

      刪除
    2. 您好!! 還是一樣跳出來很多遍

      程式碼 是直接複製您登入會員 才看得道的那個
      請問 難道不對嗎!?!?

      刪除
    3. 不好意思,從您目前提供的這些訊息,我無法猜出發生什麼狀況...

      刪除
    4. 我也遇到相同問題.重新製作一個新的表單也一樣....

      刪除
    5. 我無法猜出什麼情況下會發生這樣的問題,會收到重複內容的讀者,請把該表單的的共用權限分享給我的帳號 waynefu.g@gmail.com , 並設定給我全部的權限, 來看看是什麼問題。

      刪除
  6. 抱歉 我試了一下
    一直沒再寄一封到另一個信箱
    後來選擇偵錯
    TypeError: 無法讀取 undefined 的「namedValues」屬性。 (第 2 行,檔案名稱:程式碼)

    應該是自己填mail那一行
    請問是哪邊錯誤了 感謝

    回覆刪除
    回覆
    1. 不好意思,以上提供的這些訊息,無法猜出發生什麼狀況...

      刪除
  7. 您好,參考了最新的文章,想請問要怎麼修改信件內容呢?另外他有辦法在提交表單時也cc給自己一份嗎?謝謝

    回覆刪除
    回覆
    1. >> 有辦法在提交表單時也cc給自己一份嗎?
      可以參考留言 #4 的方法

      >> 請問要怎麼修改信件內容呢?
      你要把信件內容改成什麼樣子?

      刪除
    2. 您好,感謝回覆。希望可以再加上一些訊息及圖片,是在k行的『html = "",』這邊寫上html語法嗎?謝謝

      刪除
    3. 1. 如果你熟悉 html 語法
      2. js 語法裡面的單、雙引號能夠交替使用正確
      3. 要加入的額外訊息是放在所有資料之前

      符合以上 3 點的話,如你所說的,可放在 k 行你說的地方。

      如果要加入的訊息在所有資料之後,那麼可放在 U 行,插入以下內容:

      html += "額外訊息 html 碼";

      刪除
    4. 謝謝回覆。不好意思想再詢問,要如何才能指定發給某一行的人呢?謝謝

      刪除
    5. 從你的案子來看,客製要求不少,已超過學術討論的範圍,建議直接循 http://www.wfublog.com/2013/06/service-suggest-cooperation.html →「客製諮詢」的管道,寫客製程式處理。

      刪除
  8. 您好,. 依照上面的方式後,跳出運算子之後遺漏名稱。 (第 1 行,檔案名稱:程式碼) -- 就無法繼續第四項之後的功能耶,是那裡有問題嗎?

    回覆刪除
    回覆
    1. 你好,請見「六、常見 FAQ」→ Q1 的回覆。

      刪除
  9. 你好,我沒有看到你提供的程式碼耶,請問可以在這裡提供給我嗎,謝謝。

    回覆刪除
    回覆
    1. 你好,請先按指示加入會員

      刪除
  10. 你好 我想於內容添加網址 請問程式碼要怎麼打呢?

    回覆刪除
  11. 請問 我的表單寄出正常
    但是 收到的內容卻 重複好幾次 只要表單需要輸入文字的欄位或是選項沒有選的那一項就會一直重複
    7-11店名及店號共6碼 和 巧克力杏仁酥餅 沒有填寫 就一直重複出現 要如何解決呢? 謝謝你~


    時間戳記:2015/11/7 下午 3:00:28
    原味奶油酥餅 NT.70 每一包100公克 (奶素):原味奶油酥餅1包---70元

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:
    取貨方式:台中市面交(免運費) 地點私訊

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:
    姓名:XXX
    電話:91234567
    E-mail電子信箱:********@hotmail.com
    備註:哈囉

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    巧克力杏仁酥餅 NT.80 每一包100公克 (奶素):
    7-11店名及店號共6碼 (請記得填寫):
    未命名的問題:

    回覆刪除
    回覆
    1. 前面也有好幾位發生同樣的狀況,但沒有任何資訊可判斷是什麼情形,謝謝你提供了描述詳細的錯誤回報,這樣我知道是什麼原因了 → 在填表者沒輸入資料的情況下,導致程式無法判斷該筆資料應屬於那個欄位,所以空白欄位才會重複印出。

      現在我已經修正了程式,做了防呆機制,請重新安裝程式,就可解決這個問題了!

      刪除
  12. 哈囉 我今天是著貼上後執行,他跑出錯誤

    TypeError: 無法讀取 undefined 的「namedValues」屬性。 (第 2 行,檔案名稱:)

    namedValues 是甚麼需要改過嗎?

    回覆刪除
    回覆
    1. 請參照「六、常見 FAQ」→ Q2 的回答。

      刪除
  13. 你好我照上面改後出現一樣的問題
    TypeError: 無法讀取 undefined 的「namedValues」屬性。 (第 12 行,檔案名稱:程式碼)
    可以幫看看因該要怎麼修嗎
    function autoNotify(data) {
    var adminEmail = "chenny841102@gmail.com"
    subject = "食糖訂購通知",
    emailTitle = "email",
    quotaLimit = 10,
    namedValues = data.namedValues,
    values = data.values,
    l = values.length,
    notifyEmail = namedValues[emailTitle][0],
    quota = MailApp.getRemainingDailyQuota(),
    html = "",
    i, j;

    for (i = 0; i < l; i++) {
    for (j in namedValues) {
    if (values[i] == namedValues[j][0]) {
    html += j + ":" + namedValues[j][0] + "
    ";
    delete namedValues[j];
    }
    }
    }
    MailApp.sendEmail({
    to: notifyEmail,
    subject: subject,
    htmlBody: html
    });
    if (quota == (quotaLimit + 2)) {
    MailApp.sendEmail({
    to: adminEmail,
    subject: subject,
    body: "今日 Google 表單寄信額度剩下 " + quotaLimit + "封"
    });
    }
    }

    回覆刪除
    回覆
    1. 你好, 請參照安裝程式碼 B 行,包住 email 字串的雙引號後面,需要有一個小寫逗號 "," 喔!

      刪除
  14. 您好:我已經照文章的順序進行了一次,但都沒有收到通知是甚麼原因呢?

    回覆刪除
    回覆
    1. 不好意思,從您提供的訊息,無法猜出發生什麼狀況。您可參考其他留言,想辦法提供更多訊息給我,比較有機會判斷是什麼狀況。

      刪除
    2. 您好:以下是我製作的表單https://docs.google.com/forms/d/146Bwsr0zPdU2fsafJmj-rXtkMtF78zJ6oKZJXoeefC8/viewform?formkey=dHhmLTZqTldSbkVmX1NJRVBaRmFCcmc6MQ

      以下是程式碼:
      function autoNotify(data) {
      var adminEmail = "musictrashcan@gmail.com", // 通知自己的系統訊息
      subject = "Google 表單自動通知-美容保健科專業教室借用系統", // 信件標題
      emailTitle = "email", // 表單中收件者 email 這個項目的標題
      quotaLimit = 10, // 每天寄信額度剩下 10 封時, 通知自己
      namedValues = data.namedValues,
      values = data.values,
      l = values.length,
      notifyEmail = namedValues[emailTitle][0],
      quota = MailApp.getRemainingDailyQuota(),
      html = "",
      i, j;

      for (i = 0; i < l; i++) {
      for (j in namedValues) {
      if (values[i] == namedValues[j][0]) {
      html += j + ":" + namedValues[j][0] + "
      ";
      delete namedValues[j];
      }
      }
      }
      MailApp.sendEmail({
      to: adminEmail,
      subject: subject,
      htmlBody: html
      });
      if (quota == (quotaLimit + 2)) {
      MailApp.sendEmail({
      to: adminEmail,
      subject: subject,
      body: "今日 Google 表單寄信額度剩下 " + quotaLimit + "封"
      });
      }
      }

      然後這是今天我收到的google 錯誤訊息

      Your script, 美保科專業教室借用系統回覆, has recently failed to finish successfully. A summary of the failure(s) is shown below. To configure the triggers for this script, or change your setting for receiving future failure notifications, click here.

      The script is used by the document 美容保健科專業教室借用與儀器使用登記表.

      Summary:

      Error Message Count
      TypeError: 無法讀取 undefined 的「0」屬性。 (line 2, file "程式碼") 4
      Details:

      Start Function Error Message Trigger End
      12/10/15 4:34 PM autoNotify TypeError: 無法讀取 undefined 的「0」屬性。 (line 2, file "程式碼") formSubmit 12/10/15 4:34 PM
      12/10/15 4:38 PM autoNotify TypeError: 無法讀取 undefined 的「0」屬性。 (line 2, file "程式碼") formSubmit 12/10/15 4:38 PM
      12/10/15 5:15 PM autoNotify TypeError: 無法讀取 undefined 的「0」屬性。 (line 2, file "程式碼") formSubmit 12/10/15 5:15 PM
      12/11/15 9:47 AM autoNotify TypeError: 無法讀取 undefined 的「0」屬性。 (line 2, file "程式碼") formSubmit 12/11/15 9:47 AM
      Sincerely,

      Google Apps Script

      Need help? Visit the Google Apps Script documentation. Please do not reply to this message. (c) 2015 Google

      再麻煩您~~謝謝

      刪除
    3. 從製作的表單來看,發現並沒有設定 "email" 這個欄位,因此我想你的用意只是寄信給自己而已,而不是寄給填表人。可參考第一篇「製作表單格式」→「二、製作新版 Google 表單」,有介紹適合這個工具的使用情境。

      如果只需要通知自己的話,請參考「六、常見 FAQ」→ Q3 的步驟即可,可不用安裝這個工具。

      另外,為何會出現這些錯誤訊息,已經整理到 Q4 了,請參閱。

      刪除
  15. 回覆
    1. 請先比對一下安裝程式碼,我看到第一個字母少了 f 喔

      刪除
    2. 抱歉,因為內文PO錯 所以刪除 ,更正在#16

      刪除
  16. waynefu.g@gmail.com

    我可以分享授權 麻煩您幫我一下嗎?感恩

    回覆刪除
    回覆
    1. 不好意思,請參考 http://www.wfublog.com/2014/08/where-ask-blogger-question-skill.html ,WFU BLOG 不鼓勵在留言 #15 問題問完得到答案後,又自刪留言的舉動。

      刪除


    2. 抱歉,因為內文PO錯,所以 刪除掉,不知道違規惹,

      以下是更正後的版本,設定都有走到,也走到最後一步。但是 還是無法自動收到信件,請問
      我哪邊出錯了,謝謝您。


      function autoNotify(data) {
      var adminEmail = "tt@gmail.com",
      subject = " 表單自動通知",
      emailTitle = "email",
      quotaLimit = 10,
      namedValues = data.namedValues,
      values = data.values,
      l = values.length,
      notifyEmail = namedValues[emailTitle][0],
      quota = MailApp.getRemainingDailyQuota(),
      html = "",
      i, j;

      for (i = 0; i < l; i++) {
      for (j in namedValues) {
      if (values[i] == namedValues[j][0]) {
      html += j + ":" + namedValues[j][0] + "
      ";
      delete namedValues[j];
      }
      }
      }
      MailApp.sendEmail({
      to: notifyEmail,
      subject: subject,
      htmlBody: html
      });
      if (quota == (quotaLimit + 2)) {
      MailApp.sendEmail({
      to: adminEmail,
      subject: subject,
      body: "今日 Google 表單寄信額度剩下 " + quotaLimit + "封"
      });
      }
      }

      刪除
    3. 你的情形與留言 #14 雷同,可先參考該則留言的回覆進行檢驗。

      刪除
  17. 不好意思我有先做功課
    把所有留言都看完
    但還是無法找出我的錯誤
    所以想請您指導一下

    以下是我的表單連結
    https://docs.google.com/forms/d/1UiYFH_kYdP-uoGsQxc01erkhJF_o-0bAND37stvGQmY/viewform

    程式碼如下
    function autoNotify(data) {
    var adminEmail = "ladeesse928@gmail.com",
    subject = "La D'eesse 甜點訂單通知",
    emailTitle = "Email",
    quotaLimit = 10,
    namedValues = data.namedValues,
    values = data.values,
    l = values.length,
    notifyEmail = namedValues[emailTitle][0],
    quota = MailApp.getRemainingDailyQuota(),
    html = "",
    i, j;

    for (i = 0; i < l; i++) {
    for (j in namedValues) {
    if (values[i] == namedValues[j][0]) {
    html += j + ":" + namedValues[j][0] + "
    ";
    delete namedValues[j];
    }
    }
    }
    MailApp.sendEmail({
    to: notifyEmail,
    subject: subject,
    htmlBody: html
    });
    if (quota == (quotaLimit + 2)) {
    MailApp.sendEmail({
    to: adminEmail,
    subject: subject,
    body: "今日 Google 表單寄信額度剩下 " + quotaLimit + "封"
    });
    }
    }

    我測試了好幾次
    我的表單有E-mail的欄位
    怎麼填寫者還是收不到通知信
    實在找不出問題
    不好意思麻煩你了
    謝謝喔

    回覆刪除
    回覆
    1. 不好意思,請看「2016.1.2 公告」,您的網站屬於商業用途,請用聯絡表單與我聯繫。

      刪除
  18. /* Gogole Form 專用發送EMail程序 */
    function sendMails(e) {
    // 取得使用者送出的資料(陣列)
    var currentItemResponses = e.response.getItemResponses();
    // 注意,每一筆array entry用來表示每個表單的問題與答案。
    // 在本範例中,第一個entry是姓名(index 0),第二個entry是EMail (index 1)。
    // 我們使用getItem可以獲得提問的問題選項物件,getResponse則是取得該問題的輸入答案。
    // 例如index 0的提問選項為「使用者姓名」,而輸入的答案為「Allen」。則可以用以下語法獲得所需資料。
    // Logger.log("Question %s = %s", currentItemResponses[0].getItem().getTitle(), currentItemResponses[0].getResponse());

    // 取得姓名輸入資料
    var userName = currentItemResponses[0].getResponse();
    // 取得EMail輸入資料
    var userEMail = currentItemResponses[1].getResponse();

    /* 設定寄件內容,Mail.App.sendEMail()這個函式,
    第一個參數為「EMail位址」,第二個參數為「標題」,第三個參數為「內容」。
    以這個範例而言,我設定標題為 "表單測試: 使用者名稱",內容為"姓名:xxx submitted by Allen"
    */

    MailApp.sendEmail(userEMail, "【午茶小聚x旅遊講座x舊城導覽】"+ userName,
    "親愛的" + userName + ":\n您已成功報名\n\n敬請匯款至:\n銀行:合作金庫銀行(006)\n ");

    }

    TypeError: 無法讀取 undefined 的「response」屬性。 (第 4 行,檔案名稱:程式碼)

    測試報名但卻無法沒有收到系統自動回覆的信件,目前顯示是由於以上訊息所以無法執行,請問程式指令有可以修正的地方嗎?

    回覆刪除
    回覆
    1. 這個...你好像問錯人囉~~

      這些程式碼並不是我寫的啊, 看看你從哪裡得到的, 問問那位作者吧~~

      刪除
  19. 謝謝您的分享^^

    不過我的填寫項目中並不包含email,所以我將emailTitle的項目改為「姓名」,經測試一樣可以讀取全部內容,在此提供參考~

    話說作者真得很厲害,不用到1000多行,30幾行就能解決問題了。

    回覆刪除
    回覆
    1. 不客氣~
      如果不需要寄信給填表者的話,可參考「六、常見 FAQ」 → Q3 處理即可,不一定要安裝這個工具。

      刪除

張貼留言注意事項:

◎ 勾選「通知我」可收到後續回覆的mail!
提問請附網址、詳細描述狀況,如提供的資訊不足,則無法回覆。
◎ 請在相關文章留言,與文章無關的主題請至「Blogger 中文論壇」。
◎ 若詢問 CSS 、非官方範本問題、或貴站為商業網站 ,請參考「本站諮詢頁面」→「1. 諮詢服務」
◎ 若留言要輸入語法,"<"、">"這兩個符號請用其他符號代替,否則語法會消失!
◎ 若發現留言不見了,通常是因為 "複製貼上" 的內容常被系統判定為垃圾留言,請不用擔心,我會定期將留言恢復。
◎ 本站「已關閉自刪留言功能」。