Google 日曆: 透過ID取得日曆 getCalendarById()

 


如果你剛踏入 Google Apps Script 的世界,很快就會遇到一題:如何把事件「確實」發到我想要的那個日曆?答案就是 getCalendarById()。

與其把所有事情都丟到預設主日曆,不如直接指向專案的共用日曆或會議室資源,資料才不會散一地。這篇的節奏會很輕鬆:先教你從日曆介面找出 Calendar ID,再用最短的程式碼跑出第一支列出行程的腳本。

接著我們會一步步補上常用技巧:篩選關鍵字、建立單次與整天活動、把試算表列轉成多筆事件。文末整理幾個大家常問的問題與排錯思路,像是 getCalendarById() 回傳 null、授權視窗一直跳、或事件建立了卻抓不到 ID 等等。目標很單純:讓你第一次用就上手,之後改出自己的版本也不會卡。希望本篇文章可以幫助到需要的您。


目錄

{tocify} $title={目錄} 


為什麼要用 getCalendarById()?

在 Apps Script 中,CalendarApp.getCalendarById(id) 能用「日曆的 ID」直接取得某一個特定日曆物件(Calendar),後續就能對該日曆讀取事件、建立新事件、查詢時區/名稱、設定顏色、檢查是否隱藏等。相較於 getDefaultCalendar() 只能操作你的個人主日曆,getCalendarById() 讓你可以精準指向:

        你的副日曆(secondary calendar)

        團隊共用日曆(Google 群組或專案日曆)

        資源日曆(會議室/設備)

        甚至他人的公開日曆(或你有權限存取的日曆)

官方文件明確列出這個方法與周邊能力,後文會引用對應條目;你可以先快速確認:CalendarApp 類別底下就有 getCalendarById(id) 與各種操作方法。


前置觀念:什麼是 Calendar ID?哪裡看得到?

Calendar ID ≠ 日曆名稱。 它通常是一串類似 Email 的字串。幾個常見型式:

你的主日曆(Primary): 通常就是你的 Gmail 地址,例如 you@example.com。

副日曆/共用日曆: 多為類似 xxxxxxxxxxxxxxxxxxxx@group.calendar.google.com 的字串。

資源日曆(會議室/設備): 可能也是 email 格式或系統生成字串。


到哪裡找 Calendar ID?

最新版 Google 日曆介面流程如下(2025-07-15 的校園 IT 教學頁也示範了一樣的步驟):

1.    在左側日曆清單中,將滑鼠移到某個日曆名稱上,點 三個點的選單。

2.    選 「設定與共用」(Settings and sharing)。

3.    往下捲到 「整合日曆(Integrate calendar)」 區塊。

4.    在那裡就能看到 Calendar ID。


補充:不少外部教學也提到相同脈絡的查找方式(左邊清單 → 設定 → 整合日曆)。


方法速覽:getCalendarById() 能做什麼?

取得 Calendar 物件後,你可以呼叫很多實用方法,例如:

getName() / getId() / getTimeZone() / isHidden() / isOwnedByMe():查屬性。

getEventsForDay(date, options) 或 getEvents(start, end, options):在時間範圍抓事件。

createEvent(title, startTime, endTime, options)、createAllDayEvent(title, date, options):建立事件。


最小可執行範例

目標:列出特定日曆今天的事件標題

function listTodayEvents() {
  // 1) 把你的 Calendar ID 填進來(可用主日曆 Email 或 group.calendar.google.com 那串)
  var CAL_ID = 'your-calendar-id@group.calendar.google.com';

  // 2) 取得 Calendar 物件
  var cal = CalendarApp.getCalendarById(CAL_ID); // 若 ID 錯誤或沒權限,cal 可能為 null

  if (!cal) {
    throw new Error('找不到該日曆,請檢查 Calendar ID 或你的存取權限。');
  }

  // 3) 抓今天 00:00 ~ 23:59 的事件
  var today = new Date();
  var start = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
  var end   = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59);

  var events = cal.getEvents(start, end); // 也可用 getEventsForDay(today)
  Logger.log('共 ' + events.length + ' 筆:');

  events.forEach(function(e, i) {
    Logger.log((i + 1) + '. ' + e.getTitle());
  });
}


一步步帶你走:從 ID 到建立事件

1.    取得日曆物件

var cal = CalendarApp.getCalendarById('you@example.com'); // 你的主日曆
// 或者:
var cal = CalendarApp.getCalendarById('xxxxxxxxxxxxxxxxxxxx@group.calendar.google.com'); // 副/共用日曆
if (!cal) throw new Error('Calendar 取得失敗。');


