✦ 問問 Gemini 寫 GAS ✕ 內建 Gemini Spark 協同實戰

Office GAS 雙劍合璧工作台
讓 Gemini 當大腦、GAS 當自動化雙手

不用背誦程式語法、也不必申請複雜的外部 API 金鑰!在 Google Workspace(Sheets、Docs、Slides)中,直接用「內建 Gemini Spark (✦)」負責語意理解、摘要與內容生成,再請「問問 Gemini (Ask Gemini)」幫我們撰寫 Google Apps Script (GAS) 負責固定格式、批次拆表、自訂選單與跨產品自動化,兩者相得益彰!

✦ 內建 Gemini Spark:動腦生成與分析 💬 問問 Gemini:白話文轉 GAS 程式碼 ⚙️ Apps Script:一鍵批次與跨檔連動 👤 講師:謝老師
Google Workspace 辦公自動化「雙劍合璧」黃金分工 ✦ 第一把劍:內建 Gemini Spark 【AI 語意大腦|非結構化創意】 • 摘要會議紀錄、撰寫企劃與信件 • 試算表情緒分類、標籤萃取與翻譯 • 簡報大綱構思與視覺配圖生成 ⚙️ 第二把劍:問問 Gemini 寫 GAS 【自動化雙手|100% 精準批次執行】 • 建立專屬「自訂功能表按鈕」 • 批次拆表、統一字型配色、清格式 • 跨產品連動 (Sheets➔Docs➔Gmail) ✕ 🏆 相得益彰:免寫程式、免串 API Key,3 分鐘完成企業級 AI 自動化工作流! 應用涵蓋:Google Sheets 試算表 ✕ Google Docs 文件 ✕ Google Slides 簡報 ✕ Gmail & Calendar

💡 Tab 1|為什麼要把「問問 Gemini 寫 GAS」與「內建 Gemini Spark」混合使用?

雙劍合璧核心方法論

許多人在使用 Google Workspace 時常遇到兩個極端:只用右側的「✦ 內建 Gemini Spark」,雖然能幫忙寫文案、做摘要,但遇到「要把 100 筆資料拆成 10 個分頁、套用公司標準配色、或是批次轉成 PDF 寄信」時,AI 側邊欄無法替你執行這些固定流程;反過來說,若想寫 Google Apps Script (GAS),一般行政與業務人員又覺得寫程式門檻太高。把兩者結合,剛好完美互補!

① 只用內建 Gemini Spark (✦) 半自動

  • 強項:擅長自然語言生成、摘要文件、試算表智慧填寫與生圖。
  • 瓶頸:每次都要手動下指令、無法一鍵批次拆分幾十個分頁、無法固定套用精準色碼與欄寬、無法自動排程寄信。

② 傳統自己手寫 GAS 程式 高門檻

  • 強項:可控制 Google 生態系所有按鈕、格式與跨檔案自動化。
  • 瓶頸:需背誦 SpreadsheetApp、DocumentApp 等 API 語法;若要在 GAS 裡呼叫外部 AI 還要申請 API Key 與綁信用卡。

③ 問問 Gemini 寫 GAS ✕ 內建 Spark 🏆 雙劍合璧

  • 大腦交給內建 Spark:直接在畫面裡用 Gemini 完成摘要、分類、草稿與配圖(免 API Key)。
  • 雙手交給 GAS(由問問 Gemini 代寫):用白話文請 Gemini 寫出 GAS 腳本,在頂部產生「專屬按鈕」,1 秒執行排版、拆表與跨檔寄信!
