使用Google App Script導入自動化流程,稍稍減輕你的行政勞務

這邊先打個預防針,再如何導入自動化管理,始終還是需要人的介入,所以最終還是會需要花些時間參與其中,但至少可以從部分重複性的勞動中解放出來,隨者我們很多行為都在電腦中操作,有時候我們會發現我們做的事情就是重複性的點擊和寄件,這時候其實這些行為也可以被自動化,這就是所謂的機器人流程自動化(Robotic Process Automation)(P.S: 假如要很…技術宅的來說明的話),從簡單的點擊自動化到判讀發報告工具等等都是這類的概念。

這是開始接手一點點行政工作的夥伴常常會遇到的情境,這邊就以醫院總醫師業務為例。

“新學期開始,你的科又要迎來新的Clerk,每週都有不同梯次的人,你也要提醒帶的醫師記得上課,又要在課後收集Clerk的作業和評分,光處理這些事物,大概就佔用到你一半以上的時間”

令人崩潰的迷因

相信身邊很多開始需要處理行政雜務的朋友,常需要做的事情就是各種提醒和收集評分表或是報告,一部分的人慢慢的會使用如Gmail, Google Form, Google doc, Google sheet等等工具導入電子化,但最煩的是日期到了你必須自己來寄信、彙整、收集。

但其實可以再往下多自動化一步。(假如你是Google工具重度使用者的話)

這邊分享一下你可以使用Google App Script來讓這些工具自動化完成,做到如下:

特定日期發信提醒上課講師,給予講師當天課程學生名單,且將評分表附在信中寄給學生或是相對應的老師!

什麼是Google App Script?

我們常常在用的如Gmail, Google Slides, Google Sheet, Google Form等等都是所謂的Google Apps,而我們使用的時候都是使用圖形化介面,在瀏覽器中開啟信箱,寫信和收信,附上郵件,在google doc上面協作,撰寫草稿,或是利用Google Slides來做簡報,使用Google Form來設計問券,這些工具就是所謂的Google App,正常情況下你就是利用滑鼠來使用,但其實最近兩年Google為了讓企業或是個人能更高效地利用,導入了所謂的Google App Script工具,讓你使用簡單的代碼,便能輕鬆的自動化這些當初用滑鼠來使用的情節,且可以輕鬆地串接每個App,讓工作流程自動化且排程化。

簡單來說,你每個建立的google doc, google slide, googlde sheet, googlde form都是一個可以用程式來調用的檔案,具有唯一的物件Id。很酷吧!

如何建立一個Google App Script檔案?

那會不會很麻煩,假如想要使用Google App Script來操控我們在google Apps裡的檔案?一點也不,你不需要安裝任何程式,或是建立整個編程環境,流程就像是你建立一個Google Doc檔案一樣。

直接在你的googld drive中,就能建立一個Google App Script檔案

編輯和撰寫Google Apps Scripts

點開你建立的Google Apps Script就會自動進入他的編輯器中,如同下面的畫面:

整個畫面就如同一個簡單的編輯器,裡面可以直接撰寫代碼來控制你的文件,主要是使用Javascript的語法,所以相對容易,你不用在自己學習新的語法和觀念,只需要搞懂Google App Scrip裡面調用Gmail, Google Sheet, Google Form的函式即可,以及你想要怎麼去串接資料來達成你想要的任務。

基本邏輯,每個Google檔案都是可以被取用的物件

第一個重要觀念在使用Google App Scripts是每一個你的google檔案,都有一串獨一無二的Id,且都是顯示在網址之中,非常一清二楚。

這邊是我每封信件的一個範本,這邊一點開,你從瀏覽器就能看到這個文件的Id,這就可以在App Script中調用,另一方面,因為Google在權限管理做得很好,所以不同帳號的人基本上是不能調用彼此文件的,所以我這邊露出這Id基本上不會讓別人可以任意修改(希望我的理解沒錯,不然….我的檔案就有危險惹)

基本範例:一個自動寄出提醒當天上課教師的Email

這個功能在做什麼呢?簡單描述一下,每天這個函數會被排程在早上八點的時候執行,執行時,他會去檢查我們的課程排程google sheet表單,看今天的日期是哪個老師上課,有老師上課的話,就是檢查另一個學生組別的google sheet,看這老師帶的組別,裡面有哪些學生,接者他再去抓取我們的問券範本google form,把這些學生的姓名和上課資料放進去問券,接者在抓取我們設計的Email範本,把相關老師姓名、學生姓名以及問券連結放上去,接者邊把這封信寄給這位老師,同時CC給我。

