How to parse Gmail messages to extract data to Google Sheets - parsing

I'm working on a R&D project where I collect my server side statistics using Linux commands and output the same to my mail. Now my plan is to read and parse the Gmail content which has my data of the server (as below) and extract it to Google Sheets. My Gmail content looks like below which has data in rows and columns.
Date&Time JVM PID CPU MEM FGC
03-09-2017-09-08-PM abc01_xzy01 12345 1.2% 2.75 3
03-09-2017-09-08-PM abc01_xzy01 12345 3.5% 2.71 4
03-09-2017-09-08-PM abc01_xzy01 12345 4.6% 2.79 5
My idea here is to pull exactly the same way into a Google Sheet. I'm using the below code but it's unable to read the content. I'm thinking if it's related to the RegExp used. Could you please tell me how exactly the code has to be written in the if statement.
function parseEmailMessages(start) {
start = start || 0;
var threads = GmailApp.getInboxThreads(start, 100);
var sheet = SpreadsheetApp.getActiveSheet();
for (var i = 0; i < threads.length; i++) {
var tmp,
message = threads[i].getMessages()[0],
// subject = message.getSubject(),
subject = "SERVER TEST REPORT",
content = message.getPlainBody();
if (content) {
tmp = content.match(/Date&Time:\s*([A-Za-z0-9\s]+)(\r?\n)/);
var username = (tmp && tmp[1]) ? tmp[1].trim() : 'No Date & Time';
tmp = content.match(/JVM:\s*([A-Za-z0-9\s]+)(\r?\n)/);
var username = (tmp && tmp[1]) ? tmp[1].trim() : 'No JVM';
sheet.appendRow([username, email, subject, comment]);
}
}
}
My output just prints No Date & Time and No JVM in the Google Sheets. I want to print the names and data in the columns and rows as given in the mail. Can someone please help me on this and tell me what is the mistake and how to pull the data like expected. Thanks in advance.

If all that is in your email is what you posted above, this will put it in your spreadsheet. Change the email subject and sheet name to suit your needs.
function getGmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var threads = GmailApp.search('IMPORTANT1', 0, 10);
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].getPlainBody();
var msg=msg.trim()
}
}
result1(msg)
}
function result1(range) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Sheet1")
var lr=sheet1.getLastRow()
var output=[]
var line=range.split("\n")
for(j=0;j<line.length;j++){
output.push(line[j].split(" "))
}
sheet1.getRange(lr+1, 1, output.length, output[0].length).setValues(output)
}

Related

Trying to send email from Google Sheet to Gmail. Tab name is Analysis

Need your help and expert guidance as I need my google sheet to send emails every time a condition becomes true in "K" column which is named "Subject" as a header in the tab name "Analysis". Whenever I run the below code. Similarly last 3 lines I get while running the code as errors. Please explain in a simple possible way and not too much technical
function sendEmail(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Analysis");
var range = ss.getRange("J2:J35");
range.clear();
var n = ss.getLastRow();
for (var i = 2;i<n+1; i++){
var emailRequired = ss.getRange(i,9).getValue();
var subject = ss.getRange(i,11).getvalue();
var message = ss.getRange(i,12).getvalue();
if (emailRequired=="YES"){
MailApp.sendEmail("ksm272364#gmail.com",subject,message);
ss.getRange(i,10).setvalue("YES");
}
}
}
1:21:51 PM Error
TypeError: ss.getRange(...).getvalue is not a function
sendEmail # Code.gs:8

getactive() function returning to null and defaulting to first sheet