「內建 Gemini Spark 動腦」✕「問問 Gemini 寫 GAS 動手」標準協作三部曲 Step 1|內建 Gemini Spark 動腦 在檔案內直接生成或整理內容 📊 Sheets:智慧分類 / 情緒貼標 把雜亂回饋轉成結構化欄位內容 📝 Docs:Help me write 撰寫初稿 根據會議紀錄或大綱快速產出企劃文 📽️ Slides:構思大綱與生成配圖 產出分頁結構與高質感視覺插圖 Step 2|請「問問 Gemini」寫 GAS 用自然語言描述你要的自動化動作 💬 對「問問 Gemini」這樣說: 「請幫我寫一段 Google Sheets 的 GAS, 在頂部新增『報表自動化』選單,點擊後 依 C 欄部門自動拆成獨立分頁並美化…」 function onOpen() { SpreadsheetApp.getUi() .createMenu('🚀 自動化')... Step 3|貼入 GAS 變成專屬按鈕 從此一鍵執行,100% 穩定不走鐘 1. 擴充功能 ➔ Apps Script 貼上 取代預設程式碼,按磁碟片儲存 2. 重新整理網頁出現「自訂選單」 同事也能直接點按鈕,不必懂程式碼 ⚡ 1 秒完成拆表、排版、轉檔與寄信

🛠️ 零基礎必看:如何把「問問 Gemini」寫好的 GAS 放進 Google 產品裡?

只需做一次・4 步驟完成
STEP 1|開啟編輯器

點選頂部「擴充功能 ➔ Apps Script」

在 Google Sheets、Docs 或 Slides 上方選單列,點擊「擴充功能 (Extensions)」➔「Apps Script」,會開出一個新分頁。

STEP 2|全選貼上並儲存

清空原本的 myFunction 後貼上

把編輯器裡預設的幾行字全部刪掉,貼上「問問 Gemini」幫你寫好的完整程式碼,按上方💾 儲存專案(或 Ctrl+S)。

STEP 3|首次執行與授權

點選「▷ 執行」並通過安全性核准

第一次執行時 Google 會跳出「需要授權」視窗,這是因為腳本是你自己寫的(尚未送交 Google 商店審核),請安心放行。

STEP 4|回到檔案點選單

重新整理檔案,上方出現專屬按鈕!

只要在 Prompt 裡請 Gemini 加上 onOpen() 自訂選單,回到試算表/文件按 F5 重整,上方就會長出你的專屬魔法按鈕!

⚠️ 第一次執行 GAS 跳出「Google 尚未驗證這個應用程式」怎麼辦?(必教口訣)
這是初學者最常卡關的地方!當跳出警告畫面時,請依序點擊:
① 點擊左下角小字「進階 (Advanced)」 ➔ ② 點擊最下方「前往『未命名專案』(不安全)」 ➔ ③ 點擊「允許 (Allow)」。
(因為這支程式就住在你自己的 Google 雲端硬碟裡、只有你自己能用,所以百分之百安全!)

📥 實戰測試底稿範本下載中心(.xlsx / .docx / .pptx 完整對應各 Tab 欄位)

📦 一鍵打包下載全套 4 份底稿 (.zip)

為了讓你與學員能立即動手測試本頁所有 GAS 程式碼與內建 Gemini Spark,我們已預先製作好 4 份結構完全對齊 GAS 腳本欄位的 Office 底稿範本(故意保留未美化素色、殘留 **星號** 與急件測試資料,執行 GAS 時一鍵變身超有感!):

TAB 2 底稿|Excel (.xlsx)

📊 客戶回饋與拆表實戰底稿

內含「總表(12筆含負面急件與4大部門)」+「練習區_待Gemini分析」雙工作表。

📥 下載 Tab2_Sheets.xlsx
TAB 3 底稿|Word (.docx)

📝 企劃書清除星號與排版底稿

內含大量殘留 **粗體星號**、H1/H2 標題、2 張素色表格與【待辦/急件/重要】關鍵字。

📥 下載 Tab3_Docs.docx
TAB 4 底稿|PowerPoint (.pptx)

📽️ 簡報速生器與講稿底稿

第 2 頁內建可直接複製的 5 頁「標題|重點|口白」大綱,一鍵長出投影片與備忘稿!

📥 下載 Tab4_Slides.pptx
TAB 5 底稿|Excel (.xlsx)

🚀 跨產品自動草稿與寄信底稿

內含 A~E 欄學員名單、Gemini 專屬回饋與「已寄出防呆跳過」測試列,可立即產生 Gmail 草稿。

📥 下載 Tab5_跨產品.xlsx
💡 手動上傳 Office 檔案(.xlsx / .docx / .pptx)到 Google 雲端硬碟後的關鍵轉檔提醒:
當你把 .xlsx、.docx 或 .pptx 上傳到 Google Drive 並點開時,若檔名旁邊出現綠/藍/橘色的 .XLSX / .DOCX / .PPTX 標籤(代表處於 Office 相容檢視模式,此時不會顯示 Apps Script 選單),請點選左上角選單:
👉 「檔案 (File)」 ➔ 「另存為 Google 試算表 / Google 文件 / Google 簡報」,就會立刻開啟原生 Google 檔案並出現 「擴充功能 ➔ Apps Script」!

🎯 請「問問 Gemini」幫你寫 GAS 的黃金四要素公式

萬用 Prompt 模板

想讓「問問 Gemini」一次寫出不會報錯、又好用的 GAS 程式碼,提示詞只要包含以下 4 個要素:

🧩 GAS 詠唱黃金四要素拆解
1. 【目標產品與觸發方式】 指定是 Google Sheets / Docs / Slides,並要求「在檔案頂部新增一個自訂選單(使用 onOpen)」,這樣才不用每次進後台按執行。 2. 【明確的欄位位置或目標結構】 告訴 Gemini 資料在哪裡(例如:「第 1 列是標題列,C 欄是部門名稱,F 欄是金額」)。 3. 【要執行的具體動作與視覺標準】 清楚列出步驟(例如:「依 C 欄拆分成不同分頁、標題列設為深藍底白字 #1a73e8、凍結第一列、自動調整欄寬」)。 4. 【防呆與完成提示】 加上「若分頁已存在請先清空更新而非報錯,執行完畢後跳出 Toast 或 Alert 提示完成」。
📋 萬用 GAS 生成提示詞模板(可直接複製修改)
請幫我寫一段適用於【Google Sheets / Docs / Slides】的 Google Apps Script (GAS) 完整程式碼。

需求如下:
1. 【自訂選單】:請包含 onOpen() 函式,在頂部選單新增一個名為「🚀 AI 自動化工具箱」的選單,裡面有一個項目叫「【填入功能名稱】」。
2. 【資料結構】:我的檔案中,【描述資料位置,例如:工作表「總表」的第 1 列是標題,A 欄是日期、B 欄是客戶、C 欄是 Gemini 產出的分類標籤】。
3. 【執行動作】:當我點擊選單按鈕時,請自動幫我:
   - 動作一:【例如:依照 C 欄的分類標籤,自動建立對應名稱的子工作表並將資料複製過去】
   - 動作二:【例如:將所有分頁的第 1 列標題設為深藍底(#1a73e8)白字粗體、凍結第 1 列,並自動調整欄寬】
4. 【防呆機制】:如果子工作表已經存在,請覆寫更新內容不要報錯;全部執行完成後,請跳出視窗提示「處理完成!」。
請提供完整可貼上執行的程式碼,並加上繁體中文註解。

🔥 進階神技:讓「問問 Gemini」直接讀 .html 教材,網頁秒變專屬 AI 助教!

附 [HTML] 精準來源標記

很多人以為「問問 Gemini (Ask Gemini)」只能拿來摘要一般新聞網頁或看 PDF;其實直接把 .html 網頁檔(例如您現在正在看的這份 index.html 教材,或從系統匯出的 HTML 報表)餵給「問問 Gemini」,效率高得驚人!
因為 HTML 具備天然的語意標籤(<title>、<h1>~<h4>、<table>、<section>),AI 不必像讀 PDF 那樣猜測跨頁排版,能在 1 秒內精準讀懂 1,800 行教材架構並標註 [HTML] 引用出處!

📸 講師實測:把本頁 index.html 丟給「問問 Gemini」秒梳理解析 🔍 點圖放大
問問 Gemini 讀取 index.html 教材並附上 [HTML] 引用標籤實測截圖

▲ 實測亮點觀察:① 上傳或讀取 </> index.html 後,只輸入一句「我是AI老師,我想指導學生善用 gemini spark+ask gemini…」;② AI 瞬間識別出「謝老師規劃之 Office GAS × ✦ 問問 Gemini 雙劍合璧實戰工作台」,並附上 [HTML] 來源標籤自動梳理出核心脈絡與教學指導架構!

💡 為什麼把本頁 .html 餵給「問問 Gemini」是學員課後最強外掛?
  • 免複製貼上範例程式碼:直接叫它看這份 HTML 裡的第幾個 Tab,幫你改成你公司的欄位!
  • 零排版錯亂:.html 的結構樹(DOM)比 PDF 更乾淨,AI 抓表格與程式碼區塊 100% 不斷行。
  • 一源多用(老師/主管必備):一秒把整份 HTML 實戰教材轉成「部門內訓大綱」、「SOP 檢核表」或「課後測驗題」。
🎓 用法 A|老師/種子講師:一秒梳理教材架構與帶課話術
我是 AI 老師(或部門內部種子講師),我想指導學員善用「內建 Gemini Spark + 問問 Gemini (Ask Gemini) 寫 GAS」。請讀取這份 index.html 教材,幫我梳理出:
1. 這份教材的核心脈絡與教學亮點
2. 適合帶領零程式基礎學員實作的 3 個循序漸進步驟
3. 每個步驟容易卡關的提醒與課堂引導提問
🛠️ 用法 B|學員實作:請 AI 參考本頁 HTML 範例直接客製化改寫 GAS
請讀取這份 index.html 教材中「Tab 2(Google Sheets 拆表美化)」與「Tab 5(跨產品寄信)」的 GAS 範本結構。
現在請幫我改寫成適合我部門的 GAS 程式碼:
- 我的總表名稱叫「115年教育訓練報名表」
- 第 1 列是標題,B 欄是「學員姓名」、D 欄是「所屬處室」、F 欄是「Email」、H 欄是「審核狀態」
- 請幫我加上頂部自訂選單:一鍵依 D 欄「所屬處室」拆成獨立分頁美化,並在 H 欄打勾時自動寄出錄取通知信!

📊 Tab 2|Google Sheets 試算表:AI 智慧分類貼標 ✕ GAS 一鍵拆表與高質感美化

📥 下載本頁實測底稿 (.xlsx)
🧪 實測底稿說明(Tab2_Sheets_客戶回饋與拆表實戰底稿.xlsx):
內含兩個工作表:① 「總表」(已預填 12 筆客戶回饋、情緒判定與 4 大負責部門,故意保持素色,上傳轉為 Google 試算表後可直接貼入下方 GAS 測試「紅底警示+一鍵拆出 4 個部門分頁」);② 「練習區_待Gemini分析」(僅含 A~C 欄原始回饋,供練習用右側 ✦ 問問 Gemini 自動填出 D~F 欄)。

真實工作痛點:當你收回 200 筆「客訴與問卷回饋」或「各部門採購申請單」時,既需要看懂文字內容並分類(語意理解),又需要把總表依部門或情緒拆成獨立分頁、標記紅色警示、鎖定表頭並美化格式(重複性苦工)。看我們如何用「內建 Gemini Spark + Ask Gemini 寫 GAS」在 2 分鐘內搞定!

Google Sheets 雙劍合璧流程:先用內建 Gemini 填好 AI 欄位,再用 GAS 一鍵拆表美化 ① 內建 Gemini Spark (✦) 動腦填欄位 在試算表 D 欄、E 欄交給 AI 判斷: • A~C 欄:日期|客戶|原始回饋內容 • D 欄 (✦ AI 情緒):正面 / 中立 / 負面急件 • E 欄 (✦ AI 派工部門):客服部 / 物流部 / 產品部 💡 用法:打開右上角「✦ 問問 Gemini」側邊欄 或選取範圍使用智慧填寫,批次產出 D、E 欄! ② 問問 Gemini 產出 GAS 腳本 請 Gemini 把固定苦工寫成選單按鈕: 1. 自動標記「負面急件」整列淺紅底 2. 依 E 欄「派工部門」自動拆分成 獨立子工作表(客服部/物流部…) 3. 自動設定墨綠標題列、斑馬紋、 凍結首列與自動欄寬 4. 自動產出「📊 部門統計摘要表」 ③ GAS 一鍵執行成果(1 秒完成) 頂部選單:🚀 報表自動化 ➔ 一鍵拆表與美化 🔥 負面急件自動亮紅燈提醒主管優先處理 底部自動長出整齊分頁標籤: [總表] [📊統計摘要] [客服部] [物流部] [產品部] 每個分頁皆已套好專業表頭、欄寬與凍結窗格!
✦ 第一步(動腦):在 Google Sheets 裡請「內建 Gemini Spark」生成分類與情緒標籤
打開試算表右上角的 ✦ 問問 Gemini 側邊欄,輸入:
「請幫我分析目前工作表 C 欄的『客戶回饋內容』,幫我建立表格或填入 D 欄『情緒判定(正面/中立/負面急件)』與 E 欄『建議負責部門(客服部/物流部/產品部)』及 F 欄『一句話處理建議』。」
💬 第二步:對「問問 Gemini」下的 GAS 提示詞
請幫我寫一段 Google Sheets 的 Google Apps Script (GAS) 程式碼。

我的試算表第一個工作表為「總表」,第 1 列是標題列(A:日期、B:客戶名稱、C:回饋內容、D:情緒判定、E:負責部門、F:處理建議)。

請幫我寫出以下功能:
1. 建立 onOpen() 選單,名稱為「📊 AI 報表神器」,內含:
   - 「1. 標記急件並美化總表」
   - 「2. 依負責部門自動拆出子工作表」
2. 當點選「1. 標記急件並美化總表」時:
   - 將第 1 列標題設為深綠底(#0d9488)白字粗體、置中,並凍結第 1 列。
   - 檢查 D 欄(第 4 欄),若內容包含「負面」或「急件」,將該筆整列背景設為淺紅底(#fee2e2)、文字深紅粗體;其餘資料列設為白灰相間的視覺效果。
   - 自動調整 A 到 F 欄的欄寬。
3. 當點選「2. 依負責部門自動拆出子工作表」時:
   - 讀取「總表」E 欄(第 5 欄)的所有不重複部門名稱。
   - 為每個部門建立獨立工作表(若已存在則先清空內容再寫入),複製標題列與屬於該部門的所有資料列,並同樣套用深藍標題列(#1a73e8)、凍結首列與自動調整欄寬。
   - 完成後跳出視窗告知共拆出幾個部門分頁。
⚙️ 產出的 GAS 完整程式碼(可直接貼入 Apps Script)
/**
 * Google Sheets 雙劍合璧實戰:急件標記、報表美化與自動依部門拆表
 * 講師:謝老師|AI 辦公自動化實戰範例
 */
function onOpen() {
  const ui = SpreadsheetApp.getUi();
  ui.createMenu('📊 AI 報表神器')
    .addItem('1. 標記急件並美化總表', 'formatMainSheet')
    .addItem('2. 依負責部門自動拆出子工作表', 'splitSheetsByDepartment')
    .addToUi();
}

/**
 * 功能一:美化總表並自動將「負面/急件」整列標記為淺紅底警示
 */
function formatMainSheet() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('總表') || ss.getSheets()[0];
  const lastRow = sheet.getLastRow();
  const lastCol = sheet.getLastColumn();
  if (lastRow < 2) {
    SpreadsheetApp.getUi().alert('目前沒有足夠的資料列可處理!');
    return;
  }

  // 1. 設定第 1 列標題格式與凍結
  const headerRange = sheet.getRange(1, 1, 1, lastCol);
  headerRange
    .setBackground('#0d9488')
    .setFontColor('#ffffff')
    .setFontWeight('bold')
    .setHorizontalAlignment('center');
  sheet.setFrozenRows(1);

  // 2. 讀取資料並依 D 欄(第 4 欄)情緒判定標色
  const data = sheet.getRange(2, 1, lastRow - 1, lastCol).getValues();
  const bgColors = [];
  const fontColors = [];
  const fontWeights = [];

  for (let i = 0; i < data.length; i++) {
    const sentiment = String(data[i][3] || '');
    const isUrgent = sentiment.includes('負面') || sentiment.includes('急件');
    const rowBg = isUrgent ? '#fee2e2' : (i % 2 === 0 ? '#ffffff' : '#f8fafc');
    const rowColor = isUrgent ? '#991b1b' : '#1e293b';
    const rowWeight = isUrgent ? 'bold' : 'normal';

    bgColors.push(new Array(lastCol).fill(rowBg));
    fontColors.push(new Array(lastCol).fill(rowColor));
    fontWeights.push(new Array(lastCol).fill(rowWeight));
  }

  const bodyRange = sheet.getRange(2, 1, lastRow - 1, lastCol);
  bodyRange.setBackgrounds(bgColors)
           .setFontColors(fontColors)
           .setFontWeights(fontWeights)
           .setVerticalAlignment('middle');

  sheet.autoResizeColumns(1, lastCol);
  ss.toast('總表美化與急件紅底標記完成!', '✅ 執行成功', 4);
}

/**
 * 功能二:依 E 欄(第 5 欄:負責部門)自動拆分獨立工作表
 */
function splitSheetsByDepartment() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const mainSheet = ss.getSheetByName('總表') || ss.getSheets()[0];
  const allValues = mainSheet.getDataRange().getValues();
  if (allValues.length < 2) return;

  const headers = allValues[0];
  const deptMap = {};

  // 依第 5 欄 (index 4) 分組
  for (let i = 1; i < allValues.length; i++) {
    const row = allValues[i];
    const deptName = String(row[4] || '未分類').trim();
    if (!deptMap[deptName]) deptMap[deptName] = [];
    deptMap[deptName].push(row);
  }

  const deptNames = Object.keys(deptMap);
  deptNames.forEach(dept => {
    let targetSheet = ss.getSheetByName(dept);
    if (!targetSheet) {
      targetSheet = ss.insertSheet(dept);
    } else {
      targetSheet.clear();
    }

    const outputRows = [headers, ...deptMap[dept]];
    targetSheet.getRange(1, 1, outputRows.length, headers.length).setValues(outputRows);

    // 美化子工作表標題與欄寬
    targetSheet.getRange(1, 1, 1, headers.length)
      .setBackground('#1a73e8')
      .setFontColor('#ffffff')
      .setFontWeight('bold');
    targetSheet.setFrozenRows(1);
    targetSheet.autoResizeColumns(1, headers.length);
  });

  SpreadsheetApp.getUi().alert('🎉 拆表完成!共自動更新了 ' + deptNames.length + ' 個部門工作表:\n' + deptNames.join('、'));
}

📸 零基礎手把手實機圖解:從「雙 AI 生成」到「首次授權放行」與「一鍵拆表美化」(10 步驟全紀錄)

🔍 點擊任一截圖皆可全螢幕放大檢視

許多同學第一次貼上 GAS 按下「執行」時,看到 Google 跳出「需要授權」與「這個應用程式未經 Google 驗證」紅色三角形警告就會嚇到不敢點!其實這只是因為這段腳本是你自己剛建立的私人工具(未上架公開商店),只要照著下方 Step 4 ~ Step 7 點選「進階 ➔ 前往未命名的專案 ➔ 繼續」(每份檔案只需授權一次),就能立刻解鎖上方專屬選單!

Step 01|雙劍合璧:試算表 Gemini 語意貼標 + 問問 Gemini 寫出 GAS 🔍 點圖放大
Step 1 試算表 Gemini 貼標與問問 Gemini 生成 GAS 程式碼
先用試算表內建 Gemini 自動填妥 D 欄(情緒判定)、E 欄(負責部門)、F 欄(處理建議);再點開 Chrome 右上角「✦ 問問 Gemini」,請它依目前試算表結構寫出完整 GAS 程式碼。
Step 02|開啟腳本後台:點選頂部「擴充功能 ➔ Apps Script」 🔍 點圖放大
Step 2 點選擴充功能 Apps Script
在 Google 試算表上方選單列點選「擴充功能 (Extensions)」➔「Apps Script」,瀏覽器會自動開啟綁定這份試算表的程式碼編輯器分頁。
Step 03|清空預設程式碼:刪除原本的 myFunction() 🔍 點圖放大
Step 3 清空預設 function myFunction
進入 程式碼.gs 編輯區後,按 Ctrl + A 全選並刪除預設的空白 function myFunction() { }(避免兩個函式撞名或殘留括號報錯)。
Step 04|貼上儲存並點「執行」:跳出首次「需要授權 ➔ 審查權限」 🔍 點圖放大
Step 4 按儲存與執行後點選審查權限
貼上完整 GAS 程式碼,按上方磁碟片「💾 儲存專案」,接著點擊「▶ 執行」。此時會跳出「需要授權」對話框,請點擊藍色「審查權限」按鈕。
Step 05|新手必學放行 ①:看到未經 Google 驗證時,點左下角「進階」 🔍 點圖放大
Step 5 點選左下角進階
⚠️ 別按藍色的「返回安全的位置」!因為這支腳本住在你自己的 Google 帳號裡,請直接點擊左下角的小字「進階」。
Step 06|新手必學放行 ②:點選最下方「前往『未命名的專案』(不安全)」 🔍 點圖放大
Step 6 點選前往未命名的專案
展開進階說明後,點擊最底部連結「前往『未命名的專案』(不安全)」(代表你信任自己在試算表裡寫的這段自動化巨集)。
Step 07|新手必學放行 ③:點選右下角「繼續」完成首次授權 🔍 點圖放大
Step 7 點選右下角繼續完成授權
核對權限範圍(僅存取你的 Google 試算表)後,點擊右下角「繼續」。整份試算表只需要授權這一次,往後使用選單按鈕都不會再跳出!
Step 08|執行完畢確認:底部執行記錄顯示「開始執行 ➔ 執行完畢」 🔍 點圖放大
Step 8 執行記錄顯示執行完畢
授權通過後,Apps Script 底部「執行記錄」會顯示「開始執行 ➔ 執行完畢」,代表自訂選單已經成功掛載到你的試算表上!
Step 09|實戰成果 ①:點選「📊 AI 報表神器 ➔ 1. 標記急件並美化總表」 🔍 點圖放大
Step 9 點選 AI 報表神器標記急件並美化總表
切回 Google 試算表分頁,頂部選單列已經長出「📊 AI 報表神器」!點選「1. 標記急件並美化總表」,所有「負面急件」整列瞬間變成紅底深紅粗體字、首列自動深綠底白字並凍結!
Step 10|實戰成果 ②:點選「2. 依負責部門自動拆出子工作表」1 秒拆出 4 分頁! 🔍 點圖放大
Step 10 自動拆出物流部產品部帳務部客服部 4 個部門分頁
再點選「2. 依負責部門自動拆出子工作表」,1 秒內底部自動長出「物流部、產品部、帳務部、客服部」4 張格式整齊的子工作表,並跳出「🎉 拆表完成!」通知視窗!

📝 Tab 3|Google Docs 文件:AI 草擬摘要 ✕ GAS 一鍵清理 Markdown 殘留與標準品牌排版

📥 下載本頁實測底稿 (.docx)
🧪 實測底稿說明(Tab3_Docs_企劃書清除星號與企業排版底稿.docx):
這份 Word 底稿刻意埋入了 10 處 **粗體星號殘留**、未上色的 H1/H2 標題、2 張素色表格,以及多處「待辦/重要/急件/TODO/注意」字眼。上傳至 Google Drive 並點選「檔案 ➔ 另存為 Google 文件」後,執行下方 GAS 即可一鍵體驗瞬間變成正式品牌企劃書的快感!

真實工作痛點:我們常在 Google Docs 裡用 ✦ Help me write 生成企劃書、會議紀錄,或從外部 AI 貼上文章,結果整份文件裡到處都是殘留的 **粗體星號**、標題字型大小不一、表格沒有表頭底色、重點關鍵字也沒有醒目標記。與其手動改半小時,不如請「問問 Gemini」幫我們寫一顆「📐 文件品牌排版魔法師」按鈕!

Google Docs 雙劍合璧流程:內建 Gemini 負責寫出好內容,GAS 負責一鍵變成正式公文/企劃書格式 ① 內建 Gemini Spark (✦) 撰寫與摘要 ✦ Help me write / 問問 Gemini: • 將凌亂會議逐字稿整理成「決議事項」 • 根據大綱擴寫完整專案計畫書與風險評估 • 產出對照表格與待辦事項清單 ⚠️ 常見殘留:**星號**、字距不一、素色表格 ② 問問 Gemini 撰寫 Docs GAS 請 Gemini 寫出 4 大排版自動化: 1. 自動尋找 `**文字**` 轉為真粗體並刪星號 2. H1/H2 標題統一套用企業深藍與段距 3. 文件內所有表格首列自動改為深藍白字 4. 自動將【待辦/重要】關鍵字加上螢光筆 ③ 一鍵產出長官最愛的正式排版 壹、專案背景與目標 (H1 標準深藍) 本計畫透過 AI 導入達成三大核心指標... 工作項目 | 負責單位 | 預計完成日 系統測試 | 資訊部門 | 2026/11/15 ✨ 零星號殘留、行距 1.5 倍、表格全美化!
💬 對「問問 Gemini」下的 Docs GAS 提示詞
請幫我寫一段適用於 Google Docs 的 Google Apps Script (GAS) 程式碼。

我常使用 Gemini 在 Docs 裡生成企劃書草稿,希望能一鍵完成標準化排版:
1. 請建立 onOpen() 選單,名稱為「📝 文件排版魔法師」,內含:
   - 「1. 清除 Markdown 星號並轉為真粗體」
   - 「2. 套用企業標準標題與表格美化」
   - 「3. 高亮標記所有【重要/待辦】關鍵字」
2. 「清除 Markdown 星號並轉為真粗體」功能:
   - 自動搜尋文件中所有形如 `**文字**` 的段落,將裡面的文字設為粗體,並把前後的 `**` 符號刪除。
3. 「套用企業標準標題與表格美化」功能:
   - 將所有 HEADING_1 設為深藍色(#1a73e8)、粗體;HEADING_2 設為墨綠色(#0d9488)、粗體。
   - 將內文段落行距統一設為 1.5 倍。
   - 將文件中所有表格(Table)的第 1 列設為深藍底(#1a73e8)白字粗體,其餘列設為淺灰邊框。
4. 「高亮標記關鍵字」功能:
   - 自動尋找文件中所有的「待辦」、「重要」、「急件」、「TODO」、「注意」,使用 RangeElement 的 getStartOffset() 與 getEndOffsetInclusive() 將背景標上亮黃色螢光筆(#fef08a)與紅字粗體。
⚙️ 產出的 Docs GAS 完整程式碼(可直接貼入)
/**
 * Google Docs 雙劍合璧實戰:AI 草稿一鍵轉企業標準排版與清理星號
 * 講師:謝老師|AI 辦公自動化實戰範例
 */
function onOpen() {
  DocumentApp.getUi()
    .createMenu('📝 文件排版魔法師')
    .addItem('1. 清除 **星號** 並轉為真粗體', 'cleanMarkdownBold')
    .addItem('2. 套用企業標準標題與表格美化', 'applyCorporateStyle')
    .addItem('3. 螢光筆高亮【重要/待辦】關鍵字', 'highlightKeywords')
    .addToUi();
}

/**
 * 功能一:將 **文字** 轉為真正的粗體並移除 **
 */
function cleanMarkdownBold() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  let count = 0;

  paragraphs.forEach(p => {
    const textObj = p.editAsText();
    let str = textObj.getText();
    const regex = /\*\*([^*]+)\*\*/g;
    let match;
    const matches = [];
    while ((match = regex.exec(str)) !== null) {
      matches.push({ start: match.index, end: regex.lastIndex - 1 });
    }
    // 由後往前處理,避免索引偏移
    for (let i = matches.length - 1; i >= 0; i--) {
      const m = matches[i];
      textObj.setBold(m.start, m.end, true);
      textObj.deleteText(m.end - 1, m.end);
      textObj.deleteText(m.start, m.start + 1);
      count++;
    }
  });

  DocumentApp.getUi().alert('✅ 清理完成!共將 ' + count + ' 處 **星號** 轉為正式粗體。');
}

/**
 * 功能二:統一 H1/H2 標題顏色、行距與所有表格表頭美化
 */
function applyCorporateStyle() {
  const body = DocumentApp.getActiveDocument().getBody();

  // 1. 處理段落與標題
  body.getParagraphs().forEach(p => {
    p.setLineSpacing(1.5);
    const heading = p.getHeading();
    if (heading === DocumentApp.ParagraphHeading.HEADING1) {
      p.editAsText().setForegroundColor('#1a73e8').setBold(true);
    } else if (heading === DocumentApp.ParagraphHeading.HEADING2) {
      p.editAsText().setForegroundColor('#0d9488').setBold(true);
    }
  });

  // 2. 美化文件內所有表格
  body.getTables().forEach(table => {
    table.setBorderColor('#cbd5e1');
    const numRows = table.getNumRows();
    for (let r = 0; r < numRows; r++) {
      const row = table.getRow(r);
      const isHeader = (r === 0);
      for (let c = 0; c < row.getNumCells(); c++) {
        const cell = row.getCell(c);
        cell.setBackgroundColor(isHeader ? '#1a73e8' : (r % 2 === 0 ? '#f8fafc' : '#ffffff'));
        cell.editAsText()
            .setForegroundColor(isHeader ? '#ffffff' : '#1e293b')
            .setBold(isHeader);
      }
    }
  });

  DocumentApp.getUi().alert('🎉 企業標準標題與表格美化已全部套用!');
}

/**
 * 功能三:自動高亮標記關鍵字
 */
function highlightKeywords() {
  const body = DocumentApp.getActiveDocument().getBody();
  const keywords = ['待辦', '重要', '急件', 'TODO', '注意'];
  let total = 0;

  keywords.forEach(kw => {
    let found = body.findText(kw);
    while (found) {
      const elem = found.getElement().asText();
      elem.setBackgroundColor(found.getStartOffset(), found.getEndOffsetInclusive(), '#fef08a');
      elem.setForegroundColor(found.getStartOffset(), found.getEndOffsetInclusive(), '#b91c1c');
      elem.setBold(found.getStartOffset(), found.getEndOffsetInclusive(), true);
      total++;
      found = body.findText(kw, found);
    }
  });

  DocumentApp.getUi().alert('🔍 標記完成!共高亮標示了 ' + total + ' 處關鍵字。');
}

📽️ Tab 4|Google Slides 簡報:AI 大綱構思 ✕ GAS 一鍵批次長出投影片與講者備忘稿

📥 下載本頁實測底稿 (.pptx)
🧪 實測底稿說明(Tab4_Slides_簡報速生器與講稿自動生成底稿.pptx):
上傳至 Google Drive 並點選「檔案 ➔ 另存為 Google 簡報」後,簡報第 2 頁已內建 5 行可直接複製的「標題|重點|講者口白」大綱素材(或直接按確定使用 GAS 內建預設大綱),點一下選單立即自動長出投影片與底部講者備忘稿!

真實工作痛點:在 Google Slides 裡,內建的 Gemini Spark 雖然可以幫單張投影片生成圖片或改寫文字,但當你有一份 8~15 頁的報告大綱時,一頁一頁新增投影片、貼標題、貼條列重點、還要把講稿貼進下方「講者備忘稿 (Speaker Notes)」非常耗時!透過「Ask Gemini 產結構大綱 + GAS 批次生出所有頁面與講稿 + Slides 內建 Gemini 補配圖」,簡報製作速度直接提升 10 倍!

Google Slides 雙劍合璧流程:Gemini 產結構化大綱 ➔ GAS 一鍵生成全套投影片與講稿 ➔ 內建 Spark 補視覺配圖 ① 請 Gemini 產出結構化簡報大綱 請 Gemini 將文章濃縮為「每行一頁」格式: 標題 | 重點1;重點2;重點3 | 講者口白 範例: AI 導入目標|省時50%;降低錯誤|各位主管好... 雙劍合璧架構|Spark動腦;GAS動手|這頁說明... ✨ 連每頁上台要講的口白都一起由 AI 寫好! ② GAS 一鍵批次建立投影片與講稿 點選選單「📽️ 批次生成投影片」: 1. 自動依行數建立 N 張新投影片 2. 自動填入大標題與條列重點 3. 自動把第 3 欄口白寫入每頁底部的 「講者備忘稿 (Speaker Notes)」 ⚡ 10 頁簡報骨架 + 演講稿 2 秒瞬間完成! ③ Slides 內建 Gemini Spark 視覺完稿 回到 Slides 右側打開 ✦ Gemini: • 點選「幫我建立圖片」生成專屬插圖 • 或根據當頁文字一鍵插入情境配圖 • 搭配 GAS「一鍵統一全簡報字型」 🏆 結構、內容、講稿、視覺一次到位!
✦ 第一步(動腦):請 Gemini 把手邊的報告轉成「GAS 簡報速生格式」
對 Gemini 說:「請將這份內容規劃成 6 頁簡報大綱,每頁一行,嚴格使用『頁面標題 | 重點1;重點2;重點3 | 100字講者上台口白』的格式輸出,不要加其他多餘符號。」
💬 第二步:對「問問 Gemini」下的 Slides GAS 提示詞
請幫我寫一段適用於 Google Slides 的 Google Apps Script (GAS) 程式碼。

功能需求:
1. 建立 onOpen() 選單,名稱為「📽️ AI 簡報速生器」,包含兩個功能:
   - 「1. 貼上大綱批次生成投影片(含講者備忘稿)」
   - 「2. 一鍵為所有投影片加上重點頁尾標章」
2. 當點選「1. 貼上大綱批次生成投影片」時:
   - 跳出一個 Prompt 輸入框,讓我貼上由 Gemini 產出的多行大綱(每行格式為:`標題 | 重點1;重點2;重點3 | 講者備忘稿`)。
   - 若我未輸入,請內建 3 頁預設的 AI 辦公室轉型示範大綱直接生成。
   - 針對每一行使用 `pres.appendSlide()` 新增投影片並清空預設元素後,用 `slide.insertTextBox()` 建立深藍色粗體標題與條列式內文(請勿使用 PredefinedLayout.TITLE_AND_BODY,確保 PowerPoint 轉檔母片也 100% 相容),並將第 3 欄自動寫入該頁的 Speaker Notes(講者備忘稿)中!
3. 當點選「2. 一鍵為所有投影片加上頁尾標章」時:
   - 在每張投影片右下角自動加上一個小文字方塊「AI 辦公室自動化實戰」。
⚙️ 產出的 Slides GAS 完整程式碼(可直接貼入)
/**
 * Google Slides 雙劍合璧實戰:大綱一鍵批次生成投影片 + 自動寫入講者備忘稿
 * 講師:謝老師|AI 辦公自動化實戰範例
 */
function onOpen() {
  SlidesApp.getUi()
    .createMenu('📽️ AI 簡報速生器')
    .addItem('1. 貼上大綱批次生成投影片(含講稿)', 'generateSlidesFromOutline')
    .addItem('2. 一鍵為全簡報加上右下角標章', 'addFooterBadgeToAllSlides')
    .addToUi();
}

/**
 * 功能一:解析「標題 | 重點1;重點2 | 講者備忘稿」批次建立投影片
 * (100% 相容 PowerPoint .pptx 轉檔母片與原生 Google 簡報)
 */
function generateSlidesFromOutline() {
  const ui = SlidesApp.getUi();
  const res = ui.prompt(
    '📽️ 批次生成投影片與講者備忘稿',
    '請貼上大綱(格式:標題 | 重點1;重點2 | 講稿)。\n若直接按確定,將自動生成 5 頁雙劍合璧示範投影片:',
    ui.ButtonSet.OK_CANCEL
  );
  if (res.getSelectedButton() !== ui.Button.OK) return;

  let rawText = res.getResponseText().trim();
  if (!rawText) {
    rawText = [
      '為什麼需要 AI 雙劍合璧? | 單靠對話視窗無法批次改格式與跨檔搬移;單靠寫程式對行政人員門檻太高;內建 Gemini 動腦 + GAS 動手完美互補 | 各位主管好,這張投影片說明我們為什麼把內建 Gemini 與 GAS 結合使用。',
      '痛點一:試算表分類與拆表苦工 | 過去每週花 2 小時人工篩選與複製分頁;現在用 Gemini 判斷情緒與負責部門;點一下 GAS 按鈕 1 秒拆出各部門報表 | 在試算表場景中,我們讓 AI 先做好分類,再由腳本一鍵拆出子工作表。',
      '痛點二:文件草稿星號殘留與排版 | AI 生成文章常帶有雙星號與素色表格;透過 Docs GAS 一鍵轉為真粗體並刪除星號;自動將所有表格首列套用企業深藍標準色 | 在文件場景中,再也不用人工逐段調整字型與表格顏色。',
      '痛點三:簡報逐頁貼字與寫講稿耗時 | 先請 Gemini 產出「標題|重點|口白」結構;執行 Slides GAS 自動建立投影片與演講稿;最後用右側 Gemini 補充視覺插圖 | 就如同您現在看到的這幾頁投影片,連同我下方的演講稿都是 2 秒自動生成的!',
      '下週導入行動與預期效益 | 各部門挑選 1 個最高頻的週報或通知流程;建立共用試算表與專屬自動化按鈕;預計全公司每月可節省超過 120 小時工時 | 最後我們建議從各部門最常做的週報開始導入,謝謝大家!'
    ].join('\n');
  }

  // 若瀏覽器單行輸入框自動把多行換行轉為空白,自動在講稿句尾與下一頁標題間補回換行
  rawText = rawText.replace(/([。!!])\s+(?=[^||\n]{2,45}[||])/g, '$1\n');

  const pres = SlidesApp.getActivePresentation();
  const lines = rawText
    .split(/\r?\n/)
    .map(l => l.replace(/^[•\-*\d.]+\s*/, '').trim())
    .filter(l => l.includes('|') || l.includes('|'));
  let createdCount = 0;

  lines.forEach(line => {
    const parts = line.split(/[||]/).map(s => s.trim());
    const titleText = parts[0] || '未命名標題';
    const bullets = (parts[1] || '').split(/[;;]/).map(b => b.trim()).filter(Boolean);
    const notesText = parts[2] || '';

    // 相容 .pptx 轉檔母片:直接新增投影片並清除預設框,改用 insertTextBox 精準排版
    const slide = pres.appendSlide();
    slide.getPageElements().forEach(el => el.remove());

    const titleShape = slide.insertTextBox(titleText, 40, 28, 640, 48);
    titleShape.getText().getTextStyle()
      .setFontSize(22)
      .setForegroundColor('#1a73e8')
      .setBold(true);

    if (bullets.length > 0) {
      const bodyShape = slide.insertTextBox(bullets.join('\n'), 45, 92, 630, 240);
      bodyShape.getText().getTextStyle()
        .setFontSize(15)
        .setForegroundColor('#1e293b')
        .setBold(false);
      bodyShape.getText().getListStyle()
        .applyListPreset(SlidesApp.ListPreset.DISC_CIRCLE_SQUARE);
    }

    if (notesText) {
      slide.getNotesPage().getSpeakerNotesShape().getText().setText(notesText);
    }
    createdCount++;
  });

  ui.alert('🎉 生成完成!已自動建立 ' + createdCount + ' 張投影片並寫入講者備忘稿。\n現在可打開右側「✦ Gemini」為重點頁面生成配圖!');
}

/**
 * 功能二:批次在每張投影片右下角加上標章
 */
function addFooterBadgeToAllSlides() {
  const pres = SlidesApp.getActivePresentation();
  const slides = pres.getSlides();
  slides.forEach(slide => {
    const box = slide.insertTextBox('AI 智慧辦公實戰', 560, 370, 145, 24);
    box.getText().getTextStyle().setFontSize(9).setForegroundColor('#64748b').setBold(true);
  });
  SlidesApp.getUi().alert('✅ 已為全部 ' + slides.length + ' 張投影片加上右下角標章!');
}

🚀 Tab 5|跨產品綜合大招:Sheets 名單 + 內建 Gemini 客製評語 ➔ GAS 自動產 Docs 證書並寄出 Gmail

📥 下載本頁實測底稿 (.xlsx)
🧪 實測底稿說明(Tab5_跨產品_Sheets結合Gmail自動草稿與寄信底稿.xlsx):
內含 5 筆報名與提問名單(第 1 筆已標記 ✅ 已寄出 示範防呆跳過機制;第 2~4 筆已預填 Gemini 個人化回覆,可將 B3 信箱改為你自己的 Email 後點選「1. 批次建立 Gmail 草稿」到 Gmail 草稿匣檢視成果;第 5 筆留白供練習用右側 ✦ 問問 Gemini 生成回覆)。

為什麼這是必學大招?單一產品內的「✦ 內建 Gemini Spark」無法跨越檔案邊界去「自動複製 Docs 範本、轉成 PDF、再用 Gmail 批次寄給 50 個人」。但當我們先在 Google Sheets 裡用內建 Gemini 為每個人寫好客製化問候或審核評語,再請 「問問 Gemini」幫我們寫一段跨產品 GAS,就能一鍵串起整個 Google Workspace 生態系!

跨產品自動化工作流:Forms/Sheets 收集 ➔ 內建 Gemini 客製化文案 ➔ GAS 跨檔套版與寄信 1. Sheets + ✦ 內建 Gemini 名單與 AI 客製化評語欄位: • A欄:姓名 | B欄:Email • C欄:提交主題或心得 • D欄:✦ Gemini 生成專屬回饋 • E欄:寄送狀態 (防重複寄信) 大腦先為每個人寫出溫暖內容 2. GAS 跨產品控制中心 由「問問 Gemini」撰寫腳本: • 逐列讀取 E 欄未標記「已寄出」者 • 自動組合個人化主旨與信件 HTML • 呼叫 GmailApp / CalendarApp • 成功後在 E 欄壓上時間戳記 雙手負責 100% 精準跨檔派送 3. 一鍵觸發 Google 生態系三大自動化產出 📧 Gmail 客製化通知信自動寄出(或存為草稿檢查) 自動帶入收件人姓名與 D 欄 Gemini 專屬回饋,支援先存草稿人工確認後再寄! 📄 Google Docs / Drive 專屬通知書套版歸檔 自動替換範本中的 {{姓名}}、{{AI回饋}},並匯出成獨立 PDF 附加於信件中。 🛡️ E 欄自動回填「✅ 已處理 (AI 實戰 15:30)」防呆不重寄!
💬 對「問問 Gemini」下的跨產品 GAS 提示詞
請幫我寫一段串接 Google Sheets 與 Gmail 的 Google Apps Script (GAS) 程式碼。

我的試算表欄位如下(第 1 列為標題):
- A 欄:學員/客戶姓名
- B 欄:Email 信箱
- C 欄:報名項目或提問內容
- D 欄:由內建 Gemini 產出的「個人化回覆與建議」
- E 欄:寄送狀態

請幫我設計:
1. 在頂部建立「🚀 跨產品自動化」選單,包含两个按鈕:
   - 「1. 批次產生 Gmail 草稿(含人工檢查)」
   - 「2. 批次直接寄出信件並標記時間戳記」
2. 程式執行時,請逐列檢查:
   - 若 B 欄沒有 Email,或 E 欄已經包含「已」字樣,則自動跳過(防止重複寄送)。
   - 將 A 欄姓名、C 欄項目與 D 欄 Gemini 個人化建議,組合成排版美觀的 HTML 信件。
   - 若點選「產生草稿」,則使用 `GmailApp.createDraft()` 建立草稿並在 E 欄填入「📝 已建草稿 + 時間」並標為淺黃底。
   - 若點選「直接寄出」,則先跳出確認視窗,確認後使用 `GmailApp.sendEmail()` 寄出,並在 E 欄填入「✅ 已寄出 + 時間」並標為淺綠底。
⚙️ 產出的跨產品 GAS 完整程式碼(含草稿檢查與防重寄)
/**
 * 跨產品綜合實戰:Sheets 名單 + Gemini 客製評語 ➔ 批次產生 Gmail 草稿或寄信(含防重寄機制)
 * 講師:謝老師|AI 辦公自動化實戰範例
 */
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('🚀 跨產品自動化')
    .addItem('1. 批次建立 Gmail 草稿(安全人工檢查模式)', 'createPersonalizedDrafts')
    .addItem('2. 批次直接寄出 Gmail 信件(含防重寄標記)', 'sendPersonalizedEmails')
    .addSeparator()
    .addItem('3. 📊 查詢今日剩餘免費寄信額度', 'checkRemainingEmailQuota')
    .addToUi();
}

function checkRemainingEmailQuota() {
  const remaining = MailApp.getRemainingDailyQuota();
  SpreadsheetApp.getUi().alert(
    '📊 今日 Gmail 自動寄信剩餘額度',
    '您目前的 Google 帳號今天還可以透過 GAS 自動寄出:' + remaining + ' 封信!\n\n' +
    '💡 額度參考:\n• 個人 @gmail.com 帳號(含付費 Google One / Gemini Pro 個人戶):GAS 皆固定為每日 100 封(若改走外部 SMTP 應用程式密碼則為 500 封/日)\n• 公司專屬網域 Workspace (@company.com 正式付費滿期):GAS 最高每日 1,500 封(SMTP / API 為 2,000 封/日)',
    SpreadsheetApp.getUi().ButtonSet.OK
  );
}

function createPersonalizedDrafts() {
  processMailWorkflow(true);
}

function sendPersonalizedEmails() {
  const ui = SpreadsheetApp.getUi();
  const confirm = ui.alert(
    '📧 確認批次寄信',
    '即將針對 E 欄尚未處理的名單直接寄出客製化信件,是否繼續?',
    ui.ButtonSet.YES_NO
  );
  if (confirm === ui.Button.YES) {
    processMailWorkflow(false);
  }
}

/**
 * 核心工作流:支援「僅建草稿 (isDraft=true)」與「直接寄出 (isDraft=false)」
 */
function processMailWorkflow(isDraft) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const lastRow = sheet.getLastRow();
  if (lastRow < 2) return;

  const range = sheet.getRange(2, 1, lastRow - 1, 5);
  const rows = range.getValues();
  let count = 0;

  for (let i = 0; i < rows.length; i++) {
    const [name, email, topic, aiReply, status] = rows[i];
    if (!email || String(status).includes('已')) continue;

    const subject = '【專屬回饋通知】' + name + ' 您好,關於「' + topic + '」的 AI 建議與回覆';
    const htmlBody = [
      '<div style="font-family:sans-serif; line-height:1.7; color:#1e293b; max-width:600px;">',
      '  <h3 style="color:#1a73e8;">親愛的 ' + name + ' 您好:</h3>',
      '  <p>感謝您提交關於 <strong>「' + topic + '」</strong> 的資訊,以下為我們為您整理的重點建議:</p>',
      '  <div style="background:#f8fafc; border-left:4px solid #1a73e8; padding:12px 16px; margin:14px 0;">',
           String(aiReply || '感謝您的參與!').replace(/\n/g, '<br>'),
      '  </div>',
      '  <p style="font-size:12px; color:#64748b;">本信件由 Google Sheets ✕ Gemini 智慧工作流輔助產生</p>',
      '</div>'
    ].join('');

    const timestamp = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy/MM/dd HH:mm');
    const statusCell = sheet.getRange(i + 2, 5);

    if (isDraft) {
      GmailApp.createDraft(email, subject, '', { htmlBody: htmlBody });
      statusCell.setValue('📝 已建草稿 (' + timestamp + ')').setBackground('#fef9c3');
    } else {
      GmailApp.sendEmail(email, subject, '', { htmlBody: htmlBody });
      statusCell.setValue('✅ 已寄出 (' + timestamp + ')').setBackground('#dcfce7');
    }
    count++;
  }

  SpreadsheetApp.getUi().alert(
    isDraft
      ? '📝 已成功建立 ' + count + ' 封 Gmail 草稿!請打開 Gmail「草稿匣」檢查無誤後再寄出。'
      : '🎉 已成功寄出 ' + count + ' 封客製化信件,並於 E 欄標記完成時間!'
  );
}
🛟 實戰 Debug 錦囊:如果執行 GAS 時跳出紅字錯誤訊息怎麼辦?
千萬別自己一行一行找錯!直接把紅色錯誤文字複製起來,貼回給「✦ 問問 Gemini」並說:
「我剛剛執行這段 GAS 時跳出這行錯誤訊息:【貼上紅字錯誤】,請幫我修正並給我完整的新版程式碼。」——Gemini 通常在 5 秒內就能幫你修好!

📬 關鍵必懂:GAS 免費寄信額度、寄件人規則,以及「GAS 原生寄信 vs. 外部程式呼叫 Google API / SMTP」差在哪?

🔐 資安與架構觀念

👤 誰會成為寄件人(From)?動態授權

  • 誰點擊選單並完成授權,就用誰的 Gmail 寄信!(即當下操作的 Active User,而非固定為試算表擁有者)。
  • 因此把試算表分享給同事或學員時,每個人點選「建立草稿」或「直接寄出」,都會進到自己個人的 Gmail 草稿匣與寄件備份,不會誤用別人的信箱。
  • 唯一例外:若在 Apps Script 後台手動設定了「⏰ 定時排程觸發(Time-driven Trigger)」,才會固定以「設定排程的人」當寄件人。

📊 為什麼付費個人帳號在 GAS 也是 100 封?重要盲點

  • 個人 @gmail.com(含付費買 Google One / Gemini Pro):只要信箱尾綴是 @gmail.com,在 GAS 底層皆視為個人 Consumer 帳號,GAS 寄信上限一律鎖定為 100 封/日!
  • 若同一個 @gmail.com 改走「16 碼應用程式密碼 (SMTP)」或「Gmail API」:每日上限會提升 5 倍至 500 封/日(滾動 24 小時計算)。
  • 公司自訂網域 Workspace(@company.com):需為企業網域且過試用暖機期,GAS 上限才會開放至 1,500 封/日(走外部 SMTP / API 則為 2,000 封/日)。
💡 常見疑問:「以前用 Python 或 Excel VBA 自動寄 Gmail,不是都要開兩步驟驗證、申請 16 碼『應用程式密碼』嗎?為什麼 GAS 完全不用?」
自從 Google 於 2022 年 5 月關閉「低安全性應用程式存取」並在 2024 年 9 月全面強制外部工具驗證後,任何「從 Google 外部連線進來」的程式都必須經過繁瑣驗證。但 Google Apps Script (GAS) 本身就運行在 Google 雲端內部(第一方原生環境),不走外部 SMTP 通道,因此只要在瀏覽器點擊「審查權限 ➔ 繼續」即可直接寄信!
比較項目 ① GAS 內部原生寄信(本課做法 ⭐)
GmailApp / MailApp
② 外部程式走傳統 SMTP
Python smtplib / Excel VBA / 舊腳本
③ 外部程式呼叫 Google Gmail API
Python / Node.js 獨立系統串接
運作位置與通道 Google 雲端內部原生執行
直接呼叫內部 GmailApp 服務,不經過外部網路 SMTP 埠號。
外部電腦/伺服器連線
需透過網路連線至 smtp.gmail.com(Port 465 或 587)。
外部電腦/伺服器呼叫 REST API
透過 HTTPS 呼叫 gmail.googleapis.com 端點。
是否需申請 16 碼
「應用程式密碼」?
❌ 完全不用!
免開兩步驟驗證、免找 16 碼密碼。
⚠️ 強制必須!
必須先開啟 Google 兩步驟驗證,再申請 16 碼 App Password 寫入程式。
❌ 不用應用程式密碼
但須改走更複雜的 GCP OAuth 2.0 憑證交換流程。
是否需建立 GCP 專案
與下載 JSON 憑證?
❌ 完全不用!
首次執行時於畫面點擊「審查權限 ➔ 進階 ➔ 繼續」即完成內部 OAuth 授權。
❌ 不用建立 GCP 專案,
但常被公司防火牆封鎖 SMTP 埠號(Port 25/465/587)導致連線失敗。
⚠️ 強制必須!
需進 Google Cloud Console 建立專案、啟用 Gmail API、設定 OAuth 同意畫面、下載 credentials.json 並產生 token.json。
資安風險與分享性 🛡️ 最高(零帳密外洩風險)
程式碼內完全不含任何帳號密碼,整份試算表直接複製給同事即可各自安全使用。
⚡ 高風險
16 碼密碼常被明文寫在程式碼或 .env 中,檔案外流即遭盜寄。
🔒 中高(需妥善保管 Token)
需自行管理 credentials.json 與 Refresh Token 更新機制。
每日寄信額度上限
(滾動 24 小時)
• 個人 @gmail.com(含 Google One / Gemini 付費戶):100 封/日
• 企業網域 Workspace(@company.com 正式期):1,500 封/日
(註:Workspace 新開通試用期亦會暫時限縮於 100~500 封)
• 個人 @gmail.com(含 Google One 付費戶):500 封/日(比 GAS 多 5 倍!)
• 企業網域 Workspace:2,000 封/日(若設定 Workspace SMTP Relay 最高可達 10,000 封/日)
• 個人 @gmail.com(含 Google One 付費戶):500 封/日
• 企業網域 Workspace:2,000 封/日
(另受每分鐘 API Quota Units 併發速率限制)
最佳適用場景與突破限制做法 辦公室日常自動化首選(100 封內):名單通知、報表派送、建立草稿。
💡 若想在 GAS 突破 100 封,可用 UrlFetchApp 串接 Brevo(免費 300 封/日)或 Resend API!
本機 Python 腳本需寄送 100~500 封/日時,改走 16 碼應用程式密碼 + SMTP 即可突破 GAS 的 100 封限制。 企業大型外部網站後端、ERP/CRM 獨立伺服器系統整合。