質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

9486閲覧

【GAS】エラー TypeError: Cannot read property '0' of undefined

donguriko

総合スコア30

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

0クリップ

投稿2022/01/22 14:52

編集2022/02/03 23:36

前提・実現したいこと

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/ツールのバージョンなど)

回答は急ぎません。
お忙しいところ大変申し訳ありませんが、非エンジニアビギナーでも
わかるレベルでのアドバイス、解説をいただけると大変助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

itagagaki

2022/01/22 15:31

Logger.log(myEvent); で何が表示されているか、わかりますか? ログの中でこれを見つけるのは難しそうな気もするので Logger.log("myEvent="+myEvent); のようにして実行してみたほうがいいかもしれません。 また、Logger.logではなくconsole.logのほうがいいかもしれません。
donguriko

2022/01/23 00:53

itagagakiさま コメントありがとうございます。 console.log結果~下に掲載します console.log("myEvent " + myEvent);       ↓ myEvent Tue Jan 04 2022 10:00:00 GMT+0900 (Japan Standard Time),Tue Jan 04 2022 10:30:00 GMT+0900 (Japan Standard Time),テスト1,Wed Jan 05 2022 10:30:00 GMT+0900 (Japan Standard Time),Wed Jan 05 2022 11:00:00 GMT+0900 (Japan Standard Time),テスト2,Thu Jan 06 2022 11:00:00 GMT+0900 (Japan Standard Time),Thu Jan 06 2022 11:30:00 GMT+0900 (Japan Standard Time),テスト3,Fri Jan 07 2022 11:30:00 GMT+0900 (Japan Standard Time),Fri Jan 07 2022 13:00:00 GMT+0900 (Japan Standard Time),テスト4,Mon Jan 10 2022 09:30:00 GMT+0900 (Japan Standard Time),Mon Jan 10 2022 10:00:00 GMT+0900 (Japan Standard Time),テスト10,Tue Jan 11 2022 10:00:00 GMT+0900 (Japan Standard Time),Tue Jan 11 2022 11:00:00 GMT+0900 (Japan Standard Time),テスト11,Wed Jan 12 2022 10:30:00 GMT+0900 (Japan Standard Time),Wed Jan 12 2022 11:00:00 GMT+0900 (Japan Standard Time),テスト12,Thu Jan 13 2022 11:00:00 GMT+0900 (Japan Standard Time),Thu Jan 13 2022 11:30:00 GMT+0900 (Japan Standard Time),テスト13,Fri Jan 14 2022 11:30:00 GMT+0900 (Japan Standard Time),Fri Jan 14 2022 12:00:00 GMT+0900 (Japan Standard Time),テスト14 ■不勉強で恐縮ですが、教えてください。  「Logger.logではなくconsole.logのほうがいいかもしれません。」の理由を教えていただけますか? こういう時はこっちがいい等、両者の違いが何か、どう使い分ければいいのかがよく分からず。
itagagaki

2022/01/23 01:11

少なくとも、その実行時の myEvent は undefined ではないようですね。 私の勘ですが let startTime = myEvent[i][0]; で、myEvent が undefined だったため TypeError: Cannot read property '0' of undefined となったのではないかと推測しています。 プログラムを実行して、このエラーメッセージが出力される直前の console.log("myEvent " + myEvent); の出力をもう一度確認してみてください。 Logger.logはトリガーで実行したときにはログに出力されません。 cosole.logなら、トリガーで実行したときもスクリプトエディタで実行したときも出力されます。 なので私はたいていconsole.logを使います。 ただLogger.logには書式が使えるという利点があります。
donguriko

2022/01/23 01:20

itagagakiさま ご返信ありがとうございます。 トリガー設定はまだしていません。 コードを記載する画面? の「実行ボタン」を押して動かしてます。 掲載したのはその時のログです。 そして、今回も又一見ただしく動いてそうにみえるのですが下のエラーが立ちます。 (以下、実行ログ画面から転載)            ↓ TypeError: Cannot read property '0' of undefined getCalendarEvents @ テスト 予定取得20220122.gs:76
donguriko

2022/01/23 01:49

qnoirさま お忙しい中、丁寧な解説、本当にありがとうございます。 エラーの意味と読み方? とても勉強になります。 配列の理解、まだ 消化しきれていないですね。 いただいた回答を再度じっくりと読み返し、理解を深めたいと思います。 又、直接方式と経由方式についても考え方を教えていただきありがとうございます。 メリ、デメ、とてもよく分かりました。 いつも丁寧なご指導本当にありがとうございます。 qnoirさまの丁寧なご指導に報いるべく、頑張って知識を深めたいと思います。 ありがとうございました。
donguriko

