要怎麼簡單快速地做出客製化地文件?今天,我們會教用 GAS 搭配 Goolge Doc。那因為在 Google Slide 中的 Element 也是相同的,所以這邊就會講細一點,之後就可以一起服用。換句話說,今天會教說怎麼透過 GAS 調整 Google Doc 和 Google Slide 裡面的元素。那今天的問題可以有以下的排列組合——
雖然總共有 4x4 共 16 種的排列組合,我們會用案例一個個來說明。基本上前天講了講新增與讀取,昨天專注於刪除,今天終於可以講到「更新」了,就讓我們開始吧!
答案在今天的文章當中!
考慮到有些夥伴不一定會都看過前面的文章,就撈叨一點把基本步驟再次附上,如果會的夥伴可以直接跳到 Q1。
我們已經知道大致上,每一個 Google 文件都會有 Element (元件),且每一個 Element 都會有 Attribute (屬性)。今天我們主要會介紹藍色的 Element 的部分。
那我們把 Element 展開來看,裡面有很多小的物件,這邊抓出其中最常用的四種。分別是段落、照片、表格與清單。
那我們的目標就是透過讀取、寫入、更新與刪除(對的,參照 CRUD 的 format)來帶大家讓是怎麼操作這些表格。這邊就節錄一本書中的「段落、照片、表格與清單」,來作為今天我們的範例。
這一集我們有個重要的的觀念,也就是我們可以透過 getParent()
和 getChildren()
來取得上下層關係的物件。如果這個關係不懂,一定要回到前一天看,因為今天會大量用到。完整的上下層概念,可以參考 Google 的官方文件。
好,那我們就開始吧!
那這次我們不會用 Google Sheet,而是直接用 Google Doc 進入,借一下 D16 的影片。
一樣第一次會有存取驗證需要大家按一下。這邊仍是借用一下 D2 的影片。
getBody()
我們先用 getActiveDocument()
抓出正在綁定的文件;那假設我們都是針對主要內文(Body)的部分,所以我們先設定好 getbody()
。
let doc_body = DocumentApp.getActiveDocument().getBody();
因為更新有比較複雜的細節,我們就先來講講刪除。
那不管是刪除還是更新,我們都要先取得目標的物件。所以先讓我們取得清單,為此我們先做出三份清單。
接著,我們要讀取清單,並進行更動。
getListItems()
讀取清單接下來,我們試著用 getListItems()
來讀取清單的內容。
function readLists(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
for (let i=0; i < list_items.length; i++){
Logger.log(list_items[i].getText())
}
}
理論上跑起來會是清單含有的所有文字,但這是理論上。來確認一下跑起來如何——
看起來沒抓到範圍,是怎麼回事?原因是getListItems()
要抓的是「Google Doc」認可的清單。而我只是打上點點或數字,並不代已經是它認可的清單格式,這個時候就會出問題。換句話說,我們要重新確認一下自己的文本。以下示範如何調整成正確的格式——
好,那實際運作的 getListItems()
會跑出什麼樣子呢?(注意,影片中的清單為了說明,有再微調)
可以得知:
也附上小測驗第一題的答案。
getListId()
和 setListId()
設定清單項目的歸屬要注意 getListItems()
得到的不會是「有幾份清單」,而是有幾個清單的子項目。截稿的目前 GAS 未開放可以直接操作的 List Item。那,我們要怎麼知道這些項目屬於相同的 List 呢?這時要用到 getListId()
來核對。
function getListItemsParentTable(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
for (let i=0; i < list_items.length; i++){
Logger.log(list_items[i].getText() +" "+list_items[i].getListId())
}
}
這邊我們直接用圖解,說明執行後的結果。
可以看出,只要中間有隔出一行,就會被視為不同的表單。那我們要如何讓就算有空一行,仍被視為同樣的表單呢?這時就要用到 setListId()
了。假如我想用一段程式碼,讓圖中的所有合格清單項目,都歸屬於同一個清單。
function setListItemsSameList(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
let item_1 = list_items[0];
for (let i=0; i < list_items.length; i++){
list_items[i].setListId(item_1).setGlyphType(DocumentApp.GlyphType.NUMBER);
}
}
跑起來長這樣——
可以發現,被認為是清單的物件數字全部變成連貫的了!(原本藍色的 1 2 3 變為 5 6 7)那這邊有兩點要注意。
setListId()
後面要放的 不是 ID,而是你想要設定跟它作為同一張表的 ListItem
,以上面的程式碼來說,我就以第一個 item_1 作為歸屬處。.setGlyphType(DocumentApp.GlyphType.NUMBER)
來讓 List 可以是數字為基底。有人問說為什麼紅色的範例清單沒有動,因為它不是 Google Doc 認可的清單,在上頭的 Step 3 的有提到原因與改進方式。
好,那總算搞定清單的讀取了,接著就讓我們用來玩「更新內容」吧!
setNestingLevel(nestingLevel)
設定層級在清單中,我們很常用 Tab
鍵來調整層級,而這功能在 GAS 中即是 setNestingLevel(nestingLevel)
,預設的層級即為 0。那我們來看如何設置從 0 開始的層級。
function setListItemLevel(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
for (let i=0; i < list_items.length; i++){
Logger.log(i)
list_items[i].setNestingLevel(i);
}
}
跑起來長這樣——
那為什麼還有一個藍色的項目沒有變成子項目呢?因為 nestingLevel
的最大值是 8,也就是我們最多只能創造九層(0 ~ 8)。
removeFromParent()
將單一 ListItem 拔除如果我們只想移除其中特定的 Item,不想影響其上或下階層的內容,那我們可以用 removeFromParent()
。抓出想移除的 ListItems,將其移出。
function removeItemListFromParent(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
for (let i=0; i < list_items.length; i++){
if (i==7){
list_items[i].removeFromParent();
}
}
跑出來長這樣——
merge()
將兩個 ListItem 合併如果今天我們想將層級不同的清單(List)進行合併,要怎麼做?這時可以透過 Merge。這邊我們試著合併範例清單二的第一項(區別技術性與調適性挑戰,ListItemIndex = 7)和第三項(聆聽選外之音,ListItemIndex = 9)
function mergeListItemss(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
for (let i=0; i < list_items.length; i++){
if (i==7){
list_items[i].merge();
}
}
}
跑起來長這樣——
我這邊示範了兩組數字,分別是 i==7 & i==9 ,可以發現其合併的邏輯是:「與下面一項合併」,更細節來說,是
replaceText()
更改文字內容那總算到我們的文字部分拉, replaceText(parttern, replacement)
其實在前幾章就有偷用到,這邊完整講述一下使用方式。
pattern
的部分是要用所謂的「正規表示法」,那部分我們再找時間細講,我自己的建議是直接寫上「要改的文字內容」;replacement
則要放你想換上的東西,可以理解成「另外的文字」。當然進階版你要換成圖片或其他物件其實是可以的。那我們來看看怎麼用,這邊我就單純示範將句號換成驚嘆號的方式——
function replaceText(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
for (let i=0; i < list_items.length; i++){
list_items[i].replaceText("。","!");
}
}
跑起來長這樣——
提醒的是,我這樣的指令碼,是針對 ListItem 進行更改,文中其他的段落或表格都不會被動到。
insertText()
插入文字內容那這邊我們就實作一個用 insertText(childIndex, text)
在每個 ListItem 的之前,插入一個數字。
function readLists(){
let doc_body = DocumentApp.getActiveDocument().getBody();
let list_items = doc_body.getListItems();
for (let i=0; i < list_items.length; i++){
list_items[i].insertText(0, i)
}
}
跑起來長這樣——
那可以發現:
那如果設定數字為 2 的話,各位客官可以自己跑一次看看,會出現錯誤。因為對 ListItem
來說,下面唯一的 Child ,就是列點內的內容。
今天學的大多都可以套用到「段落」與「表格」,不過要搭配前面兩天一起消化。那如果是非文字部分像是照片、圖表,基本上更新的方式建議直接刪掉舊的,加上新的。其他的今天的內容應該都可以 Cover。
好,那今天就到這邊。今天我們主要交代了 Element 的「如何更新」;如果還有問題,透過留言之外,也可以到 Facebook Group,想開很久這次鐵人賽才真的開起來,歡迎來當 Founding Member。如果不想錯過可以訂閱按讚小鈴鐺(?),也歡迎留言跟我說你還想知道什麼做法/主題。我們明天見。