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

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

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

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

ループ

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

解決済

【GAS】二次元配列のデータ取得方法とループ処理

donguriko
donguriko

総合スコア14

Google Apps Script

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

ループ

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

1回答

0評価

0クリップ

484閲覧

投稿2022/03/20 05:25

編集2022/03/26 06:21

前提・実現したいこと

スプレッドシート内に「入力シート」「マージシート」の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

function copyToMerge1() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const mySheet1 = ss.getSheetByName("入力シート"); const mySheet2 = ss.getSheetByName("【●●】マージ"); const mySheet3 = ss.getSheetByName("【■■】マージ"); //【ブロック内のループ】 //件数データありの最終行(InMaxRow)、転記処理対象の行数(targetRows)の取得 const InMaxRow = mySheet1.getRange(18, 4).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); const MaxIndex = InMaxRow - 8; console.log("MaxIndex " + MaxIndex); //Index最大値は4の想定 //「部署」~「所要時間」までの5列分をgetRange(行、列、▲行分、■列分) で // 二次元配列(Values)として取得 // ループ処理は0スタートでrがMaxIndex以下になるまで繰返し。 for (r = 0; r <= MaxIndex; r++) { const myDetaRange = mySheet1.getRange(8 +r, 3, 1, 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); //【マージシートへの転記処理】 //▼「×××マージ」シート(mySheet2)の件数(E列)にデータありの最終行(OutMaxRow1)の取得 const OutMaxRow1 = mySheet2.getRange(mySheet2.getMaxRows(), 5).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); console.log("OutMaxRow1 " + OutMaxRow1); //10が出る想定 //▼作業日(入力シートセルE3)の内容を「マージシート(mySheet2)」のB列に転記 const myDate = mySheet1.getRange("E2").getValue(); console.log("myDate " + myDate); mySheet2.getRange(OutMaxRow1 + 1 + r, 2, 1, 1).setValue(myDate); 1 //▼二次元配列(Values)の内容(5項目)を「マージシート(mySheet2)」のD列~G列に転記 //getRange(行、列、▲行分、■列分) mySheet2.getRange(OutMaxRow1 + 1 + r, 4, 1, 5).setValues(values); //▼マージシートへの転記結果を「入力シート(mySheet1)」の「転記処理」欄に追記する //getRange(行、列、▲行分、■列分) mySheet1.getRange(8 + r, 3 + 5, 1, 1).setValue("転記済"); } //▼ダイアログMsgの表示 Browser.msgBox("「マージシート」への転記処理が完了しました。\n「転記処理」列に「転記済」表示があれば問題なく転記処理がされています。", Browser.Buttons.OK); }

試したこと

ログを確認すると、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

function copyToMerge1() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const mySheet1 = ss.getSheetByName("キイロ入力シート"); const mySheet2 = ss.getSheetByName("【●●】マージ"); const mySheet3 = ss.getSheetByName("【■■】マージ"); //★ブロック間のループ //「部署」~「所要時間」までの6列×転記処理対象最終行(MaxRows)分 //で1ブロックとする。 //ブロックの開始col(blockCol)はC列(3col)とし、6colとばしで7ブロック目(39col目)まで for (blockCol = 3; blockCol <= 6*6 +3; blockCol +=6) { //★ブロック内のデータ取得 //件数データありの最終行(InMaxRow)、転記処理対象最終行(MaxRows)の取得 const InMaxRow = mySheet1.getRange(18, blockCol+1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); const MaxRows = InMaxRow - 7; console.log("MaxRows " + MaxRows); //5の想定 //「部署」~「所要時間」までの5列分×MaxRows行分をgetRange(行、列、▲行分、■列分) で // 二次元配列(Values)として1回でまとめて取得 const myDetaRange = mySheet1.getRange(8, blockCol, MaxRows, 5); console.log("myDetaRange " + myDetaRange.getA1Notation()); const values = myDetaRange.getValues(); console.log("values " + values); //★マージシートへの転記処理 //▼「×××マージ」シート(mySheet2)の件数(E列)にデータありの最終行(OutMaxRow1)の取得 const OutMaxRow1 = mySheet2.getRange(mySheet2.getMaxRows(), 5).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); console.log("OutMaxRow1 " + OutMaxRow1); //10が出る想定 //▼作業日(入力シートセルE3)の内容を「マージシート(mySheet2)」のB列に転記 const myDate = mySheet1.getRange("E2").getValue(); console.log("myDate " + myDate); mySheet2.getRange(OutMaxRow1+1, 2, MaxRows, 1).setValue(myDate); 1 //▼二次元配列(Values)の内容(5項目)を「マージシート(mySheet2)」のD列~G列に転記 //getRange(行、列、▲行分、■列分) mySheet2.getRange(OutMaxRow1 +1, 4, MaxRows, 5).setValues(values); //▼マージシートへの転記結果を「入力シート(mySheet1)」の「転記処理」欄に追記する //getRange(行、列、▲行分、■列分) mySheet1.getRange(8, blockCol+5, MaxRows, 1).setValue("転記済"); } //▼ダイアログMsgの表示 Browser.msgBox("「●●マージシート」への転記処理が完了しました。\\n入力シートの「転記処理」列に「転記済」表示があれば問題なく転記処理がされています。", Browser.Buttons.OK); }

良い質問の評価を上げる

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

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

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

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

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

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

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

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

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

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

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

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

Google Apps Script

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

ループ

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。