I am trying to have my function use three sheets within its embedded spreadsheet: two fixed sheets and one active/open sheet. I need it to read the sheet I have open because that is the sheet I am changing week to week, but it is automatically defaulting to using the first sheet rather than the sheet I have opened. I altered this function from an existing function I have that works, and on this new one I only changed the message and its assigned variables. I really know absolutely nothing about coding but have been learning so I can create a custom message from a code a previous coworker wrote. I appreciate all of the help I can get x10000
function createMessage(address, dirtrider, day, window, outby, phone) {
{ var message = 'Hello ' + address + ', welcome to IVCC\'s composting program! You\'ll be receiving weekly automated reports from this number (a weekly reminder to put your bucket out and a notification if any incorrect items were discarded into your bucket). To stop receiving these messages, reply STOP. We are currently restructuring our biking routes, therefore you may be receieving a new Dirtrider according to this message. Starting next week, you\'re assigned Dirtrider will be ' + dirtrider + ', and you\'re new bucket will arrive weekly on ' + day + '\'s sometime between ' + window + '. Please have your bucket outside your front door by ' + outby + ' on this day weekly unless notified of a change. This is an automated messaging service, so please reach out to your Dirtrider directly at ' + phone + ' with any questions or concerns about your service. Thanks for composting with us! -IVCC Team';
}
return message;
}
// function to verify numbers and messages before sending //
function PrintMessages() {
var mainsheet = SpreadsheetApp.getActiveSheet();
var data = mainsheet.getDataRange().getValues();
var contactsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Contact Sheet");
var contacts = contactsheet.getDataRange().getValues();
var messageLog_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Message Log");
var messageLog = messageLog_sheet.getDataRange().getValues;
var mLrow = 2 //row to start at on Message Log spreadsheet
// runs through every row of active spreadsheet, i = row //
for (var i = 2; i < data.length; i++) {
// set variables based on values in sheet and create message//
var address = data[i][0];
var day = data[i][1];
var window = data[i][2];
var outby = data[i][3];
var dirtrider = data[i][4]
var phone = data[i][5]
var message = createMessage(address, dirtrider, day, window, outby, phone);
// reference seperate contact sheet, j = column //
var nresidents = contacts[i][2];
for (var j = 1; j <= nresidents; j++) {
// log address, phone number, and message function //
var address = contacts[i][0];
var number = contacts[i][j+2];
var messageArray = [[address, number, message]];
var range = messageLog_sheet.getRange(mLrow, 1, 1, 3); //ENTER COMMENTS
range.setValues(messageArray);
var mLrow = mLrow + 1;
}
}
}

Google Script to Parse/Filter Data and Set Several sub SpreadSheets from master Spreadsheet

