Coping CSV file from Gmail Attachment by name - google-apps-script

I want to only copy the CSV attachment to google sheets from an email.
The email has multiple attachments, in different file formats.
The attachment I want to copy over is consistently the same name in csv format.
I am using this code but its not pulling the attachment I want to copy to google sheet.
Can someone help me with this.
function getCSV() {
var myLabel = GmailApp.getUserLabelByName("I-Data New"); // specify label in gmail
var threads = myLabel.getThreads(0,1);
var msgs = GmailApp.getMessagesForThreads(threads);
var attachments = msgs[0][0].getAttachments();
var csv = attachments[0].getDataAsString();
var data = Utilities.parseCsv(csv);
var a = data.length ;
var b = data[0].length;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.openById('12ApSC0WVn1sZxb9VF6_CZR9L5xuGY5WHMLyyGMc').getSheetByName('IData');
sheet.getRange('A2:AM6026').clearContent();
var range = sheet.getRange(2,1, data.length,data[0].length);
range.setValues(data);
}

Loop over the attachments and get the filename. Quick edit to your existing code:
function getCSV() {
var myLabel = GmailApp.getUserLabelByName("I-Data New"); // specify label in gmail
var threads = myLabel.getThreads(0, 1);
var msgs = GmailApp.getMessagesForThreads(threads);
var attachments = msgs[0][0].getAttachments();
attachments.forEach(att => {
const name = att.getName()
if (name == "myFileName.csv") {
var data = Utilities.parseCsv(att.getDataAsString());
var sheet = SpreadsheetApp.openById('12ApSC0WVn1sZxb9VF6_CZR9L5xuGY5WHMLyyGMc').getSheetByName('IData');
sheet.getRange('A2:AM6026').clearContent();
var range = sheet.getRange(2, 1, data.length, data[0].length);
range.setValues(data);
}
})
}

Related

Import data from URL into all sheets in a Google drive Folder

I am trying to import data from a specific URL into all sheets that are in a Google drive folder, then only keep the data that contains the name of the file.
Getting the files from the folder seems to be working but I cannot manage to have SpreasheetApp working (I think this is where the problem comes from). Maybe there is something wrong with how I manage to get ranges.
Here is what I have done so far :
function myfunction()
{
var root = DriveApp.getFoldersByName("Produits");
while (root.hasNext())
{
var folder = root.next(); //If the folder is available, get files in the folder
var files = folder.getFiles();
while(files.hasNext()) //For each file,
{
var spreadsheet = SpreadsheetApp.open(files.next());
//import data from URL
var csvUrl = "myURL";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent);
var activeSpreadSheet = SpreadsheetApp.open(files);
var sheets = activeSpreadSheet.getSheets();
var sheet = sheets[sheetIndex]
sheet.getRange(2, 1, csvData.length, csvData[0].length).setValues(csvData);
// Always show 3 decimal points
var cell = sheet.getRange("D2:D");
cell.setNumberFormat("00");
//Only keep data that contains the file name
var name = sheet.getName();
let range = sheet.getDataRange(),
maxRows = sheet.getMaxRows(),
srchCol_1 = 2,
srchPatt_1 = new RegExp(name)
newRangeVals = range.getValues().filter(r => r[0] && srchPatt_1.exec(r[srchCol_1])),
numRows = newRangeVals.length;
range.clearContent();
sheet.getRange(2,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
sheet.deleteRows(numRows + 1, maxRows - numRows);
//Clean headers
var cell = sheet.getRange(1,1);
cell.setValue("Marchand");
var cell = sheet.getRange(1,2);
cell.setValue("Image");
var cell = sheet.getRange(1,3);
cell.setValue("Titre de l'offre");
var cell = sheet.getRange(1,4);
cell.setValue("Prix");
var cell = sheet.getRange(1,5);
cell.setValue("Lien");
var cell = sheet.getRange(1,6);
cell.setValue("Categorie");
}
}
}
Change
var activeSpreadSheet = SpreadsheetApp.open(files);
var sheets = activeSpreadSheet.getSheets();
to (spreadsheet has already been defined previously)
var sheets = spreadsheet.getSheets()
and give a value to sheetIndex, for instance
var sheets = spreadsheet.getSheets();
var sheetIndex=0
var sheet = sheets[sheetIndex]

Insert the link into the keyword in the sheet file