2022/01/23 07:32 編集

qnoirさま ご回報内容熟読させていただきました。 「配列は0はじまり」がまだ身についていない事、痛感しました。 慣れるまではコード記載する際、頭が混乱しないよう余白に連番をふる などの工夫をして感覚を身につけていきたいと思います。 2点追加で質問です。 ①修正案2 について - mySheet.getRange(4, 6, myEvent.length ,1).setValue("登録済"); + mySheet.getRange( i + 4, 6, 1, 1).setValue("登録済");  「 i + 4」とすることで、エラーで処理がとまった場合、エラー後はPGMで iを取り?に 行けず、その結果、転記処理も止まるので、コードをiとした方がよい、 という理解であっていますか? 勉強になりました。 ②処理1)カレンダー登録情報を配列として取得する部分のコード 恥ずかしながらこの部分のコードはWEBで参照したコードを自分なりに 読み解き、コメント追記しながら流用させていだきました。 が、何故、以下の3stepをふんで二次元配列にしている(しないといけない)のか、 正直消化不良気味です。 a)空の二次元配列の箱valuesを作る b)カレンダー登録情報を一次元配列recordとして取得 c)二次元配列の箱valuesに一次元配列recordを投入。 スプレッドシートで書き出ししたい形式が二次元なのに対し、 カレンダー登録情報は一次元となっているため、一次元→二次元にするために まずa)の箱を作っておき、pushでそこにデータをいれている、という イメージですか? 回答は急ぎませんので、お時間ある時にレクチャーいただけると助かります。 お手を煩わせて申し訳ありません。
退会済みユーザー

退会済みユーザー

2022/01/24 01:24

ご質問の件、私の回答のコメントの方に回答しました。確認宜しくお願いします。
guest

回答1

0

ベストアンサー

①誤りの箇所、どのように修正すればよいのか

・エラーの箇所について

TypeError: Cannot read property '0' of undefined getCalendarEvents @ テスト 予定取得20220122.gs:76

この文末の「予定取得20220122.gs:76」は、
「予定取得20220122.gs の 76行目」でエラーが発生していることを示しています。

・修正案
ループの下記部分をmaxRow2 - 3に修正してみてはいかがでしょうか。

diff

