Google 文件:建立 Google 文件 create()

 


每天開新文件、貼內容、調標題、再分享給同事——做久了真的會崩潰。其實這些重複動作,完全可以交給 Google Apps Script。

用 DocumentApp.create() 先一鍵生出文件,再把段落、表格、連結通通自動寫進去,最後取得 URL 丟回試算表或寄信通知,流程一次走完。

這篇會用白話範例帶你從零開始:建立文件、設定樣式、搬到指定資料夾、設定權限,到「大量產生多份報告」的做法與避坑清單。不需要高深背景,只要會開 Apps Script,就能把原本半小時的例行事,縮成一個按鈕。把腦力留給分析,雜事交給程式。希望本篇文章可以幫助到需要的您。


目錄

{tocify} $title={目錄} 


為什麼要用程式來開新文件?

如果你每天都要把資料、報表或範本輸出成多份 Google 文件(Google Docs),手動「新增 → 命名 → 貼內容 → 排版 → 分享」會很耗時。Google Apps Script(GAS) 提供的 DocumentApp 服務,讓你用一行程式就能建立全新的文件,再把段落、表格、連結統統塞進去,甚至自動命名與分享。核心入口就是這個方法:

const doc = DocumentApp.create('你的文件標題');


這行會回傳一個 Document 物件,代表剛建立的那份 Google 文件,接著你就能對它做各種操作(例如 getBody().appendParagraph()、saveAndClose())。這些行為都出現在官方參考與教學示例中,可以視為標準做法。


快速上手:從零寫到可用的最小範例

範例一:最短程式碼,產生一份空白文件並加一段文字

function createSimpleDoc() {
  const doc = DocumentApp.create('我的第一份自動化文件'); // 建立文件
  doc.getBody().appendParagraph('這份文件由 Apps Script 自動建立。'); // 加一段話
  doc.saveAndClose(); // 儲存並關閉
  Logger.log('文件網址:%s', doc.getUrl());
}


DocumentApp.create(name):建立並開啟一份新文件,回傳 Document。

getBody().appendParagraph():往文件主體追加段落。

saveAndClose():把變更寫回並關閉文件(大量寫入時更穩定)。


註:官方示例中常見的教學,就是先 create(),再 getBody().appendParagraph(),最後取 getUrl() 給使用者。


DocumentApp.create() 到底做了什麼?

1.    在你的 Google 雲端硬碟建立一份新文件,並回傳對應的 Document 物件。

2.    這份文件預設會建立在你的雲端硬碟根目錄(My Drive),稍後你可以用 DriveApp 把它移到指定資料夾(後面會示範)。

3.    回傳物件可直接操作:寫文字、表格、分頁、圖片、設定標題等,再用 saveAndClose() 收尾。


新手常見疑問

要不要一定 saveAndClose()?

腳本結束時系統會自動處理,但大量寫入或長迴圈情境,建議你手動分段 saveAndClose(),避免觸發「變更太多、請先儲存」的錯誤。

可否直接建立在指定資料夾?

DocumentApp.create() 只能建在根目錄,建立後再用 DriveApp 移動是通用解。社群與官方討論也都是採用「先建後移」的流程。

建立後怎麼馬上把網址給使用者?

doc.getUrl() 就是連結,寫回試算表或發通知信都可行(官方 Quickstart 就是這樣示範)。


實戰操作:從建立、寫入、移動、分享到存取

步驟 1:建立與命名

const doc = DocumentApp.create('每月營運報表_2025-10');


建立完成即回傳 Document 物件,可立刻操作。


步驟 2:寫入段落、標題、表格

const body = doc.getBody();
body.appendParagraph('一、總覽').setHeading(DocumentApp.ParagraphHeading.HEADING1);
body.appendParagraph('以下為本月重點指標與摘要說明。');

const table = body.appendTable([
  ['指標', '數值', 'MoM', 'YoY'],
  ['營收', 'NT$ 12,300,000', '+5.3%', '+12.1%'],
  ['新客數', '1,284', '+2.1%', '+9.7%'],
]);
table.getRow(0).editAsText().setBold(true);

body.appendParagraph('二、細項分析').setHeading(DocumentApp.ParagraphHeading.HEADING1);


Paragraph、Table 等元素用法可查 Document/Body/Table 參考。


