2

我在 Google Drive 电子表格中开发了一个 Google Apps 脚本,它处理带有特定标签(下​​载通知)的电子邮件并将这些添加到电子表格中。我正在通过电子表格的脚本编辑器运行它。

我最初的解决方案效率很低——每次对所有电子邮件都重复整个分析,这导致运行时间每天都在增加。前几天我收到一条错误消息“超出运行时间”,这并不奇怪。

我的问题是,当尝试更新脚本以提高效率时,我遇到了一些奇怪的问题。该脚本要么在处理几封电子邮件后随机停止,要么只是拒绝启动。特别是脚本调试器,它开始加载但从未启动。

在过去的几天里,我已经尝试了几次,甚至使用相同的代码(在同一个帐户中)创建了一个新的电子表格,但仍然存在这些问题。

有时当脚本设法运行一段时间时,我注意到脚本输出日志与日志记录中的最近更改不匹配。我当然在运行之前保存了脚本。感觉好像有一些锁阻止我的脚本运行/更新/刷新?

这里有没有人认识到这些问题?

代码附在下面。两个相关的切入点是:

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();

};
4

1 回答 1

0

更新:我运行的任何脚本都会在大约 5 秒后停止,即使它没有调用任何服务。我尝试了以下代码:

function test() {
  Logger.log("Test begins");
  Utilities.sleep(5000);
  Logger.log("Test ends");
} 

脚本在大约 5 秒后终止,但没有打印最后一行。如果将延迟减少到 3 秒,则它的行为与预期相同。

另外,为了让修改后的脚本能正常更新,我需要保存,启动,点击取消,然后重新启动,否则日志输出好像是老版本的。(我正在通过脚本编辑器运行它。)

此外,即使对于上面的小脚本,调试器也拒绝启动。我的帐户似乎有问题(johan.kraft@percepio.se)。有没有谷歌员工可以检查这个?

于 2012-12-20T20:43:54.647 回答