I am new to App Script. My code is below. I have been trying to take data out of an email and put it into different columns in google sheets. I have managed to achieve this and it works but because labels are applied to threads I get duplicates!
I have tried to figure out how to stop this from happening by using the email ID, date etc but I haven't been successful. Any help would be greatly appreciated.
function email_sheet() {
var ss = SpreadsheetApp.openById("");
var sheet = ss.getSheetByName("Sheet1");
var label = GmailApp.getUserLabelByName("ChosenLabel");
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var date = messages[j].getDate();
var body = messages[j].getPlainBody();
var name = "";
var accnum = "";
var paytype ="";
var amount = "";
var status = "";
/** Break Down the Email */
if(body.indexOf("Recipient : ")>0) {
var end = body.substring(body.indexOf("Recipient : ")+12,body.length);
name = end.substring(0, end.indexOf("\n"));
}
if(body.indexOf("AN")>0) {
var end = body.substring(body.indexOf("AN")+2,body.length);
account = end.substring(0, end.indexOf("\n"));
var [accnum, paytype] = account.split(" ");
}
if(body.indexOf("Amount : ")>0) {
var end = body.substring(body.indexOf("Amount : ")+9,body.length);
amount = end.substring(0, end.indexOf("\n"));
}
if(body.indexOf("Transaction Status : ")>0) {
var end = body.substring(body.indexOf("Transaction Status : ")+21,body.length);
status = end.substring(0, end.indexOf("\n"));
}
sheet.appendRow([date, name, accnum, paytype, amount, status]);
}
threads[i].removeLabel(label);
threads[i].addLabel(GmailApp.getUserLabelByName("All Transactions"))
}
} ```
You can for instance limit to unread mails and at the end mark them as already read, for instance
function mail() {
var requete ="is:unread {label:ChosenLabel label:OtherLabel}"
var ss = SpreadsheetApp.getActive().getSheetByName("Mail");
var threads = GmailApp.search(requete);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var msg = messages[j].getPlainBody();
var sub = messages[j].getSubject();
var dat = messages[j].getDate();
ss.appendRow([dat, sub, msg])
}
}
GmailApp.markThreadsRead(threads);
}
Related
Just started learning Javascript/Google Apps Script, so please be patient with me.
My goal is to create an automated email script that emails a reminder when the inventory stock has dipped below a certain level.
To start, I have a Google Sheet with 3 tabs: ContactSheet, ReorderSheet, and EmailSheet. These tabs have columns, respectively: person's name and email address; item name, number, manufacturer, current stock, and threshold for reorder; subject line and message.
Code below. No runtime errors, but the emails either do not send or they send out for only the first or last item in the spreadsheet. (Should be sending out exactly 5 emails for 5 different items.) I think the issue is with the if statement --- I'm assuming that the variables are not able to call on their respective indices, if that makes sense. I've tried converting the variables to arrays with no success. This version works best according to the logger, and only breaks down at the last block.
Thanks in advance.
function sendEmail() {
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var ContactSheet = Spreadsheet.getSheetByName('ContactSheet');
var ReorderSheet = Spreadsheet.getSheetByName('ReorderSheet');
var EmailSheet = Spreadsheet.getSheetByName('EmailSheet');
var SubjectLine = EmailSheet.getRange(2,1).getValue();
var Message = EmailSheet.getRange(2,2).getValue();
var N = ReorderSheet.getLastRow();
for(var i = 2; i < N+1; i++) {
var ItemName = ReorderSheet.getRange(i,1).getValue();
var ItemNumber = ReorderSheet.getRange(i,2).getValue();
var ItemManufacturer = ReorderSheet.getRange(i,3).getValue();
var ItemStock = ReorderSheet.getRange(i,4).getValue();
var ItemReorder = ReorderSheet.getRange(i,5).getValue();}
var M = ContactSheet.getLastRow();
for(var j = 2; j < M+1; j++) {
var Name = ContactSheet.getRange(j,1).getValue();
var EmailAddress = ContactSheet.getRange(j,2).getValue();}
if (ItemStock < ItemReorder) {
SubjectLine = SubjectLine.replace("<item>",ItemName);
Message = Message.replace("<name>",Name).replace("<item>",ItemName).replace("<itemnumber>",ItemNumber).replace("<manufacturer>",ItemManufacturer);
MailApp.sendEmail(EmailAddress, SubjectLine, Message);}
}
This for loop does not contain the sendEmail method:
for (var i = 2; i < N + 1; i++) {
var ItemName = rsh.getRange(i, 1).getValue();
var ItemNumber = rsh.getRange(i, 2).getValue();
var ItemManufacturer = rsh.getRange(i, 3).getValue();
var ItemStock = rsh.getRange(i, 4).getValue();
var ItemReorder = rsh.getRange(i, 5).getValue();
}
So your always only dealing with the data on the last row
Same with this one:
for (var j = 2; j < M + 1; j++) {
var Name = csh.getRange(j, 1).getValue();
var EmailAddress = csh.getRange(j, 2).getValue();
}
This structure will send emails to every email address:
function sendEmail() {
var ss = SpreadsheetApp.getActive();
var csh = ss.getSheetByName('ContactSheet');
var rsh = ss.getSheetByName('ReorderSheet');
var esh = ss.getSheetByName('EmailSheet');
var subject = esh.getRange(2, 1).getValue();
var message = esh.getRange(2, 2).getValue();
var N = rsh.getLastRow();
var M = csh.getLastRow();
for (var j = 2; j < M + 1; j++) {
var Name = csh.getRange(j, 1).getValue();
var EmailAddress = csh.getRange(j, 2).getValue();
for (var i = 2; i < N + 1; i++) {
var ItemName = rsh.getRange(i, 1).getValue();
var ItemNumber = rsh.getRange(i, 2).getValue();
var ItemManufacturer = rsh.getRange(i, 3).getValue();
var ItemStock = rsh.getRange(i, 4).getValue();
var ItemReorder = rsh.getRange(i, 5).getValue();
if (ItemStock < ItemReorder) {
subject = subject.replace("<item>", ItemName);
message = message.replace("<name>", Name).replace("<item>", ItemName).replace("<itemnumber>", ItemNumber).replace("<manufacturer>", ItemManufacturer);
MailApp.sendEmail(EmailAddress, subject, message);
}
}
}
}
i use the following code in Google Apps Script and i wanna get all messages in the inbox. This code gives "Cannot convert Array to number[][]. (line 19, file "Code")" error. How can i fix this code?
var myspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var mysheet = myspreadsheet.getSheets()[0];
var start = 0;
var max = 19;
var count = 0;
while (count < 7) {
var threads = GmailApp.getInboxThreads(start, max);
var messages = GmailApp.getMessagesForThreads(threads);
//var froms = [];
messages.get
for (var i = 0; i < threads.length; i++) {
var thisThread = threads[i];
var messages = thisThread.getMessages();
var messageCount = thisThread.getMessageCount();
for ( var m = 0; m<=messageCount; m++) {
var lastMessage = messages[m];
froms = ([lastMessage.getId(), lastMessage.getSubject(), lastMessage.getTo(), lastMessage.getFrom(), lastMessage.getCc(), JSON.stringify(lastMessage.getDate()), lastMessage.getReplyTo()]);
mysheet.getRange(1, 1, froms.length, 7).setValues(froms);
froms = [];
}
}
start = start + 100;
count++;
}
}
Try changing this: froms = ([lastMessage.getId(), lastMessage.getSubject(), lastMessage.getTo(), lastMessage.getFrom(), lastMessage.getCc(), JSON.stringify(lastMessage.getDate()), lastMessage.getReplyTo()]);
to this: froms = ([[lastMessage.getId(), lastMessage.getSubject(), lastMessage.getTo(), lastMessage.getFrom(), lastMessage.getCc(), JSON.stringify(lastMessage.getDate()), lastMessage.getReplyTo()]]);
But really I think you have even bigger problems with your script.
I'd use something like this. But I can't test it very well because I don't keep a lot of junk in my inbox.
function emailsStuff() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheets()[0];
sh.clearContents();
var threads=GmailApp.getInboxThreads()
for(var i=0;i<threads.length;i++) {
var messages=GmailApp.getMessagesForThread(threads[i]);
for(var j=0;j<messages.length;j++) {
var msg=messages[j];
sh.appendRow([msg.getId(), msg.getSubject(), msg.getTo(), msg.getFrom(), msg.getCc(), JSON.stringify(msg.getDate()), msg.getReplyTo()]);
}
}
}
I'm currently developing a sheet that shows results from a set of data based on some filters but the data loads to slowly when getting the results, I've tried to follow the Best Practices from Google Documentacion with no luck, how can I set an array for the data to load faster?
Below is the code commented with what I've already tried
function realizarBusqueda() {
var inicio = SpreadsheetApp.getActive().getSheetByName("INICIO");
var aux_tags = SpreadsheetApp.getActive().getSheetByName("Aux_Tags");
var data = SpreadsheetApp.getActive().getSheetByName("Data");
var data_lc = data.getLastColumn();
var data_lr = data.getLastRow();
var searchRange = data.getRange(2,1, data_lr, data_lc);
var inicio_lc = inicio.getLastColumn();
inicio.getRange("A8:L1000").clearContent();
inicio.getRange("A8:L1000").clearFormat();
var countRows = inicio.getMaxRows();
inicio.deleteRows(20, (20-countRows)*-1);
if (inicio.getRange("B4").isBlank()) {
inicio.getRange("A8:L1000").clearContent();
inicio.getRange("A8:L1000").clearFormat();
var countRows = inicio.getMaxRows();
inicio.deleteRows(20, (20-countRows)*-1);
SpreadsheetApp.flush();
}
else if ((inicio.getRange("B4").getValue() != "" &&
inicio.getRange("C4").getValue() === "")) {
//filtrado 1
var arrayDatos = searchRange.getValues();
var inicio_fr = 8;
//var row = new Array(11);
for (var j = 2; j <= data_lr; j++) {
//row[j] = new Array(data_lr);
if (aux_tags.getRange("P2").getValue() === arrayDatos[j-2][4]) {
var inicio_fc = 1;
for (var i = 0; i < arrayDatos[j-2].length; i++) {
//row[j][i] = arrayDatos[j-2][i];
var row = arrayDatos[j-2][i];
inicio.getRange(inicio_fr, inicio_fc).setValue(row);
inicio_fc++;
}
inicio_fr++;
}
//inicio.getRange("A8").setValues(row);
}
}
I expect the output to load lots faster, currently what I've tried is commented, the code as-is is working but too slow
I just wanted to update this subject because I figured out myself, see attached the new code with the use of new 2D arrays
...
//filtrado 1
var arrayDatos = searchRange.getValues();
var inicio_fr = 8;
var rows = [];
var row = [];
for (var j = 2; j <= data_lr; j++) {
if (aux_tags.getRange("P2").getValue() === arrayDatos[j-2][4]) {
var inicio_fc = 1;
for (var i = 0; i < arrayDatos[j-2].length; i++) {
row.push(arrayDatos[j-2][i]);
if (i == 11) {
rows.push(row);
row = [];
}
}
}
}
inicio.getRange(8, 1, rows.length, rows[0].length).setValues(rows);
}
Now instead of writing on row at a time, I just write the whole array at once
I'm trying to:
Go into a Drive folder and retrieve the spreadSheetIDs of existing spreadsheets
Go into each spreadsheet and get some data
Copy that data into a TargetSheet
With the condition that the data does not exist already
From 1-3 I have no issues, but I cannot correctly search and match if the data exists already.
This is my code so far. If I run the code twice on the same data set, some data is copied when it should not be, since it already exists.
Any help, please?
function getReportData() {
//Sources
var reportFolder = DriveApp.getFolderById('ReportFolderID') // Get Status reports folder
var reportsList = reportFolder.getFiles(); //Returns FileIterator object
var spreadSheets = [];
var targetSSheet = SpreadsheetApp.openById('TargetSheetID');
var targetSheet = targetSSheet.getActiveSheet();
var lastRow = targetSheet.getLastRow();
var searchRange = targetSheet.getRange(2, 1, lastRow, 2);
var searchRangeV = searchRange.getValues();
var allStatuses = [];
//Populate the reportSheets list with latest report sheet IDs
while (reportsList.hasNext()) {
var reports = reportsList.next(); //Object of type file
spreadSheets.push(reports.getId());
}
// Loop through the list of report sheets
for (i = 0; i < spreadSheets.length; i++) {
var spreadSheet = SpreadsheetApp.openById(spreadSheets[i]);
var activeSheet = spreadSheet.getActiveSheet();
var individualStatus = [];
// Gets project report data
var projectName = activeSheet.getRange("B3:B4").getValue();
var reportDate = activeSheet.getRange("I3:I4").getValue();
var projectStatus = activeSheet.getRange("G9:i9").getValue();
// Creates reports array
individualStatus.push(reportDate, projectName, projectStatus);
allStatuses.push(individualStatus)
}
//Cleans the status array of existing ones
for (j = 0; j < allStatuses.length; j++) {
var searchKey = allStatuses[j][0] + allStatuses[j][1];
searchKey
Logger.log(searchKey)
for (k = 0; k < searchRangeV.length; k++) {
var matchKey = searchRangeV[k][0] + searchRangeV[k][1];
if (searchKey == matchKey) {
allStatuses.splice(j, 1)
break;
} else {
Logger.log(searchKey)
Logger.log(matchKey)
}
}
}
//Copies the data to Target Sheet
for (var project = 0; project < allStatuses.length; project++) {
//Gets the last row each time it goes through the loop
var latestRow = targetSheet.getLastRow();
var lastColumn = targetSheet.getLastColumn();
for (var status = 0; status < allStatuses[project].length; status++) {
targetSheet.getRange(latestRow + 1, status + 1, 1, 1).setValue(allStatuses[project][status])
}
}
}
with this code I use to save attachment to a shared google drive folder and got notified when a change happen to it by a mail. All is fine as long as I search for pdf attachments. As I set file:xls the messages returned are far more than expected. Not only, the threads returned by the debug are correct, as well as insert the query in the search filed in Gmail, but the getmessages() returned in this case 38 messages (and attachements! And not only xls but also a pdf) of the query parameters. The conversation view is disabled in Gmail, the only match with this attachments is the from: field.
I tried to change the reference data (by adding newer_than), and nothing changed; I changed the for cycle, and nothing changed. Am I missing something really stupid or is this a kind of bug with xls?
function salvataggioTavoloTecnico(){
var folderName = 'tavoloTecnico';
var p = 0;
var f1s= DriveApp.getFoldersByName(folderName).next().getFiles();
while (f1s.hasNext()) {
var f1 = f1s.next();
p++
} Logger.log(p);
var d = new Date();
d.setDate(d.getDate()-1);
var n = d.getFullYear() + "/" + addZero(d.getMonth()+1) + "/" + addZero(d.getDate());
var query = 'in:anywhere has:attachment filename:XLS newer_than:5d (from:mariano.casillo#mit.gov.it OR from:donato.castigliego#mit.gov.it OR from:luciano.aloia#mit.gov.it)';
//var query = 'in:anywhere has:attachment filename:xls '+ 'after:'+n+' (from:mariano.casillo#mit.gov.it OR from:donato.castigliego#mit.gov.it OR from:luciano.aloia#mit.gov.it)';
var elenco = GmailApp.search(query);
var quanteMail = elenco.length; Logger.log(quanteMail);
labelName = GmailApp.createLabel('Movimenti - Tavolo tecnico');
for (var i = 0 ; i < quanteMail; i++) {
//for ( var i in elenco) {
elenco[i].addLabel(labelName);
var thr = elenco[i];
var nn = thr.getMessageCount();
Logger.log(nn);
var mesgs = thr.getMessages();
var www = mesgs.length;
for(var j = 0 ; j < www ; j ++){
var attachments = mesgs[j].getAttachments();
var rrr = attachments.length;
for(var k = 0 ; k < rrr ; k ++) {
var attachment = attachments[k];
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
DriveApp.getFoldersByName(folderName).next().addFile(file);
}
}
}
var c = 0;
var f2s = DriveApp.getFoldersByName(folderName).next().getFiles();
while (f2s.hasNext()) {
var f2 = f2s.next();
c++
}
if ( c > p) { GmailApp.sendEmail("me#me.com", " avviso "+folderName, "Un nuovo file รจ stato aggiunto")};
}
I still don't know why the search by code return more messages out of the parameters, but I workaround it by search in the "wrong" messages only those I need by parse the date, like this, and now it works:
......
var threads = GmailApp.search(query);
for ( var i in threads) {
threads[i].addLabel(labelName);
var mesgs = threads[i].getMessages();
var www = mesgs.length;
for(var j = 0 ; j < www ; j ++){
if ( mesgs[j].getDate() < d ){} else {
var attachments = mesgs[j].getAttachments();
var rrr = attachments.length;
for(var k = 0 ; k < rrr ; k ++) {
var attachment = attachments[k];
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
DriveApp.getFoldersByName(folderName).next().addFile(file);
}
}
}
}
.......