Regex(Extract, Replace, etc..) d'éléments d'un mail

Bonjour!

tout d'abord, je tiens a préciser que ce sujet a déjà été évoqué ici [lien] d'une manière différente, mais je veux ( j'aimerai ) m'exercer sur le format de ces formules ( Regexreplace, Regexextract,..).

je vais avoir une utilité professionnel pour extraire des bons de commandes, factures, etc.. lorsque j'aurais compris. Je vais donc me faire la main sur les mêmes exemple que l'autre sujet.

1ere question ! ( surement la plus importante avant de commencer ! )

Sur quel format sommes nous ? je m'exerce sur https://regex101.com/ et j'obtiens des résultats sur plusieurs formats..

image

Voici mon mail Ex. ( j'en aurais surement un autre a traiter sous un format diffèrent, mais je commence par le facile :D )

Hi, alexis!

Your RealT order has been processed, and your tokens have been delivered.

Order #205699 — September 2, 2021
Product Quantity Price
8531 Intervale St, Detroit, MI 48238 1 $51.53
2950-2952 Monterey St, Detroit, MI 48206 1 $50.00
20552 Waltham St, Detroit, MI 48205 1 $50.96
17616 Beland St, Detroit, MI 48234 1 $53.56
Subtotal: $206.05
Payment method: Credit Card
Total: $206.05
Head to https://realt.co/marketplace/ to keep building your portfolio!

Thanks for investing with RealT!

Join us on… Telegram Twitter Instagram

je peux extraire le numéro de commande par ex.

=REGEXEXTRACT(C3,"Order .([0-9]+)")

ainsi que le montant total

=REGEXEXTRACT(C3,"Total: (.+)")

Déjà une question : une solution pour avoir 2 choix pour une formule ? ( la solution que j'ai trouvé me donne 1 résultat par colonne… c'est pas idéal )Et je ne parviens pas a Arrayformula ces formules également

et ensuite ce que je n'arrive pas du tout a faire, après un grand nombre de tentative ^^'

image

j'aimerai avoir les quantités, prix, article sur des colonnes différentes, ça je pense que je suis ok ( un split ou des " | " sur la formule devrait faire l'affaire )

mais c'est pour sortir directement l'ensemble des lignes comme le screen ci-dessus ! je sais pas faire.. voici l'une de mes tentatives, pas le résultat attendu

image

PS : Mike, le script que tu m'as faire a partir du traitement "Body" apporte ce résultat, mais je ne comprend pas exactement le schéma d'extraction, pourtant je me suis creuser la tête sur ton script

Si c'est plus fiable / pratique / facile de travailler sur la version HTML, je reprendrais le fils de l'autre sujet pour comprendre et appliquer par moi même si besoins.

merci !

https://docs.google.com/spreadsheets/d/1CWrHPFQz17FRksyHd0FHa1ftbD07PCZFcbbS4WyaqZw/edit?usp=sharing

Bonjour,

Le prix

\$([0-9.]+)$

et pour extraire le produit, extraire la zone ciblée avant.

^([\w .\,-]+)

Bonne Journée

Bonjour, Alex,

je te laisse avec imoka pour tout ce qui est regex

je reviens sur ce point

PS : Mike, le script que tu m'as faire a partir du traitement "Body" apporte ce résultat, mais je ne comprend pas exactement le schéma d'extraction, pourtant je me suis creuser la tête sur ton script


https://docs.google.com/spreadsheets/d/1CWrHPFQz17FRksyHd0FHa1ftbD07PCZFcbbS4WyaqZw/edit?usp=sharing

J'ai fait cela moi ? ah ben oui ... mais si c'est ce script, qu'est-ce qui semble nébuleux ? j'y ai ajouté quelques explications

function mail() {

  // définition des critères d'extraction des mails
  // mails non lus et labellisés comme suit
  var requete ="is:unread {label:realT/Orders label:realT/Tokens}"
  var ss = SpreadsheetApp.getActive().getSheetByName("Mail");
  var threads = GmailApp.search(requete);

  // pour chaque fil de discussion
  for (var i = 0; i < threads.length; i++) {
    // je capte les messages du fil
    var messages = threads[i].getMessages();

    // pour chaque message, je prends le contenu, la date et l'émetteur
    for (var j = 0; j < messages.length; j++) {
      var msg = messages[j].getPlainBody();
      var sub = messages[j].getSubject();
      var dat = messages[j].getDate();
      var test = messages[j].getFrom();
      var free = ss.getLastRow()+1 

      // j'affecte à la première ligne vide
      ss.getRange('A'+free+':C'+free).setValues([[dat, sub, msg]])
    }
  }
  // je trie par date
  var r = ss.getRange(2, 1, ss.getLastRow()-1, ss.getLastColumn());    
  r.sort([{column: 1, ascending: false}]);

  // j'applique un format date
  ss.getRange('A:A').activate();
  ss.getActiveRangeList().setNumberFormat('dd.MM.yyyy');

  GmailApp.markThreadsRead(threads);
}

bonjour

J'ai fait cela moi ? ah ben oui

non celui que tu as mis vient de moi ^^',

je parlais de celui-ci : ( a partir du "importHTML" )

var requete = "label:inbox is:unread to:me NOT label:done";
var feuille = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('mails')

function capturerEmails() {
  let label = GmailApp.getUserLabelByName("done");
  if (!label) {label = GmailApp.createLabel("done")}
  var threads = GmailApp.search(requete);
  threads.forEach(thread => {
    var msgs = thread.getMessages();
    for (var j in msgs) {
      var r = feuille.getLastRow()+1
      var data = [] 
      var prov = []
      var msg = msgs[j].getBody().replace(/\n|\t/g,'')
      prov.push(msgs[j].getDate()) 
      prov.push(msgs[j].getSubject()) 
      prov.push(msg) 
      data.push(prov)
      feuille.getRange(r,1,1,3).setValues(data);
      feuille.getRange(r,4,1,1).setValue(importOrder(msg));
      var a = (importTableHTML(msg))
      feuille.getRange(r,5,a.length,a[0].length).setValues(a);
    }
    label.addToThread(thread);
  })
}

//importation du titre contenu dans la balise h2
function importOrder(source) {
  var data=''
    var debut = source.indexOf('<h2')
    var fin = source.indexOf('</h2')
    var titre = source.substring(debut,fin)
    debut = titre.indexOf('>')+2
    data = titre.substring(debut)
  return(data);
}

//importation du tableau (contenu de tbody)
function importTableHTML(source) {
  var data = [];
  try{
    var debut = source.indexOf('<tbody')
    var fin = source.indexOf('</tbody')
    var html = source.substring(debut,fin)
    var trs = html.split('<tr')
    for (var i=1;i<trs.length;i++){
      var tds = trs[i].split('<td')
      var prov=[]
      for (var j=1;j<tds.length;j++){
        prov.push(stripTags('<td'+tds[j]))
      }
      data.push(prov)
    }
  }catch(e){
    data.push([''])
  }
  return(data);
}

function stripTags(body) {
  var regex = /(<([^>]+)>)/ig;
  return body.replace(regex,"").replace(/\r\n|\n|\r|\t/g,'');
}

je te laisse avec imoka pour tout ce qui est regex

ok pas de soucis !

Bonjour,

Le prix

\$([0-9.]+)$

et pour extraire le produit, extraire la zone ciblée avant.

^([\w .\,-]+)

Bonne Journée

bonjour Imoka, je regarde tout ça et je reviens vers toi ensuite :) merci

