前提・実現したいこと
2つのGoogleカレンダー(カレンダー①、②)があります。
カレンダー①の予定をカレンダー②にコピーさせるGASを作りたいです。
以下の方法でのコピーを試みています。
1)カレンダー①の登録内容をスプレッドシートに書出し
2)書き出した内容を配列で取得し、カレンダー②に予定登録
3)スプレッドシートに「登録済」のフラグを追記
発生している問題・エラーメッセージ
下のエラーが出てしまっています。
TypeError: Cannot read property '0' of undefined getCalendarEvents @ テスト 予定取得20220122.gs:76
該当のソースコード
以下、コード全部記載します。
GAS
1function getCalendarEvents() { 2 const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 const mySheet = ss.getSheetByName("転記シート"); 4 5 const CAL1 = ' ~割愛~ @group.calendar.google.com'; //★転記元カレンダー★ 6 const calendar1 = CalendarApp.getCalendarById(CAL1); 7 8 const CAL2 = ' ~割愛~ @group.calendar.google.com'; //★転記先カレンダー★ 9 const calendar2 = CalendarApp.getCalendarById(CAL2); 10 11 const startTime = new Date('2022/01/04 00:00:00'); 12 const endTime = new Date('2022/01/31 00:00:00'); 13 14 //★あとで修正★ 15 //同期処理の周期 16 //const syncDays = 14; 17 //endTime.setDate(startTime.getDate() + syncDays); 18 const events1 = calendar1.getEvents(startTime, endTime); 19 20 //▼転記シートの記載内容をクリアする 21 //最終行(maxrow1)の取得 22 const maxRow1 = mySheet.getRange(mySheet.getMaxRows(), 3).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 23 console.log("maxRow1 " + maxRow1); 24 25 //getRange(行、列、▲行分、■列分) 26 const myRange = mySheet.getRange(4, 3, maxRow1, 3); 27 console.log(myRange.getA1Notation()); 28 myRange.clearContent(); 29 30 //▼カレンダーの情報を二次元配列(values)として取得 31 //<1>空の二次元配列valuesを生成 32 const values = []; 33 34 //<2>一次元配列(record)を作成後にpushメソッドで二次元配列valuesに追加 35 //配列内は「StartTime」「EndTime」「タイトル」が1行分のデータ 36 for (const event of events1) { 37 const record = [ 38 event.getStartTime(), 39 event.getEndTime(), 40 event.getTitle(), 41 ]; 42 43 //<3>配列(values)内にrecordのデータを追加 44 values.push(record); 45 console.log(record); 46 console.log("values.length " + values.length); 47 console.log("values[0] " + values[0]); 48 } 49 50 //▼スプレッドシートに二次元配列(values)のデータを書き出し 51 //getRange(行、列、▲行分、■列分) 52 mySheet.getRange(4, 3, values.length, values[0].length).setValues(values); 53 54 //転記先カレンダーに登録済の予定を削除する 55 const events2 = calendar2.getEvents(startTime, endTime); 56 for (const event of events2) { 57 event.deleteEvent(); 58 } 59 60 //▼データ取得範囲の指定 61 //各種予定のデータ取得範囲の指定 62 //最終行(maxRow2)の取得 63 const maxRow2 = mySheet.getRange(mySheet.getMaxRows(), 3).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 64 console.log("maxRow2 " + maxRow2); 65 66 //getRange(行目,列目,●行分,●列分) 67 //起点はセルC4(行4,列3)~L列まで 68 const eventRange = mySheet.getRange(4, 3, maxRow2 - 3, 3); 69 console.log("eventRange " + eventRange.getA1Notation()); 70 71 //▼各予定データを配列(myEvent)として取得する 72 const myEvent = eventRange.getValues(); 73 Logger.log(myEvent); 74 75 for (let i = 0; i < maxRow2 - 2; i++) { 76 let startTime = myEvent[i][0]; 77 let endTime = myEvent[i][1] 78 let title = myEvent[i][2]; 79 80 calendar2.createEvent(title, startTime, endTime); 81 82 83 //▼転記結果をスプシに追記する 84 //getRange(行、列、▲行分、■列分) 85 console.log("myEvent.length " + myEvent.length); 86 console.log("myEvent[0] " + myEvent[0]); 87 mySheet.getRange(4, 6, myEvent.length ,1).setValue("登録済"); 88 } 89} 90 91
試したこと
エラーが立ってしまっているのでどこかに問題があると思うのですが、
下を見ると1)の処理、2)の処理 3)の処理ともにできているように見えます。
<カレンダーイメージ>
赤 :転記元カレンダー
黄色:転記先カレンダー
<<教えてほしいこと 3点>>
知識不足で申し訳ありません。
①誤りの箇所、どのように修正すればよいのか
上記アドバイスをいただけないでしょうか?
どこかの定義ができていないというエラーかと思うのですが、
現コードのどこに誤りがあるのか、分かりません。
②予定コピーの手法
今回、カレンダー①→スプレッドシート→カレンダー②と経由させて
予定コピーをする手法にしました。
が、別アプローチとして、
カレンダー①→カレンダー②にダイレクトにコピーする方法も可能
でしょうか?
可能な場合、「スプレッドシート」経由と「直接方式」どちらの方が
おすすめでしょうか?
その理由(メリ、デメ等の考え方)も教えていただけると助かります。
③「直接方式」が可能かつ「おすすめ」の場合
カレンダー①の予定取得時に使用したvaluesをそのまま使用して、
カレンダー②に予定登録させる方法でできますか?
そのまま使用がNGの場合、どのようなアプローチがよいかの
アドバイスも欲しいです。
(背景)
現在、Googleカレンダー(アドレスに紐づくメインカレンダーと
いくつかのグループカレンダー)を使用しています。
Googleカレンダーの予定を別の予定管理アプリに同期させ、
外出時の予定確認時等で使用したいです。
別の予定管理アプリ(or Googleカレンダーアプリ)とアドレスに紐づく
Googleメインカレンダーの同期はできていますが、セキュリティの
関係なのかGoogleグループカレンダーと別の予定管理アプリの連携が
できず困っています。
そのため、GASで定期的にグループカレンダーの予定を連携可能な
Googleメインカレンダーに自動コピー、別の予定管理アプリとの
連携が実現できないか、を模索したい次第です。
補足情報(FW/ツールのバージョンなど)
回答は急ぎません。
お忙しいところ大変申し訳ありませんが、非エンジニアビギナーでも
わかるレベルでのアドバイス、解説をいただけると大変助かります。


回答1件
あなたの回答
tips
プレビュー