前提・実現したいこと
GASで以下の処理を行いたいです。
スプレッドシート内に「シート①」「シート②」がある。
「シート①」は以下の構成。
部署(C列)~所用時間(G列)の5列分×可変の行数分が1ブロック。
ブロックは①~⑦の全7ブロック。
まずブロック内で1行ずつ処理し、ブロック内の処理が終わったら、
次のブロックで同処理を繰り返し。
<処理1>
「シート①」の内容を「シート②」に転記。
<処理2>
シート②への転記が完了したら、各ブロックのシート①の転記処理列に
「転記済」を追記。
発生している問題・エラーメッセージ
ブロック内での処理1、2は動いています。
が、ブロック①→ブロック②へのループ処理がうまくできません。
次ブロックにいく時は右方向に6列とばしで処理するようにしたいのですが、
ヨコ方向はそのままで、下方向に1行移動してしまっています。
(ブロック①の処理範囲)
myDetaRange C8:G11
(ブロック②の処理範囲)
myDetaRange C9:G12 ← I8:M10 が正しい
(ブロック③の処理範囲)
myDetaRange C10:G13 ← O8:S8 が正しい
結果、下のエラーが立ち、処理が止まってしまいます。
TypeError: Cannot read property '0' of undefined copyToMerge1 @ 入力シート→マージシートへの転記.gs.gs:23
該当のソースコード
以下、コード全文を記載します。
GAS
1function copyToMerge1() { 2 const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 const mySheet1 = ss.getSheetByName("入力シート"); 4 const mySheet2 = ss.getSheetByName("【×××】マージ"); 5 6 //▼「×××」分のデータ取得 7 //件数(D列)にデータありの最終行(InMaxRow)の取得 8 let i; 9 for (i = 0; i <7; i += 6) { 10 const InMaxRow = mySheet1.getRange(8, i+4).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow(); 11 const targetRows = InMaxRow - 7; 12 console.log("targetRows " + targetRows); 13 14 //タテ方向(x)のループ、ヨコ方向(y)のループの二重ループで取得 15 //getRange(行、列、▲行分、■列分) 「課」~「転記処理」までの5列分を1塊として二次元配列(values)として取得 16 let x, y; 17 for (y = 0; y < 4; y += 6) { 18 for (x = 0; x <= targetRows; x++) { 19 const myDetaRange = mySheet1.getRange(8 +x, 3 +y, targetRows, 5); 20 console.log("myDetaRange " + myDetaRange.getA1Notation()); 21 const values = myDetaRange.getValues(); 22 let Branch = values[x][y]; 23 let Num = values[x][y +1]; 24 let startTime = values[x][y +2]; 25 let endTime = values[x][y +3]; 26 let length = values[x][y +4]; 27 console.log(values); 28 console.log("values[0].length " + values[0].length); 29 console.log("values.length " + values.length); 30 31 //▼二次元配列(values)で取得したデータを「マージ」シートに転記する 32 //件数(E列)にデータありの最終行(OutMaxRow1)の取得 33 const OutMaxRow1 = mySheet2.getRange(mySheet2.getMaxRows(), 5).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 34 console.log("OutMaxRow1 " + OutMaxRow1); 35 36 //getRange(行、列、▲行分、■列分) 37 mySheet2.getRange(OutMaxRow1 +1, 4, values.length, 5).setValues(values); 38 39 //▼作業日を「マージシート(mySheet2)」のB列に転記 40 const myDate = mySheet1.getRange("E2").getValue(); 41 console.log("myDate " + myDate); 42 mySheet2.getRange(OutMaxRow1 +1, 2, values.length, 1).setValue(myDate); 43 44 //転記結果を「入力シート(mySheet1)」の「転記処理」欄に追記する 45 //getRange(行、列、▲行分、■列分) 46 mySheet1.getRange(8 + x, 8 + y, 1, 1).setValue("転記済"); 47 } 48 } 49 //▼ダイアログMsgの表示 50 Browser.msgBox("「マージシート」への転記処理が完了しました。\n「転記処理」列に「転記済」表示があれば問題なく転記処理ができています。", Browser.Buttons.OK); 51 } 52} 53
試したこと
配列とループ処理の理解が不十分で申し訳ありません。
お手数ですが
・考え方
・現コードの誤りの箇所と修正方法
をご教示いただけないでしょうか?
①各ブロック内でのループ処理
MAX行数の判定列がD列、J列、P列、、、と6列とばしのため、
列指定して個々に定義ではなく、繰り返し処理とした方がよいかと
考えたのですが、ブロックごとにMAX行数が可変です。
const myDetaRange = の記載よりも前の部分でgetRangeの「▲行分」の
定義が必要かと思うのですが、どう可変定義すればよいのか迷いました。
②ループ処理順とfor文の定義順
二次元配列のループ処理順についての下のサイトを参照しました。
参照したサイト
ブロック内は下方向にループ。
ブロック内処理が完了したら、次のループへ、としたい場合、
下リンクの「N字の順番」で処理のケースにあたりますか?
それとも、「Z字の順番」で処理のケースですか?
ブロック内は、「二次元配列内の一次元配列をループ」のケースかと
思っているのですが、ブロック間のループも追加となった場合
どれにあたるのかが分からなくなってしまいました。
C列~G列までの1塊を1列と同じとみなして「N字の順番」が正解ですか?
補足情報(FW/ツールのバージョンなど)
次回から、類似のケースは自力で解決できるようになりたいです。
回答は急ぎませんので、
お手数をおかけして申し訳ありませんが、非エンジニア、ビギナーでも
理解できるレベルでの解説をいただけると助かります。

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