他會長什麼樣子呢?

基本的撰寫方式就是以寫一個函數(javascript function)的模式,然後函數內完成你想要的功能,這邊可以看到Google Apps Scripts的編輯器會自動抓取這份文件中定義的所有函數,你點選執行便能測試這些你自己撰寫的代碼。

你可以把所有要用到的檔案都放在同一個地方,這樣其實就可以很輕鬆的管理和建置你的流程,之後要交接給學弟妹也會非常方便,或是用舊的代碼來完成新的工作!

這邊分享原始代碼,給有興趣的人使用:



// 使用的代碼
// reference usage: http://www.eion.com.tw/Blogger/?Pid=1148
function autosentDOC(){
    // ======================== Basic 參數設置 ================================

    let today = new Date(); // 讀取今天的日期
    Logger.log(today); 
    Logger.log(today.toDateString()); 
    // 設定google drive中檔案的id
    // 問券:一份google form問券:用來打分數
    const form_id = '1XvhpcCV_UXDCJpIOsdaksjfo9LDwWKrkxP16sMvs' ;
    // 資料:一份google spread sheet:裡面有所有clerk的資訊,包含:姓名、梯數、開始的日期、結束的日期等等
    const sheetTeacher_id = '1tquDwugwMsy5al20f_hGChdfdsafdsGsCoXHUJF0';
    const sheetStu_id = '1EdySuvRHo3iPqdfsdfsfdsfB9Cx3sRcmFnPfdsfdo';
    // 文本:一份google doc:裡面有email的範本
    const docmd_id  = '11QphDQkYe8rdfsdfsdfeOfKlXhfQdH6bj5g';  // 內容:提醒有clerk,且要評分
    
   
    
    //const email = 'dontellyou@gmail.com' // 測試時使用自己的信箱
    // 寄信函數的參數
    const param = {
        method:'get',
        headers: {
          "Authorization":"Bearer "+ScriptApp.getOAuthToken()
        },
        muteHttpExceptions:true
      }
    // ======================== 今天上課的教學醫師 =============================
    // 讀取教學醫師的排程
    const gs_MT = SpreadsheetApp.openById(sheetTeacher_id);

    const gs_MT_sheet = gs_MT.getSheetByName('schedule');

    const gs_data = gs_MT_sheet.getDataRange().getValues();
    // 讀取學生組別資料

    const gs_Stu = SpreadsheetApp.openById(sheetStu_id);

    const gs_Stu_sheet = gs_Stu.getSheetByName('member');

    const gs_Stu_data = gs_Stu_sheet.getDataRange().getValues();
    // ======================== 從google sheet取得 Clerk的名單資料 ======

    // 讀取google drive中的google sheet 檔案
    //const ss = SpreadsheetApp.openById(sheet_id);
    // 讀取這個google sheet中的分頁,分頁名稱為2021_2022_Clerk_CPcourse
    //const sheet = ss.getSheetByName('2021_2022_Clerk_CPcourse');
    // 讀取這個分頁中的所有資料
    //const data = sheet.getDataRange().getValues();
    
    // 將資料中,所有clerk課程開始日期比今天小且clerk課程結束日期比今天晚的“所有”資料
    let currentTeachers = gs_data.filter(function(item, index, array){
      //Logger.log(item[0]); 
      let tmpDate = new Date(item[0]);
      return tmpDate.toDateString() == today.toDateString()   
      });
    // 將資料中,clerk課程開始日期比今天小且clerk課程結束日期比今天晚的“第一筆”資料
    let currentTeacher = gs_data.find(function(item, index, array){
      let tmpDate = new Date(item[0]);
      return tmpDate.toDateString() == today.toDateString()     
      });
    
  
 
    // 判斷今天有組別的話,組別名單
    
    if(currentTeachers.length == 0){
       Logger.log('今天沒有老師要上課');
    }else{
      // 假如本兩週有clerk學生,則執行下面的代碼來建立問券
        //看一下currentClerk物件內容(debug使用)
    Logger.log("todayTeacher"); 
    Logger.log(currentTeacher[3]);
    Logger.log("today group");  
    Logger.log(currentTeacher[2]); 
    Logger.log(currentTeachers); 
      // 這週有clerk,看是否是第一週
      // 這梯有clerk,且本週為要上課的日子gs_Stu_data
      const currentClerksNamesArray = gs_Stu_data.filter(function(item, index, array){
      //Logger.log(item[0]); 
      return item[0] == currentTeacher[2]   
      });

      const currentClerksNames = Array.from(currentClerksNamesArray, item => item[2]);
      Logger.log("today group names");  
      Logger.log(currentClerksNamesArray); 
      Logger.log(currentClerksNames); 
      // ======================== 修改問券的資料,根據今天之clerk名單 ==============
      // 讀取google drive中事先建立的google form
      const form = FormApp.openById(form_id) ;
      // 讀取這個google form的問題
      const items = form.getItems();
      // 一個個確認這問券中的問題
      items.forEach((item)=>{
        
        if(item.getIndex() == 0){
        // 假如是這問券的第一個問題
          const nameItem = item.asMultipleChoiceItem();
        // 將這梯的醫學生名字放進去問券第一題的選項之中
          nameItem.setChoiceValues(currentClerksNames);
          Logger.log(currentClerksNames,'名字放入問券!');
         }
        if(item.getIndex() == 1){
        // 假如是這問券的第二個問題
          const nameItem = item.asMultipleChoiceItem();
        // 將這梯的日期放到問券之中 
          nameItem.setChoiceValues([today.toDateString()]);
          Logger.log([today.toDateString()],'日期放入問券!');
        }
  
      })
      // 這梯有一學生
       //讀取email範本:有clerk學生的版本
       //const form = FormApp.openById(form_id) ; 
       const url = 'https://docs.google.com/document/d/'+docmd_id+'/export?format=html';
       let html = UrlFetchApp.fetch(url, param);
       html = html.getContentText();
       // 將信件放入老師名稱
       html = html.replace(/#teacher/g, currentTeacher[3]);
       // 將信件放入clerk名稱
       html = html.replace(/#name/g, currentClerksNames);
       // 將信件放入google form的連結
       html = html.replace(/#link/g, form.getPublishedUrl());
       // 將信件放入這梯clerk的名字
       html = html.replace(/#time/g, currentTeacher[2]);
       // 信件的主旨
       const subject = 2022 + ' 第'+currentTeacher[2]+'組'+' 檢驗醫學部-實診暨臨診-案例討論課當日評核';

       const prop = {
        htmlBody:html,
        cc:'testemail@gmail.com'
       };
       // 寄信
       GmailApp.sendEmail(currentTeacher[4], subject,'',prop);
    }
    
  }

GenomesDAO:定序你的基因,鑄造一個NFT

延續前一篇的內容社群、區塊鏈、NFT和新型態生技開源模式,但又有點展開,來分享最近看到的一個基因定序服務跟NFT結合的項目,他們初衷很單純,但卻直指目前許多DTC基因檢測產品的問題:

如何確保你的基因資料不被幫你定序的公司自由使用且販售,但又能讓你決定你是否要提供你的基因資訊給予如研究組織、藥廠、生技公司有償或是無償地使用

GenomesDAO便是最近看到一個想要解決這個問題的公司,且以一個NFT項目發行的模式來參與Web3.0的世界。他的模式蠻有趣的,整個使用流程如下:

藉由購買或是鑄造一個Geneticats的NFT後,可以使用這個NFT來兌換實體的定序採檢套組,這個套組可以寄到世界各地,你只要用這個採檢棒刮取口腔中的粘膜,把一些細胞刮下來,再寄回去,經過約14-16周的檢體處理和定序,基因資訊會完成處理,將你的序列用AMD加密的方式儲存,此時便能利用你的資料來挖礦(售予藥廠、生技公司、研究機構使用你的資訊,並且給予你$GENE幣),同時可以使用你的資料再來鑄造成另外一個生成式的藝術作品。

這類將科學主題使用NFT的風潮,其實不算少見,甚至在Narure上面還有文章再分享這個現象:

How scientists are embracing NFTs, Nicola Jones, Nature

比如哈佛大學的George Church,就把自己的基因鑄造成NFT,在去年跟他實驗室創建的基因定序公司Nebula策劃了一場NFT拍賣,這場活動則是為了要激起大家對於基因數據的意識,宣傳大於實際的意義,因為事實上Goerge Church教授的基因序列已經是共享的資訊了,他早在2005年推動的Personal Genome Project就把它自己的基因序列也一起放在這個資料庫之中。

相信未來會有越來越多新型態的生技創業模式,尤其是打破原本募資想法的流程,讓民眾參與其中!