【问题标题】:Google Apps Script to extract data from Gmail and fill in multiple matching rows in Google Sheets用于从 Gmail 中提取数据并在 Google 表格中填写多个匹配行的 Google Apps 脚本
【发布时间】:2021-11-17 15:39:24
【问题描述】:

Google Apps Script to extract data from Gmail and fill in matching row in Google Sheets 开始,还有另一封电子邮件,其中包含在一封电子邮件中的多个跟踪号。示例...

Your order is ready to be redeemed/ delivered. 
Order No. 91401111 
Tracking No. (Actual Weight/Chargeable Weight) JK5SD8F4M6 (2.1lb) 
J6HDO9L665 (2.1lb) 
J3SDG76435 (9.8lb) 
Courier UPS
Shipment No. 23879924905

我想提取电子邮件中的数据并填写正确的单元格,例如这样...

目前脚本是这样的……

function extractDetails(message){

  var emailData = {
    body: "Null",
    trackingno: "Null",
    weight: "Null",
    orderno: "Null",
    courier: "Null",
    shipmentno: "Null"
  }

  emailData.body = message.getPlainBody();
  emailData.trackingno = emailData.body.match(/(?<=Tracking No. \(Actual Weight/Chargeable Weight\) ).*/).toString().trim();
  emailData.weight = emailData.body.match(/????????/).toString().trim();
  emailData.orderno = emailData.body.match(/(?<=Order No. ).*/).toString().trim();
  emailData.courier = emailData.body.match(/(?<=Courier ).*/).toString().trim();
  emailData.shipmentno = emailData.body.match(/(?<=Shipment No. ).*/).toString().trim();

  var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = activeSheet.getSheetByName('Sheet1');
  var range = sheet.getRange("A2:A" + sheet.getLastRow()).createTextFinder(emailData.trackingno).findNext();

  if (range) {
    range.offset(0, 3).setValue(emailData.weight);
    range.offset(0, 4).setValue(emailData.orderno);
    range.offset(0, 5).setValue(emailData.courier);
    range.offset(0, 6).setValue(emailData.shipmentno);
  } else {
    sheet.appendRow([emailData.trackingno, '', '', emailData.weight, emailData.orderno, emailData.courier, emailData.shipmentno]);
  }
}

我知道上述脚本中几乎没有错误。首先,我不知道如何编写正则表达式来找到权重。然后,我不知道如何提取所有跟踪号。我可能应该将提取的跟踪号存储在一个数组中,然后使用 for 循环进行匹配。请帮忙。谢谢。

【问题讨论】:

    标签: javascript regex google-apps-script google-sheets


    【解决方案1】:

    我相信你的目标如下。

    • 您想从以下文本中检索 Order No、Courier、Shipment No、Parcel Weight 和 Tracking No 的值。

        Your order is ready to be redeemed/ delivered. 
        Order No. 91401111 
        Tracking No. (Actual Weight/Chargeable Weight) JK5SD8F4M6 (2.1lb) 
        J6HDO9L665 (2.1lb) 
        J3SDG76435 (9.8lb) 
        Courier UPS
        Shipment No. 23879924905
      
    • 您想通过搜索跟踪编号将值放入电子表格。

    • 您希望使用 Google Apps 脚本实现此目的。

    在这种情况下,下面的示例脚本怎么样?在这种情况下,我使用您的示例文本来测试脚本。

    示例脚本:

    我认为在您的脚本中,我的示例脚本中的textemailData.body 相同。

    function myFunction(){
      // This text is from your question.
      const text = `Your order is ready to be redeemed/ delivered. 
    Order No. 91401111 
    Tracking No. (Actual Weight/Chargeable Weight) JK5SD8F4M6 (2.1lb) 
    J6HDO9L665 (2.1lb) 
    J3SDG76435 (9.8lb) 
    Courier UPS
    Shipment No. 23879924905`;
    
      // 1. Retrieve each value you want to retrieve.
      const obj1 = text.split("\n").reduce((o, e) => {
        const regex = new RegExp("([A-Z0-9]+) \\(([0-9.]+)lb\\)");
        if (e.includes("Order")) {
          o.orderNo = Number(e.trim().split(" ").pop());
        } else if (e.includes("Courier")) {
          const t = e.trim().split(" ");  // Modified
          t.shift();  // Modified
          o.courier = t.join(" ");  // Modified
        } else if (e.includes("Shipment")) {
          o.shipmentNo = Number(e.trim().split(" ").pop());
        } else if (regex.test(e)) {
          const [, trackingNo, parcelNo] = e.match(regex);
          o.trackingNo.push({trackingNo: trackingNo, parcelNo: parcelNo});
        }
        return o;
      }, {orderNo: "", courier: "", shipmentNo: "", trackingNo: []});
    
      // 2. Create an object for searching tracking No.
      const obj2 = obj1.trackingNo.reduce((o, {trackingNo, parcelNo}) => Object.assign(o, {[trackingNo]: [parcelNo, obj1.orderNo, obj1.courier, obj1.shipmentNo]}), {});
    
      // 3. Retrieve existing values from Spreadsheet and creating new values for putting to Spreadsheet.
      var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = activeSheet.getSheetByName('Sheet1');
      var range = sheet.getRange("A2:G" + sheet.getLastRow());
      var newValues = range.getValues().map(([a, b, c, ...efg]) => {  // Modified
        var temp = [];
        if (obj2[a]) {
          temp = [a, b, c, ...obj2[a]];
          delete obj2[a];
        } else {
          temp = [a, b, c, ...efg];  // Modified
        }
        return temp;
      });
    
      // 4. If the tracking No is not found, the values are appended to the last row.
      var tempAr = Object.entries(obj2);
      if (tempAr.length > 0) {
         newValues = newValues.concat(tempAr.map(([k, v]) => [k, "", "", ...v]));
      }
    
      // 5. Clear sheet and put the new values to the sheet.
      range.clearContent();
      sheet.getRange(2, 1, newValues.length, newValues[0].length).setValues(newValues);
    }
    

    注意:

    • 在此示例脚本中,当您的文本与问题中的文本不同时,可能无法使用该脚本。所以请注意这一点。

    参考资料:

    【讨论】:

    • 谢谢!它几乎可以 100% 工作!很少有我需要你的帮助... 1. 当我用不同的文本再次运行该函数时,它会清除以前输入的值。如何防止这种情况? 2. 如果 Courier 名称由 2 个单词组成,例如: “DHL快递”,它只返回快递。如何让它返回快递员姓名的全名?
    • @Masterkenobi 感谢您的回复。我不得不为我糟糕的英语水平道歉。不幸的是,我无法理解您的新 2 个问题。我可以问你关于新的 2 个问题的详细信息吗?
    • 对不起。首先,它清除先前输入的值。我不想那样。
    • 第二,如果快递名称有“DHL Express”之类的两个字,则只返回“Express”。如何让它返回完整的名称?
    • @Masterkenobi 感谢您的回复。关于First, it clears the values that was previously entered. I don't want that.,我更新了我的答案。你能确认一下吗?关于Second, if the courier name has two words like "DHL Express", it returns "Express" only. How to make it returns complete name?,很遗憾,我无法理解你想要做什么。我为我糟糕的英语水平道歉。我可以问你关于你新的第二个问题的细节吗?
    猜你喜欢
    • 2021-11-17
    • 2015-12-29
    • 2021-10-19
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多