//importation du tableau (contenu de tbody)
function importTableHTML(source) {
  // je prépare l'exportation des données vers la feuille
  var data = [];

  // essaie
  try{
    // je cherche le début et la fin de tbody dans le string et j'en extrais le texte adhoc
    var debut = source.indexOf('<tbody')
    var fin = source.indexOf('</tbody')
    var html = source.substring(debut,fin)

    // je vais découper les lignes (balise tr)
    var trs = html.split('<tr')
    for (var i=1;i<trs.length;i++){
      // je vais découper les cellules (balise td)
      var tds = trs[i].split('<td')
      var prov=[]
      // pour chaque cellule, je retiens son contenu que je mets dans un array provisoire (j'ajoute le terme de découpe <td pour que le stripTags fonctionne)
      for (var j=1;j<tds.length;j++){
        prov.push(stripTags('<td'+tds[j]))
      }

      // j'ajoute l'array provisoire à data
      data.push(prov)
    }

  // si pas trouvé je mets un blanc
  }catch(e){
    data.push([''])
  }

  // je renvoie vers la feuille
  return(data);
}

function stripTags(body) {
  var regex = /(<([^>]+)>)/ig;
  return body.replace(regex,"").replace(/\r\n|\n|\r|\t/g,'');
}

une autre façon de faire sans doute plus élégante, mais plus difficile à comprendre

