Google 文件:取得文件標題title getName()

 


如果你剛踏進 Apps Script 的世界,getName() 聽起來也許有點樸素,但它超常用:想在畫面上彈出目前文件的名稱?寄信時把文件標題放進主旨?或做一個清單列出多份文件的名稱?通通靠它。

這篇用最貼近實務的方式帶你上手:先講清楚 getName() 回傳的是什麼、什麼時候該用 getActiveDocument(),什麼時候改用 openById() 或 openByUrl();再一步步示範常見情境,像是批次列名、寄信通知、加上時間戳改名。

也不會閃躲坑洞:授權範圍要怎麼過、為什麼找不到 openByName()、遇到 .docx 檔該怎麼辦、跑很多檔案時怎麼避免超時。你只要照著貼、改兩行參數,就能跑起來。希望本篇文章能夠幫助到需要的您。


目錄

{tocify} $title={目錄} 


為什麼要在專案裡用 getName()?

        在自動化處理 Google 文件(Google Docs)時,我們常需要讀取目前文件的標題(也就是使用者在檔案左上角看到的名稱)。不論你是做批次報表、產生合約、建立匯出清單,或只是要把檔名寫進郵件主旨,getName() 都是最乾脆的入口。

        在 Apps Script 的文件物件(DocumentApp.Document)上,getName() 會回傳該文件的標題字串。官方參考文件是這樣定義的:Retrieves the title of the document.(回傳文件標題)。

小提醒:同一個物件也支援 setName() 用於改名(設定文件標題),兩者一讀一寫,搭配起來就能做完整的檔名治理流程(下面有實作)。


getName() 跟誰一起用最順?

通常會搭配三種入口把文件「抓」進來,然後再取名:

已綁定文件(Container-bound)

        用 DocumentApp.getActiveDocument() 取得當前綁定的那份文件,再 .getName()。這條路線最適合在「文件裡點選自訂選單或外掛」時使用。官方也明確說明 getActiveDocument() 是取與腳本綁在一起的那份文件。

用文件 ID 開啟

        DocumentApp.openById('文件ID') → .getName()。當你的流程手上有一串 ID(像是從資料表或雲端硬碟清單來的),這是最穩定的做法。

用文件 URL 開啟

        DocumentApp.openByUrl('完整URL') → .getName()。當系統裡保存的是網址而非 ID,就走這條。


權限(Scopes)會影響嗎?

會。只要你要讀取或操作 Google Docs,腳本通常需要以下其中一個 scope:

    https://www.googleapis.com/auth/documents.currentonly

    https://www.googleapis.com/auth/documents

這兩個在 Document 類別的多數方法(包含 getName())上都有標註。第一次執行時,Apps Script 會要求你授權。


實作步驟與範例

範例 1:讀取「目前這份」文件的名稱(綁定腳本)

適用情境:在 Google Docs 內建一個自訂選單,點了就秀文件名。

function onOpen() {
  DocumentApp.getUi()
    .createMenu('自動化')
    .addItem('顯示文件名稱', 'showDocName')
    .addToUi();
}

function showDocName() {
  const doc = DocumentApp.getActiveDocument(); // 取綁定的文件
  const name = doc.getName();                  // 讀標題
  DocumentApp.getUi().alert(`這份文件的名稱是:${name}`);
}


為什麼可行:getActiveDocument() 回傳與此腳本綁定的文件實例;getName() 讀到該實例的標題。


範例 2:用文件 ID 讀取名稱(最穩健)

function printDocNameById() {
  const id = 'YOUR_DOC_ID';
  const doc = DocumentApp.openById(id);
  Logger.log(doc.getName());
}


何時用:你在表單回覆、試算表或資料庫裡記錄的是檔案 ID。openById() 是 Apps Script 官方推薦的「指定檔案」方式。


範例 3:用 URL 讀取名稱(來源是連結)

function printDocNameByUrl() {
  const url = 'https://docs.google.com/document/d/xxxxxxxxxxxxxxxxxxxx/edit';
  const doc = DocumentApp.openByUrl(url);
  Logger.log(doc.getName());
}


何時用:你的系統裡保存、傳遞的是完整網址而不是 ID。


範例 4:把文件名稱拿去寄信(主旨+連結一起丟)

function emailDocLinkToMe() {
  const doc = DocumentApp.getActiveDocument();
  const subject = `[文件通知] ${doc.getName()}`;
  const body = `這是文件連結:\n${doc.getUrl()}`;
  MailApp.sendEmail(Session.getActiveUser().getEmail(), subject, body);
}


說明:getName() 拿標題,getUrl() 拿可存取的網址。官方在 getUrl() 條目也示範了把名稱與連結一起用在郵件裡。


範例 5:批次列出一整串文件名稱(從 ID 陣列來)

function listManyDocNames(ids) {
  return ids.map(id => {
    try {
      return { id, name: DocumentApp.openById(id).getName() };
    } catch (err) {
      return { id, name: null, error: String(err) };
    }
  });
}

// 測試
function demoListManyDocNames() {
  const ids = ['ID_A', 'ID_B', 'ID_C'];
  const results = listManyDocNames(ids);
  results.forEach(r => Logger.log(JSON.stringify(r)));
}


範例 6:讀完就改名(setName())

function renameWithTimestamp(id) {
  const doc = DocumentApp.openById(id);
  const oldName = doc.getName();
  const newName = `${oldName} - 已歸檔 ${Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyyMMdd_HHmm')}`;
  doc.setName(newName); // 改標題
  return { id, oldName, newName };
}


