2014年6月20日金曜日

Google Apps Script : 配列の最初から最後までループを回すときの注意点

Google Apps Scriptを使って、自分のGmail受信トレイから特定のラベルを付けたメールの内容をGoogle Spreadsheetに入力するスクリプトを書いていてはまってしまったので、ここに書いておきます。

まず、はまったスクリプトがこちら。

---以下スクリプト---
function getMessageFromGmail() {

    var label = GmailApp.getUserLabelByName("Label name");
    var threads = label.getThreads();
    row = 1;
   
    for(var n=0;n<=threads.length;n++) {
        var thread = threads[n];
        var msgs = thread.getMessages();
       
        for(m in msgs) {
            var msg = msgs[m];
            var date = msg.getDate();
            var from = msg.getFrom();
            var to = msg.getTo();
            var subject = msgs[m].getSubject();
            var body = msgs[m].getPlainBody();
           
            sheet.getRange(row,1).setValue(date);
            sheet.getRange(row,2).setValue(subject);
            sheet.getRange(row,3).setValue(body);
            row = row + 1;
        }
    }
}
---以上スクリプト---

次に、問題が解決したスクリプトがこちら。

---以下スクリプト---
function getMessageFromGmail() {

    var label = GmailApp.getUserLabelByName("Label name");
    var threads = label.getThreads();
    row = 1;
   
    for(var n=0;n<threads.length;n++) {
        var thread = threads[n];
        var msgs = thread.getMessages();
       
        for(m in msgs) {
            var msg = msgs[m];
            var date = msg.getDate();
            var from = msg.getFrom();
            var to = msg.getTo();
            var subject = msgs[m].getSubject();
            var body = msgs[m].getPlainBody();
           
            sheet.getRange(row,1).setValue(date);
            sheet.getRange(row,2).setValue(subject);
            sheet.getRange(row,3).setValue(body);
            row = row + 1;
        }
    }
}
---以上スクリプト---

違いは1箇所。1つめのforループを回す回数を示すn<threads.lengthが、<=か<だけです。基本を分かっている人にはバカにされ笑われてしまいそうですが、独学だとこんなところにはまってしまいます。

このスクリプトでは、まず、

    var label = GmailApp.getUserLabelByName("Label name");
    var threads = label.getThreads();

のところでGmailの受信トレイから"Label name"という名前のラベルの付いたスレッド(配列)を取得して、threadsという名前をつけています。
次に、配列threadsの中身をforループを使って順番に見ていき、n番目のスレッドを

    var thread = thread[n]
    var msgs = thread.getMessages();

としてthreadという名前の変数に入れ、thread(これも配列)の中身をgetMessages()メソッドを使って取りだしてmsgsという名前をつけています。

上の失敗例を実行すると、関数実行中のメッセージがなかなか消えず、消えたと思ったらvar msgs = thread.getMessages();のところでmessagesがgetできないというエラーメッセージが表示されます。

エラーの理由は、上にも書いた通り、forループの繰り返し回数指定にありました。
Google Apps Script (JavaScriptやPythonでも同様)では、配列(Pythonではリスト)のインデックスは0から始まるため、上のスクリプトのように配列の長さをループの繰り返し回数に指定する場合、

for(var n=0;n<=threads.length;n++)

と書くと、配列の長さより1回分多くループを回してしまうことになります。そのため、配列内の長さを超えたところでgetMessages()メソッドを実行使用してエラーとなっていました。

ものすごく単純なことなのですが、先駆者のみなさんのスクリプトのコピペで勉強を始めた身としては、引っかかって良かったと思える失敗でした。

0 件のコメント:

コメントを投稿

SyntaxHighlighter