Post

Slack 打造全自動 WFH 員工健康狀況回報系統

玩轉 Slack Workflow 搭配 Google Sheet with App Script 增加工作效率

Slack 打造全自動 WFH 員工健康狀況回報系統

Slack 打造全自動 WFH 員工健康狀況回報系統

玩轉 Slack Workflow 搭配 Google Sheet with App Script 增加工作效率

Photo by [Stephen Phillips — Hostreviews.co.uk](https://unsplash.com/@hostreviews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText){:target="_blank"}

Photo by Stephen Phillips — Hostreviews.co.uk

前言

因應全面居家工作,公司關心所有成員的健康,每日均需回報身體有無狀況並由 People Operations 統一紀錄管理。

我們的 優化前 的 Flow

  1. [自動化] Slack Channel 每日早上 10 點定時發送提醒大家健康表單的訊息(優化前唯一自動化的地方)
  2. 員工點擊連結打開 Google Form 填寫健康問題
  3. 資料存回 Google Sheet 回應紀錄
  4. [人工] People Operations 於每日接近下班時比對名單篩出忘記填寫的員工
  5. [人工] 於 Slack Channel 發送填寫提醒訊息 & 一個一個 tag 忘記填寫的人

以上是敝司的健康回報追蹤流程,每間公司依照規模及運作方式一定有所不同,本文僅以此做為優化範例,學習 Slack Workflow 使用、基本 App Script 撰寫,實際還是要 by case 實作。

問題點

  • 需跳出 Slack Context 使用瀏覽器打開 Google Form 網頁才能填寫,尤其在手機上更不方便
  • Google Form 僅能自動帶入 Email 訊息,無法自動加上填寫人名稱、部門資訊
  • 每日人工比對、人工 tag 非常花費人力時間

解決方案

做過蠻多自動化的小東西,這個流程資料源固定(員工名單)、條件單純、動作很例行;一看就覺得很適合自動化,一開始沒做是因為找不到好的填寫方式(實際是找不到有趣可研究的點);所以也就放著沒管,直到看到 海總理的這則 PO 文 才發現 Slack Workflow 不只是可以做定時傳訊息,還有 Form 表單的功能:

圖片取自: [海總理](https://www.facebook.com/tzangms/posts/10157880898787657){:target="_blank"}

圖片取自: 海總理

這下手就開始癢了啊!!

如果能搭配 Slack Workflow From 加上傳訊息的自動化,豈不是能解決上面提到的 所有痛點 ,原理可行!於是開始著手實作。

優化後 的 Flow

首先上一下優化後的流程及結果。

  1. [自動化] Slack Channel 每日早上 10 點定時發送提醒大家健康表單的訊息
  2. 從 Google Form 或 Slack Workflow Form 填寫健康問題
  3. 資料均存回 Google Sheet 回應紀錄
  4. People Operations 於每日接近下班時點擊「產生未填寫名單」按鈕
  5. [自動化] 使用 App Script 比對員工名單、填寫名單篩出未填寫名單
  6. [自動化] 點擊「產生&發送訊息」自動發送未填寫提醒&自動 tag 對象
  7. 收工!

成效

(個人預估)

  • 填寫時間每位員工每日能減少約 30 秒
  • People Operations 處理這件事每日能減少約 20 ~ 30 分鐘

運作原理

透過撰寫 App Script 來管理 Sheet。

  1. 將外部輸入的資料都存放在 Responses Sheet
  2. 撰寫 App Script Function 將 Responses 的資料依照填寫日期分發到各日期的 Sheet,若無則建立新的日期 Sheet,Sheet 名稱直接使用日期,方便辨識取用
  3. 取得當前日期的 Sheet 與員工名單比對,產生未填寫名單 Sheet 的資料
  4. 讀取未填寫名單 Sheet 組合出訊息並發送到指定 Slack Channel
  • 串接 Slack APP API 可自動讀取指定 Channel 匯入員工名單
  • 訊息內容使用 Slack UID Tag <@UID> 就能標記未填寫的成員。

身份識別

串起 Google From 與 Slack 的身份識別資訊是 Email,所以請確保公司同仁都是使用公司 Email 填寫 Google Form、Slack 個人資訊部分也都有填寫公司 Email。

開始動手做

問題、優化方式、成果講完後,接下來來到實作環節;讓我們一起一步步完成這個自動化 Case。

篇幅有點長,可依照略過自己已了解的區塊,或直接從完成結果建立副本,邊看邊改邊學。

完成結果表單: https://forms.gle/aqGDCELpAiMFFoyDA

完成結果 Google Sheet:

建立健康回報 Google Form 表單 & 連結回覆到 Google Sheet

步驟省略,有問題請直接 Google,這邊假定你已經建立&連結好了健康回報表單。

表單要記得勾選「Collect emails」:

收集填寫者的 Email 以利之後比對名單用。

怎麼連結回覆到 Google Sheet?

於表單的上方切換到「回覆」點擊「Google Sheet Icon」即可。

更改連結的 Sheet 名稱:

這邊建議將連結的 Sheet 名稱由 Form Responses 1 改為 Responses 方便使用。

建立 Slack Workflow Form 填寫入口

傳統的 Google From 填寫入口有了之後,我們先來新增 Slack 填寫方式。

於 Slack 任意對話視窗中找到「 輸入匡 下方 」的「藍色閃電⚡️」點擊下去

在選單底下「Search shortcuts」中輸入「workflow」選擇「Open Workflow Builder」

這邊會列出你建立的或參與的 Workflow,點選右上角「Create」建立新 Workflow

第一步,輸入 workflow 名稱(Workflow Builder 介面顯示用)

Workflow 觸發方式,選擇「Shortcut」

目前一共有 5 種 slack workflow 觸發時間點:

  • Shortcut:手動觸發「藍色閃電⚡️」選項,會出現在 workflow 選單中,點擊即可開始 workflow。
  • New channel member:當 Target Channel 有新成員加入時…. (EX: 歡迎訊息)
  • Emoji reactions:當有人對 Target Channel 中的訊息按下指定表情符號時…(或許可拿來做重要訊息已讀請按 XXX Emoji,以此知道誰已讀了?)
  • Scheduled date & time:排程,指定時間到時…(EX: 定時發提醒回報訊息)
  • Webhook:外部 Webhook 觸發,進階功能,可與第三方或自己架 API 串起內部工作流程。

這邊我們選擇「Shortcut」建立手動觸發選項。

選擇這個 Workflow Shortcut 要加入在「哪一個 Channel 輸入匡」之下及輸入「要顯示的名稱」

*一個 workflow shortcut 僅能加入在一個 channel 中

Shortcut 建立完成!開始建立 workflow 步驟,點擊「Add Step」加入步驟

選擇「Send a form」Step

Title :輸入表單標題

Add a question :輸入第一個問題的題目(可自行在標題標注問題編號 ex: 1.,2.,3….)

Choose a question type

  • Short answer:單行輸入匡
  • Long answer:多行輸入匡
  • Select from a list:單選列表
  • Select a person:選擇一位同個 Workspace 內的成員
  • Select a channel or DM:選擇一位同個 Workspace 內的成員 或 Group DM 或 Channel

「Select from a list」為例:

  1. Add list item:可新增一個選項
  2. Default selection:選擇預設選項
  3. Make theis required:將此問題設為必填

  1. Add Question:可新增更多問題
  2. 右方「↓」「⬆」可調整順序、「✎」可展開編輯
  3. 可選擇是否要將表單填寫內容回傳至 Channel 或 某人

也可以選擇傳送回覆到…:

  • Person who clicked ….:點擊這個表單的人(形同填寫的人)
  • Channel where workflow started:這個 workflow 添加到的 Channel

表單完成後點擊「Save」儲存步驟。

*這邊我們取消勾選將表單填寫內容回傳,因為想要在後面步驟自行客製化訊息內容。

將 Slack workflow from 與 Google Sheet 串接

如果還沒有將 Google Sheet App 加入到 Slack 可先 點此安裝 APP

繼上一步後,點擊「Add Step」加入新步驟,我們選擇 Google Sheets for Workflow Builder 的「Add a spreadsheet row」步驟。

  1. 首先要完成 Google 帳號的授權,點擊「Connect account」
  2. Select a spreadsheet:選擇目標回應的 Google Sheet,請選擇一開始建立的 Google Form 之 Google Sheet
  3. Sheet:同上
  4. Column name:第一個欲填入值的 Column,這邊先選問題ㄧ

點擊右下角「Insert Variable」選擇「Response to 問題一…」,插入之後可由左下角「Add Column」加入其他欄位,以此類推完成問題二、問題三….

填寫人的 Email,可選擇「Person who submitted form」

在點擊插入的變數,選擇「Email」即可自動帶入填寫人的 Email。

  • Mention (default):tag 該 User,Raw data 是 <@User ID>
  • Name:User 名稱
  • Email:User Email

Timestamp 欄位比較 tricky 等下再補充設定方法,先點「Save」儲存後回到頁面右上角按「Publish」發布 Shortcut。

看到發布成功訊息後,可以回到 Slack Channel 試試看。

這時候點閃電之後會出現剛剛建立的 Workflow form,可以點來填寫玩玩。

左:電腦 右:手機版

左:電腦 / 右:手機版

我們可以填寫資訊「Submit」測試看看是否正常。

成功!但可以看到 Timestamp 欄位為空,下一步我們來解決這個問題。

Slack workflow from 取得填寫時間

Slack workflow 沒有 current timestamp 的 global variable 可用,至少目前還沒有,只找到一篇 reddit 上的許願文章

一開始異想天開在 Column Value 輸入 =NOW() 但這樣所有紀錄的時間永遠是當前時間,完全錯誤。

同樣拜 reddit 那篇文章 大神網友提供的 tricky 方法,可以建一個乾淨的 Timestamp Sheet 裡面放一個列資料、欄位 =NOW() 先用 Update 迫使欄位變為最新,在 Select 得到當前 Timestamp。

如上圖結構,點此 查看範例

  • Row: 類似 ID 的用處,直接設「1」,之後設定 Select & Update 會要用到,告知資料列。
  • Timestamp:設定值 =NOW() 讓他永遠顯示當前時間
  • Value:用以觸發 Timestamp 欄位更新時間,內容隨意,這邊是把填寫人的 Email 塞進來放,反正只要能觸發更新就好。

可在 Sheet 上按右鍵「Hide Sheet」隱藏此 Sheet,因為沒有要讓外部使用。

回到 Slack Workflow Builder 編輯剛剛 建立的 workflow form。

點擊「Add Step」新增步驟:

往下滑選擇「Update a spreadsheet row」

「Select a spreadsheet」選擇剛剛的 Sheet,「Sheet」選擇新建立的「Timestamp」Sheet。

「Choose a column to search」選擇「Row」,Define a cell value to find 輸入「1」。

「Update these columns」「Column name」選擇「Value」、「Value」點選「Insert variable」->「Person who submitted」->「選擇 Email」。

點「Save」完成!現在已經完成觸發 Sheet 中的 timestamp 更新了,再來是讀取出來用。

回到編輯頁後再點一次「Add Step」加入新步驟,這次選「Select a spreadsheet row」我們要讀取 Timestamp 出來。

Search 部分同「Update a spreadsheet row」,按「Save」。

Save 完回到步驟列表頁,我們可以把滑鼠移到步驟上用拖曳更改順序。

將順序改「Update a spreadsheet row」->「Select a spreadsheet」->「Add a spreadsheet row」。

意即:Update 觸發 timestamp 更新 -> 讀取 Timestamp -> 在新增 Row 時拿來用。

在「Add a spreadsheet row」點「Edit」編輯:

拉到最下面按左下角「Add Column」在點右下角「Insert a variable」,找到「Select a spreadsheet」Section 中的「Timestamp」變數,注入進去。

按「Save」儲存步驟後回到列表頁,右上角點「Publish Change」發布更改。

這時候我們再測試一次 workflow shortcut 看看 timestamp 有沒有正常寫入。

成功!

Slack workflow form 增加填寫回執

同 Google Form 填寫回執,Slack workflow form 也可以。

在編輯步驟頁我們可以再加入一個步驟,點擊「Add Step」。

這次選擇「Send a message」

「Send this message to」選擇「Person who submitted form」

訊息內容依序輸入題目名稱、「Insert a variable」選擇「Response to 題目 XXX」,也可在最後插入「Timestamp」,按「Save」儲存步驟後再按「Publish Changes」即可!

另外也可使用「Send a message」將填寫結果傳送到特定 Channel 或 DM。

成功!

Slack workflow form 的設定大概到此結束,其他玩法可以自由搭配發揮。

Google Sheet with App Script!

接下我們需要撰寫 App Script 來處理填寫資料。

首先在 Google Sheet 上方工具欄選擇「Tools」->「Script editor」

可以點擊左上角給專案一個名稱。

現在我們可以開始撰寫 App Script!App Script 是基於 Javascript 設計,所以可以直接使用 Javascript 程式碼用法搭配 Google Sheet 的 lib。

將 Responses 的資料依照填寫日期分發到各日期的 Sheet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function formatData() {
  var bufferSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Responses') // 儲存回覆的 Sheet 名稱
  
  var rows = bufferSheet.getDataRange().getValues();
  var fileds = [];
  var startDeleteIndex = -1;
  var deleteLength = 0;
  for(index in rows) {
    if (index == 0) {
      fileds = rows[index];
      continue;
    }

    var sheetName = rows[index][0].toLocaleDateString("en-US"); // 將 Date 轉換成 String,使用美國日期格式 MM/DD/YYYY
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); // 取得 MM/DD/YYYY Sheet
    if (sheet == null) { // 若無則新增
      sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(sheetName, bufferSheet.getIndex());
      sheet.appendRow(fileds);
    }

    sheet.appendRow(rows[index]); // 將資料新增至日期 Sheet
    if (startDeleteIndex == -1) {
      startDeleteIndex = +index + 1;
    }
    deleteLength += 1;
  }

  if (deleteLength > 0) {
    bufferSheet.deleteRows(startDeleteIndex, deleteLength); // 搬移到指定 Sheet 後,移除 Responses 裡的資料
  }
}

在 Code 區塊中貼上以上程式碼,並按「control」+「s」儲存。

再來我們要在 Sheet 中新增觸發按鈕( 只能手動按按鈕觸發,無法在資料寫入時做自動分

  1. 首先在建立一個新的 Sheet,取名「未填寫名單」
  2. 上方工具列選擇「Insert」->「Drawing」

使用此介面,拉出一個按鈕。

「Save and Close」後可調整、移動按鈕;點擊右上角「…」選擇「Assign script」

輸入「formatData」function 名稱。

可點擊加入的按鈕試試功能

若出現 「Authorization Required」則點選「Continue」完成驗證

在身份驗證的過程中會出現「Google hasn’t verified this app」這是正常的,因為我們寫的 App Script 沒有經過 Google 驗證,不過沒關係這是寫給自己用的。

可點選左下角「Advanced」->「Go to Health Report (Responses) (unsafe)」

點擊「Allow」

App Script 執行中會顯示「Running Script」這時候請勿再按,避免重複執行。

顯示執行成功後,才能再次執行。

成功!將填寫資料依照日期分組。

取得當前日期的 Sheet 與員工名單比對,產生未填寫名單 Sheet 的資料

我們再加入一段 Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 與員工名單 Sheet & 本日填寫 Sheet 比對,產出未填寫名單
function generateUnfilledList() {
  var listSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('員工名單') // 員工名單 Sheet 名稱
  var unfilledListSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('未填寫名單') // 未填寫名單 Sheet 名稱
  var today = new Date();
  var todayName = today.toLocaleDateString("en-US");

  var todayListSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(todayName) // 取得本日 MM/DD/YYYY Sheet
  if (todayListSheet == null) {
    SpreadsheetApp.getUi().alert('找不到'+todayName+'本日的 Sheet 或請先執行「整理填寫資料」');
    return;
  }

  var todayEmails = todayListSheet.getDataRange().getValues().map( x => x[1] ) // 取得本日 Sheet Email Address 欄位資料列表 (1 = Column B)
  // index start from 0, so 1 = Column B
  // output: Email Address,zhgchgli@gmail.com,alan@gamil.com,b@gmail.com...
  todayEmails.shift() // 移除第一個資料,第一個是欄位名稱「Email Address」無意義
  // output: zhgchgli@gmail.com,alan@gamil.com,b@gmail.com...

  unfilledListSheet.clear() // 清除未填寫名單...準備重新填入資料
  unfilledListSheet.appendRow([todayName+" 未填寫名單"]) // 第一行顯示 Sheet 標題

  var rows = listSheet.getDataRange().getValues(); // 讀取員工名單 Sheet
  for(index in rows) {
    if (index == 0) { // 第一列是標題欄位列,存下來,讓後續產生資料也可補上第一列標題
      unfilledListSheet.appendRow(rows[index]);
      continue;
    }
    
    if (todayEmails.includes(rows[index][3])) { // 如果本日 Sheet Email Address 中有此員工的 Email 則代表有填寫,continue 略過... (3 = Column D)
      continue;
    }

    unfilledListSheet.appendRow(rows[index]); // 寫入一行資料到未填寫名單 Sheet
  }
}

一樣儲存後,照前面加入 Code 的方法,再加入一個按鈕並 Assign script — 「generateUnfilledList」。

完成後可點擊測試:

未填寫名單產生成功!如果沒有出現內容請先確定:

  • 員工名單已填寫,或可先輸入測試資料
  • 要先完成「整理填寫資料」動作

讀取未填寫名單 Sheet 組合出訊息並發送到指定 Slack Channel

首先我們要加入 Incoming WebHooks App 到 Slack Channel,我們會透過此媒介來傳送訊息。

  1. Slack 左下角「Apps」->「Add apps」
  2. 右邊搜尋匡搜尋「incoming」
  3. 點擊「Incoming WebHooks」->「Add」

選擇未填寫訊息想要傳到的 Channel。

記下最上方的「Webhook URL」

往下滑可設定傳送訊息時,傳送 Bot 顯示的名稱及大頭貼;改完記得按「Save Settings」。

回到我們的 Google Sheet Script

再加入一段 Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function postSlack() {
  var ui = SpreadsheetApp.getUi();
  var result = ui.alert(
     '您確定要發送訊息?',
     '發送未填寫提醒訊息到 Slack Channel',
      ui.ButtonSet.YES_NO);
  // 避免誤觸,先詢問確認

  if (result == ui.Button.YES) {
    var unfilledListSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('未填寫名單') // 未填寫名單 Sheet 名稱
    var rows = unfilledListSheet.getDataRange().getValues();
    var persons = [];
    for(index in rows) {
      if (index == 0 || index == 1) { // 略過標題、欄位標題那兩行
        continue;
      }
      
      var person = (rows[index][4] == "") ? (rows[index][2]) : ("<@"+rows[index][4]+">"); // 標記對象,如果有 slack uid 優先使用,沒有則單純顯示暱稱;2 = Column B / 4 = Column E
      if (person == "") { // 都沒視為異常資料,忽略
        continue;
      }
      persons.push(""+person+'\n') // 將對象存入陣列
    }

    if (persons.length <= 0) { // 無對象需要被標記通知時,大家都有填,取消訊息送出
      return;
    }

    var preText = "*[健康回報表公告:loudspeaker:]*\n公司關心各位的身體健康,煩請以下隊友記得每日填寫健康狀況回報,謝謝:wink:\n\n今日未填健康狀況回報名單\n\n" // 訊息開頭內容...
    var postText = "\n\n填寫健康狀況回報能讓公司了解隊友們的身體狀況,煩請隊友們每日都要確實填寫唷>< 謝謝大家:woman-bowing::skin-tone-2:" // 訊息結尾內容...
    var payload = {
      "text": preText+persons.join('')+postText,
      "attachments": [{
          "fallback": "這邊可放 Google Form 填寫連結",
          "actions": [
            {
                "name": "form_link",
                "text": "前往健康狀況回報",
                "type": "button",
                "style": "primary",
                "url": "這邊可放 Google Form 填寫連結"
            }
          ],
          "footer": ":rocket:小提示:點擊輸入匡下方的「:zap:️閃電」->「Shortcut Name」,即可直接填寫。"
        }
      ]
    };
    var res = UrlFetchApp.fetch('這邊輸入你 slack incoming app 的 Webhook URL',{
      method             : 'post',
      contentType        : 'application/json',
      payload            : JSON.stringify(payload)
    })
  }
}

一樣儲存後,照前面加入 Code 的方法,再加入一個按鈕並 Assign script — 「postSlack」。

完成後可點擊測試:

成功!!!(顯示 @U123456 沒成功標記人是因為 ID 是我亂打的)

到此主要的功能都已完成!

備註

請注意官方建議使用新的 Slack APP API 的 chat.postMessage 來傳送訊息,Incoming Webhook 簡便的這個方式之後會棄用,這邊偷懶沒有使用,可搭配下一章「匯入員工名單」會需要 Slack App API 一起調整成新方法。

匯入員工名單

這邊會需要我們創建一個 Slack APP。

1.前往 https://api.slack.com/apps

2. 點擊右上角「Create New App」

3. 選擇「 From scratch

4. 輸入「 App Name 」跟 你想要加入的 Workspace

5. 建立成功後,在左邊選單選擇「OAuth & Permissions」設定頁

6. 往下滑到 Scopes 區塊

依次「Add an OAuth Scope」以下項目:

7. 回到最上面點擊「Install to workspace」or「Reinstall to workspace」

*如果 Scopes 有新增,也要回來這點重新安裝。

8. 安裝完成,取得複製 Bot User OAuth Token

9. 使用網頁版 Slack 打開想要匯入名單的 Channel

從瀏覽器取得網址:

1
https://app.slack.com/client/TXXXX/CXXXX

其中 CXXXX 就是這個 Channel 的 Channel ID,記下此訊息。

10.

回到我們的 Google Sheet Script

再加入一段 Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function loadEmployeeList() {
  var formData = {
    'token': 'Bot User OAuth Token',
    'channel': 'Channel ID',
    'limit': 500
  };
  var options = {
    'method' : 'post',
    'payload' : formData
  };
  var response = UrlFetchApp.fetch('https://slack.com/api/conversations.members', options);
  var data = JSON.parse(response.getContentText());
  for (index in data["members"]) {
    var uid = data["members"][index];
    var formData = {
      'token': 'Bot User OAuth Token',
      'user': uid
    };
    var options = {
      'method' : 'post',
      'payload' : formData
    };
    var response = UrlFetchApp.fetch('https://slack.com/api/users.info', options);
    var user = JSON.parse(response.getContentText());

    var email = user["user"]["profile"]["email"];
    var real_name = user["user"]["profile"]["real_name_normalized"];
    var title = user["user"]["profile"]["title"];
    var row = [title, real_name, real_name, email, uid]; // 依照 Column 填入

    var listSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('員工名單'); // 員工名單 Sheet 名稱
    listSheet.appendRow(row);
  }
}

但這次我們不需要再加入按鈕,因為匯入僅第一次需要;所以只需存擋後直接執行即可。

首先按「control」+「s」存檔,上方下拉選單改選擇「loadEmployeeList」,點擊「Run」就會開始匯入名單到員工名單 Sheet。

手動新增新員工資料

爾後如果有新員工加入,可直接在員工名單 Sheet 新增一列,填入資訊,Slack UID 可在 Slack 上直接查詢:

點擊要查看 UID 的對象,點擊「View full profile」

點擊「More」選擇「Copy member ID」即是 UID。 UXXXXX

DONE!

以上所有步驟都已完成,可以開始自動化的追縱員工的健康狀況。

完成檔如下,可直接從以下 Google Sheet 建立副本修改後使用:

補充

  • 如果想要用 Scheduled date & time 定時發送 form 訊息,要注意這情況下的 form 只能被填一次,所以不適合在這邊使用…(至少目前版本還是這樣),所以 Scheduled 填寫提醒訊息依然只能用純文字+Google Form 連結。

  • 目前沒有辦法用超連結連到 Shortcut 打開 Form
  • Google Sheet App Script 防止重複執行:

如果要防止不小心在執行中又再次按到導致重複執行,可在 function 一開始加上:

1
2
3
4
5
if (PropertiesService.getScriptProperties().getProperty('FUNCTIONNAME') == 'true') {
  SpreadsheetApp.getUi().alert('忙碌中...請稍後再試');
  return;
}
PropertiesService.getScriptProperties().setProperty('FUNCTIONNAME', 'true');

Function 執行結束時加上:

1
PropertiesService.getScriptProperties().setProperty('FUNCTIONNAME', 'true');

FUNCTIONNAME 取代為目標 Function 名稱。

用一個 Global 變數管制執行。

與 iOS 開發相關的應用

可用來串 CI/CD,用 GUI 包裝原本醜醜的指令操作,例如搭配 Slack Bitrise APP,用 Slack Workflow form 組合啟動 Build 命令:

送出之後會發送指令到有 Bitrise APP 的 private channel,EX:

1
bitrise workflow:app_store|branch:develop|ENV[version]:4.32.0

就能觸發 Bitrise 執行 CI/CD Flow。

延伸閱讀

有任何問題及指教歡迎 與我聯絡

有自動化相關優化需求也歡迎 發案給我 ,謝謝。

===

本文首次發表於 Medium ➡️ 前往查看

Buy me a beer

2,262 Total Views
Last Statistics Date: 2025-01-17 | 2,071 Views on Medium.
This post is licensed under CC BY 4.0 by the author.