Please help me:
I have a sheet file with 2 columns
Column A is the keyword, column B is the link to insert the keyword. Eg:
Column A Column B
Key1 Link1
Key2 Link2
... ...
How to automatically find keywords in the DOCS file and then insert Link?
Here is my idea, but it doesn't work
function insertLink() {
var file,files,folder,folders,newestFileID;
var filethaythe = DriveApp.getFilesByName('Set Link');
var ss = SpreadsheetApp.open(filethaythe.next());//ID sheet thư viện thay thế
SpreadsheetApp.setActiveSpreadsheet(ss);
SpreadsheetApp.setActiveSheet(ss.getSheets()[0]);
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Trang tính1');
var sheet = ss.getSheetByName('Trang tính1');
var values = sheet.getDataRange().getValues();
folders = DriveApp.getFoldersByName('test3');
while (folders.hasNext()) {
folder = folders.next();
files = folder.getFilesByType("application/vnd.google-apps.document");
while (files.hasNext()){
file = files.next();
var newestFileID = file.getId();
Utilities.sleep(500);
var currentDoc = DocumentApp.openById(newestFileID);
var dongcuoi= sh.getLastRow();
var dc = dongcuoi +1;
var rgtxt = currentDoc.getBody();
var rgrep = ss.getSheets()[0].getRange("A1:B"+dc);
var repA = rgrep.getValues().filter(r => r.every(c => c.toString()));
repA.forEach(e => rgtxt.setLinkUrl(...e));
currentDoc.saveAndClose();
break
}
};
}
I believe your goal as follows.
You want to set the hyperlink to the word on Google Document.
The words and hyperlinks are retrieved from Google Spreadsheet.
In this case, how about the following modification?
Modified script:
function insertLink() {
// 1. Retrieve values from Spreadsheet.
var file,files,folder,folders,newestFileID;
var filethaythe = DriveApp.getFilesByName('Set Link');
var ss = SpreadsheetApp.open(filethaythe.next());
var sheet = ss.getSheetByName('Trang tính1');
var values = sheet.getDataRange().getValues();
// 2. Retrieve Google Document.
folders = DriveApp.getFoldersByName('test3');
while (folders.hasNext()) {
folder = folders.next();
files = folder.getFilesByType("application/vnd.google-apps.document");
while (files.hasNext()) {
file = files.next();
var newestFileID = file.getId();
// 3. Search words and set hyperlinks on Google Document.
var currentDoc = DocumentApp.openById(newestFileID);
var rgtxt = currentDoc.getBody();
values.forEach(([a, b]) => {
var s = rgtxt.findText(a);
while (s) {
var start = s.getStartOffset();
s.getElement().asText().setLinkUrl(start, start + a.length - 1, b);
s = rgtxt.findText(a, s);
}
});
currentDoc.saveAndClose();
break
}
}
}
In order to search the word, the method of findText is used. And, the method of setLinkUrl sets the hyperlink to the searched word.
References:
findText(searchPattern, from)
setLinkUrl(startOffset, endOffsetInclusive, url)

Google Script on Attaching List of excel files from a Spreadsheet

I two spreadsheet Main and AddFiles wherein Add file has Two columns Subject and Attachments where under attachments is the list of excel file names with like file1.xlsx and file2.xlsx. Where I uploaded this file in my Google Drive under the Report folder.
I used the code below but always got an error on the last execution. It doesn't recognize the .getAs(MimeType.xlsx)
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange(2,1,1,1)
data = dataRange.getValues()
var e = data[0][0]
for (var i = 0; i < (e-1); i++) {
draftmail();
}
function draftmail(){
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange(1,1,1,1)
var data = dataRange.getValues()
var msg = data[0][0]
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("AddFiles");
var startRowx = 1
var numRowx = 1
var dataRangeTox = sheet.getRange(startRowx,3,numRowx,1)
var datax = dataRangeTox.getValues()
for (x in datax) {
var rowx = datax[x];
var to = rowx[0];
var Starta = 2 + i
var numRowa = 1
var dataRangeToa = sheet2.getRange(Starta,1,1,1)
var dataa = dataRangeToa.getValues()
for (a in dataa) {
var rowa = dataa[a];
var subject = rowa[0];
var Startb = 2 + i
var numRowb = 1
var dataRangeTob = sheet2.getRange(Startb,2,1,1)
var datab = dataRangeTob.getValues()
for (b in datab) {
var rowb = datab[b];
var datafile = rowb[0];
var file = DriveApp.getFilesByName(datafile)
var startRowy = 1
var numRowy = 1
var dataRangeToy = sheet.getRange(startRowy,4,numRowy,1)
var datay = dataRangeToy.getValues()
for (y in datay) {
var rowy = datay[y];
var carboncopy = rowy[0];
if (file.hasNext()){
GmailApp.createDraft(to,subject,msg,{ cc: carboncopy}, {
attachments: [file[0].getAs(MimeType.xlsx)],
})
}
}
}
}
}
}
Modification points:
Assuming that everything else works properly in your code, you should make the following changes:
cc and attachments should be passed as a single json object.
file[0] should be file.next().
MimeType.xlsx should be MimeType.MICROSOFT_EXCEL.
Solution:
GmailApp.createDraft(to,subject,msg,
{ cc: carboncopy,
attachments: [file.next().getAs(MimeType.MICROSOFT_EXCEL)]
})
References:
Class GmailApp
Google Apps Script: XLSX from Gmail to Google Sheets: invalid mime type. Content type seems to be application/octet?
Class FileIterator
When you call
file = DriveApp.getFilesByName(datafile)
it returns a FileIterator collection, which is not indexed like an array (file[0]) but rather requires you to call file.next() to get the next file.
In addition, the MimeType Enum for an .xlsx file is MimeType.MICROSOFT_EXCEL.
So change
attachments: [file[0].getAs(MimeType.xlsx)]
to this instead:
attachments: [file.next().getAs(MimeType.MICROSOFT_EXCEL)]

