Stop recording to spreadsheet if Gmail Label exist - google-apps-script

I like to record an email's Subject/Sender/Date/ID into a spreadsheet by it's label and add a "Recorded" label to the email once it's recorded into the spreadsheet. I like to run the script again without re-recording emails with the label "Recorded"
I can get it to the point of recording to spreadsheet and adding the label. but everything i run the script it grabs everything again.
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var searchlabel = GmailApp.getUserLabelByName("Test");
var newlabel = GmailApp.getUserLabelByName("Recored");
var threads = searchlabel.getThreads();
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].getBody();
var sub = messages[j].getSubject();
var from = messages[j].getFrom();
var dat = messages[j].getDate();
var id = messages[j].getId();
var current = new Date();
ss.appendRow([current, dat, sub, id, from])
}
threads[i].addLabel(newlabel);
}
}
I've search the forum and everything tends to suggest to remove the existing label and rename to a different label. But what i wantenter code here is to keep the existing label.

You should the search method since it lets you filter emails that belong to a particular label. Here's the modified version.
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var searchlabel = GmailApp.getUserLabelByName("Test");
var recordlabel = GmailApp.getUserLabelByName("Recorded");
var threads = GmailApp.search("label:Test -label:Recorded");
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].getBody();
var sub = messages[j].getSubject();
var from = messages[j].getFrom();
var dat = messages[j].getDate();
var id = messages[j].getId();
var current = new Date();
ss.appendRow([current, dat, sub, id, from])
}
threads[i].addLabel(recordlabel);
}
}

You can try replacing var threads with:
var threads = GmailApp.search('label:(Test -Recored)');
This searches for all labels with Test but not Recored.
You wouldn't need var searchlabel anymore.

Related

Data is not written to Google Spreadsheet

My script copies "unread" incoming messages from mail from the marked folder to the google table, and then marks it as read. But sometimes there are failures: the script is executed, marks the letters "as read", but does not write to the table. That is, in fact, it turns out in the logger there is a record with all the contents of these letters, but they are not written to the table. In theory, you need to check whether the data was written to the table and only then mark the letters "as read". Maybe there is an error in the code that periodically makes itself felt? Guys, help me, I'm just learning.
function GmailmarkReadEnd() {
//this is just the stuff that recognizes what spreadsheet you're in
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getSheetByName('Лист2'); //gets the right sheet
/* searches your GMail for emails matching things "label:unread" + " label:support"
*/
var query = "label:unread" + " label:support";
var threads = GmailApp.search(query);
var supportStats = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var from = messages[m].getFrom(); //from field
var to = messages[m].getTo(); //to field
var time = messages[m].getDate(); //date field
var subject = messages[m].getSubject(); //subject field
var body = messages[m].getPlainBody(); //body field
var mId = messages[m].getId(); //id field to create the link later
if (query === "label:unread" + " label:support") {
supportStats.push([from,to,time,subject,body,'https://mail.google.com/mail/u/0/#inbox/'+mId]);
Logger.log(supportStats) // The log about which he spoke.
}
}
}
if(!threads.length) return; // if there are no unread ones, do nothing.
sheet.getRange(SpreadsheetApp.getActiveSheet().getLastRow()+1,2,supportStats.
length,supportStats[0].length).setValues(supportStats); //writes to the spreadsheet
GmailApp.markThreadsRead(threads); // marks as read
// ***Sorting Recorded Data by Date***
sheet.getRange('D:D').activate();
sheet.sort(4, false);
}
function GmailmarkReadEnd() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Лист2'); //gets the right sheet
const query = "label:unread" + " label:support";
var threads = GmailApp.search(query);
var supportStats = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var from = messages[m].getFrom(); //from field
var to = messages[m].getTo(); //to field
var time = messages[m].getDate(); //date field
var subject = messages[m].getSubject(); //subject field
var body = messages[m].getPlainBody(); //body field
var mId = messages[m].getId(); //id field to create the link later
supportStats.push([from,to,time,subject,body,'https://mail.google.com/mail/u/0/#inbox/'+mId]);
Logger.log(supportStats) // The log about which he spoke.
}
}
if(!threads.length) return; // if there are no unread ones, do nothing.
sheet.getRange(SpreadsheetApp.getActiveSheet().getLastRow()+1,2,supportStats.length,supportStats[0].length).setValues(supportStats); //writes to the spreadsheet
GmailApp.markThreadsRead(threads); // marks as read
sheet.sort(4,false);
}
Thanks to everyone who helped. If anything, read the comments.
function GmailmarkReadEnd() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Лист2'); //gets the right sheet
const query = "label:unread" + " label:support";
var threads = GmailApp.search(query);
var supportStats = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var from = messages[m].getFrom(); //from field
var to = messages[m].getTo(); //to field
var time = messages[m].getDate(); //date field
var subject = messages[m].getSubject(); //subject field
var body = messages[m].getPlainBody(); //body field
var mId = messages[m].getId(); //id field to create the link later
supportStats.push([from,to,time,subject,body,'https://mail.google.com/mail/u/0/#inbox/'+mId]);
Logger.log(supportStats) // The log about which he spoke.
}
}
if(!threads.length) return; // if there are no unread ones, do nothing.
sheet.getRange(sheet.getLastRow()+1,2,supportStats.length,supportStats[0].length).setValues(supportStats); //writes to the spreadsheet
GmailApp.markThreadsRead(threads); // marks as read
sheet.sort(4, false);
}

