How can I sync different, MULTIPLE calendars from ONE google sheet? - google-sheets

I would like to sync / update different calendars (bonus points for iCal but appreciate it will likely have to be Google Cal) for different clients from one google sheet
From this sheet:
https://docs.google.com/spreadsheets/d/1f6qUjGYHZtRRGCbyh5oNzM7o64B-wlkrTpB1ac64I2U/edit#gid=0
I would like info from columns C, D, E, F, G to input into a calendar entry / sync with respective calendars for clients A, B and C from column B according to the date in A
So for client A on date 06-01-2017 the following information would be added as an all day event:
Event: ABC
Location: ABC, DEF, GHI
Capacity: 5000
Seated Cap: 100
Link: www.google.com/abc
Client B on date 08-02-2017 the following would be added to Client B's calendar (but not Client A's etc)
Event: ABC
Location: ABC, DEF, GHI
Capacity: 2500
Seated Cap: 200
Link: www.google.com/abd
And as you can see there are multiple entries for the respective clients and their calendars
I have successfully got singular calendar working according to the following link but need an "if / then" specification and don't know where it goes or what code to use:
https://cloud.google.com/blog/products/g-suite/g-suite-pro-tip-how-to-automatically-add-a-schedule-from-google-sheets-into-calendar

You need to maintain a mapping of client to calendar ID somewhere so that each time you process an event row you can do:
var clientEventCal = CalendarApp.getCalendarById(clientCalendarId);
to make sure you're adding the event to the right calendar.
Note: If you share the Apps Script code you're using to create events to a single calendar using your spreadsheet structure, I can provide specific instructions on the exact changes to make!
For the sake of outlining a complete solution, let's assume you create a new sheet named "Client Calendars" containing Client or Project in column A and that client's Google Calendar ID in column B.
After you create this new client-to-client calendar ID table, you have a few options of how to use it:
Option A: Read the table directly in your code at runtime and look up the right Calendar ID to use in Apps Script code.
Option B: Add a new column to your main data sheet that uses each row's Client column value to populate the calendar ID directly onto your source data row using VLOOKUP.
(B) is probably easier, as it will require less Apps Script code modification.
A:
function createAllDayEvent(calendarId, eventName, date, location, description) {
var eventCal = CalendarApp.getCalendarById(calendarId);
var event = eventCal.createAllDayEvent(eventName, date, date, {location: location, description: description});
return event;
}
function createClientEvents(event) {
var sheet = event ? event.source.getSheets()[0] : SpreadsheetApp.getActiveSheet();
var startRow = 4;
var dataRange = sheet.getRange('A' + startRow.toString() + ':G');
var data = dataRange.getDisplayValues();
var clientCalendarSheet = ss.getSheetByName('Client Calendars');
var clientCalendarData = clientCalendarSheet.getDataRange().getValues();
// Date (Entry) | Client / Project | Event | Location | Capacity | Seated Cap | Link
var dateStr, client, eventName, location, capacity, seatedCap, link;
for (var i = startRow - 1; i < data.length; i++) {
[dateStr, client, eventName, location, capacity, seatedCap, link] = data[i];
if (!eventName) continue;
var calendarId = null;
for (var j = 0; j < clientCalendarData.length; j++) {
if (clientCalendarData[i][0] == client) {
calendarId = clientCalendarData[i][1];
break;
}
}
var date = new Date(dateStr);
var description = "Capacity: " + capacity + ", Seated Cap: " + seatedCap + ", Link: " + link;
createAllDayEvent(calendarId, eventName, date, location, description);
}
}
B:
This solution assumes data sheet column M contains client's Calendar ID (you could populate M using =IF($B4="",, VLOOKUP($B4, 'Client Calendars'!$A:$B, 2, FALSE)) assuming you've created the "Client Calendars" sheet as outlined above).
function createAllDayEvent(calendarId, eventName, date, location, description) {
var eventCal = CalendarApp.getCalendarById(calendarId);
var event = eventCal.createAllDayEvent(eventName, date, date, {location: location, description: description});
return event;
}
function createClientEvents(event) {
var sheet = event ? event.source.getSheets()[0] : SpreadsheetApp.getActiveSheet();
var startRow = 4;
var dataRange = sheet.getRange('A' + startRow.toString() + ':G');
var data = dataRange.getDisplayValues();
var calendarIdColumn = sheet.getRange('M' + startRow.toString() + ':M').getValues();
// Date (Entry) | Client / Project | Event | Location | Capacity | Seated Cap | Link
var dateStr, client, eventName, location, capacity, seatedCap, link;
for (var i = startRow - 1; i < data.length; i++) {
[dateStr, client, eventName, location, capacity, seatedCap, link] = data[i];
if (!eventName) continue;
var calendarId = calendarIdColumn[i][0];
var date = new Date(dateStr);
var description = "Capacity: " + capacity + ", Seated Cap: " + seatedCap + ", Link: " + link;
createAllDayEvent(calendarId, eventName, date, location, description);
}
}

