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

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

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

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

Google Apps Script

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

Q&A

解決済

1回答

661閲覧

【GAS】スプレッドシートのシート1を読み込んで、★条件に合致すれば、 シート1のR列と同じ名前を、シート2のA列から探し出し、 同じ行のIDを出力するというプログラムを作成しています。

tanaka_444

総合スコア19

Google スプレッドシート

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

Google Apps Script

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

0グッド

2クリップ

投稿2021/08/29 10:47

前提・実現したいこと

スプレッドシートのシート1を読み込んで、★条件に合致すれば、
シート1のR列と同じ名前を、シート2のA列から探し出し、
同じ行のIDを出力するというプログラムを作成しています。

★の条件式はあっているので、
以下部分のプログラムが間違っています。
===
シート1のR列と同じ名前を、シート2のA列から探し出し、
同じ行のIDを出力する
===

今回実施しているシート1と、シート2は以下内容になり、
条件に合致するのが、シート1の20行目のため、
シート2の「田中」のID「1000001」を出力したいのですが、上手くできません。
エラー内容は、以下になっているのですが、どこを直せばよいか分かる方教えていただけますでしょうか?
よろしくお願いします。

シート1:
イメージ説明

シート2:
イメージ説明

発生している問題・エラーメッセージ

以下のエラーメッセージが出て、正しく実装されません。
【エラー内容】
TypeError: Cannot read property '0' of undefined
test1 @ コード.gs:44

44行目は、コード内の以下部分になります。
//シート2の、A列を定義
var questioner2 = table2[i-2][0];

該当のソースコード

function test1() {

//アクティブなスプレッドシートを取得
var ss = SpreadsheetApp.getActiveSpreadsheet();

//シート1を取得
var sh = ss.getSheetByName("シート1");

//シート2を取得
var sh2 = ss.getSheetByName("シート2");

 //シート1の最終行を定義
var lastRow = sh.getLastRow();

//シート2の最終行を定義
var lastRow2 = sh2.getLastRow();

//スプレッドシート1の、O2~R最終行の値をgetValuesで取得
var table = sh.getRange(2,15,lastRow,4).getValues();

//スプレッドシート2の、A2~B最終行の値をgetValuesで取得
var table2 = sh.getRange(2,1,lastRow2,2).getValues();

//実行日時
var today = new Date();

 //2行目~14行目までを読み込み
for(var i=2; i<=lastRow; i++)
{

//シート1の、O列を定義
var anser = table[i-2][0];

//シート1の、P列を定義
var send = table[i-2][1];

//シート1の、Q列を定義
var cell = table[i-2][2];

//シート1の、R列を定義
var questioner = table[i-2][3];

//シート2の、A列を定義
var questioner2 = table2[i-2][0];

//シート2の、B列を定義
var id = table2[i-2][1];

//シート1の、O列が空白ではない、かつ、シート1の、P列が「送信可能」と入力されている、かつ、シート1の、Q列が空白の場合
if(anser!=="" && send=="送信可能" && cell=="")

{

//シート1のR列の値を含むものを、シート列のA列から探す
if(questioner == questioner2)
{

var sendid = id;

}

//ログでanserの内容を出力(後で、チャットワークに出力に修正する)
Logger.log(anser);
Browser.msgBox(anser);
Browser.msgBox(sendid);
sh.getRange(i, 17).setValue(new Date());

}

}

}

試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

TypeError: Cannot read property '0' of undefined test1 @ コード.gs:44 44行目は、コード内の以下部分になります。 //シート2の、A列を定義 var questioner2 = table2[i-2][0];

<このエラーの原因>

i」 は「シート1」の2行目から最終行まで繰り返されます。
一方、配列 table2 は「シート2」 の最大行分までしかありません。

js

1var questioner2 = table2[i-2][0];

の部分は、シート1の読み取り対象行に用いている「i」という変数を、シート2にも適用しようとしていることになります。
forループの最中に、シート2の行数を超えてデータにアクセスしようとすると、上記のエラーが発生します。

i-2 が table2 の行数(table2.length)以上の場合、 table2[i-2]undefined になります)


あと、直接のエラーの原因ではないですが、

//スプレッドシート2の、A2~B最終行の値をgetValuesで取得 var table2 = sh.getRange(2,1,lastRow2,2).getValues();

これだと、table2 は シート1の内容(ただし行数はシート2)になってしまうので、正しくは

var table2 = sh2.getRange(2,1,lastRow2,2).getValues();

となります。

<直し方の指針>
(下記は、理解しやすいよう質問者さんの考え方に沿って直したものです。
二重ループを使わない/別の関数に切り分ける等、もっと最適化できる余地はありますが、この回答では省略します。他の方が答えてくれるかもしれません)