I have a master spreadsheet with several drivers and their routes for the day. This needs to be parsed out to several driver sheets. I have one sheet with all the data in the master and another with all the drivers names and spreadsheet ids to run a loop through for all drivers listed. Just runs...no action. Last three comments need to be fixed as well as it errors here and does not like .openById.
function setRoutes(){
var ScheduleSheetURL = "https://docs.google.com/spreadsheets/...";
var ActiveSpreadSheet = SpreadsheetApp.openByUrl(ScheduleSheetURL);
var AllRoutesSheetName = "RoutesIn";
var ActiveSheet = ActiveSpreadSheet.setActiveSheet(ActiveSpreadSheet.getSheetByName(AllRoutesSheetName));
var AllRouteData = ActiveSheet.getRange('A:AZ').getValues();
ActiveSheet = SpreadsheetApp.setActiveSheet(ActiveSpreadSheet.getSheetByName("Drivers"));
//var ActiveDriverCounter = ActiveSheet.getRange("A1:A").getValues();
//var DriverCount = ActiveDriverCounter.filter(String).length;
var DriverCount = ActiveSheet.getLastRow()-1;
var idrvSheetID = "";
var ActiveDriverName = "";
var RouteData = [];
var i = 1;
for (i = 1; i++; i <= DriverCount){
//Get Route Name
ActiveSpreadSheet = SpreadsheetApp.openByUrl(ScheduleSheetURL);
ActiveSheet = ActiveSpreadSheet.setActiveSheet(ActiveSpreadSheet.getSheetByName("Drivers"));
ActiveDriverName = ActiveSheet.getRange(i,1).getValue();
Logger.log(ActiveDriverName);
//Get Drivers Route
ActiveSheet = ActiveSpreadSheet.setActiveSheet(ActiveSpreadSheet.getSheetByName(AllRoutesSheetName));
for (var i = 0; i< AllRouteData.length; i++){
if(AllRouteData[i][1] == ActiveDriverName){
RouteData.push(AllRouteData[i])
Logger.log(RouteData[i]);
}
}
ActiveSpreadSheet = SpreadsheetApp.openByUrl(ScheduleSheetURL);
//Open & Write Driver Sheet
ActiveSheet = SpreadsheetApp.setActiveSheet(ActiveSpreadSheet.getSheetByName("Drivers"));
idrvSheetID = ActiveSheet.getRange(i,2).getValue();
// ActiveSpreadSheet = SpreadsheetApp.openById(idrvSheetID);
// ActiveSheet = ActiveSpreadSheet.setActiveSheet(ActiveSpreadSheet.getSheets()[0]);
// ActiveSheet.getRange(ActiveSheet.getLastRow()+1,1,RouteData.length,RouteData[0].length).setValues(RouteData);
}
}
Issues:
There are several problems with your script:
Every time you want to work on a spreadsheet or sheet, you are using some variant of setActive. I guess you are under the assumption that you need to "activate" a sheet in order to work on it, but that's not true! If you remove all this, your code can be minimized considerably.
You are not defining the outer for loop correctly: for (i = 1; i++; i <= DriverCount){. Second parameter should be the condition, and third one should be what to do at the end of each loop iteration. You have it the other way around.
When trying to filter the routes according to the Driver (if(AllRouteData[i][1] == ActiveDriverName){), you are not specifying the correct array index (arrays are 0-indexed, so 1 here would refer to column B, which doesn't contain the driver's names, so the script won't find any match there.
You are reusing the same loop counter variable (i) in a nested loop (for (var i = 0; i< AllRouteData.length; i++){). This will mess with your outer loop.
Solution:
Considering all these, I've wrote a small script that accomplishes your purpose. I have changed some of the variables names so that they are more meaningful (please check inline comments):
function setRoutes() {
const ScheduleSheetURL = "YOUR-MAIN-SPREADSHEET-URL"; // Change to your spreadsheet URL
const SourceSpreadSheet = SpreadsheetApp.openByUrl(ScheduleSheetURL);
const RoutesSheet = SourceSpreadSheet.getSheetByName("RoutesIn");
const AllRouteData = RoutesSheet.getRange('A:AZ').getValues();
const DriversSheet = SourceSpreadSheet.getSheetByName("Drivers");
const DriverCount = DriversSheet.getLastRow()-1;
const DriversData = DriversSheet.getRange(2, 1, DriverCount, 2).getValues(); // Get all Drivers data
for (let i = 0; i < DriversData.length; i++) { // Loop through all Drivers data
const DriverData = DriversData[i]; // Specific Driver data
const DriverName = DriverData[0]; // Driver name (column A)
const DriverSpreadsheetId = DriverData[1]; // Driver spreadsheet ID (column B)
const DriverRoutes = AllRouteData.filter(routeData => routeData[0] === DriverName); //Filter routes according to driver
const DriverSpreadsheet = SpreadsheetApp.openById(DriverSpreadsheetId); // Get specific Driver spreadsheet
const DriverSheet = DriverSpreadsheet.getSheets()[0]; // Get first sheet in Driver spreadsheet
DriverSheet.getRange(DriverSheet.getLastRow() + 1, 1, DriverRoutes.length, DriverRoutes[0].length)
.setValues(DriverRoutes); // Add routes to driver spreadsheet
}
}

Zapier: BigCommerce to Google Sheet, New Row for Each Item

I have successfully linked my BigCommerce account to my Google Sheets (Drive) account so every time I receive a new order in my store the order is automatically exported into a Google Sheet. Unfortunately, an entire order is listed on one row with multiple items added into one cell. What I need is to have each product on its own row; for example, if someone orders three different products Zapier would create three new rows. This functionality exists when directly exporting orders from BigCommerce, but the "Zap" does not use the BigCommerce export function when pulling order information from my store to the Google Sheet.
I know this is a shot in the dark, but I am hoping someone might have a solution that I can implement. Thank you for your help!
I have created a script that perhaps could be used or modified, at least until you find if the process can be done within Zapier.
You can try the script in the following ss: https://docs.google.com/spreadsheets/d/1ggNYlLEeN3UYtZC_KlOGwpyII9CzOLKMnIOKIDrPJPM/edit?usp=sharing
The script assumes that orders arrive in the tab named Zapier. As things are set up, you would run the script through the Custom Menu.
If there are 2 orders or more, click the menu for each order.
The complete rows appear in the sheet FullList.
(if you want to play/try again, you will have to manually delete the rows in FullList once they are showing).
function processForNewOrders() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName('Zapier');
var destinationSheet = ss.getSheetByName('FullList');
var sourceValues = sourceSheet.getDataRange().getValues();
var destinationValues = destinationSheet.getDataRange().getValues();
var index = [];
destinationValues.forEach( function (x) {
index.push(x[0]);
})
var newOrders = [];
for (var y = sourceValues.length -1 ; y > 0 ; y --){
if(sourceValues[y][0].toString().indexOf('po_number') != -1 ) continue;
var i = index.indexOf(sourceValues[y][0]);
if(i != -1) break; // This readies only the fresh orders for processing
newOrders.push(sourceValues[y]);
}
Logger.log(newOrders)
for (var j = 0 ; j < newOrders.length ; j++){
var output = [];
var orderLine = newOrders[j];
Logger.log('orderLine = ' + orderLine);
var circuit = 0;
var items = 1
while (circuit < items){
var row = [];
for (var z = 0 ; z < orderLine.length; z++){
var cell = orderLine[z];
// Logger.log(cell);
var lines = cell.toString().split(',');
if(lines.length > 1) items = lines.length;
row.push(lines[circuit] ? lines[circuit] : lines[0]);
// Logger.log('row =' + row);
}
circuit ++;
Logger.log('circuit circuit circuit =' + circuit)
output.push(row);
}
}
Logger.log(output);
if(output != undefined)
destinationSheet.getRange(index.length+1,1,output.length,output[0].length).setValues(output);
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Custom Menu')
.addItem('Process new order', 'processForNewOrders')
.addToUi();
}

Sequence number for each different value in a colum

I have an Input column with a sequence of two different letters. As result I want to get something like on the picture. This formulas I will use with ARRAYFORMULA to get unlimited count of rows. To get BLOCK № I was trying to use =COUNTIFS($B$2:B2,"N") but it works only if I copy the formula manually down the column, but if I do:
=ARRAYFORMULA(COUNTIFS(($B$2):(B2:B),"N"))
It doesn't work.
How can I replicate the behavior of this function without needed to manually copy it?
I'd recommend writing a script to fill the Block Nos.
I'll assume the topmost letter begins at cell input!A4 and you want the Block Nos from cell input!C5 and below. Go to the menu bar of the spreadsheet and select Script Editor. Then write the following scripts:
//the main function
function writeBlocks() {
var sheet = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName('input');
var numRows = sheet.getLastRow();
var startRow = 4;
var inputCol = 1;
var outputCol = 3;
var block = 0;
//clear old Block Nos
sheet.getRange(startRow, outputCol, numRows - 3, 1)
.clearContent();
//recalculate LastRow in case there are fewer new inputs than old outputs
numRows = sheet.getLastRow();
//get input data
var input = sheet.getRange(startRow, inputCol, numRows - 3, 1)
.getValues;
//write output data
for (var i = 0; i < input.length; i++) {
block += input[i] == "N" ? 1 : 0;
sheet.getRange(startRow + i, outputCol)
.setValue(block);
}
}
//create new menu
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Calculate blocks", functionName: "writeBlocks"});
ss.addMenu("Custom functions", menuEntries);
}
Save it all, refresh the spreadsheet, and there should be a new option on the menu bar. When you select that option, it will clear the old Block Nos and generate new ones based on the current inputs. Hope this helps.

Resources