How to synchronize Google Calendar & Spreadsheet with Script - javascript

I am trying to create a Google Apps Script that keeps a Google Calendar and a "master spreadsheet" on Drive synchronized -- is this possible? I found these two posts:
http://blog.ouseful.info/2010/03/04/maintaining-google-calendars-from-a-google-spreadsheet/
http://blog.ouseful.info/2010/03/05/grabbing-google-calendar-event-details-into-a-spreadsheet/
I'm quite sure this could be done using a lot of if statements and logic, but maybe there's a simpler way?
I ended up just providing the following simple script. All that was really necessary was adding events based on two columns, and this would've taken too long to develop.
function onOpen() {
//spawns a menu with a button that triggers AddToCal
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Add event to calendar",
functionName : "AddToCal"
}];
sheet.addMenu("Data To Calendar Plugin", entries);
};
function AddToCal(){
//get the current row
var ss = SpreadsheetApp.getActiveSpreadsheet();
var cell = ss.getActiveCell();
var R = cell.getRow();
//grab values for current row to pass to calendar event
var date_of_event = ss.getRange('G'+R).getValue();
var date = new Date(date_of_event);
var event_title = ss.getRange('A'+R).getValue();
//access the calendar
var cal = CalendarApp.getCalendarById('[IDREMOVED]');
cal.createAllDayEvent(event_title,date);
ss.toast("Event added to " + cal.getName());
}

