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

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

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

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

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

2568閲覧

TypeError: Cannot read property '0' of undefined のエラーについて

suzu1916

総合スコア1

Google スプレッドシート

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

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2022/08/11 13:22

前提

スプレッドシートで複数人のYouTubeアカウントの登録者数などをリアルタイムで反映させたくて、ネットで見つけたコードを実際に使ってみたのですが、数年前の記事だったからかどうしてもエラーをはいてしまいます。

実現したいこと

・スプレッドシートの任意のシートにYouTubeアカウントの登録者数、チャンネル名、更新した日付を表示させる

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

TypeError: Cannot read property '0' of undefined

該当のソースコード

ソースコード

function getSubscriberCount() {

//APIキー
var key = "ご自分のAPIキーを入力してください";
//反映させるシート 月ごとにシートを変えたい場合などに変更してください
var sheetName = "シート1"

var ss = SpreadsheetApp.getActiveSpreadsheet()
var srcSheet = ss.getSheetByName(sheetName);

var rowTitle = 1;
var rowURL = 2;
var rowEnd = srcSheet.getDataRange().getLastRow();
var rowToday = rowEnd + 1;
var colDate = 1;
var colStart = 2;
var colEnd = srcSheet.getDataRange().getLastColumn();

var formatDate = Utilities.formatDate(new Date(),"JST","yy/MM/dd");
srcSheet.getRange(rowToday,1).setValue(formatDate);

for (i=colStart; i<=colEnd; i++) {

var channelURL = srcSheet.getRange(rowURL,i).getValue();
var channelID = channelURL.slice(32);

//登録者数を取得
var dataURL = "https://www.googleapis.com/youtube/v3/channels?part=statistics&id=" + channelID +"&key=" + key;
var response = UrlFetchApp.fetch(dataURL)
var subscribe = JSON.parse(response.getContentText()).items[0].statistics.subscriberCount;

//チャンネルタイトルを取得
var dataURL = "https://www.googleapis.com/youtube/v3/channels?part=snippet&id=" + channelID +"&key=" + key ;
var response = UrlFetchApp.fetch(dataURL)
var channnelTitle = JSON.parse(response.getContentText()).items[0].snippet.title;

//登録者数をシートに挿入
srcSheet.getRange(rowToday,i).setValue(subscribe);

//チャンネルタイトルをシートに挿入
srcSheet.getRange(rowTitle,i).setValue(channnelTitle); 
}

};

function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [
{
name : "Youtubeチャンネル登録者数取得",
functionName : "getSubscriberCount"
}
];
sheet.addMenu("スクリプト実行", entries);
};

試したこと

TypeError: Cannot read property '0' of undefined
getSubscriberCount @ コード.gs:31

と表示されていたので、その部分を消してみたりしました。
その後もエラーの表示される部分をとりあえず消去してエラーはでなくなったものの、日付以外も何も出ないまま完了してしまいました。

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

https://note.com/nakashio_note/n/n28c1979224a1
参考にしたのはこの記事で、2019年のものなので色々変わっているのかもしれないと思いましたが、何をどう変更すればよいのかわからず困っております。

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

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

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

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

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

jimbe

2022/08/11 17:06

ご提示のコードは java ではありません。適切な言語のタグを付けて頂かないと、その言語が出来る人に質問を見て頂けない可能性が上がってしまいます。
suzu1916

2022/08/15 08:32

回答ありがとうございます! 勝手にJavaかと思い込んでおりました、修正致しますありがとうございます!
guest

回答1

0

ベストアンサー

◆エラーから推定される原因について

TypeError: Cannot read property '0' of undefined
getSubscriberCount @ コード.gs:31
と表示されていた

js

1var subscribe = JSON.parse(response.getContentText()).items[0].statistics.subscriberCount;

この部分で「TypeError: Cannot read property '0' of undefined」というエラーが発生したということですね。

つまり、items が undefined になっている、ということになります。

そして、items が undefined になっているということは、
JSON.parse(response.getContentText()) が items というプロパティを持っていないということが考えられます。

つまり、API からチャンネル ID を指定して結果を取得しようとしたが、該当する結果が何もないということが考えられます。

結果がゼロとなってしまう原因として、下記の可能性が考えられます。


正しいチャンネル URL がスプレッドシートに入力されていない。

→ スプレッドシートに入力されている URL が「 https://www.youtube.com/channel/UC******* 」の形式になっていない可能性があります。

