Import Data from Gmail into Google Spreadsheet - regex

I have an email sent out on a daily basis that I need to pull data from to a Google Sheet. I have read on this and found a solution that worked for other's, but I've been unable to get it to work on mine. This is the code I've tried modifying:
function menu(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Macros')
.addItem('parse mail', 'email')
.addToUi();
}
function parseMail(body) {
var a=[];
var keystr="First Name : ,Last Name : ,Customer ID : ,Invoice : ";
var keys=keystr.split(",");
var i,p,r;
for (i in keys) {
p=keys[i]+"\n([a-zA-Z0-9\ \,\.]*)\n";
r=new RegExp(p,"m");
try {a[i]=body.match(p)[1];}
catch (err) {a[i]="no match";}
}
}
function email() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var threads = GmailApp.search('subject: "Fwd: ARB Subscription*"');
var a=[];
for (var i = 0; i < threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j = 0; j < messages.length; j++) {
a[j]=parseMail(messages[j].getPlainBody());
}
}
var nextRow=s.getDataRange().getLastRow()+1;
var numRows=a.length;
var numCols=a.length[0];
s.getRange(nextRow,1,numRows,numCols).setValues(a);
}
I've tried modifying the code, but the error I am getting is Cannot convert Array to Object[][] Line 35. any advice would be greatly appreciated

Get the dimensions of the data range as below.
Also, when you are setting the values on the range the size of two-dimensional array a must match the size of the range.
var dataRange = s.getDataRange();
var nextRow = dataRange.getLastRow() + 1;
var numRows = dataRange.getNumRows();
var numCols = dataRange.getNumColumns();
s.getRange(nextRow,1,numRows,numCols).setValues(a);

Related

How do I get an alert prompt when an "if" statement returns no 'finds' in Google Apps Script?

//Invoice find and transfer to Warehouse Sheet
function searchInvoiceWhSh() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var shUserForm = ss.getSheetByName("Warehouse Form")
var shSalesSheet = ss.getSheetByName("Sales")
var sValue = shUserForm.getRange("G5").getValue();
var sData = shSalesSheet.getDataRange().getValues();
var currentRow = 9
for (var i=0; i<sData.length; i++) {
var row = sData[i];
if (row[0] == sValue) { //do something}
currentRow += 2
}}
I've used this to search for an "Invoice number" from the "Sales" worksheet and when found to transfer the data back to the user form.
If, for example, the invoice number is typed incorrectly into the "sValue" cell, then no data will be transferred.
How do I code a prompt message to ask the user to check the invoice number as no records were found?
Try:
function searchInvoiceWhSh() {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const shUserForm = ss.getSheetByName("Warehouse Form")
const shSalesSheet = ss.getSheetByName("Sales")
const sValue = shUserForm.getRange("G5").getValue()
const sData = shSalesSheet.getDataRange().getValues()
const targetData = sData.filter(row => row[0] === sValue)
if (targetData.length) {
// Value(s) found
targetData.forEach(row => {
Logger.log(row)
})
} else {
SpreadsheetApp.getUi().alert(`No match found.`)
}
}
This will search for the sValue provided as in your code, but will store the row in a variable once found. If it's not found, it will create an alert pop-up with your specified message.
Alternatively, you can check out UI Class for other pop-up options.
Try it like this:
function myfunk() {
var ss = SpreadsheetApp.getActive()
var fsh = ss.getSheetByName("Warehouse Form")
var ssh = ss.getSheetByName("Sales")
var fv = fsh.getRange("G5").getValue();
var svs = ssh.getDataRange().getValues();
let m = 0;
svs.forEach((r, i) => {
if (r[0] == fv) {
m++;
}
SpreadsheetApp.getUi().alert(`${m} matches found`)
});
}
Always provides a result

Making a list using api in google sheets