・上述のように、シート1 と シート2 ではシート自体が異なるので、読み取る処理を分けます。
具体的には、シート2を読み取る部分を j という変数を使って、別のループに切り分けます。

js

1 //シート2の2行目~最終行までを読み込み 2 for (var j = 2; j <= lastRow2; j++) { 3 //シート2の、A列を定義 4 var questioner2 = table2[j - 2][0]; 5 6 //シート2の、B列を定義 7 var id = table2[j - 2][1]; 8 if (questioner===questioner2) { 9 // IDを設定してforループを抜ける 10 sendid = id; 11 break; 12 } 13 }

このループを元々のforループの中に入れます。


全体としては下記になります。
(後半でIDが見つからなかった場合のエラー処理も追加しています)

js

1 2function test1() { 3 4 //アクティブなスプレッドシートを取得 5 var ss = SpreadsheetApp.getActiveSpreadsheet(); 6 7 //シート1を取得 8 var sh = ss.getSheetByName("シート1"); 9 10 //シート2を取得 11 var sh2 = ss.getSheetByName("シート2"); 12 13 //シート1の最終行を定義 14 var lastRow = sh.getLastRow(); 15 16 //シート2の最終行を定義 17 var lastRow2 = sh2.getLastRow(); 18 19 //スプレッドシート1の、O2~R最終行の値をgetValuesで取得 20 var table = sh.getRange(2,15,lastRow,4).getValues(); 21 22 //スプレッドシート2の、A2~B最終行の値をgetValuesで取得 23 var table2 = sh2.getRange(2,1,lastRow2,2).getValues(); // sh -> sh2に修正 24 25 //実行日時 26 var today = new Date(); 27 28 //2行目~14行目までを読み込み 29 for (var i = 2; i <= lastRow; i++) { 30 31 //シート1の、O列を定義 32 var anser = table[i - 2][0]; 33 34 //シート1の、P列を定義 35 var send = table[i - 2][1]; 36 37 //シート1の、Q列を定義 38 var cell = table[i - 2][2]; 39 40 //シート1の、R列を定義 41 var questioner = table[i - 2][3]; 42 43 var sendid = null; // 追加 44 45 //シート1の、O列が空白ではない、かつ、シート1の、P列が「送信可能」と入力されている、かつ、シート1の、Q列が空白の場合 46 if (anser !== "" && send == "送信可能" && cell == "") { 47 //シート1のR列の値を含むものを、シート2のA列から探す 48 49 //シート2の2行目~最終行までを読み込み // ここから追加 50 for (var j = 2; j <= lastRow2; j++) { 51 //シート2の、A列を定義 52 var questioner2 = table2[j - 2][0]; 53 54 //シート2の、B列を定義 55 var id = table2[j - 2][1]; 56 57 // IDが見つかったら sendid を設定してforループを抜ける 58 if (questioner === questioner2) { 59 sendid = id; 60 break; 61 } 62 } 63 64 if (sendid != null) { 65 //ログでanserの内容を出力(後で、チャットワークに出力に修正する) 66 Logger.log(anser); 67 Browser.msgBox(anser); 68 Browser.msgBox(sendid); 69 sh.getRange(i, 17).setValue(new Date()); 70 } else { 71 // 名前が見つからなかった場合のエラー処理 72 var message = "名前「" + questioner + "」はシート2に存在しません。" 73 Logger.log(message); 74 // Browser.msgBox(message); 75 } 76 } 77 } 78}

投稿2021/08/29 12:27

編集2021/08/29 12:44
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tanaka_444

2021/08/29 13:51

ありがとうございます! 教えていただいた方法で、実行できました。 エラー処理までありがとうございますm(_ _)m もし分かれば、以下追加で教えていただけますでしょうか? 今回、シート1のR列の値と完全一致するものを、シート2のA列から探して、 一致すればIDを取得していますが、 部分一致の場合、どのように記載すればよいでしょうか? 以下の、if文の条件式内の書き方を変更すればよいでしょうか? ネットで、比較演算子で調べてみましたが、「部分一致」する場合の 書き方が載っていなかったため、もし分かれば教えていただきたいです。 よろしくお願いしますm(_ _)m === // IDが見つかったら sendid を設定してforループを抜ける if (questioner === questioner2) { sendid = id; break; } ===
退会済みユーザー

退会済みユーザー

2021/08/29 14:07

たとえば 「questioner2 の一部に questioner が含まれているかどうか」を判定する場合は if (questioner2.indexOf(questioner) !== -1) { //含まれている場合 } else { //含まれていない場合 } となります。
tanaka_444

2021/08/29 14:19

なるほど、ありがとうございます。 ネットで検索しても出てきました。助かりましたm(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問