Determining the extension of an e-mail attachment automatically (whether it's XLSX or CSV) and applying the right parsing technique

I have two Google Script codes that automate the process of importing email attachments from Gmail (it's automatically labeled) into Google Sheets. So far I managed to make it work for CSV and XLSX files separately. Please see both codes below. My question is: how do I combine those two codes into one, so that it could determine the file extension automatically and apply the right parsing technique when copying the contents of the files in the respective Google Sheet. Thank you!
For XLSX files:
function getXLSX() {
var thread = GmailApp.getUserLabelByName("Invoicing").getThreads(0,1);
/* var message = thread[0].getMessages()[0]; // Get first message */
var messages = thread[0].getMessages();
var len = messages.length;
var message=messages[len-1] //get last message
var attachments = message.getAttachments(); // Get attachment of first message
var xlsxBlob = attachments[0]; // Is supposes that attachments[0] is the blob of xlsx file.
var convertedSpreadsheetId = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS}, xlsxBlob).id;
var sheet = SpreadsheetApp.openById(convertedSpreadsheetId).getSheets()[0]; // There is the data in 1st tab.
var data = sheet.getDataRange().getValues();
Drive.Files.remove(convertedSpreadsheetId); // Remove the converted file.
//var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet_new = SpreadsheetApp.openById("1jRh8sj_jAaZKH4xbdpI9Q4to1tKuGWTTO2MzHlU").getSheetByName("Data drop");
/*for (var i = 0; i > sheet_new.length; i++) {
var range = sheet_new[i].getRange("A:I");
range.clearContents();
}*/
sheet_new.clearContents();
var range = sheet_new.getRange(1,1, data.length,data[0].length);
range.setValues(data);
}
For CSV files:
function getCSV() {
var thread = GmailApp.getUserLabelByName("Invoicing").getThreads(0,1);
/* var message = thread[0].getMessages()[0]; // Get first message */
var messages = thread[0].getMessages();
var len = messages.length;
var message=messages[len-1] //get last message
var attachments = message.getAttachments(); // Get attachment of first message
var csv = attachments[0].getDataAsString();
var data = Utilities.parseCsv(csv);
var a = data.length ;
var b = data[0].length;
//var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.openById("1jRh8sj_jAaZKH4xbdpI9Q4to1tKuGWTTO2MzHlU").getSheetByName("Data drop");
sheet.getRange("A:J").clear();
var range_final = sheet.getRange(1,1, data.length,data[0].length);
range_final .setValues(data);
}
How about this modification? In this modification, the mimeType is compared and each script is run. Please think of this as just one of several answers.
Modified script:
function myFunction() {
var thread = GmailApp.getUserLabelByName("Invoicing").getThreads(0,1);
var messages = thread[0].getMessages();
var len = messages.length;
var message = messages[len-1]; //get last message
var attachments = message.getAttachments(); // Get attachment of first message
var blob = attachments[0]; // Is supposes that attachments[0] is the blob of xlsx file.
blob.setContentTypeFromExtension();
if (blob.getContentType() == MimeType.MICROSOFT_EXCEL) {
// Process for XLSX
var convertedSpreadsheetId = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS}, blob).id;
var sheet = SpreadsheetApp.openById(convertedSpreadsheetId).getSheets()[0]; // There is the data in 1st tab.
var data = sheet.getDataRange().getValues();
Drive.Files.remove(convertedSpreadsheetId); // Remove the converted file.
var sheet_new = SpreadsheetApp.openById("1jRh8sj_jAaZKH4xbdpI9Q4to1tKuGWTTO2MzHlU").getSheetByName("Data drop");
sheet_new.clearContents();
var range = sheet_new.getRange(1,1, data.length,data[0].length);
range.setValues(data);
} else if (blob.getContentType() == MimeType.CSV) {
// Process for CSV
var csv = blob.getDataAsString();
var data = Utilities.parseCsv(csv);
var a = data.length ;
var b = data[0].length;
var sheet = SpreadsheetApp.openById("1jRh8sj_jAaZKH4xbdpI9Q4to1tKuGWTTO2MzHlU").getSheetByName("Data drop");
sheet.getRange("A:J").clear();
var range_final = sheet.getRange(1,1, data.length,data[0].length);
range_final.setValues(data);
}
}
Note:
This modified script supposes as follows.
The index of 0 of attachment files is the file you need.
The index of 0 of attachment files is XLSX file or CSV file.
Filenames of XLSX and CSV files have the extension of .xlsx and .csv, respectively.
Reference:
setContentTypeFromExtension()
If I misunderstood your question and this was not the result you want, I apologize.