文件:getCalendarById(id) 會回傳該 Calendar,之後就能呼叫 getName()、getTimeZone() 等。


2.    查日曆屬性(驗證拿到的是誰)

Logger.log('Name=' + cal.getName());
Logger.log('ID=' + cal.getId());
Logger.log('TimeZone=' + cal.getTimeZone());
Logger.log('OwnedByMe=' + cal.isOwnedByMe());


這些屬性方法都在 Calendar 類別文件中列出,有對應範例。


3.    建立單次事件

function createOneEvent() {
  var cal = CalendarApp.getCalendarById('your-calendar-id@group.calendar.google.com');
  if (!cal) throw new Error('找不到日曆。');

  var start = new Date('2025-10-15T14:00:00'); // ISO 也可
  var end   = new Date('2025-10-15T15:30:00');

  var event = cal.createEvent('產品碰面會議', start, end, {
    description: '議程:Roadmap / 風險 / 資源',
    location: 'A 棟 3F 會議室',
    guests: 'pm@example.com,lead@example.com',
    sendInvites: true
  });
  Logger.log('Created: ' + event.getId());
}


createEvent() 的選項在官方頁面有列;搭配 getCalendarById() 即可將事件建到目標日曆而不是預設主日曆。


4.    建立整天或多天事件

cal.createAllDayEvent('黑客松 Day 1', new Date('2025-11-02'), { description: '開幕' });
cal.createAllDayEvent('黑客松 Day 2', new Date('2025-11-03'), { description: '決賽' });


也可用 createAllDayEventSeries() 產生連續整天事件;更多變化見官方方法清單。


5.    查詢事件(區間/條件)

// 抓未來 7 天所有事件
var now = new Date();
var nextWeek = new Date(now.getTime() + 7*24*60*60*1000);
var events = cal.getEvents(now, nextWeek, { search: '會議' }); // 依關鍵字過濾
events.forEach(function(e){ Logger.log(e.getTitle() + ' @ ' + e.getStartTime()); });


getEvents(start, end, options) 與 getEventsForDay(date, options) 都在同一份 CalendarApp 文件上列舉。


授權與存取權限

1.    Apps Script 第一次執行會要求授權。你會看到要存取 Google 日曆的權限。之後若改動範圍,也可能再次要求。

2.    你必須對目標日曆有足夠權限(至少能建立/編輯事件)。否則雖能取得 ID,getCalendarById() 也可能回 null 或在建立事件時拋錯。實務上很多人踩在這:ID 沒錯,但你沒有寫入權。 相關討論中常見回覆就是「請確認你用的是 Calendar ID 而不是名稱,並且你對該日曆有存取權」。

3.    要給別人(或表單提交者)的日曆建事件? 不是拿對方 Email 就能寫。若對方的主日曆沒有授權給你,getCalendarById(對方 email) 可能拿不到可寫入的物件或直接 null。解法通常是:請對方共用某個日曆給你、或改用你方的共用專案日曆承載事件。


進階:資源日曆/共用日曆的 ID 與注意事項

資源日曆(會議室/設備) 通常由系統管理員在 Google Workspace 後台建立,會有自己的 ID。你一樣可以用 getCalendarById() 指向該資源,只要你有權限。

共用日曆(@group.calendar.google.com)建議把 ID 存在常數或屬性(PropertiesService)裡,避免硬編碼散落在多支腳本,也方便環境切換。


錯誤處理與偵錯範式

1.    防呆:先驗證 cal 是否為 null

function safeGetCal(id) {
  var cal = CalendarApp.getCalendarById(id);
  if (!cal) {
    throw new Error('無法取得日曆:' + id + '。請確認 ID 與權限。');
  }
  return cal;
}


2.    包裝建立事件(含重複嘗試與紀錄)

function createEventSafe(calId, title, start, end, options) {
    var cal = safeGetCal(calId);
  for (var i=0; i<2; i++) { // 簡單重試
    try {
      var ev = cal.createEvent(title, start, end, options || {});
      Logger.log('Created: ' + ev.getId());
      return ev;
    } catch (err) {
      Utilities.sleep(500);
      if (i === 1) throw err;
    }
  }
}


3.    事件 ID 與「可再取回」的注意(常見誤解)

有些人會把 getEvents() 取得的事件 ID 存起來,事後用 getEventById() 取回,卻遇到取不到或格式不合。實務討論裡最常見結論:請確保你拿的是 Apps Script 需要的事件 ID 格式,以及事件來源一致。若混用 Calendar API v3 的 ID/ICalUID 等,會對不上。遇到這類情況,請回頭檢查你的取得/儲存來源與方法。


常見錯誤與雷點