I am attempting to pull faction information from torns api but it puts all data into a single cell rather than listing. heres what ive got so far.
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Faction members')
.addItem('Pulls faction member info','callNumbers')
.addToUi();
}
function callNumbers() {
var response = UrlFetchApp.fetch("https://api.torn.com/faction/42911?selections=basic&key=xFtPCG2ygjbhmKWI");
Logger.log(response.getContentText());
var fact = response.getContentText();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1,2).setValue([fact]);
}```
You could try to parse the information using JSON.parse. Something like:
function callNumbers() {
var response = UrlFetchApp.fetch("https://api.torn.com/faction/42911?selections=basic&key=xFtPCG2ygjbhmKWI");
Logger.log(response.getContentText());
var fact = response.getContentText();
var myObject = JSON.parse(fact);
// define an array of all the object keys
var headerRow = Object.keys(myObject);
// define an array of all the object values
var row = headerRow.map(function(key){ return myObject[key]});
// define the contents of the range
var contents = [
headerRow,
row
];
// select the range and set its values
var ss = SpreadsheetApp.getActive();
var rng = ss.getActiveSheet().getRange(1, 1, contents.length, headerRow.length )
rng.setValues(contents)
}

Issues with textfinder and IF

I have a piece of code that was scrounged together from another code that is known working. What it does is searches a column using textfinder for a value, in this case, yesterday's date, if nothing is found, it should send an email.
function findAndSendMail() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('FormResponses');
var ss2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('AlertDate');
var search = ss2.getRange("B2").getValue(); //cell has yesterday's date
var lastRow = ss.getLastRow();
var range = ss.getRange(1,4,lastRow); //define range for column D, column D contains dates
//find all occurrences of search key in column D and push range to array
var ranges = range.createTextFinder(search).findAll();
if (ranges!==null) {
var message = '';
}else {
var message = 'Test';
}
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("EmailGroup").getRange("A1");
var emailAddress = emailRange.getValues();
var subject = 'Subject';
var link = "blahblahblah"
if (message) {
MailApp.sendEmail(emailAddress, subject, '**This is an automated message**\n\n' + message + '\n\n**This is an automated message**\n' + link);
}
}
As you see, it should search column D, then, if it finds something, the message variable will be blank, else if it finds nothing, it will send an email to the email addresses chosen. I'm not sure how the results from a textfinder work with this and I think the way it is written is incorrect. Any help is appreciated, unfortunately, I cannot share the document in question as my company doesn't allow sharing outside of the domain. Thank you!
Try this:
You will need to update the sheet names I moved them to end of the line comments
function findAndSendMail() {
var ss=SpreadsheetApp.getActive()
var sh1=ss.getSheetByName('Sheet1');//FormResponses
var sh2=ss.getSheetByName('Sheet2');//AlertDate
var d1=new Date(sh2.getRange("B2").getValue()); //cell has yesterday's date
var d2=new Date(d1.getFullYear(),d1.getMonth(),d1.getDate()).valueOf();
var rg1 = sh1.getRange(1,4,sh1.getLastRow(),1);
var vA=rg1.getValues().map(function(r){
var dt=new Date(r[0]);
var dtv=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
return dtv;
});
if(vA.indexOf(d2)==-1) {
var message='test';
var emailAddress = ss.getSheetByName("Sheet3").getRange("A1").getValue();//EmailGroup
var subject = 'Subject';
var link = "blahblahblah"
}
if (message) {
MailApp.sendEmail(emailAddress, subject, '**This is an automated message**\n\n' + message + '\n\n**This is an automated message**\n' + link);
//SpreadsheetApp.getUi().alert('I found something');//just for testing
}
}
This version sends an email if yesterday is not found.
In answer to you last question:
function findAndSendMail() {
var ss=SpreadsheetApp.getActive()
var sh1=ss.getSheetByName('Sheet1');//FormResponses
var sh2=ss.getSheetByName('Sheet2');//AlertDate
var d1=new Date(sh2.getRange("B2").getValue()); //cell has yesterday's date
if(isDate(d1)) {
var d2=new Date(d1.getFullYear(),d1.getMonth(),d1.getDate()).valueOf();
var rg1 = sh1.getRange(1,4,sh1.getLastRow(),1);
var vA=rg1.getValues().map(function(r){
var dt=new Date(r[0]);
var dtv=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
return dtv;
});
if(vA.indexOf(d2)==-1) {
var message='test';
var emailAddress = ss.getSheetByName("Sheet3").getRange("A1").getValue();//EmailGroup
var subject = 'Subject';
var link = "blahblahblah"
}
if (message) {
MailApp.sendEmail(emailAddress, subject, '**This is an automated message**\n\n' + message + '\n\n**This is an automated message**\n' + link);
//SpreadsheetApp.getUi().alert('I found something');//just for testing
}
}else{
SpreadsheetApp.getUi().alert('Data is sheet2!B2 is not a date')
return;
}
}
function isDate(date){
return(Object.prototype.toString.call(date) === '[object Date]');
}

Replacing Google Doc text with Spreadsheet Data using RegEx

I am making a merge code to take data from my spreadsheet and populate merge tags in a Google Doc. The part of the code I am unable to write correctly is the part that writes the tags back to the Google Doc. I have been able to locate the tags but the code doesn't replace them.
Here is what I've written so far.
function mergeApplication() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Merge Data");
var range = sheet.getActiveRange();
var formSheet = ss.getSheetByName("Form Responses");
var lastRow = formSheet.getLastRow();
var lastColumn = sheet.getMaxColumns();
function checkAndComplete() {
var urlColumn = lastColumn;
var checkColumn = (urlColumn - 1);
var checkRange = sheet.getRange(2, checkColumn, (lastRow - 1), 1);
var check = checkRange.getBackgrounds();
var red = "#ff0404";
var yellow = "#ffec0a";
var green = "#3bec3b";
for (var i = 0; i < check.length; i++) {
if (check[i] == green) {
continue;
} else {
var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
var dataRow = sheet.getRange((i+2), 1, 1, (lastColumn - 2));
function mergeTasks() {
function docCreator() {
// var templateConditionRange = sheet.getRange((i+2), column);
// var templateConditionCheck = templateConditionRange.getValues();
var docTemplate1 = DriveApp.getFileById(id);
// var docTemplate2 = DriveApp.getFileById(id);
// var docTemplate3 = DriveApp.getFileById(id);
var folderDestination = DriveApp.getFolderById(id);
var clientName = sheet.getRange((i+2), 3).getValue();
var date = sheet.getRange((i+2), 1).getValue();
// if (templateConditionCheck[i] == "") {
var docToUse = docTemplate1;
// }
// if (templateConditionCheck[i] == "") {
// var docToUse = docTemplate2;
// }
// if (templateConditionCheck[i] == "") {
// var docToUse = docTemplate3;
// }
var docName = "Merge Tester Doc for " + clientName + " [" + date + "]";
var docCopy = docToUse.makeCopy(docName, folderDestination);
var docId = docCopy.getId();
var docURL = DriveApp.getFileById(docId).getUrl();
var docToSend = DriveApp.getFileById(docId);
var docBody = DocumentApp.openById(docId).getBody().getText();
function tagReplace() {
var taggedArray = [docBody.match(/\<{2}[\w\d\S]+\>{2}/g)];
var headerArray = [sheet.getRange(1, 1, 1, (lastColumn - 2)).getValues()];
var dataArray = [dataRow.getValues()];
var strippedArray = [];
Logger.log("The preliminary length of taggedArray is " + taggedArray.length);
Logger.log(taggedArray);
function tagStrip() {
for (var t = 0; t < taggedArray.length; t++) {
var strippedString = taggedArray[t].slice(2, -3).toString();
strippedArray.push(strippedString);
Logger.log("The current strippedArray length is " + strippedArray.length);
}
Logger.log("The final strippedArray length is " + strippedArray.length);
Logger.log("The final taggedArray length is " + taggedArray.length);
Logger.log("The final, completed strippedArray is " + strippedArray);
}
function dataMatch() {
for (var s = 0; s < strippedArray.length;) {
for (var h = 0; h < headerArray.length;) {
if (strippedArray[s] == headerArray[h]) {
docBody.replaceText(taggedArray[s].String(), dataArray[h].String());
h=0;
s++;
} else {
h++;
}
}
}
}
tagStrip;
dataMatch;
}
function emailCreator() {
var emailTag = sheet.getRange((i+2), (urlColumn - 2)).getValue();
var emailBody = HtmlService.createHtmlOutputFromFile("Email Template").getContent();
var personalizers = clientName + " [" + date + "]";
var subject = "Merge Tester Email for " + personalizers;
MailApp.sendEmail(emailTag, subject, emailBody, {
name: "Christopher Anderson",
attachments: [docToSend],
html: emailBody,
});
}
tagReplace();
statusCell.setBackground(yellow);
emailCreator();
urlCell.setValue(docURL)
}
statusCell.setBackground(red);
docCreator();
statusCell.setBackground(green);
}
mergeTasks();
}
}
}
checkAndComplete();
}
The problem section is here:
function tagReplace() {
var taggedArray = [docBody.match(/\<{2}[\w\d\S]+\>{2}/g)];
var headerArray = [sheet.getRange(1, 1, 1, (lastColumn - 2)).getValues()];
var dataArray = [dataRow.getValues()];
var strippedArray = new Array();
Logger.log("The preliminary length of taggedArray is " + taggedArray.length);
Logger.log(taggedArray);
function tagStrip() {
for (var t = 0; t < taggedArray.length; t++) {
var strippedString = taggedArray[t].slice(2, -3).toString();
strippedArray.push(strippedString);
Logger.log("The current strippedArray length is " + strippedArray.length);
}
Logger.log("The final strippedArray length is " + strippedArray.length);
Logger.log("The final taggedArray length is " + taggedArray.length);
Logger.log("The final, completed strippedArray is " + strippedArray);
}
function dataMatch() {
for (var s = 0; s < strippedArray.length;) {
for (var h = 0; h < headerArray.length;) {
if (strippedArray[s] == headerArray[h]) {
docBody.replaceText(taggedArray[s].String(), dataArray[h].String());
h=0;
s++;
} else {
h++;
}
}
}
}
tagStrip;
dataMatch;
}
It doesn't even log anything having to do with strippedArray.
It seems to be skipping over that section entirely.
Am I using the correct method of completing this task and/or is there a simpler way of doing it?
It's worth mentioning that my tags in the doc have 2 "<>" around them. That's the reason for my RegEx looking how it does.
Also, when logging the .length of taggedArray, it returns a value of 1.
You never actually call tagStrip which is supposed to work on strippedArray.
You declare it with function tagStrip(){} and later you reference the function with tagStrip; but you never actually call it. The same is happening with dataMatch.
Try calling the two functions by writing
tagStrip();
dataMatch();
If you don't include the parentheses you don't call it you just run the function Objects as statements.
Here is a portion of code I use in my add-on Simply Send, I use the same <<>> merge tags.
//copy template
var mDocDrive = doc.makeCopy(title, folder);
var mDoc = DocumentApp.openById(mDocDrive.getId());
var mDocDriveApp = DriveApp.getFileById(mDoc.getId());
var docToAttach = mDoc.getUrl();
var driveToShare = mDocDriveApp;
// replace text inside template
var body = mDoc.getBody();
body.replaceText("<<SS Title>>", title);
body.replaceText("<<timestamp>>", lastR.timestamp);
body.replaceText("<<username>>", lastR.email);
for (i in lastR.theResponses){
var cur = lastR.theResponses[i];
var name = cur.title;
name = name.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); // this will allow fields that include special characters.
var response = cur.response;
var searchPattern = "<<"+name+">>";
body.replaceText(searchPattern, response);
}
// this will replace any unused tags with nothing.
var ques = getQuestionList();
for (j in ques){
var curq = ques[j].name;
curq = curq.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
var searchPattern2 = "<<"+curq+">>";
body.replaceText(searchPattern2, "");
}
mDoc.saveAndClose();
//create pdf
if (mmDefaults.shareAs == "pdf"){
// uncomment if you want to make the pdf in the merge folder
var asPdf = mDoc.getAs('application/pdf');
asPdf.setName(mDoc.getName()+ ".pdf");
var pdf = DriveApp.createFile(asPdf);
folder.addFile(pdf);
DriveApp.removeFile(pdf);
mDocDriveApp.setTrashed(true);
var docToAttach = pdf;
driveToShare = pdf;
}

Tweet in Action Script 3 loading

I am new to ActionScript 3 and got the following question:
I am trying to rebuild a AS3 code to load my Tweets to my website. In the original file I got a link to a XML file that gets the link of my tweets. But I want to make the connection without the XML file. So in my AS3 code I want to make the link to my tweets
Can someone help me with this to make the link in my AS3 code?
This is my current AS3 file with a settingsLoader to my settings.xml. Can someone tell me what to change and were I need to place my link?
import flash.net.URLLoader;
import flash.net.URLRequest;
import com.adobe.serialization.json.JSON;
import flash.errors.IOError;
import flash.events.IOErrorEvent;
stop();
var myXML:XML;
var settingsLoader:URLLoader = new URLLoader();
var twitterUrl:String="";
var tweetNumber:int=0;
var myData:Object;
var oldData:Object;
var tweets:Object;
var myLoader:URLLoader=new URLLoader();
var rnd=new Array;
var oldXML:XML;
var newTweet:String="";
var arrTweets=new Array;
var totalTweets:int=0;
settingsLoader.load(new URLRequest("settings.xml"));
settingsLoader.addEventListener(Event.COMPLETE,processSettings);
function processSettings(e:Event):void{
myXML=new XML(e.target.data);
twitterUrl=myXML.twitUrl;
myLoader.load(new URLRequest(twitterUrl));
myLoader.addEventListener(Event.COMPLETE,processJSON);
}
function processJSON(e:Event):void{
myData=JSON.decode(e.target.data);
if(myData.success){
sortTweets(myData.data);
}
}
function sortTweets(jData:Object){
tweets=jData;
rnd=between(0,myData.count-1);
totalTweets=myData.count;
trace(rnd);
for(var j=0;j<=myData.count-1;j++){
var tmpMessage=tweets[rnd[j]].text;
var tmp="";
tmp=tmpMessage.split(" ");
newTweet="";
for(var i:int = 0;i<tmp.length;i++){
if(tmp[i].substring(0,1)==="#"){
tmp[i]="<font color='#EA1111'>"+tmp[i]+"</font>";
newTweet+=tmp[i]+" ";
}else if((tmp[i].substring(0,4)==="http")||(tmp[i].substring(0,3)==="www")){
//niets doen
}else{
newTweet+=tmp[i]+" ";
}
}
var tweet:Object=new Object;
tweet.tHandle="#"+tweets[rnd[j]].senderScreenName;
tweet.tMessage=newTweet;
arrTweets.push(tweet);
}
for(var k:int = 0;k<arrTweets.length;k++){
trace(arrTweets[k].tHandle);
}
play();
}
function between(startNumber:int, endNumber:int):Array{
var baseNumber:Array = new Array();
var randNumber:Array = new Array();
for(var i:int =startNumber; i<=endNumber; i++){
baseNumber[i] = i;
}
for(i=endNumber; i>startNumber; i--){
var tempRandom:Number = startNumber + Math.floor(Math.random()*(i - startNumber));
randNumber[i] = baseNumber[tempRandom];
baseNumber[tempRandom] = baseNumber[i];
}
randNumber[startNumber] = baseNumber[startNumber];
return randNumber;
}
//niet meer nodig
function processLocalSettings(e:IOErrorEvent):void{
settingsLoader.load(new URLRequest("settings.xml"));
settingsLoader.addEventListener(Event.COMPLETE,processSettings);
}