1- for (let i = 0; i < maxRow2 - 2; i++) { 2+ for (let i = 0; i < maxRow2 - 3; i++) { 3 let startTime = myEvent[i][0]; 4 let endTime = myEvent[i][1] 5 let title = myEvent[i][2];

さらに、現状だと、最初から全行に「登録済」が記入されてしまう(仮にエラー等で途中で止まっても、まだコピーされていない行まで「登録済」になってしまう)ので、最後の行は下記のように修正してはいかがでしょうか。

diff

1 //▼転記結果をスプシに追記する 2 //getRange(行、列、▲行分、■列分) 3 console.log("myEvent.length " + myEvent.length); 4 console.log("myEvent[0] " + myEvent[0]); 5- mySheet.getRange(4, 6, myEvent.length ,1).setValue("登録済"); 6+ mySheet.getRange( i + 4, 6, 1, 1).setValue("登録済"); 7 }

・エラーの原因について
76行目はfor文の部分だと思いますが、その行より前をさかのぼって
eventRange と myEvent を定義している部分について見てみましょう。

//getRange(行目,列目,●行分,●列分) //起点はセルC4(行4,列3)~L列まで  const eventRange = mySheet.getRange(4, 3, maxRow2 - 3, 3); //▼各予定データを配列(myEvent)として取得する const myEvent = eventRange.getValues(); Logger.log(myEvent); const myEvent = eventRange.getValues();

ここで、仮にシートの10行目までデータが入っていて、maxRow2=10だと仮定します。

eventRange = mySheet.getRange(4, 3, maxRow2 - 3, 3);

eventRange = mySheet.getRange(4, 3, 10 - 3, 3);

eventRange = mySheet.getRange(4, 3, 7, 3);
となるので
(第3引数が「7」なので)eventRangeの行範囲は7行分 です。
(言い方を変えると、4行目から10行目までの7行分です)

したがってmyEventは、7行×3列の2次元配列になっています。
myEventのデータが7行ということは
myEventの1次元目のインデックスの最大値は「7」ではなく「6」(0始まりで7番目)になっています。

その下で、forループを回していますが

for (let i = 0; i < maxRow2 - 2; i++) { let startTime = myEvent[i][0]; let endTime = myEvent[i][1] let title = myEvent[i][2];

このコードだと

for (let i = 0; i < maxRow2 - 2; i++) {

「iは 0 から < maxRow2 - 2 = 10-2 =8未満("<"なので)」すなわち
「iは 0 から 7 まで」の8行分、ループを回すことになります。

よって、ループの最後 i=7 のとき、
myEvent[7]にアクセスすることになりますが
これは、上述の、myEventの1次元目のインデックス最大値「6」を超えてアクセスすることになります。

myEvent[7]は、インデックスの最大値6を超えているため undefined になる

myEvent[7][0] は undefined[0] の意味になる

「TypeError: Cannot read property '0' of undefined(undefinedの'0'というプロパティーを読み取れません)」というエラーが表示されます。

したがって、for-ループの範囲指定のところは
i < maxRow2 - 3
に直し、取得した範囲(2次元配列)のインデックス最大値を超えないようにすれば、掲題のエラーはなくなると思われます。


②予定コピーの手法

今回、カレンダー①→スプレッドシート→カレンダー②と経由させて予定コピーをする手法にしました。
が、別アプローチとして、カレンダー①→カレンダー②にダイレクトにコピーする方法も可能でしょうか?
可能な場合、「スプレッドシート」経由と「直接方式」どちらの方がおすすめでしょうか?
その理由(メリ、デメ等の考え方)も教えていただけると助かります。

→ 個人的には、「スプレッドシート」経由の方がよいと思います。

「スプレッドシート」経由のメリット:
カレンダー→カレンダーへの直接コピーの場合、仮に途中でバグやGASの実行制限時間を超えた等の理由でスクリプト止まってしまった場合
どこまでデータをコピー完了したのかが記録されていないため、コピー先のカレンダーの内容を確認する必要が生じます。
現状は、スプレッドシートに記載したスケジュールイベントを、全部コピー先から削除するようになっているようなので問題はないかもしれませんが
仮にこの処理を変更して、削除せずにコピーする方法に変えた場合、すでにコピーが完了したスケジュールは重複して記録されてしまいます。

スプレッドシートに、転記元のスケジュールデータとコピー先へのコピー状況を記録することで、このような事態に対応しやすくなります。
(きちんと対応するには、「登録済の行はスキップする」という処理を追加しないといけないかもしれませんが)

デメリット:
スプレッドシートに記録する処理の分だけ時間が余計にかかります。
また、スプシへの書き込み処理のAPI消費がわずかだとしても、直接方式よりAPIを多く消費することに変わりはない為、制限がかかる可能性もあります。
コピー全体の処理が制限時間(無料のGoogle Workspaceならば6分)を超えそうな場合は、たとえば5分ごとに分割して処理を行う等の工夫が必要になります。
もっとも、カレンダーからカレンダーへ直接コピーする場合も、API制限と処理時間にひっかかる可能性はあります。
仮に直接方式でも時間制限に引っかかる場合は、どこまでコピー完了したかについて、ログまたはコピー先のカレンダーを確認しないとわかりません。
ログに表示されている内容は一時的なものですし、プログラム上で扱おうと思っても難しいです。(ログテキストを手動コピーして加工する必要あり)
処理経過を記録できるスプレッドシート経由方式の方が、プログラムで簡単に扱えます。

投稿2022/01/23 01:37

編集2022/01/23 03:15
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/01/24 03:34 編集

>「 i + 4」とすることで、エラーで処理がとまった場合、エラー後はPGMでiを取り?に 行けず、その結果、転記処理も止まるので、コードをiとした方がよい、という理解であっていますか? おおむねそのとおりです。 修正後のコードであれば、途中で止まったばあいでも、コピーが正常に終わった分だけしかスプレッドシートに記録されていないため、状況の把握しやすくなります。 またそもそも、修正前のコードだと、ループの度に同じ範囲に同じ値を書き込んでいるため、時間がかかるだけであまり意味がありません。仮にまとめて結果を記録するなら、ループが終わった直後の一回だけ書き込めば十分です。 > 何故、以下の3stepをふんで二次元配列にしている(しないといけない)のか、正直消化不良気味です。 これは、「一つ一つgetRange().setValue()で書き込む事もできるはずなのに、なぜ二次元配列を作って書き込んでいるのか?」という意味でしょうか?
donguriko

2022/02/02 13:04

qnoirさま 返信が遅くなり申し訳ありません。 そして、どこが分からないのかがうまく説明できず申し訳ありません。 データ取得元が表形式のデータで二次元配列としてデータ取得をする場合だと、 以下の流れでデータを取得しているかと。 イ)最初にデータ取得範囲をgetRangeで指定 ロ)const「任意の配列名」= getRangeで表データの範囲指定し「.getValues」 する ※ ハ)取得する各項目の[タテ][ヨコ]位置を指定 ニ)for文でタテ、ヨコ方向の繰り返しループを指定  ※ロ)の工程が「a)空の二次元配列の箱valuesを作る」と   「c)二次元配列の箱valuesに一次元配列recordをpushで投入」に相当するものですか??   「.getValues」で空の箱にデータを投入できるので、push処理の必要がないのですか? push処理が必要なケースと不要なケースの違いが今ひとつよく分からず。。。  この説明で伝わりますでしょうか?   
退会済みユーザー