1.    把「日曆名稱」當成 ID 傳入

如 getCalendarById('行銷部日曆') —— 這會失敗。要傳的是 Calendar ID,不是顯示名稱。

2.    沒有權限卻想寫入他人主日曆

你可以知道對方的 email,但那不代表你有寫入他主日曆的權限。請改用已授權給你的共用日曆或請管理員設定存取權。

3.    找不到 ID 放哪裡看

介面更新後路徑仍然固定:左側清單 → 三點 → 設定與共用 → 整合日曆 → Calendar ID。

4.    事件時間格式混亂

createEvent() 需要起迄皆為 Date(含時分秒)。若你從試算表來,請先把字串轉 Date,或用 new Date('YYYY-MM-DDTHH:mm:ss')。

5.    跨日/整天事件的邊界

整天事件請用 createAllDayEvent() 或 createAllDayEventSeries();否則跨日邏輯與時區會讓你很痛苦。

6.    重複事件(Recurring)處理不當

需要用規則(RRULE)與結束條件(UNTIL/COUNT)正確描述;否則只建立一筆或週期錯亂。這在社群提問中很常見。

7.    混用 Calendar API 與 Apps Script Calendar 服務的 ID

兩套模型有些差異,請不要混淆 eventId/ICalUID。若你用到 Advanced Calendar API,請全程遵守同一套 API 的約定。


常見任務的實作範例

1.    把 Google 試算表資料寫進指定日曆


function sheetToCalendar(calId, sheetName) {
  var cal = safeGetCal(calId);
  var sh  = SpreadsheetApp.getActive().getSheetByName(sheetName || 'Events');
  var rows = sh.getDataRange().getValues(); // 假設第一列是標題:Title | Start | End | Location | Guests
  for (var r = 1; r < rows.length; r++) {
    var [title, startStr, endStr, location, guests] = rows[r];
    if (!title || !startStr || !endStr) continue;

    var start = new Date(startStr), end = new Date(endStr);
    cal.createEvent(title, start, end, {
      location: location || '',
      guests: (guests || '').toString().replace(/\s+/g, ''),
      sendInvites: true
    });
  }
}


2.    批次拉出下週行程到試算表

function exportNextWeek(calId, sheetName) {
  var cal = safeGetCal(calId);
  var now = new Date();
  var nextWeek = new Date(now.getTime() + 7*24*60*60*1000);
  var events = cal.getEvents(now, nextWeek);

  var sh = SpreadsheetApp.getActive().getSheetByName(sheetName || 'Export') || 
           SpreadsheetApp.getActive().insertSheet('Export');
  sh.clear().appendRow(['Title','Start','End','Location','Creators']);

  events.forEach(function(e){
    sh.appendRow([
      e.getTitle(),
      e.getStartTime(),
      e.getEndTime(),
      e.getLocation(),
      e.getCreators().join(',')
    ]);
  });
}


3.    建立整天系列活動(連續多天)

function createAllDaySeries(calId, startDate, days) {
  var cal = safeGetCal(calId);
  var start = new Date(startDate); // 例如 '2025-12-01'
  for (var i=0; i<days; i++) {
    var d = new Date(start.getFullYear(), start.getMonth(), start.getDate() + i);
    cal.createAllDayEvent('研討會 Day ' + (i+1), d);
  }
}


測試與發佈的實務建議

分環境管理 ID:

        用 Script Properties 存 CAL_ID_DEV、CAL_ID_PROD,避免手誤發到正式日曆。

開發用沙盒日曆:

        新建一個私有副日曆,只給開發團隊;等驗證 OK 再換成正式 ID。

Log 與錯誤統計:

        將 event.getId()、getTitle()、getStartTime() 寫到試算表或日誌方便追蹤。

權限最小化:

        僅讓腳本對必要的日曆有寫權;共用日曆比讓腳本寫他人主日曆安全。以上做法都呼應社群中反覆出現的權限/ID 失誤案例。


問題集

Q1:getCalendarById() 回傳 null?

A:九成是 ID 錯或沒權限。請回到日曆設定頁確認 Calendar ID,並檢查你是否對該日曆有讀/寫權。

Q2:我用同事的 email 當 ID,為何建不了事件?

A:email 不是萬能通關。你需要對方授權或改用共用日曆。

Q3:事件 ID 存起來後,為何 getEventById() 抓不到?

A:請確認你存的是Apps Script 事件 ID,別把 Calendar API 的另一種 ID 或 ICalUID 混用。

Q4:如何限制只抓含某關鍵字的事件?

A:getEvents(start, end, { search: '關鍵字' })。官方在 CalendarApp 有列出 options 可用參數。


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