Related

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;
}
}
}

getRange variable range

I am trying to use a google sheet to rank a list of elements. This list is continually updated, so it can be troublesome to update the list if i already have hundreds of elements ranked and need to rank 10 new ones. Rather than having to re-rank some of the previously ranked elements every time (whether manually or using formulas), i thought it easier to write a macro that would re-rank for me.
1 - element A
2 - element B
3 - element C
new element: element D
For instance if i wanted element D to be ranked 2nd, i would need to change element B to 3 and element C to 4. This is tedious when doing hundreds of elements.
Here is my code so far but I get stuck with the getRange lines. Rankings are in column A.
function RankElements() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var r = s.getActiveCell();
var v1 = r.getValue();
var v2 = v1 + 1
var v3 = v2 + 1
var lastRow = s.getLastRow();
s.getRange(1,v2).setValue(v2);
s.getRange(1,v3).autoFill(s.getRange(1,v3+":"+1,lastRow), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
s.getRange(1,v3+":"+1,lastRow).copyTo(s.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
s.getFilter().sort(1, true);
};
You can do the following:
Iterate through all values in column A.
For each value, check if (1) ranking is equal or below the new one, and (2) it's not the element that is being added.
If both these conditions are met, add 1 to the current ranking.
It could be something like this:
function RankElements() {
const sheet = SpreadsheetApp.getActiveSheet();
const cell = sheet.getActiveCell();
const row = cell.getRow();
const newRanking = sheet.getActiveCell().getValue();
const firstRow = 2;
const columnA = sheet.getRange(firstRow, 1, sheet.getLastRow() - 1).getValues()
.map(row => row[0]); // Retrieve column A values
for (let i = 0; i < columnA.length; i++) { // Iterate through column A values
if (columnA[i] >= newRanking && (i + firstRow) != row) {
sheet.getRange(firstRow + i, 1).setValue(columnA[i] + 1); // Add 1 to ranking
}
}
sheet.getFilter().sort(1, true);
};

How to parse Gmail messages to extract data to Google Sheets

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)
}

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();
}

Combine two Google spreadsheet together and keep it sync

I have two sheet from others and wish to create another one which combine both sheet together.
e.g.
SheetA:
Name value
A 10
B 20
SheetB:
Name value
C 30
D 40
Then I want to create one SheetC:
Name value
A 10
B 20
C 30
D 40
And if I change SheetC, I wish data synced to SheetA or SheetB automatically.
I can implement the doc combine with below script:
function runme() {
var docA = "<Doc Id A>";
var docB = "<Doc Id B>";
var sheetName = "Sheet1";
appendSheet(docA,sheetName);
appendSheet(docB,sheetName);
}
function appendSheet(docId,sheetName) {
var sourceSpread = SpreadsheetApp.openById(docId);
var sourceSheet = sourceSpread.getSheetByName(sheetName)
var activeSpread = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = activeSpread.getActiveSheet();
var activeSheetName = activeSheet.getSheetName();
sourceRng = sourceSheet.getDataRange();
sourceRows = sourceRng.getValues(),
activeSheet.appendRow(sourceRows[0]);
for (i = 1; i < sourceRows.length; i += 1) {
activeSheet.appendRow(sourceRows[i]);
}
Logger.log("total: " + i);
}
But it seems it's difficult to sync information from docC to docA and docB.

Resources