步驟 3:儲存與關閉(建議)

doc.saveAndClose();


可避免「一次寫入過多變更」的例外,特別是巨量生成文件或在迴圈中寫入。


步驟 4:把文件移到指定資料夾

const file = DriveApp.getFileById(doc.getId());
const target = DriveApp.getFolderById('你的資料夾ID');
target.addFile(file);                   // 加到目標資料夾
DriveApp.getRootFolder().removeFile(file); // 從根目錄移除(等於搬移)


這是實務上最穩的「先建後移」流程;社群長年以此為準。


步驟 5:設定檔名與分享權限(選用)

doc.setName('【內部】每月營運報表_2025-10'); // 改名
file.addEditor('teammate@example.com');       // 加編輯者
file.addViewer('boss@example.com');           // 加檢視者


setName() 與分享 API 在 Document/Drive 參考中皆有記載。


進階情境:從資料自動產出一批文件(批次生文)

以下情境:你有一張試算表,每列是「一個部門」的 KPI,要自動為每個部門各產出一份報告。流程:讀資料 → 逐列 create() → 寫內容 → 存網址回表 → 移動到資料夾。

function batchCreateDeptReports() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName('KPI');
  const rows = sh.getDataRange().getValues();
  const folder = DriveApp.getFolderById('你的資料夾ID');

  const header = rows.shift(); // 去標題列
  const [deptCol, revenueCol, newUserCol] = [0, 1, 2]; // 假設欄位

  rows.forEach((r, i) => {
    const dept = r[deptCol];
    const revenue = r[revenueCol];
    const newUsers = r[newUserCol];

    const doc = DocumentApp.create(`部門月報_${dept}`);
    const body = doc.getBody();
    body.appendParagraph(`${dept} 部門月報`).setHeading(DocumentApp.ParagraphHeading.TITLE);
    body.appendParagraph(`本月營收:${revenue}`);
    body.appendParagraph(`本月新客:${newUsers}`);

    // 加表格
    body.appendTable([
      ['KPI', '數值'],
      ['營收', `${revenue}`],
      ['新客', `${newUsers}`],
    ]);

    doc.saveAndClose();

    // 移動檔案
    const file = DriveApp.getFileById(doc.getId());
    folder.addFile(file);
    DriveApp.getRootFolder().removeFile(file);

    // 把連結寫回試算表第 5 欄
    sh.getRange(i + 2, 5).setValue(doc.getUrl());
  });
}


此模式等同於多數官方/社群文章推薦的流程:create() → getBody() 寫入 → saveAndClose() → getUrl() → 移動/分享。


模板實務:用既有範本 + 取代文字

雖然本文主軸是 create(),但很多人會搭配「模板複製」來得到更漂亮的排版。你可以:

        1.    先 DriveApp.getFileById(templateId).makeCopy(newName) 建出文件,

        2.    再 DocumentApp.openById(newId) 取代 { {placeholder} }。

這與 create() 互補,兩者都屬官方與社群的主流做法。


權限、授權與觸發器注意事項

授權 Scope:

        常見寫入操作會需要 https://www.googleapis.com/auth/documents(或 documents.currentonly)等權限,首次執行會跳授權。官方 Body/Document 參考都有標示。

觸發器:

        若把程式掛在 時間觸發器 或 表單提交觸發器 上跑,初次或修改後都可能重新要求授權。

自訂函數限制:

        在 Google 試算表的 自訂函數 內,嚴格限制對檔案系統的寫入與網路請求,直接 create() 可能報權限或限制錯誤;建議用按鈕觸發的一般函數或觸發器來跑。社群討論與官方教學也多採這類結構。


預設建立位置與「搬移」最佳實務

如前所述,create() 一律建在 My Drive 根目錄。要落在特定資料夾,建議用:

const file = DriveApp.getFileById(doc.getId());
target.addFile(file);
DriveApp.getRootFolder().removeFile(file);


這個「先加入目標、再從根移除」的流程,已在多篇社群問答裡被反覆確認。


大量寫入、效能與穩定度

分批 saveAndClose():

        若你在單一文件內做超大量的 appendParagraph/appendTable,可能碰到「變更過多」錯誤。建議分段存檔再 openById() 繼續。

減少操作次數:

        能一次組成陣列建立表格就不要逐格寫(官方 Table 參考也建議在大量資料時用陣列)。