function importTableHTML(url) {
  var html = '<table' + UrlFetchApp.fetch(url).getContentText().match(/(?<=\<table).*(?=\<\/table)/g) + '</table>';
  var trs = [...html.matchAll(/<tr[\s\S\w]+?<\/tr>/g)];
  var data = [];
  for (var i=0;i<trs.length;i++){
    var tds = [...trs[i][0].matchAll(/<(td|th)[\s\S\w]+?<\/(td|th)>/g)];
    var prov = [];
    for (var j=0;j<tds.length;j++){
      donnee=tds[j][0].match(/(?<=\>).*(?=\<\/)/g)[0];
      prov.push(donnee);
    }
    data.push(prov);
  }
  return(data);
}

Merci ! Je vais étudier tes explications, je comprend déjà mieux 😊

Bonne journée / soirée ( je sais jamais ahah )

Bonjour Imoka

Le prix

\$([0-9.]+)$

ne fonctionne pas

et pour extraire le produit, extraire la zone ciblée avant.

^([\w .\,-]+)

le resultat ==> " RealT"

je n'obtiens pas l'ensemble des lignes comme partagé sur le doc que j'ai mis dans le sujet ( ce n'est peut-être tout simplement pas possible en l'état )

feuille Mail4

={"Prix","Produits","Quantité";ARRAYFORMULA(REGEXEXTRACT(A7:A10,"\$[\d.]+$")),ARRAYFORMULA(REGEXREPLACE(A7:A10,"^(.*).{9}$","$1")),ARRAYFORMULA(REGEXREPLACE(A7:A10,"^.*(.).{7}$","$1"))}

Bonne Journée

Bonjour ImoKa,

merci pour ce début de réponse ! mais je vois que tu as traité le mail en dehors de la case ou il est généré pour que chaque lignes correspondent a une ligne dans le Sheets.

hors, si tu regardes ma 1ere page, le mail est contenu dans une seul cellule ( d'où la difficulté )

image

Bonne journée

Bonjour,

Regarde l'encadré vert.

Bonne Journée

Et pour finir dans la case bleu, la formule définitive.

={"Prix","Produits","Quantité";ARRAYFORMULA(REGEXEXTRACT(QUERY({TRANSPOSE(SPLIT(C3,"
")),ARRAYFORMULA(SI(REGEXMATCH(TRANSPOSE(SPLIT(C3,"
")),"\$[\d.]+"),0,1)),ARRAYFORMULA(SIERREUR(SI(ARRAYFORMULA(CNUM(SUBSTITUE(REGEXREPLACE(REGEXEXTRACT(TRANSPOSE(SPLIT(C3,"
")),"(?: \d+?){2}"),"\d+ (\d+)","$1")," ","")))>0,0,1),1))},"SELECT Col1 WHERE Col2 = 0 AND Col3 = 0",0),"\$[\d.]+")),ARRAYFORMULA(REGEXREPLACE(QUERY({TRANSPOSE(SPLIT(C3,"
")),ARRAYFORMULA(SI(REGEXMATCH(TRANSPOSE(SPLIT(C3,"
")),"\$[\d.]+"),0,1)),ARRAYFORMULA(SIERREUR(SI(ARRAYFORMULA(CNUM(SUBSTITUE(REGEXREPLACE(REGEXEXTRACT(TRANSPOSE(SPLIT(C3,"
")),"(?: \d+?){2}"),"\d+ (\d+)","$1")," ","")))>0,0,1),1))},"SELECT Col1 WHERE Col2 = 0 AND Col3 = 0",0),"^(.*).{9}$","$1")),ARRAYFORMULA(CNUM(SUBSTITUE(REGEXREPLACE(REGEXEXTRACT(QUERY({TRANSPOSE(SPLIT(C3,"
")),ARRAYFORMULA(SI(REGEXMATCH(TRANSPOSE(SPLIT(C3,"
")),"\$[\d.]+"),0,1)),ARRAYFORMULA(SIERREUR(SI(ARRAYFORMULA(CNUM(SUBSTITUE(REGEXREPLACE(REGEXEXTRACT(TRANSPOSE(SPLIT(C3,"
")),"(?: \d+?){2}"),"\d+ (\d+)","$1")," ","")))>0,0,1),1))},"SELECT Col1 WHERE Col2 = 0 AND Col3 = 0",0),"(?: \d+?){2}"),"\d+ (\d+)","$1")," ","")))}

Bonne Journée

top !

merci beaucoup :)

Rechercher des sujets similaires à "regex extract replace etc elements mail"