コード中の「var channelID = channelURL.slice(32);」
というのは、チャンネル URL の32文字目以降を切り取って、それをチャンネルIDとする、という意味です。

ですから、スプレッドシートの2行目に入力する URL は、
・その URL が、存在する(=アクセス可能である)チャンネルのURLであること
・「https://www.youtube.com/channel/UC〜 」 で始まる、半角56文字の文字列であること
・UC 以降の文字が(UC を含めて)24文字
でなければなりません。

たとえば、YouTube のチャンネルページのURLには、
https://www.youtube.com/channel/UC******* 」
という形式だけではなく、
https://www.youtube.com/user/ユーザーが任意に設定した文字列
https://www.youtube.com/c/ユーザーが任意に設定した文字列
という形式のものもあります。

仮に、後者2つのような形式の URL がスプレッドシートに入力されている場合、プログラム上は 存在しないチャンネル ID のデータを呼び出すことになるため、結果がゼロになり、質問のエラーが発生するということになります。


対策

API が返してきた結果の数を調べ、ゼロの場合は処理をスキップするようにします。
API が返してきた結果の数は、pageInfo.totalResults で取得できます。

また、元々のコードでは statistics と snippet 取得のためにAPIを2回呼び出して無駄にクォータを消費しているので、一回の呼び出しで済むように変更しています。

js

1var dataURL = "https://www.googleapis.com/youtube/v3/channels?part=statistics,snippet&id=" + channelID + "&key=" + key;

の部分。
注)API クォータ超過時のエラートラップは、ここでは本題ではないため実装していません。

js

1function getSubscriberCount() { 2 //APIキー 3 var key = "自分のAPIキー; 4 //反映させるシート 5 var sheetName = "シート1" 6 var authorUrl = "https://teratail.com/questions/aucio02i665ci9" 7 var ss = SpreadsheetApp.getActiveSpreadsheet() 8 var srcSheet = ss.getSheetByName(sheetName); 9 10 var rowTitle = 1; 11 var rowURL = 2; 12 var rowEnd = srcSheet.getDataRange().getLastRow(); 13 var rowToday = rowEnd + 1; 14 var colDate = 1; 15 var colStart = 2; 16 var colEnd = srcSheet.getDataRange().getLastColumn(); 17 18 var formatDate = Utilities.formatDate(new Date(), "JST", "yy/MM/dd"); 19 srcSheet.getRange(rowToday, 1).setValue(formatDate); 20 21 for (var i = colStart; i <= colEnd; i++) { 22 23 var channelURL = srcSheet.getRange(rowURL, i).getValue(); 24 var channelID = channelURL.slice(32); 25 26 var dataURL = "https://www.googleapis.com/youtube/v3/channels?part=statistics,snippet&id=" + channelID + "&key=" + key; 27 var response = UrlFetchApp.fetch(dataURL, options); 28 var res = JSON.parse(response.getContentText()); 29 if (res.pageInfo.totalResults === 0) { 30 // 結果数がゼロの場合、スキップ 31 console.log('URL:「' + channelURL + '」の結果はゼロでした。存在しないチャンネルIDか、URLの形式が正しくない可能性があります。処理をスキップします。'); 32 continue; 33 } 34 //登録者数を取得 35 var subscribe = res.items[0].statistics.subscriberCount; 36 37 //チャンネルタイトルを取得 38 var channnelTitle = res.items[0].snippet.title; 39 40 //登録者数をシートに挿入 41 srcSheet.getRange(rowToday, i).setValue(subscribe); 42 43 //チャンネルタイトルをシートに挿入 44 srcSheet.getRange(rowTitle, i).setValue(channnelTitle); 45 } 46 console.log('処理を完了しました。'); 47}; 48 49function onOpen() { 50 var sheet = SpreadsheetApp.getActiveSpreadsheet(); 51 var entries = [ 52 { 53 name: "Youtubeチャンネル登録者数取得", 54 functionName: "getSubscriberCount" 55 } 56 ]; 57 sheet.addMenu("スクリプト実行", entries); 58};

投稿2022/08/13 02:22

編集2022/08/15 09:05
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

suzu1916

2022/08/15 08:31

とてもわかりやすい丁寧な回答、本当にありがとうございます!! 今出先なので帰宅したらURLの再確認と改善して頂いたコードで再チャレンジしてみます!! 勉強を始めたばかりで困り果てていたので本当に助かりました!!ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問