如果你常常得為週會或提案熬夜排簡報,其實不用再一頁頁複製貼上。Google Apps Script 裡的 Google Slides 服務,就是讓你用程式幫你生投影片的那雙手。它能建立簡報、插入文字/圖片/表格、套用版面,還能一次全檔替換佔位字。
小案子用 SlidesApp 就很順;大量頁面就交給進階 Slides(API)批次處理。這篇會先用白話把概念、類別和常見任務講清楚,再帶你從零寫到實戰,並整理踩雷與維護心法,讓簡報製作變成穩定可重複的流程。希望本篇文章能夠幫助到需要的您。
目錄
{tocify} $title={目錄}
為什麼要用 Slides 服務?
如果你經常需要做週會簡報、銷售提案、或把試算表/表單的資料自動匯入投影片,那你不必再手動複製貼上。Google Apps Script 的 Slides 服務(SlidesApp)能讓你用程式去建立、讀寫、修改Google 簡報(Slides),包含新增投影片、插入文字/圖片/表格、套版面、替換佔位文字、調整樣式與版面等。它是內建服務,直接在 Apps Script(雲端端 JS 環境)可用;同時也有一個進階服務(Advanced Slides),可呼叫 Google Slides API v1 做更底層、批次化的操作。官方說明清楚指出 Slides 服務可建立、存取與修改簡報;進階服務則把 REST API 帶進 Apps Script 環境,支援 batchUpdate 等高階能力。
快速定位:
Slides 服務(SlidesApp)=「好上手、JS 物件導向」,適合 80% 自動化需求。
進階 Slides 服務=「直通 Slides API」,適合需要批次效能與 API 完整表現的情境。
整體版圖:Slides 服務 vs Slides API(你該選哪個?)
Slides 服務(SlidesApp):像在操作活生生的簡報物件,有 SlidesApp, Presentation, Slide, PageElement, Shape, TextRange, Table, Image… 這些類別與方法。寫起來直覺、語意清楚,對初學者超友善。
進階 Slides 服務(Advanced Slides/Slides API):用 API 請求(如 presentations.batchUpdate)一次送出多個操作,效能與一致性更好(尤其大量改版面或跨百頁簡報的情況)。同時也能觸及 SlidesApp 還沒包裝到的細節。
選擇建議:
1. 小量、自動填稿、替換文字、插幾張圖:先用 SlidesApp。
2. 大量批次(上百頁)、需要 API 才有的操作:用進階 Slides(或直接用各語言的 Slides API 用戶端)。
核心概念與名詞對照
Presentation:整份簡報檔本身(.getSlides() 取得所有頁)。
Slide:單一投影片頁面(大多基於 Master 與 Layout)。
PageElement:投影片上的任何元素總稱:文字框(Shape/文本框)、圖片(Image)、線條、表格(Table)等。
Shape(文本框/形狀):放文字的地方最多;其中文字由 TextRange 表示,可改字體、字色、對齊、超連結等。
Table:表格元素,可逐格寫入。
Master / Layout / NotesPage:版面與備註頁(想做一致風格、佈局,靠它們)。
以上類別與方法在 SlidesApp 參考手冊能查到完整清單與示例。
授權與存取:我要怎麼開始?
1. 在雲端硬碟「+ 新增 → 更多 → Apps Script」,或在任何 Google 文件中「擴充功能 → Apps Script」。
2. 程式內直接 SlidesApp.create('我的簡報') 或 SlidesApp.openById(PRESENTATION_ID) 開檔。第一次執行會跳出授權畫面,允許腳本存取你的簡報檔。
3. 若使用進階 Slides 服務:到「服務」面板啟用「Slides API」,之後可用 Slides.Presentations.batchUpdate() 等呼叫;同時建議用批次請求整合多個操作以提升效能。
Slides 服務(SlidesApp)類別地圖與常用方法
1. 入口:SlidesApp
開啟或建立簡報:openById(), openByUrl(), create()。
取得目前開啟的簡報:getActivePresentation()。
常用枚舉(列舉型別):對齊、顏色、形狀種類、定位方式等(實務上能避免魔術字串)。
2. Presentation
取頁:getSlides()
取主版、版面:getMasters(), getLayouts()
全域替換文字:replaceAllText(find, replace)(大量替換很實用)。
3. Slide
新增元素:insertShape(), insertImage(), insertTable()
控制順序、複製、刪除:duplicate(), remove()
以版面建立頁面,保持一致視覺。
4. PageElement 與子型別
Shape(文字框/形狀):getText() → 取得 TextRange;setContentAlignment() 等。
TextRange:.setText(), .replaceAllText(), .getTextStyle()(字體、大小、粗斜體、顏色、底線、連結)。
Image:設定大小、位置;可從 URL 插入。
Table:存取 getCell(row, col).getText().setText('...')。
從零開始的實作:由小到大三段式
範例 A:建立簡報、加一頁、放一段文字
function demoCreateAndWrite() {
// 1) 建立新簡報
const pres = SlidesApp.create('每週例會 - 自動化產生');
// 2) 取得第一頁(建立後自帶一頁)
const slide = pres.getSlides()[0];
// 3) 插入一個文字框(形狀)
const shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 50, 50, 600, 120);
shape.getText().setText('本週重點與行動項目');
// 4) 粗體與大小
const style = shape.getText().getTextStyle();
style.setBold(true).setFontSize(28);
}
上述流程對應到 SlidesApp → Presentation → Slide → Shape → TextRange 的操作鏈。類別與方法在官方參考可查。
範例 B:把試算表資料批次寫進表格與文字框
思路:先在版面上放好佔位文字(如 {{title}}、{{owner}}),用 replaceAllText() 做全域替換,再針對特定頁插入表格並逐格填值。
function demoReplaceAndTable() {
const pres = SlidesApp.openById('YOUR_PRESENTATION_ID');
// 1) 全域替換(標題與負責人)
pres.replaceAllText('{{title}}', 'Q4 行銷企劃');
pres.replaceAllText('{{owner}}', '行銷部 / Tina');
// 2) 在第二頁插入 4x3 表格並填資料
const slide = pres.getSlides()[1];
const table = slide.insertTable(4, 3);
const headers = ['項目', 'KPI', 'Owner'];
headers.forEach((h, i) => table.getCell(0, i).getText().setText(h));
const rows = [
['FB 廣告', 'CTR ≥ 2.5%', 'Allen'],
['SEO 內容', '新文 12 篇/月', 'Becky'],
['電商檔期', '轉換率 +15%', 'Charles']
];
rows.forEach((r, rIdx) => r.forEach((val, cIdx) => {
table.getCell(rIdx + 1, cIdx).getText().setText(val);
}));
}
replaceAllText() 屬於 Presentation 的常用方法;表格寫入則用 Table.getCell().getText().setText()。
範例 C:套版面、插圖、定位與樣式
function demoLayoutAndImage() {
const pres = SlidesApp.openById('YOUR_PRESENTATION_ID');
const slide = pres.appendSlide(pres.getLayouts()[0]); // 用預設第一個版面
// 插入圖片(x, y, w, h)
const image = slide.insertImage('https://picsum.photos/800/450', 60, 160, 640, 360);
// 插入標題文字框
const title = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 60, 60, 640, 80);
title.getText().setText('11 月活動視覺預覽').getTextStyle().setBold(true).setFontSize(32);
}
這裡示範 appendSlide()、getLayouts()、insertImage()、insertShape() 與 TextRange 的樣式操作。
進階:Advanced Slides 服務與批次更新
當你需要一次對很多頁做高度一致的修改(例如全檔字體替換、對齊調整、批量換圖),用 Slides 服務逐一呼叫會慢。進階 Slides 服務可把多個請求塞到 presentations.batchUpdate 一次送出,網路來回少、速度明顯提升。在 Apps Script 先於「服務」啟用 Slides API,然後像這樣用:
(示意:把第一頁的文字全改為粗體 24pt)
function demoBatchUpdate() {
const presId = 'YOUR_PRESENTATION_ID';
const requests = [
{
updateTextStyle: {
objectId: 'TEXT_BOX_OBJECT_ID',
style: { bold: true, fontSize: { magnitude: 24, unit: 'PT' } },
fields: 'bold,fontSize'
}
}
];
Slides.Presentations.batchUpdate({ requests }, presId);
}
官方指南建議把多個操作合併成單次 batch 請求以獲得最佳效能。
補充:若你改用 JVM 生態(例如 Kotlin/Java 服務端),也能用 Slides API Java Client(套件 com.google.api.services.slides.v1),同樣支援批次更新與完整 API。
常見任務清單
1. 建立簡報與命名:SlidesApp.create('名稱')。
2. 開啟既有簡報:openById(id) / openByUrl(url)。
3. 新增/複製/刪除投影片:appendSlide(), duplicate(), remove()。
4. 全檔替換佔位文字:Presentation.replaceAllText(find, replace)。
5. 插入圖片(URL 或 Blob):Slide.insertImage()。
6. 插入文字框並設定樣式:insertShape(ShapeType.TEXT_BOX) → getText().getTextStyle()。
7. 建立表格並逐格寫入:insertTable(rows, cols) → getCell(r,c).getText().setText()。
8. 讀取已存在元素:Slide.getPageElements(),再依型別處理。
9. 套版面/主版:用 getLayouts() / getMasters() 確保一致視覺。
10. 設定對齊、位置、尺寸:多數元素支援 setLeft/Top/Width/Height() 與對齊枚舉。
11. 套用超連結:透過 TextRange.getTextStyle().setLinkUrl()(Apps Script 端),或在 API 層級使用對應文字樣式欄位。
12. 批次更新(效能優化):Slides.Presentations.batchUpdate()。
常見錯誤與雷點
1. 搞混 Slides 服務 vs Slides API
現象:你抄了 SlidesApp 的範例,卻去找 API 回傳的 slides[0].shapes 之類路徑,結果是 undefined。
解法:確認你用的是哪個環(Slides 服務物件方法 vs REST API 結構)。API 的頁面元素通常走 pageElements。
2. 未啟用進階 Slides 服務就呼叫 Slides.*
現象:呼叫 Slides.Presentations.batchUpdate() 報錯。
解法:到 Apps Script「服務」啟用 Slides API,並使用正確的請求結構。官方文件有範例與建議批次化更新。
3. 想用 HEX 設色,但 API 只收 RGB
現象:丟 #FF8800 不生效。
解法:轉成 RGB(0–1 的小數或 0–255/再正規化),API 僅支援 RGB 欄位。
4. 替換文字同時要改樣式
現象:replaceAllText() 能換字串,但不能同時改樣式。
解法:先替換,再以 TextRange 或 API 的 updateTextStyle 批量處理;大型專案建議改用 batchUpdate 一次送。
5. 大量頁面逐一迴圈太慢
現象:100+ 頁,每頁多次呼叫,跑很久。
解法:能合併就合併,改用進階 Slides 的 batchUpdate。
6. 圖片插入失敗(存取權或 URL)
現象:insertImage(url) 報錯/無法載入。
解法:確認 URL 可匿名讀取或改用 Drive Blob;必要時先把圖片放在可公開讀取的位置。
7. 版面跑掉/樣式不一致
原因:手動插入元素 vs 版面定義衝突。
建議:多用 Layout 與 Master,在版面上留佔位(placeholder),再程式填值。
8. 權限/Scopes 不足
現象:首次執行或換帳號後報權限錯。
解法:重新授權;若走 API Client(Kotlin/Java),請檢查使用的作用域(SlidesScopes)。
效能、結構化與維護建議
1. 版面先行,資料後填
設計一份「範本簡報」:標題、內文、圖片區、表格位置都固定,程式只負責填資料與替換佔位符。這樣改版容易又穩定。
2. 批次化更新
多個樣式或內容改動,儘量收斂到一次 batchUpdate。API 官方建議這麼做,速度差很有感。
3. 抽離設定與資料
把字體大小、顏色、邊界與 X/Y/W/H 等寫入設定檔(JSON/試算表),程式只讀設定與資料源,後續維護不必改程式碼。
4. 錯誤處理與回滾策略
寫入前先複製一份簡報(版本備援);或將每次產生的結果另存新檔,利於除錯。
5. 日誌與標記
在元素的文字裡加隱藏標記(例如 <!--DATA:section=overview-->),方便之後找元素位置與狀態(Apps Script 可讀寫字串、API 可讀文字元素)。
與其他 Google 服務的整合思路
Sheets → Slides:
把 KPI、銷售、排行、圖表導入簡報(可用圖表嵌入或資料貼上)。
Docs → Slides:
把文章摘要或重點轉為簡報頁。
Calendar / Gmail → Slides:
周報、會議摘要、問題單彙整自動生成簡報。
雲端硬碟 → Slides:
循序讀取雲端圖片,批次做視覺牆/作品集。
(整合與 UI 擴充亦可透過 Apps Script 的「自訂選單、對話框、側邊欄」完成。)
問題集
1. 我要改整份簡報的字體與大小,有沒有一鍵完成?
沒有單一神函式;可配合 Presentation.getSlides() → 逐頁找 TextRange,或用 API batchUpdate 的 updateTextStyle。
2. 想要把 {{placeholder}} 全部換掉並套樣式?
先 replaceAllText(),再對匹配結果或定位到的元素做樣式;或直接用 API 的 updateTextStyle。
3. 可以從 URL 插入圖片嗎?
可以,Slide.insertImage(url, x, y, w, h);確保 URL 可讀。
4. 怎麼做表格並填資料?
insertTable(r,c) 建表 → getCell(r,c).getText().setText()。
5. 我要處理超連結文字
透過 TextRange.getTextStyle().setLinkUrl() 設置。
6. HEX 色碼可用嗎?
API 端不接受 HEX;需轉 RGB。
7. 要不要自己刻版面?
建議先設計好「範本簡報」的 Master/Layout,再填資料,維護性最高。
8. 效能卡住怎麼辦?
儘量合併操作到 batchUpdate,避免大量回合。
9. Slides 服務可做的一定等於 API 嗎?
多數任務 OK,但 API 細節更全;缺少的就走進階服務。
10. Google 官方對 Slides 產品定位?
工作區產品頁面:雲端簡報協作、模板、AI 輔助等。這是應用層,不等於開發 API,但幫助你理解產品邏輯。