Yes, it's possible to write a two-way event synchronization script, but it isn't going to be simple. Those two posts you refer have parts that could be reused, but they are quite elementary compared to the challenges you'll face with actual synchronization. You may want to read over Using Google Apps Script for a event booking system which does create calendar entries based on a spreadsheet (but doesn't do on-going synchronization). I've done some debugging of that script in past.
Synchronization would need to support:
Creation of events in either location
Modification of event details in either location (although you could opt to consider only a subset of event details for simplification)
Deletion of events in either location
Recurrence, e.g. CalendarEvent.getEventSeries() handling (or choose to avoid)
This is pseudo-code that you could start with:
Open Calendar, Read Calendar events into calArray (will all attributes you care for)
Open Spreadsheet, Read Spreadsheet events into sheetArray
For each event in calArray:
Search for calEvent in sheetArray.
If found, compare lastUpdated values.
If equal, do nothing
Otherwise copy most recently updated to least recently updated
Continue with next event
If not found then copy calEvent to new sheetEvent, including lastUpdated value.
Continue with next event
For each event in the sheetArray (...that hasn't been handled yet)
Similar logic above.
Write updated sheetArray to spreadsheet.
Write updated calEvents to calendar API (see note 1 below)
Notes:
All updates to calEvents could be made to array and written to calendar API immediately, as an alternative to a bulk update. This would eliminate the need to track the changes locally, although it would be a good idea to touch the lastUpdated value.
You will want to use CalendarEvent.getLastUpdated() when reading calEvents, and store a similar value in your spreadsheet (tied to an onEdit trigger) to facilitate comparisons.
It would simplify comparisons to record CalendarEvent.getId() against events in the spreadsheet. You also have CalendarEvent.setTag(key,value) that could be used to record custom metadata into the calendar, for instance to indicate events that originated or have been synchronized with your spreadsheet. (These tags are not accessible through the GCal UI, so would only be accessible via script.)
You should think about the range of dates or number of events you want to deal with, and limit the scope of the script. If you don't, you are sure to run into execution time limits in real operation.
Some Calendar Event characteristics don't lend themselves to easy expression in a spreadsheet, for instance:
Guest list
Reminder list

As mentioned (thanks Henrique) in the other post I've spent some time - it was actually what brought me to GAS originally - on data exchange between spreadsheets and calendars mainly because people I worked with where used to organize their time schedule (for a highschool) in spreadsheets and I had to take care of the transition to Google Calendars.
After some time though it appeared that the online Calendar interface is far more effective to create events so they don't use the sheet to Calendar scripts anymore !!
On the other hand, the printing and presentation options in GCal are very limited so the other direction is still very useful and we use it all the time !
I know this will seem to be out of subject regarding the original question and maybe too anecdotic but I just wanted to point out that you should thoroughly think about what you really need before reinventing the wheel... As Mogsdad mentioned, some events parameter are not easily described in spreadsheet logic and finally it could become a lot more complicated to use than the original tool.
The only really useful tool I developed using bidirectional data transfer is a 'batch modification tool" when I need to delete or edit a big number of similar events.
For example if we need to change a teacher's name for some reason all along the year I import all the events for a number of class, replace the name in the spreadsheet and update back the class calendar... it takes me 5 minutes and is very easy but these are very specific use cases and I'm not sure it is very common.
Anyway I wouldn't call that "synchronization" since it only takes some events some time and changes them... I've never attempted to keep a spreadsheet up to date with a calendar, from my experience calendars are pretty reliable and I consider them as the original data source. As I already said, we import data in spreadsheets every week just for printing and local archiving.
Sorry for this long and a bit vague comment (that was way too long to fit in a normal 500 chrs comment ;-)

No there isn't. And although a lot of issues regarding Apps Script Calendar Service has been solved (timezones, all day events, queries and so on), it's still a fairly complex task.
I know Serge, the top contributor here in SO on #google-apps-script tag, has developed quite some scripts involving the Calendar Service.
But I don't know of anyway that made a two-way update between a calendar and a spreadsheet. It should be a hard one. If you ever do, please be kind to share :)

I wrote a script that synchronizes between GCalendar and a GSheet. You may be able to use it as is, or can certainly borrow ideas from it. There are separate commands for copying events each way: https://github.com/Davepar/gcalendarsync

Related

Google Apps Script Multiple users using same functions and javascript issues

I am looking for some advice on what to read up on. I am trying to make a webapp for my school that teachers can user for the school reward system. It is designed as a front end to a google sheets spreadsheet. The teachers log how many housepoints a child has earned in a lesson via a table with a column of text inputs (one for each child in the class) The webapp then adds these to the spreadsheet using the appendrow method.
I have one problem currently and need some advice on what I should do about another issue I can see on the horizon!
Current issue:
I have a javascript function that checks the housepoint values that have been added to each child collects a list of ids and the number of housepoints and sends these to google apps script as attributes of an object via a for loop.The apps script then strips the attributes and adds the data to a spreadsheet. The issue is as I understand it the apps script takes too long to append the rows and the javascript for loop does not wait for the apps script to catch up. The result is that it misses some of the data out and only appends a fraction of the rows it should do. Is there a way to get the javascript function to pause and wait for the app script to say its ready for the next object?
Potential issue: As this script is meant to be used by multiple teachers at the same time I am worried that if the same function (to add the housepoints to the spreadsheet) is called at the same time by different users what will the app script do? I would imagine it will collapse. I have tried to investigate what to do on this and have to say I do not understand what I am reading. What I really want is the app script to "park" each request in a cue and then chug through them at its own speed. Is this possible?
As you may have guessed I am not an experienced programmer, I am willing to read up and learn but just would like someone to point me in the right direction. Many thanks in advance for your time.

Send email programmatically

I wrote a custom function called sendEmails in a script linked to a google spreadsheet. It works when I run the function through the script editor, however, it does not work when I run it through the spreadsheet.
My goal is to let the spreadsheet run without having a user and send an alert (in my case an email) automatically when a condition is met on the spreadsheet's cells.
This is the not working code:
=if(V3=X3,sendEmails(),"Waiting")
The alert can be anything that I can read using my phone or another computer.
With custom functions you are limited by the kinds of services that you can use because custom functions never ask for authentication. https://developers.google.com/apps-script/guides/sheets/functions#using_apps_script_services
You could add your function to the add-on toolbar or setup an installable trigger to run the sendEmails() function.
Here is some more documentation to help you out.
https://developers.google.com/apps-script/guides/menus
https://developers.google.com/apps-script/guides/triggers/installable
Without a look at the full list of code, it's difficult to say. Two possibilities based on your single line of code.
1) It's not enough to say =if(V3==X3) and assume that if they become equal, they will trigger. You must specify for the spreadsheet when it should check if these are equal (For example, on spreadsheet edit, or at a specified time interval).
2) In your if statement, you are specifying that V3 SHOULD equal X3, not checking if it is. =if(V3==X3) or =if(V3===X3) resolves this.

Panes/Widget interaction

