Background
The reason why I'm doing this is because at my company, we get emails a lot from different locations that have relevant data we need for other processes. The problem is that this data is always in a CSV or excel file format, and downloading the file, then copying all of the data, then pasting it in the proper location takes away time that people could be using on other relevant business-related tasks.
To mitigate the above issue, I've been working on a Google App Script library for my company that simplifies a lot of the functions that we use on a regular basis inside of app script. Because I'm still fairly new to JS and how function overloading works, I realized I can concatenate some of the functions currently in the library more succinctly, so they're more readable. Below is an example of what 4 internal functions looked like inside another function, and then with some fiddling what I was able to decrease it to.
What the code does is fairly simple, a user specifies an emailSubject
and a targetSheet
. These two parameters must always be specified. What this does is it looks into the user's Gmail and finds the first email that matches user-specified emailSubject
. Once it finds that email, it will take the first attachment (currently only if it is an excel or CSV file), takes the data from that attachment, and then pastes it onto a google spreadsheet, specifically on the sheet that the user specified as targetSheet
. The other parameters are attachmentNumber
, row
, and column
. attachmentNumber
is used in the case that an email has multiple attachments, but the user only wants to pull a specific attachment that is not the first one. attachmentNumber
will NOT correspond to the index in the attachments array in the emailAttachmentRetrieval
function, as that is already taken into account. (So if the attachment is the fifth attachment in an email, the user just needs to enter 5 and not worry about index number of the attachments array). row
and column
are the index of both the row and column on the targetSheet
data is initially pasted to that the user specified if they don't want the data to be pasted starting at row 1, column 1. I call the functions function1, function2, etc., because that was the way that I found it online, but if there is a different naming convention that would be superior, I am also open to hearing it.
My Request
I'm not a fan of just using if-else statements, as I know that there are other, better ways of doing this that I am currently not aware of. I tried using switch-case, but couldn't figure out how that could be an implemented properly, or even if it was an improvement. I think one of the issues is that attachmentNumber
is causing issues as a parameter in functions 2 and 3. Any advice would be appreciated, and I can provide further details as necessary
My Code
function emailAttachment() {
var function1 = function(emailSubject, targetSheet){
let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(targetSheet)
let data = emailAttachmentRetrieval(emailSubject, 1)
ss.getRange(1, 1, data.length, data[0].length).clear().setValues(data)
}
var function2 = function(emailSubject, targetSheet, attachmentNumber){
if(attachmentNumber < 1){
throw new Error('Attachment number cannot be less than 1')
} else{
let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(targetSheet)
let data = emailAttachmentRetrieval(emailSubject, attachmentNumber)
ss.getRange(1, 1, data.length, data[0].length).clear().setValues(data)
}
}
var function3 = function(emailSubject, targetSheet, row, column){
if(row < 1 || column < 1){
throw new Error('Row and column number cannot be less than 1')
} else{
let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(targetSheet)
let data = emailAttachmentRetrieval(emailSubject, 1)
ss.getRange(row, column, data.length, data[0].length).clear().setValues(data)
}
}
var function4 = function(emailSubject, targetSheet, attachmentNumber, row, column){
if(attachmentNumber < 1){
throw new Error('Attachment number cannot be less than 1')
} else if(row < 1 || column < 1){
throw new Error('Row and column number cannot be less than 1')
} else{
let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(targetSheet)
let data = emailAttachmentRetrieval(emailSubject, attachmentNumber)
ss.getRange(row, column, data.length, data[0].length).clear().setValues(data)
}
try{
if(arguments.length === 2){
function1(arguments[0], arguments[1])
} else if(arguments.length === 3){
function2(arguments[0], arguments[1], arguments[2])
} else if(arguments.length === 4){
function3(arguments[0], arguments[1], arguments[2], arguments[3])
} else if(arguments.length === 5){
function4(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4])
}
} catch(e){
Logger.log(e)
}
}
My Attempt at Improving It:
function emailAttachment1(emailSubject, targetSheet, attachmentNumber, row, column) {
let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(targetSheet)
if(attachmentNumber === null && row === null && column === null){
let data = emailAttachmentRetrieval(emailSubject, 1)
ss.getRange(1,1,data.length, data[0].length).clear().setValues(data)
} else if(row === null && column === null){
if(attachmentNumber < 1){
attachmentError()
} else{
let data = emailAttachmentRetrieval(emailSubject, attachmentNumber)
ss.getRange(1,1,data.length,data[0].length).clear().setValues(data)
}
} else if(attachmentNumber === null){
if(row < 1 || column < 1){
rowColumnError()
} else{
let data = emailAttachmentRetrieval(emailSubject, 1)
ss.getRange(row, column, data.length, data[0].length).clear().setValues(data)
}
} else{
if(attachmentNumber < 1){
attachmentError()
} else if(row < 1 && column < 1){
rowColumnError()
} else{
let data = emailAttachmentRetrieval(emailSubject, attachmentNumber)
ss.getRange(row, column, data.length, data[0].length).clear().setValues(data)
}
}
}
Other Relevant Code:
function emailAttachmentRetrieval(emailSubject, attachmentNumber){
var msgs = GmailApp.getMessagesForThreads(GmailApp.search('subject: ' + emailSubject,0,1))
for (var i = 0 ; i < msgs.length; i++) {
for (var j = 0; j < msgs[i].length; j++) {
var attachments = msgs[i][j].getAttachments()
}
}
if(attachmentNumber < attachments.length){
throw new Error('attachment number is outside the scope of the attachments array')
} else{
var convertedSpreadsheetId = Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS}, attachments[attachmentNumber-1]).id
var data = SpreadsheetApp.openById(convertedSpreadsheetId).getSheets()[0].getDataRange().getValues()
Drive.Files.remove(convertedSpreadsheetId)
}
return data
}
function attachmentError(){
throw new Error('Attachment number cannot be less than 1')
}
function rowColumnError(){
throw new Error('Row and column number cannot be less than 1')
}