setName() 是設定「文件標題」(使用者在左上角看到的名稱)。用它能做版本標記、歸檔戳記或流程狀態追蹤。官方條目明載 Sets the document title.。


與 DriveApp 的名稱有沒有差?

        多數情況下,Docs 的標題 = 雲端硬碟的檔名,所以 Document#getName() 與 DriveApp.getFileById(id).getName() 看到的會一致。實務上若你需要同時取 ID / 標題 / MIME 類型 來分流(例如排除非 Google Docs 的 .docx),就會用 DriveApp 取得檔案清單,再以 ID 交給 DocumentApp 做內容層處理。

(補充:若你想「用檔名開啟文件」,DocumentApp 沒有提供 openByName(),社群也都有相同結論——請先用 DriveApp 找到目標檔案,再拿到 ID。)


常見錯誤與雷點

1.    getActiveDocument() 取不到東西或回錯文件

現象:在獨立腳本(Standalone)呼叫 getActiveDocument(),卻不是你想要的文件。

原因:

        官方文件寫得很白,getActiveDocument() 回傳的是「與腳本綁定的那份文件」,不是你桌面上目前開著的任意文件。獨立腳本通常沒有綁定對象。

解法:改用 openById() 或 openByUrl() 明確指定目標。

2.    權限(Scopes)沒給,第一次執行就噴

現象:第一次執行就跳出需要授權,或被拒。

原因:文件服務需要 documents 相關 scope。

解法:依流程授權;若你在 Workspace 網域下受控,找網域管理員核准必要範圍。

3.    用「檔名」找文件直接失敗

現象:以為有 openByName(),結果呼叫不存在的方法。

解法:先用 DriveApp 依名稱搜尋,拿到 ID 再 openById() 開啟。這是普遍建議的做法。

4.    用在非 Google Docs(像 .docx)導致例外

現象:openById() 成功,但 .getName() 前就報型別不符/不能用 DocumentApp 操作。

原因:DocumentApp 只吃 Google Docs。

解法:先用 DriveApp.getFileById(id).getMimeType() 判斷是不是 application/vnd.google-apps.document;不是的話先轉檔或跳過。

5.    大量迴圈直呼 openById() 效能下滑

現象:大量文件清單逐一開啟,速度緩慢甚至觸發配額限制。

解法:

        能不開文件就不開,名稱其實 DriveApp 也能拿(只要你不需要內容)。

        需要內容再開;其餘只要名稱就 DriveApp.getFileById(id).getName()。

        批次處理時加上 Utilities.sleep() 做節流,或分批執行。

6.    改名後其他系統還沒跟上

現象:剛 setName(),Drive 上或第三方系統顯示還是舊名。

原因:雲端同步需要時間。

作法:

        若後續馬上要依檔名做路由,建議以 ID 為準,名稱用來展示即可。官方也鼓勵透過 ID 與 URL 指向正確資源(例如 getUrl())。


進階實戰:把名稱變成流程的「狀態指示器」

範例 7:自動在檔名上加上處理階段標籤

function markDocStage(id, stage) {
  const doc = DocumentApp.openById(id);
  const base = doc.getName().replace(/\s*\[.*?\]\s*$/, ''); // 去掉舊標籤
  doc.setName(`${base} [${stage}]`);
}


用法:markDocStage('ID_xxx', '待審') → 原始名稱 [待審]。流程切換時再呼叫把標籤換掉。

範例 8:把檔名做為郵件主旨、URL 進信件內

function notifyOwner(id, to) {
  const doc = DocumentApp.openById(id);
  const subject = `文件已更新:${doc.getName()}`;
  const body = `請查閱:\n${doc.getUrl()}\n(這封信由系統自動發送)`;
  MailApp.sendEmail(to, subject, body);
}


getUrl() 的官方範例就示範把名稱與連結一起寄出,這一招做通知最直觀。


測試與驗收建議

授權先走一遍:

        第一次跑任何用到 Document 的腳本,都先在測試帳號授權。

ID 驗證:

        從外部來源拿到的 ID,先 DriveApp.getFileById(id) 看看存不存在、型別是否 Google Docs。

名稱一致性:

        若你的系統同時用 DriveApp 與 DocumentApp 讀名稱,建議挑一方作為「標準輸出」,避免 UI 同步延遲造成短暫不一致。

批次配額:

        大量文件時,避免每筆都 openById();能用 Drive 名稱就用 Drive 名稱,必要時分批執行。

綁定 vs. 獨立:

        需要 getActiveDocument() 的腳本請建成 Container-bound Script(在文件中開啟擴充功能 → Apps Script),否則用 ID/URL。


問題集

Q1:getName() 回傳的內容是什麼?

是這份 Google 文件的標題,也就是你在 Docs 介面左上角看到的名稱。

Q2:我能只靠「檔名」找到文件嗎?

DocumentApp 沒有 openByName()。請改用 DriveApp 搜尋檔名,拿到 ID 後再 openById()。

Q3:我想改名,要用哪個方法?

用 Document#setName(newTitle)。官方定義:Sets the document title.。

Q4:要什麼權限(Scopes)?

視操作內容可能需要 documents.currentonly 或 documents。第一次跑會跳授權。

Q5:可以把名稱與連結一起寄信嗎?

可以。getName() 搭 getUrl(),官方示例也這樣做。


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