特定のラベル (ダウンロード通知) の付いた電子メールを処理し、これらをスプレッドシートに追加する Google ドライブ スプレッドシートで Google Apps スクリプトを開発しました。これは、スプレッドシートのスクリプト エディターで実行しています。
私の最初の解決策は非常に非効率的でした。分析全体がすべての電子メールに対して毎回繰り返されるため、毎日の実行時間が増加しました。数日前、「実行時間が超過しました」というエラー メッセージが表示されましたが、これはおかしなことではありません。
私の問題は、スクリプトをより効率的に更新しようとすると、奇妙な問題が発生することです。スクリプトは、いくつかの電子メールを処理した後にランダムに停止するか、単に開始を拒否します。特にスクリプト デバッガーは、ロードを開始しますが開始されません。
ここ数日で何度か試しましたが、(同じアカウントで) 同じコードで新しいスプレッドシートを作成しましたが、まだこれらの問題が発生しています。
スクリプトがしばらく実行できたときに、スクリプトの出力ログがロギングの最近の変更と一致しないことに気付きました。もちろん、実行する前にスクリプトを保存しました。スクリプトの実行/更新/更新を妨げているロックがあるように感じますか?
これらの問題を認識している人はいますか?
コードは以下に添付されています。関連する 2 つのエントリ ポイントは次のとおりです。
processInbox: 特定のラベルが付いた新しい (スター付き) 電子メールに基づいてスプレッドシートを更新します。ラベルとスターは、受信時の電子メール フィルターによって設定されます。スター (「新規」を示す) は、処理後に各メッセージから削除されます。
resetAllMsgs: スプレッドシートを消去し、関連するすべてのメッセージにスターを付けます。これにより、processInbox は関連するラベルで受信したすべてのメッセージを処理します。
function resetAllMsgs() {
Logger.log("Starting ResetAll");
var d = SpreadsheetApp.getActive();
var dl_sheet = d.getSheetByName("Download List");
var dlperday_sheet = d.getSheetByName("DownloadsPerDay");
dl_sheet.clear();
dlperday_sheet.clear();
Logger.log("Clearing spreadsheet");
dl_sheet.appendRow(["", "", "Downloads", ""]);
dl_sheet.appendRow(["", "", "Downloaders", ""]);
dl_sheet.appendRow(["Last Download Date", "First Download Date", "Email" , "Product", "Download Count"]);
dlperday_sheet.appendRow(["Date", "Download Count"]);
var label = GmailApp.getUserLabelByName("Download Notification");
// get all threads of the label
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
// get all messages in a given thread
var messages = threads[i].getMessages();
Logger.log("Starring thread " + i);
for (var j = 0; j < messages.length; j++) {
Logger.log(" Starring message " + j);
// Only starred messages are processed by processInbox
messages[j].star();
Utilities.sleep(100);
}
}
};
function processInbox() {
var d = SpreadsheetApp.getActive();
var dl_sheet = d.getSheetByName("Download List");
var dlperday_sheet = d.getSheetByName("DownloadsPerDay");
// If empty spreadsheet, reset the status of all relevant e-mails and add the spreadsheet headers
if (dl_sheet.getLastRow() <= 1) {
resetAll();
}
var label = GmailApp.getUserLabelByName("Download Notification");
var k = 0;
// get all threads of the label
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
if (threads[i].hasStarredMessages()) {
// get all messages in a given thread
var messages = threads[i].getMessages();
// iterate over each message
for (var j = 0; j < messages.length; j++) {
// Unread messages are not previously processed...
if (messages[j].isStarred()) {
var msg = messages[j].getBody();
msg = msg.replace(/\r?\n/g, "");
var email = getDownloader(msg);
if (email == "") {
Logger.log("Found no downloader info: " + messages[j].getSubject() + " " + messages[j].getDate());
}
var date = formatDate(getDownloadDate(msg));
// Check if a new date
var dateCell = find(date, dlperday_sheet.getDataRange(), 0);
if (dateCell == null) {
// If new date, append row in "downloads per day"
dlperday_sheet.appendRow([date, 1]);
dlperday_sheet.getRange(2, 1, dl_sheet.getLastRow()-1, 2).sort([1]);
}
else
{
// If existing date, update row in "downloads per day"
var dlcount = dlperday_sheet.getRange(dateCell.getRow(), dateCell.getColumn()+1).getValue();
}
var productname = getProductName(msg);
// Check if e-mail (user) already exists in the downloads list
var matchingCell = find(email, dl_sheet.getDataRange(), 0);
if ( matchingCell != null ) {
// If user e-mail exists, update this row
var lastDownloadDate = dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()-1).getValue();
var lastDownloadCount = dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()+2).getValue();
if (lastDownloadDate != date) {
dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()-1).setValue(date);
}
dl_sheet.getRange(matchingCell.getRow(), matchingCell.getColumn()+2).setValue(lastDownloadCount+1);
}
else // If new user e-mail, add new download row
{
dl_sheet.appendRow([date, date, email, productname, 1]);
dl_sheet.getRange(2, 4).setValue(dl_sheet.getRange(2, 4).getValue() + 1);
dl_sheet.getRange(4, 1, dl_sheet.getLastRow()-3, 5).sort([1]);
}
// Mark message as processed, to avoid processing it on the next run
messages[j].unstar();
}
}
}
}
};
/**
* Finds a value within a given range.
* @param value The value to find.
* @param range The range to search in.
* @return A range pointing to the first cell containing the value,
* or null if not found.
*/
function find(value, range, log) {
var data = range.getValues();
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
if (log == 1)
{
Logger.log("Comparing " + data[i][j] + " and " + value);
}
if (data[i][j] == value) {
return range.getCell(i + 1, j + 1);
}
}
}
return null;
};
function getDownloader(bodystring) {
var marker = "Buyer Info";
var marker_begin_index = bodystring.indexOf(marker, 1000);
var email_begin_index = bodystring.indexOf("mailto:", marker_begin_index) + 7;
var email_end_index = bodystring.indexOf("\"", email_begin_index);
if (email_end_index < 1000)
{
return "";
}
var email = bodystring.substring(email_begin_index, email_end_index);
if (log == 1)
{
Logger.log("Found e-mail address: " + email + "");
Logger.log(" marker_begin_index: " + marker_begin_index);
Logger.log(" email_begin_index: " + email_begin_index);
Logger.log(" email_end_index: " + email_end_index);
}
latestIndex = email_end_index;
return email;
};
function formatDate(mydate)
{
var str = "" + mydate;
var dateParts = str.split("/");
var day = dateParts[1];
if (day.length == 1)
day = "0" + day;
var month = dateParts[0];
if (month.length == 1)
month = "0" + month;
return dateParts[2] + "-" + month + "-" + day;
};
function getDownloadDate(bodystring) {
var marker = "Download Date:</strong>";
var marker_begin_index = bodystring.indexOf(marker, latestIndex);
var date_begin_index = marker_begin_index + marker.length;
var date_end_index = bodystring.indexOf("<br>", date_begin_index);
latestIndex = date_end_index;
return bodystring.substring(date_begin_index, date_end_index).trim();
};
function getProductName(bodystring) {
var marker = "Item:</strong>";
var marker_begin_index = bodystring.indexOf(marker, latestIndex);
var pname_begin_index = marker_begin_index + marker.length;
var pname_end_index = bodystring.indexOf("</td>", pname_begin_index);
latestIndex = pname_end_index;
return bodystring.substring(pname_begin_index, pname_end_index).trim();
};