I/O 分離:

        先把試算表資料整批讀到陣列,再迴圈處理(避免一格一格 getValue())。這是 Apps Script 社群長期的性能建議。


常見問題與雷點

1.    TypeError: Cannot read properties of undefined (reading 'saveAndClose')

        代表 doc 不是你想的那個物件(可能作用域或回傳值搞丟),或你在模板複製後忘了用 DocumentApp.openById(newId) 取得 Document。

2.    Too many changes applied before saving document

        一次改太多,請分批 saveAndClose() 再 openById() 接續處理。

3.    Cannot find method saveAndClose(string)

        saveAndClose() 沒有參數,若你不小心傳了字串,GAS 會說「找不到這個方法」。

4.    在試算表自訂函數中 create() 報錯或無效

        自訂函數環境有沙箱限制,不適合做檔案建立;請改用一般函數 + 觸發器。

5.    移動到資料夾失敗

        確認你先 addFile() 再 removeFile(),且腳本擁有 Drive 權限。相關討論與解法請參考社群串。


互動功能加值:目錄、頁首頁尾、連結

create() 只是開門,精彩都在後面。官方參考中,你可以:

        設定標題層級與段落樣式(Heading、粗體、斜體)。

        建立表格、列表、分頁。

        建立連結或把文字轉為可點擊的 URL(實務部落格也有大量範例)。


小提醒:Google 文件不能以表格作為最後一個元素,官方 Body 參考說明在表格後會自動補一個空白段落,屬正常行為。


完整範例:從 Sheets 一鍵產生多份「部門報告」並寄信通知

這段把官方 Quickstart 的精神擴充:建立 → 寫內容 → 存連結 → 寄通知信。

function createDocsAndNotify() {
  const sh = SpreadsheetApp.getActive().getSheetByName('KPI');
  const rows = sh.getDataRange().getValues();
  const folder = DriveApp.getFolderById('你的資料夾ID');
  const emails = ['boss@example.com', 'ops@example.com'];

  rows.slice(1).forEach(r => {
    const [dept, revenue, newUsers] = r;

    const doc = DocumentApp.create(`【月報】${dept}`);
    const body = doc.getBody();
    body.appendParagraph(`${dept} 月報`).setHeading(DocumentApp.ParagraphHeading.TITLE);
    body.appendParagraph(`營收:${revenue}`);
    body.appendParagraph(`新客:${newUsers}`);
    body.appendTable([
      ['KPI', '值'],
      ['營收', revenue],
      ['新客', newUsers],
    ]);
    doc.saveAndClose();

    const file = DriveApp.getFileById(doc.getId());
    folder.addFile(file);
    DriveApp.getRootFolder().removeFile(file);

    // 通知:把文件連結寄給相關人員
    const url = doc.getUrl();
    GmailApp.sendEmail(
      emails.join(','),
      `已產生 ${dept} 月報`,
      `文件連結:${url}\n\n此信由 Apps Script 自動發送。`
    );
  });
}


測試與除錯建議

1.    先做小型資料測試(3~5 筆),觀察格式與權限是否正確。

2.    Logger 與 Execution log:把 doc.getId()、doc.getUrl() 打出來,有助於定位錯誤。

3.    分段儲存:迴圈大量生成時每 N 份就 Utilities.sleep(200) + 獨立 saveAndClose(),降低配額與變更壓力。

4.    權限先跑通:第一次執行要手動授權,之後再掛觸發器。


問題集

1.    可以直接建立在共用雲端硬碟嗎?

create() 仍是建在個人根目錄;要放到共用雲端硬碟,請在該雲端硬碟下先取得目標資料夾,再用「先加後移」方式。

2.    可以一次建立很多份嗎?

可以,但要注意 Apps Script 的執行時間與服務配額。建議分批處理並分段 saveAndClose()。

3.    文件最後一行為什麼多一個空白段落?

Google 文件不能以表格結尾,官方文件說表格後會自動補段落。

4.    Tabs(文件分頁物件)能用嗎?

近年的文件 API 引入「Tabs」概念(取得分頁、設定使用者的作用分頁等),但與 create() 核心任務無衝突。日常產出報表,多半不用動到。細節以官方參考為準。


張貼留言 (0)
較新的 較舊