透過Google表單+ App Script建立合約產生器

2022/03/20

前言

家裡目前為太陽能工程開發產業

除了承包工程之外

有時候也會自購小型的電廠

也就是跟地主簽約

地主提供場地(可能是廢棄池塘、污染農地、畜舍屋頂、工廠屋頂)給我們建置太陽能電廠

我們則要每個月支付租金給地主

 

因此我們需要與地主簽訂合約

每一個案場的合約基本上都大同小異

除了甲方(屋主)基本資料換掉之外

再來就是依照每個案場與屋主協議結果會有不同的支付租金方式(年繳或月繳)

 

身為軟體工程師

這種重複性的東西看到之後第一個直覺

就是拆成變數抽出來換成其他方式填入就好

可以直接透過軟體手段偷懶

所以我在編好第一個份合約之後

就開始著手這個專案

 

專案需求

完整操作影片如下

前面有提到要把重複的東西抽成變數

簡單做的話其實就透過google表單填入這些不同的變數即可

至於合約的部份就用一個google文件來做範本樣板

最後就是透過google app scripttrigger在收到表單提交的事件時

自動執行一些app script來更換google文件樣板的變數

然後自動輸出到指定google drive目錄即可

 

表單

首先我們把合約重複性資料抽出來做成表單

以下用簡單的幾個資料做範例

 

合約文件樣板

以下用簡化後的合約示範

將變數的部份使用雙花括號框起來

 

設定App Script並觀察收到的表單資料格式

 

建立App Script

首先

在表單的回覆google sheet中

選擇擴充功能>App Script開啟一個新的App Script專案

 

先設定log印出完整的資料

首先先定義一個createContract method

透過app script Logger將整個表單event資料印出來觀察格式

方便後續規劃

1.png

 

設定trigger

將trigger設定在收到表單call createContract method

 

提交一次表單觀察log

透過執行項目可以看到整個event的資料結構

1.png

 

大致如下

很清楚的可以看到透過namedValues屬性可以取得表單資料

{
   "authMode":"FULL",
   "namedValues":{
      "甲方姓名":[
         "板橋"
      ],
      "時間戳記":[
         "2022/3/13 下午 5:10:12"
      ],
      "管轄法院":[
         "台中"
      ],
      "月租金":[
         "18000"
      ]
   },
   "range":{
      "columnEnd":4,
      "columnStart":1,
      "rowEnd":6,
      "rowStart":6
   },
   "source":{
      
   },
   "triggerUid":"10561890",
   "values":[
      "2022/3/13 下午 5:10:12",
      "板橋",
      "18000",
      "台中"
   ]
}

 

開始依照需求建立google文件合約

知道合約格式後

基本上再多透過幾個app script class即可建立google文件合約

 

必要資料

建立資料之前首先要取得兩個參數

  1. 合約樣板google文件的ID(在網址列可取得)
  2. 要輸出的google drive目錄ID(一樣在網址列可取得)

 

開始設定app script

透過以下app script可依照需求題換樣板的變數

建立完整合約

function createContract(event) {
  this.googleDocId = 'your-google-doc-id' // google doc ID
  this.outputFolderId = 'your-google-drive-folder-id' // google drive資料夾ID
  this.googleFormEventData = event
  this.createDoc()
  this.renderDoc()
}

// 先從樣板合約中複製出一個全新的google doc(this.doc)
function createDoc() {
  const file = DriveApp.getFileById(this.googleDocId)
  this.outputFolder = DriveApp.getFolderById(this.outputFolderId)
  const today = Utilities.formatDate(new Date(), 'GMT', 'yyyy_MM_dd')
  this.docFilename = `${today}土地租賃契約`
  const copy = file.makeCopy(this.docFilename, this.outputFolder)
  this.doc = DocumentApp.openById(copy.getId())
}

// 將google doc中的變數替換為表單資料
function renderDoc() {
  const body = this.doc.getBody()
  body.replaceText(`{{name}}`, this.getFormData('甲方姓名'))
  body.replaceText(`{{amount}}`, this.getFormData('月租金'))
  body.replaceText(`{{city}}`, this.getFormData('管轄法院'))
  this.doc.saveAndClose()
}

// 方便取得google表單內容的method
function getFormData(property, first = true) {
  if(!this.googleFormEventData) return null
  if(!this.googleFormEventData.namedValues) return null
  if(!this.googleFormEventData.namedValues[property]) return null
  if(first == true) return this.googleFormEventData.namedValues[property][0]
  return this.googleFormEventData.namedValues[property]
}

 

前往trigger重新授權

因為上方的app script有用到新的權限(google doc/google drive讀寫)

因此需要前往trigger重新開啟編輯popup

並點擊儲存後重新授權給app script

2.png

否則執行後將會出現You do not have permission to call權限不足的錯誤訊息

 

完成! 提交表單測試

完成後

直接提交表單測試

就會看到輸出目錄自動產生一個google文件合約

開啟後就會看到變數被替換為表單資料

1.png

 

其他進階應用

 

自動產出PDF

如果需求上需要直接轉成PDF也很方便

透過document class的getAs method及folder class的createFile method

就可以直接輸出PDF在google drive目錄中

const pdfBlob = this.doc.getAs('application/pdf')
this.outputFolder.createFile(pdfBlob)