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

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

新規登録して質問してみよう
ただいま回答率
87.20%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

解決済

【GAS】行方向、列方向 多重ループ処理について

donguriko
donguriko

総合スコア15

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

1回答

0評価

0クリップ

798閲覧

投稿2022/02/02 15:06

編集2022/02/07 23:01

前提・実現したいこと

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

function copyToMerge1() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const mySheet1 = ss.getSheetByName("入力シート"); const mySheet2 = ss.getSheetByName("【×××】マージ"); //▼「×××」分のデータ取得 //件数(D列)にデータありの最終行(InMaxRow)の取得 let i; for (i = 0; i <7; i += 6) { const InMaxRow = mySheet1.getRange(8, i+4).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow(); const targetRows = InMaxRow - 7; console.log("targetRows " + targetRows); //タテ方向(x)のループ、ヨコ方向(y)のループの二重ループで取得 //getRange(行、列、▲行分、■列分) 「課」~「転記処理」までの5列分を1塊として二次元配列(values)として取得 let x, y; for (y = 0; y < 4; y += 6) { for (x = 0; x <= targetRows; x++) { const myDetaRange = mySheet1.getRange(8 +x, 3 +y, targetRows, 5); console.log("myDetaRange " + myDetaRange.getA1Notation()); const values = myDetaRange.getValues(); let Branch = values[x][y]; let Num = values[x][y +1]; let startTime = values[x][y +2]; let endTime = values[x][y +3]; let length = values[x][y +4]; console.log(values); console.log("values[0].length " + values[0].length); console.log("values.length " + values.length); //▼二次元配列(values)で取得したデータを「マージ」シートに転記する //件数(E列)にデータありの最終行(OutMaxRow1)の取得 const OutMaxRow1 = mySheet2.getRange(mySheet2.getMaxRows(), 5).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); console.log("OutMaxRow1 " + OutMaxRow1); //getRange(行、列、▲行分、■列分) mySheet2.getRange(OutMaxRow1 +1, 4, values.length, 5).setValues(values); //▼作業日を「マージシート(mySheet2)」のB列に転記 const myDate = mySheet1.getRange("E2").getValue(); console.log("myDate " + myDate); mySheet2.getRange(OutMaxRow1 +1, 2, values.length, 1).setValue(myDate); //転記結果を「入力シート(mySheet1)」の「転記処理」欄に追記する //getRange(行、列、▲行分、■列分) mySheet1.getRange(8 + x, 8 + y, 1, 1).setValue("転記済"); } } //▼ダイアログMsgの表示 Browser.msgBox("「マージシート」への転記処理が完了しました。\n「転記処理」列に「転記済」表示があれば問題なく転記処理ができています。", Browser.Buttons.OK); } }

試したこと

配列とループ処理の理解が不十分で申し訳ありません。
お手数ですが
・考え方
・現コードの誤りの箇所と修正方法 
をご教示いただけないでしょうか?

①各ブロック内でのループ処理
MAX行数の判定列がD列、J列、P列、、、と6列とばしのため、
列指定して個々に定義ではなく、繰り返し処理とした方がよいかと
考えたのですが、ブロックごとにMAX行数が可変です。
const myDetaRange = の記載よりも前の部分でgetRangeの「▲行分」の
定義が必要かと思うのですが、どう可変定義すればよいのか迷いました。

②ループ処理順とfor文の定義順
二次元配列のループ処理順についての下のサイトを参照しました。
参照したサイト

ブロック内は下方向にループ。
ブロック内処理が完了したら、次のループへ、としたい場合、
下リンクの「N字の順番」で処理のケースにあたりますか?
それとも、「Z字の順番」で処理のケースですか?

ブロック内は、「二次元配列内の一次元配列をループ」のケースかと
思っているのですが、ブロック間のループも追加となった場合
どれにあたるのかが分からなくなってしまいました。
C列~G列までの1塊を1列と同じとみなして「N字の順番」が正解ですか?

補足情報(FW/ツールのバージョンなど)

次回から、類似のケースは自力で解決できるようになりたいです。
回答は急ぎませんので、
お手数をおかけして申し訳ありませんが、非エンジニア、ビギナーでも
理解できるレベルでの解説をいただけると助かります。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

donguriko

2022/02/03 14:16

int32_tさま お忙しい中、アドバイスありがとうございます。 ●iで何をループさせたいか 1つ目のループでブロック間ループをさせたいです。 iは「ブロックの開始col」とします。 混乱しないようにblockcolに書替えてコード修正しました。 3col目スタートで6列で1塊×7ブロックなので、 for (blockcol = 3; blockcol < 6*7 +3; blockcol += 6) { なのですね。 ●ブロック内のループ getValuesした段階で、getRangeで指定した範囲の複数データをまとめて とれるので、ヨコ方向のループ(y)は不要なのですね。 そして、タテ軸、ヨコ軸を逆に記載しており大変失礼いたしました。 自分でも混乱してしまうので、タテ方向を「r」としてコード修正しました。 <修正後> //▼部署ブロック内のループ //「部署」~「所用時間」までの5列分をgetRange(行、列、▲行分、■列分) で // 二次元配列(Values)として取得 // 処理する行番号をrとする。 for (r = 0; r <= targetRows; r++) { const myDetaRange = mySheet1.getRange(8, blockcol, targetRows, 5); console.log("myDetaRange " + myDetaRange.getA1Notation()); const values = myDetaRange.getValues(); //二次元配列(Values)内の項目は「部署」「件数」「開始時刻」「終了時刻」「所用時間」の5項目 //[行][列] let Branch = values[r][0]; let Num = values[r][1]; let startTime = values[r][2]; let endTime = values[r][3]; let length = values[r][4]; console.log("values " +values); console.log("values[0].length " + values[0].length); //5が出れば正解 console.log("values.length " + values.length); //targetRowsと同じ値 ※上記2点を修正しましたが、ブロック①→ブロック②への移行がうまく動かないです。  私の誤修正でしたら申し訳ありません。 ●再質問:ループ処理 二次元配列として取得したいデータのイメージは、 ヨコ方向は部署~所用時間までの5列で ブロック①分 ブロック②分 ブロック③分 とタテにつながったデータとして取得し、 タテにつながった状態のデータを「マージ」シートに 書き出ししたいです。 (以下、とんちんかんな質問でしたら申し訳ありません) a)この場合、配列内の ブロック②分の「部署」の[行][列]インデックス?は[①のtargetRows+1][0] ブロック③分の「部署」の[行][列]インデックスは[②のtargetRows+1][0] としないといけない、という理解であってますか? b)上記a)が正しい場合、  今の私のコードだと、  ブロック①だと(r = 0; r <= targetRows; r++) { でよいが、  ブロックが動くと、rは0スタートではなく、  ①のtargetRows+1スタートだということを  1個目のループ、ブロック間ループの部分でもりこまないといけない、  今コードではブロック間ループの部分でそこが書けていないから  正しく動かないという理解であっていますか? c)知識不足で申し訳ありません。  上記b)が正しい場合、ブロック間ループの部分をどう修正すればいいか 見当がつかないので、アドバイスをいただけないでしょうか?    

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します