前提・実現したいこと
スプレッドシート内に「入力シート」「マージシート」の2種があります。
「入力シート」は、「部署」~「転記処理」までの6列分×MAX10行で
1ブロック。
GASで以下の2つの処理をしたいです。
①「入力シート」の内容を「マージシート」に転記
②上記①の処理が完了したら、「入力シート」に「転記済」を追記
①の処理の際、二次元配列でデータ取得したいです。
8行目スタートで、C列~G列までの1行分をまとめて取得。
ループ処理で1行ずつ下に移動させ、取得させる想定です。
添付イメージだと、
ループ処理はIndex0からIndex4まで計5回処理の想定。
発生している問題・エラーメッセージ
下のエラーが出てしまいます。
1つ目の8行目のデータ取得はできているのですが、
2つ目の9行目のデータ取得が失敗しています。
TypeError: Cannot read property '0' of undefined copyToMerge1 @ 入力シート→マージシートへの転記ver1.1.gs:24
該当のソースコード
以下、コード全文記載します。
GAS
1function copyToMerge1() { 2 const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 const mySheet1 = ss.getSheetByName("入力シート"); 4 const mySheet2 = ss.getSheetByName("【●●】マージ"); 5 const mySheet3 = ss.getSheetByName("【■■】マージ"); 6 7 //【ブロック内のループ】 8 //件数データありの最終行(InMaxRow)、転記処理対象の行数(targetRows)の取得 9 const InMaxRow = mySheet1.getRange(18, 4).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 10 const MaxIndex = InMaxRow - 8; 11 console.log("MaxIndex " + MaxIndex); //Index最大値は4の想定 12 13 //「部署」~「所要時間」までの5列分をgetRange(行、列、▲行分、■列分) で 14 // 二次元配列(Values)として取得 15 // ループ処理は0スタートでrがMaxIndex以下になるまで繰返し。 16 for (r = 0; r <= MaxIndex; r++) { 17 const myDetaRange = mySheet1.getRange(8 +r, 3, 1, 5); 18 console.log("myDetaRange " + myDetaRange.getA1Notation()); 19 const values = myDetaRange.getValues(); 20 21 //二次元配列(Values)内の項目は「部署」「件数」「開始時刻」「終了時刻」「所用時間」の5項目 22 let Branch = values[r][0]; 23 let Num = values[r][1]; 24 let startTime = values[r][2]; 25 let endTime = values[r][3]; 26 let length = values[r][4]; 27 console.log("values " + values); 28 29 //【マージシートへの転記処理】 30 //▼「×××マージ」シート(mySheet2)の件数(E列)にデータありの最終行(OutMaxRow1)の取得 31 const OutMaxRow1 = mySheet2.getRange(mySheet2.getMaxRows(), 5).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 32 console.log("OutMaxRow1 " + OutMaxRow1); //10が出る想定 33 34 //▼作業日(入力シートセルE3)の内容を「マージシート(mySheet2)」のB列に転記 35 const myDate = mySheet1.getRange("E2").getValue(); 36 console.log("myDate " + myDate); 37 mySheet2.getRange(OutMaxRow1 + 1 + r, 2, 1, 1).setValue(myDate); 1 38 39 //▼二次元配列(Values)の内容(5項目)を「マージシート(mySheet2)」のD列~G列に転記 40 //getRange(行、列、▲行分、■列分) 41 mySheet2.getRange(OutMaxRow1 + 1 + r, 4, 1, 5).setValues(values); 42 43 //▼マージシートへの転記結果を「入力シート(mySheet1)」の「転記処理」欄に追記する 44 //getRange(行、列、▲行分、■列分) 45 mySheet1.getRange(8 + r, 3 + 5, 1, 1).setValue("転記済"); 46 } 47 48 //▼ダイアログMsgの表示 49 Browser.msgBox("「マージシート」への転記処理が完了しました。\n「転記処理」列に「転記済」表示があれば問題なく転記処理がされています。", Browser.Buttons.OK); 50} 51 52
試したこと
ログを確認すると、2回目のループ処理のデータ取得範囲myDetaRangeは、
myDetaRange C9:G9 となっていますが、
そこで処理が止まり、以降の配列データの取得ができていないようです。
以前に別件照会した、同エラーが出た際の対処→別件照会①も参照し、
forループの範囲指定を確認しましたが、今回のケースではIndex最大値の[4]
を超えていないのではないかと思っています。
<<教えてほしいこと>>
前回ご回報いただいた別件照会①の2/2の「さら問い」の配列の作り方と
ループ処理の関係が理解しきれていないようです。→別件照会①
現コードのどこに誤りがあるのか、どのように修正すればいいのかが
わかりません。
配列(Values)のデータ取得範囲myDetaRangeの指定の際、
第3引数? を1行分としている点が誤りですか?
1行ずつループ処理させたい場合は、r行分まとめて範囲指定
が正しいですか??
もし、データ取得範囲myDetaRangeを1行とする場合なら、
都度配列(Values)に取得したデータを投入していかないと
配列(Values)内のIndexが0、1、2、、、とならない、
ということですか?
何度もご教示いただいているのに習得しきれておらず本当に申し訳ありません。
次こそは、自力解決できるようになりたいので、お手数をおかけして
大変申し訳ありませんが、回答は急ぎませんのでビギナーでも理解できる
レベルでの解説をいただけないでしょうか?
補足情報(FW/ツールのバージョンなど)
本件、別照会で1度照会しています。→別件照会②
今回のコードでは、ループはブロック内のループのみ記載ですが、
前回照会ではブロック間とブロック内の2つのループをさせる想定の
コードでした。
前回回答内容をもとにコードの自力修正を試みましたが、私の知識が
足りず自力解決できませんでした。
そのため、コードを分解し、まずはブロック内で正しく処理が走るよう
1つずつ修正を試みようと思っている次第です。
今回の問題が解決できたら、次ステップとして、
ブロック②、③、、、とブロック間で連続して処理が走るように
拡張させていきたいと思っています。
(参考) 回答を受けて修正したコード(追記)
回答を受け、コードを以下のとおり修正しましたので参考掲載します。
無事処理が走りました。
アドバイスありがとうございました。大変助かりました。
GAS
1function copyToMerge1() { 2 const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 const mySheet1 = ss.getSheetByName("キイロ入力シート"); 4 const mySheet2 = ss.getSheetByName("【●●】マージ"); 5 const mySheet3 = ss.getSheetByName("【■■】マージ"); 6 7//★ブロック間のループ 8//「部署」~「所要時間」までの6列×転記処理対象最終行(MaxRows)分 9//で1ブロックとする。 10//ブロックの開始col(blockCol)はC列(3col)とし、6colとばしで7ブロック目(39col目)まで 11 for (blockCol = 3; blockCol <= 6*6 +3; blockCol +=6) { 12 13 //★ブロック内のデータ取得 14 //件数データありの最終行(InMaxRow)、転記処理対象最終行(MaxRows)の取得 15 const InMaxRow = mySheet1.getRange(18, blockCol+1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 16 const MaxRows = InMaxRow - 7; 17 console.log("MaxRows " + MaxRows); //5の想定 18 19 //「部署」~「所要時間」までの5列分×MaxRows行分をgetRange(行、列、▲行分、■列分) で 20 // 二次元配列(Values)として1回でまとめて取得 21 const myDetaRange = mySheet1.getRange(8, blockCol, MaxRows, 5); 22 console.log("myDetaRange " + myDetaRange.getA1Notation()); 23 const values = myDetaRange.getValues(); 24 console.log("values " + values); 25 26 //★マージシートへの転記処理 27 //▼「×××マージ」シート(mySheet2)の件数(E列)にデータありの最終行(OutMaxRow1)の取得 28 const OutMaxRow1 = mySheet2.getRange(mySheet2.getMaxRows(), 5).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 29 console.log("OutMaxRow1 " + OutMaxRow1); //10が出る想定 30 31 //▼作業日(入力シートセルE3)の内容を「マージシート(mySheet2)」のB列に転記 32 const myDate = mySheet1.getRange("E2").getValue(); 33 console.log("myDate " + myDate); 34 mySheet2.getRange(OutMaxRow1+1, 2, MaxRows, 1).setValue(myDate); 1 35 36 //▼二次元配列(Values)の内容(5項目)を「マージシート(mySheet2)」のD列~G列に転記 37 //getRange(行、列、▲行分、■列分) 38 mySheet2.getRange(OutMaxRow1 +1, 4, MaxRows, 5).setValues(values); 39 40 //▼マージシートへの転記結果を「入力シート(mySheet1)」の「転記処理」欄に追記する 41 //getRange(行、列、▲行分、■列分) 42 mySheet1.getRange(8, blockCol+5, MaxRows, 1).setValue("転記済"); 43 } 44 45 //▼ダイアログMsgの表示 46 Browser.msgBox("「●●マージシート」への転記処理が完了しました。\\n入力シートの「転記処理」列に「転記済」表示があれば問題なく転記処理がされています。", Browser.Buttons.OK); 47} 48 49 50 51

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/03/20 08:47 編集
退会済みユーザー
2022/03/20 13:45
2022/03/20 15:07 編集
退会済みユーザー
2022/03/20 15:38