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

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

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

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

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

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

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

Q&A

解決済

1回答

8874閲覧

GASでExceeded maximum execution timeのエラーが出た際の対応方法について

saori777

総合スコア6

Google スプレッドシート

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

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

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

Google

Googleは、アメリカ合衆国に位置する、インターネット関連のサービスや製品を提供している企業です。検索エンジンからアプリケーションの提供まで、多岐にわたるサービスを提供しています。

0グッド

0クリップ

投稿2021/08/24 06:30

現状

以下のGASのコードで、メールか情報を取得してスプレッドシートに反映させておりました。
しかし、5,000件以上のメールを処理するので、Exceeded maximum execution timeのエラーが出てしまいました、、、

function testFunction() { // 検索条件に該当するスレッド一覧を取得 var threads = GmailApp.search('subject:rapstar "[your-subject]"'); // スレッドを一つずつ取り出す threads.forEach(function(thread) { // スレッド内のメール一覧を取得 var messages = thread.getMessages(); // メールを一つずつ取り出す messages.forEach(function(message) { // メール本文を取得 var plainBody = message.getPlainBody(); // 「出身」を取り出す var area = plainBody.match(/【出身】 (.*)/); // 「ふりがな」を取り出す var kana = plainBody.match(/【ふりがな】 (.*)/); // 「お名前」を取り出す var name = plainBody.match(/【お名前】 (.*)/); // 「住所」を取り出す var address = plainBody.match(/【住所】 (.*)/); // 「年齢」を取り出す var year = plainBody.match(/【年齢】 (.*)/); // 「メールアドレス」を取り出す var mail = plainBody.match(/【メールアドレス】 (.*)/); // 「電話番号」を取り出す var tel = plainBody.match(/【電話番号】 (.*)/); // 書き込むシートを取得 var sheet = SpreadsheetApp.getActive().getSheetByName('sample'); // 最終行を取得 var lastRow = sheet.getLastRow() + 1; // セルを取得して値を転記 sheet.getRange(lastRow, 2).setValue(area[1]); sheet.getRange(lastRow, 3).setValue(kana[1]); sheet.getRange(lastRow, 4).setValue(name[1]); sheet.getRange(lastRow, 5).setValue(address[1]); sheet.getRange(lastRow, 6).setValue(year[1]); sheet.getRange(lastRow, 7).setValue(mail[1]); sheet.getRange(lastRow, 8).setValue(tel[1]); }); // スレッドに処理済みラベルを付ける var label = GmailApp.getUserLabelByName('処理済み'); thread.addLabel(label); }); }

修正案

解決策として、以下の2つを検討しました。
1.プログラムの処理を早くできるよう書き換える(配列に突っ込むなど)
2.トリガーを設定して6分の壁を越える

結論、2の取り組みを行いました。
1については、抜本的な解決にはならないと判断したからです。

そこで、以下URLを参考にして、プログラムを書き換えましたが、同じエラーになってしまいました。。。

https://www.nowte.net/google-apps-script/google-apps-script-exceeded-maximum-execution-time/

var MAX_RUNNING_TIME = 100; //スクリプト実行時間(ミリ秒) var REASONABLE_TIME_TO_WAIT = 40000; //トリガー実行までの時間 var triggerKey = 'start_row'; var scriptProperties = PropertiesService.getScriptProperties(); var startRow= scriptProperties.getProperty(triggerKey); if(!startRow){ startRow = 0 } Logger.log('startRow '+startRow); Logger.log('REASONABLE_TIME_TO_WAIT '+REASONABLE_TIME_TO_WAIT); Logger.log('MAX_RUNNING_TIME '+MAX_RUNNING_TIME); function runMe() { var startTime= (new Date()).getTime(); for(var ii = startRow; ii <= 400; ii++) { var currTime = (new Date()).getTime(); Logger.log('ii '+ii+' '+(currTime - startTime)); if(currTime - startTime >= MAX_RUNNING_TIME) { // 時間がなければトリガーセット setTrigger(currTime,ii) break; }else{ // 検索条件に該当するスレッド一覧を取得 var threads = GmailApp.search('subject:rapstar "[your-subject]"'); // スレッドを一つずつ取り出す threads.forEach(function(thread) { // スレッド内のメール一覧を取得 var messages = thread.getMessages(); // メールを一つずつ取り出す messages.forEach(function(message) { // メール本文を取得 var plainBody = message.getPlainBody(); // 「出身」を取り出す var area = plainBody.match(/【出身】 (.*)/); // 「ふりがな」を取り出す var kana = plainBody.match(/【ふりがな】 (.*)/); // 「お名前」を取り出す var name = plainBody.match(/【お名前】 (.*)/); // 「住所」を取り出す var address = plainBody.match(/【住所】 (.*)/); // 「年齢」を取り出す var year = plainBody.match(/【年齢】 (.*)/); // 「メールアドレス」を取り出す var mail = plainBody.match(/【メールアドレス】 (.*)/); // 「電話番号」を取り出す var tel = plainBody.match(/【電話番号】 (.*)/); // 書き込むシートを取得 var sheet = SpreadsheetApp.getActive().getSheetByName('sample'); // 最終行を取得 var lastRow = sheet.getLastRow() + 1; // セルを取得して値を転記 sheet.getRange(lastRow, 2).setValue(area[1]); sheet.getRange(lastRow, 3).setValue(kana[1]); sheet.getRange(lastRow, 4).setValue(name[1]); sheet.getRange(lastRow, 5).setValue(address[1]); sheet.getRange(lastRow, 6).setValue(year[1]); sheet.getRange(lastRow, 7).setValue(mail[1]); sheet.getRange(lastRow, 8).setValue(tel[1]); }); // スレッドに処理済みラベルを付ける var label = GmailApp.getUserLabelByName('処理済み'); thread.addLabel(label); }); } } } function setTrigger(time, triggerValue){ scriptProperties.setProperty(triggerKey, triggerValue); ScriptApp.newTrigger("runMe") .timeBased() .at(new Date(time+REASONABLE_TIME_TO_WAIT)) .create(); Logger.log('トリガーセット完了'); } function deleteProperty() { var sp = PropertiesService.getScriptProperties().deleteProperty(triggerKey); sp.deleteProperty(triggerKey); var triggerValue = sp.getProperty(triggerKey); Logger.log(triggerKey + ':' + triggerValue); Logger.log('トリガー削除完了'); }

どのようにコードを書き換えたら、Exceeded maximum execution timeのエラーが出なくなるか、教えていただけると幸いです、、、、

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

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

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

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

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

guest

回答1

0

ベストアンサー

これは結局、

  • APIコールを減らして処理を高速化する。
  • 一度に処理するデータ件数を減らす。

しかないです。具体的には、次のようなことが考えられます。

  1. thread.getMessages() をスレッドごとに呼ぶのではなく、GmailApp.getMessagesForThreads()を最初に1回だけ呼ぶ。

  2. plainBody.match()は正規表現文字列を渡すのではなく、予め各項目ごとに正規表現オブジェクトを作成しておく。(メールごとに暗黙的にnew RegeExp()が呼ばれるのを防ぐ。)

  3. メールごとに書き込む対象シートを取得するのではなく、最初に取得しておく。

  4. sheet.getRange(lastRow, 2).setValue(area[1]);の様に、getRangesetValueを項目ごとに呼ぶのは遅いので、予め配列にキャッシュしておいて最後に全体をセットする。

ここまでやってまだ駄目なら、

  1. 処理するデータ件数を減らすために、GamilApp.searchの条件にafter/before/newer/older等の演算子を使って期間を絞り込む。基準となる日付をプロパティ等に保持しておき、処理完了後に期間を勧める。例えば10分おきに処理を実行するトリガーを作成する。

投稿2021/08/24 08:31

draq

総合スコア2577

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

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

saori777

2021/08/25 10:53

上記、いずれの方法でもできました????‍♂️ 有難うございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問