Closed: vanishing data in Google Form after refreshing the page

I wrote a google script, which is creating form, using data from google spreadsheet. I'm using drop-down answer options. The code works normally, all data appears, but sometimes ( 3 times of 5 attempts), after refreshing browser page, some questions disappeared. Everytime it's different question, so it isn't problem with specific question.
What is the problem and how can i fix it?
UPD: Solved. Problem was in opened Google Form while code was compiled.
function myFunk(){
var SHEET_ID = FormApp.getActiveForm().getDestinationId();
var ss = SpreadsheetApp.openById(SHEET_ID);
var form = FormApp.getActiveForm();
var sheets = ss.getSheets();
var numb = sheets[1].getLastRow();
var TypeSelect = form.addListItem()
.setRequired(true);
var TypeChoices = getData(TypeSelect,sheets[1],1,numb)
TypeSelect.setChoices(TypeChoices);
var ClientSelect = form.addListItem()
.setRequired(true)
var ClientChoices = getData(ClientSelect, sheets[1],2,numb)
ClientSelect.setChoices(ClientChoices);
var phases = ["Start","End"];
var PhasesChoices=[];
var PhaseSelect = form.addMultipleChoiceItem()
.setRequired(true);
for (var t=0;t<phases.length; t++){
PhasesChoices.push(PhaseSelect.createChoice(phases[t]));
}
PhaseSelect.setChoiceValues(phases);
}
function getData(DataSelect,sheet,numbColumn,lRow){
var DataChoices = [];
var DataValues = sheet.getRange(2,numbColumn,lRow,1).getValues()
.filter(CheckFull);
var data = [];
for(var i = 0; i < DataValues.length; i++) {
data.push(DataValues[i]);
}
for(var j =0; j < data.length; j++) {
DataChoices.push(DataSelect.createChoice(data[j]));
}
return DataChoices;
}
function CheckFull(value){
return value != '';
}

How do I get script to get emails after ones already imported? (ignore emails already called by script)

Problem: Every time I run the script, the same previous emails are loaded into the spreadsheet. Given that I need to run this script weekly, I would like to ignore emails already imported from prior runs.
I believe an edit needs to be made in the for loop or perhaps add an if statement before the append
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var label = GmailApp.getUserLabelByName("Test Script");
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 msg = messages[j].getPlainBody();
var sub = messages[j].getSubject();
var dat = messages[j].getDate();
ss.appendRow([msg, sub, dat])
}
}
Output is currently:
Email 1
Email 2
Email 3
Email 1
Email 2
Email 3
Email 4
Email 1
Email 2
Email 3
Email 4
Email 5
But I would like it to just add new emails coming in:
Email 1
Email 2
Email 3
+Email 4
+Email 5
An easy solution would be to retrieve the message IDs and check if a message with given ID is already imported into the sheet.
This is how you can do it:
function myFunction(){
var messageArray=[];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var values=sheet.getDataRange().getValues();
for (var k=0; k<values.length; k++){
messageArray.push(values[k][0])
}
var label = GmailApp.getUserLabelByName("testlabel");
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 msg = messages[j].getPlainBody();
var sub = messages[j].getSubject();
var dat = messages[j].getDate();
var id= messages[j].getId()
if(messageArray.indexOf(id)==(-1)){
ss.appendRow([id, msg, sub, dat])
}
}
}
}

Method is heavily used by the script

I am very new on using Google Apps Script and has a shallow knowledge on programming. What I am trying to do is copy the values of specific columns to a different Spreadsheet. Here's my code:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var x=2, y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
for (j=0; j<maxRows; j++){
var eventID = selectedSheets[i].getRange(y,2).getValue();
var employeeName = selectedSheets[i].getRange(y,3).getValue();
var productionDate = selectedSheets[i].getRange(y,4).getValue();
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,1).setValue(eventID);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,2).setValue(employeeName);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,3).setValue(productionDate);
y++;
lastRow++;
}
}
}
However, I am experiencing this notification on the Execution hints (light bulb icon):
screenshot of the message. I am thinking that my code can be simplified. I am just not sure how to do it. Thank you in advance.
Every line with .getRange().getValue() and getRange.setValue() is a call to the file. Since you have these inside a for(){} loop, they are being called many times. Your goal is to limit these to as few as possible. Since you can read and write a range, you could do something similar to this:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
var copyValues = selectedSheets[i].getRange(y,2, maxRows, 4).getValues();
consolidatedSheet.getRange(lastRow,1, maxRows, 4).setValues(copyValues);
}
}

How to get gmail attachment name and paste it into sheets google-apps

I'm trying to get the filename of an attachment on Sheets using google apps scripts.
It gives me an error : "TypeError: Cannot find function getName in object GmailAttachment,GmailAttachment"
Any Ideas??
Here is my code :
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("Label");
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 msg = messages[j].getBody();
var sub = messages[j].getSubject();
var dat = messages[j].getDate();
var attachment = messages[j].getAttachments().getName();
ss.appendRow([msg, sub, dat]);
ss.appendRow([attachment])
}
//threads[i].removeLabel(label);
}
}
Thanks!!
getAttachements() method return a array of GmailAttachement. You must go throught the array to use the GmailAttachement.getName() method.