退会済みユーザー

2022/02/02 14:22 編集

うまい説明をするのが難しいのですが、、、 まず、「setValues(〇)の〇の部分には2次元配列を入れる」というのが前提になります。 (実際は単一値も指定できますがここでは本題ではないので割愛します) そして、「〇に入れるべき2次元配列の作り方は、何通りもある」ということです。 言い換えれば、期待する2次元配列の形になりさえいれば、どう作ってもよい(作りやすいように作ればよい)ということです。 たとえば [[1,2,3],[4,5,6],[7,8,9]] という2次元配列をつくるとき、 const a=[[1,2,3],[4,5,6],[7,8,9]] と一発で作ってもよいですし、 const a = [] const x=[1,2,3] const y=[4,5,6] const z=[7,8,9] a.push(x) a.push(y) a.push(z) と7行かけて同じ2次元配列を作ることもできます。 (以上を実行すると、aは[[1,2,3],[4,5,6],[7,8,9]]になる) コメント内の質問について言及すると、 「データ取得元が表形式のデータで二次元配列としてデータ取得をする場合だと、 以下の流れでデータを取得している(以下略)getRangeで表データの範囲指定し「.getValues」 する」 →この場合、getRangeして「getValues」した時点で、一括してgetRangeで指定した範囲の値で2次元配列が生成されます。   一方、質問文のコード内での2次元配列の作り方 「以下の3stepをふんで二次元配列にしている。 a)空の二次元配列の箱valuesを作る b)カレンダー登録情報を一次元配列recordとして取得 c)二次元配列の箱valuesに一次元配列recordを投入。」 これは、なぜこうしないといけないのか、というより、このやり方の方が作りやすいからです。 もし、3stepを踏まずに一発で同じ2次元配列を作ろうとしたら、下記のように書くことになります。 ``` const values = [ [events[0].getStartTime(), events[0].getEndTime(), events[0].getTitle()], [events[1].getStartTime(), events[1].getEndTime(), events[1].getTitle()], [events[2].getStartTime(), events[2].getEndTime(), events[2].getTitle()], [events[3].getStartTime(), events[3].getEndTime(), events[3].getTitle()], ... ... ... [events[n].getStartTime(), events[n].getEndTime(), events[n].getTitle()], ]; しかし、これは実際にはうまく行きません。 なぜならば、evevntsの行数nはカレンダーデータによって10個だったり20個だったりと不定であり、プログラムを作る時点では知りようがないからです。 なので、 ・カレンダーからeventを1つ取得し、 ・ [event.getStartTime(), event.getEndTime(), events.getTitle()]というデータを作り ・これをvaluesに1つずつpushする ・上記の操作を、最後のeventに到達するまで繰り返し という手順を踏んで、valuesという変数を2次元配列に仕立てて 最終的にsetValues(values)を行ってシートに書き込んでいるのです。 以上の説明で疑問に対する答えになりましたでしょうか? -- 「push処理が必要なケースと不要なケースの違い」についていえば、 ①個数(行数)があらかじめ固定できる場合(あらかじめ範囲指定して取得できるような場合)→push処理がなくても一発で作れる ②全部の個数(行数)が最初から固定できない場合(=いつ最後に到達するかわからず、最後に到達するまで1つ1つ取得していく必要がある場合)→push処理を使った方が作りやすい というような答えになります。 もちろん①のような場合でも②のやり方で2次元配列を作ることは可能です。2次元配列の作り方は1つではないので。
donguriko

2022/02/03 14:36

qnoirさま お忙しい中、丁寧な解説ありがとうございます。 まだ、「配列」の概念? (イメージ)が自分の中で消化しきれていないので、 目で行列のイメージが見える表形式のデータ→二次元配列はうっすらイメージできるものの、 カレンダーのeventのようなデータとなると、そもそも一次元配列なのか、二次元配列なのか から分からなくなり頭の中が混乱していました。 最初から個数が固定できる場合は、getRangeして「getValues」で一発で二次元配列を 作った方がいい。 全部の個数(行数)が最初から固定できない場合(=いつ最後に到達するかわからない場合) は、push処理を使った方が作りやすい、ということなのですね。 「配列」の理解がまだまだですが、引き続き理解を深めたいと思います。 お忙しい中、お時間を割いて丁寧にレクチャーいただき本当にありがとうございます。 ただただ感謝です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問