Good morning,
I am about to build a dashboard and I am evaluation the Freeboard product that from a first look really amaze me!
I have a couple of questions to which I could not find answers in the docs:
Is it foreseen any kind of cross-panes/widgets communication? e.g. in case i need to refresh a pane if the user interact with another. I found the freeboard.on() method but from the events' catalog I only see two events, relative to the Freeboard's instance. I couldn't find freeboard.trigger() or similar function to trigger custom event.
Is it AMD supported (RequireJS)?
Thank you very much for your time and your support.
Daniele
Git issue track
Cross widgets/panes communication is not available "out of the box" in freeboard.
There is a way to see the most current data for all datasources within any of the widgets by using the .JS Editor when connecting a widget to a datasource.
As per the help message in the editor: you can assume this .JS Editor is enclosed in a function of the form function(datasources) where datasources is a collection of objects (keyed by name) corresponding to the most current data for each datasource.
I hope this helps.

Time tracking parser

Moving on from the usual image processing script: I'm thinking of writing a Photoshop time tracking script that will log the filename, directory & time a file is created saved and closed. This is relatively easy with the Scripts Events manager.
The clever bit is writing a second script to parse this information so I clearly see what project I was working on on what day and for how long. The first part can be identified by files saved in certain directories. What's the best way forward to process the various time codes (created, saved & closed) to help me easily see the time tracked on a project?
Is this a trivial thing to do or am I opening a metaphorical can of worms here? Are there any standardised algorithms that may be of use to me?
If I understand correctly.. what you want is Logging..
A logging configuration will mainly consists of four parts.
Loggers
Handlers
Filters
Formatters
In short, a logger is mechanism for writing logs.. Each message that is written to a log is called a log record. A log record can contain metadata, and other informations to describes the event that is being logged. Theres also log level stuff which isnt important here..
After a log record has been recorded it is sent to a handler.
Handler : The handler is the engine that determines what happens to each message in a logger. It describes a particular logging behavior, such as writing a message to the screen, to a file etc.
Filters :
Self-explanatory. You can create filters to only view a specific criteria.
Formatters :
Same as the name says.. Formatting records in more readable way , List, Table , Graph.
Thats just a basic overview of the logging system.
As for your case, you mention that you can already use the exsisting tool to log the events. All you need to do is make a handler, that will interpret those logs and save in a file which can be parsed by the script engine.. csv, json
Something like :
projects : [ { "name" : "foo", " creation": "date",
"events" : [ {"action":"file-created", "timestamp":"date", " file":"sample"}]
},
"name":" bar".....
You need to tailor it to your needs.. Depending on your data and what you wanna do with it you need represent in the best way you can think of.
Then all thats is left to show the desired data in a way you want.. Thats a lot of scripting :0

Sharepoint - How to: dynamic Url for Note on Noteboard

I'm quite new to SharePoint (about 1 week into it actually) and I'm attempting to mirror certain functionality that my company has with other products. Currently I'm working on how to duplicate the tasking environment in Box.com. Essentially it's just an email link that goes to a webpage where users can view an image and comments related to that image side by side.
I can dynamically load the image based on url parameters using just Javascript so that part is not a problem. As far as the comments part goes I've been trying to use a Noteboard WebPart, and then my desire is to have the "Url for Note" property to change dependent on the same URL parameter. I've looked over the Javascript Object Model and Class Library on MSDN but the hierarchy seems to stop at WebPart so I'm not finding anything that will allow me to update the Url for Note property.
I've read comments saying that there's a lot of exploration involved with this so I've tried the following:
-loading the javascript files into VisualStudio to use intellisense for looking up functions and properties in the SP.js files.
-console.log() on: WebPartDefinitionCollection, WebPartDefinition, WebPart, and methods .get_objectData(), get_properties() on all the previous
-embedding script in the "Builder" on the Url for Note property (where it says "click to use Builder" - I'm still not sure what more this offers than just a bigger textbox to put in the URL path)
I'm certain I've missed something obvious here but am gaining information very slowly now that I've exhausted the usual suspects. I very much appreciate any more resources or information anyone has and am willing to accept that I may be approaching this incorrectly if someone has accomplished this before.
Normally I'd keep going through whatever info I could find but I'm currently on a trial period and start school back up again soon so I won't have as much time with it. Apologies if this seems impatient, I'm just not sure where else to look at the moment.
Did you check out the API libraries like SPServices or SharepointPlus? They could help you doing what you want...
For example with SharepointPlus you could:
Create a Sharepoint List with a "Note" column and whatever you need to record
When the user goes to the page with the image you just show a TEXTAREA input with a SAVE button
When the user hits the SAVE button it will save the Note to the related list using $SP().list("Your list").add()
And you can easily retrieve the information (to show them to the user if he goes back to the page) with $SP().list("Your list").get()
If I understood your problem, that way it may be easier for you to deal with a customized page :-)

Categories

Resources