If column has value do ______

How to search a column on a sheet for a value, and if the value is there continue code? I am trying to make an update system to check to see if their email is on a sheet. If their email is on a sheet then it will check if their system version is up to date. If the system is not to up to date it will then copy their data, delete their current sheet, create a copy from an example then put in their data. If the user does not have the system it will create one for them. It seems to continuously skip Checking their email.
My code uses URLs and IDs but I have taken them out for obvious reasons. Below is an example of the beginning of my code.
function readlog()
var user = Session.getEffectiveUser().getUsername();
var email = Session.getEffectiveUser().getEmail();
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var sheet = sheet.getSheetByName('8th grade')
var active = sheet.getRange('8th grade!b3:b').getValues()
if (email == active) {
//do something
}
Here is a full version of my code:
function readlog(){
var user = Session.getEffectiveUser().getUsername();
var email = Session.getEffectiveUser().getEmail();
var timezone= "CST";
var date = Utilities.formatDate(new Date(),timezone, "E MMM dd,yyyy HH:mm:ss");
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var sheet = sheet.getSheetByName('8th grade')
var active = sheet.getRange('8th grade!b3:b').getValues()
if (email == active) {
var container = DriveApp.getFoldersByName('Reading Log')
var fid = DriveApp.getFoldersByName('Reading Log').getId()
var version = sheet.getRange('8th grade!a1')
var update = container.getDescription();
if (update == version) {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('You already have a reading log, and you have the most recent update!', ui.ButtonSet.OK);
} else {
var contents = container.getFiles();
var files = DriveApp.getFolderById(fid).searchFiles(
'title contains "Reading log"');
while (files.hasNext()) {
var file = files.next();
var logtoupdate = file.getUrl;
}
var ss = SpreadsheetApp.openByUrl(logtoupdate);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var logrange = sheet.getRange('8th Grade!e5:o').getValues()
SpreadsheetApp.getActiveSpreadsheet().deleteActiveSheet();
var master = DriveApp.getFileById(URL_);
var read = master.makeCopy("Reading Log",container);
var target = read.getRange('8th Grade e5:o').setValues(logrange);
var range = sheet.getRange("A1:B2");
range.setValues([[50, 100]]);
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
}
} else {
var ss = SpreadsheetApp.openByUrl(URL_);
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var targetFolder = DriveApp.createFolder("Reading Log");
var eighth = DriveApp.getFileById(URL_);
var share = eighth.makeCopy("(Name): 8th Grade Reading Log",targetFolder);
var master = DriveApp.getFileById(URL_);
var read = master.makeCopy("Reading Log",targetFolder);
var folder = sheet.getRange('8th grade!a1');
targetFolder.setDescription(folder);
var idsheet = read.getUrl();
var idshare = share.getUrl();
var idfolder = targetFolder.getUrl()
sheet.appendRow([user,email,date,idfolder,idsheet,idshare]);
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Your Reading log is created. There is now a folder in your google drive called Reading log. Have Fun Reading!', ui.ButtonSet.OK);
}
}
Short answer
Instead of email == active use active.join('|').split('|').indexOf(email)
Explanation
getValues() return a two dimensional array.
join('|') convert this array into an string using | as separator.
split('|') convert the above string into an (one dimension) array.
indexOf(email) returns the index of the email value on the above array. If the email value is not found, -1 is returned.
On a comparison -1 is parsed as false.