My code works great, all it does is take events from a spreadsheet and creates them on google calendar.
However, one of the columns in my spreadsheet contains a formula. Everytime I run the code, the formula disappears and is replaced by whatever is on that cell at the time.
I know this is where the issue is:
// Record all event IDs to spreadsheet except for row 7
range.setValues(data);
How can you write a loop to only apply this from row[0] to row[8] but skipping row [7]?
But here is the full code for reference:
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];
sheet.addMenu("Update Calendar", entries);
}
//Export events from spreadsheet to calendar//
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "calendar_ID";
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[0]); // First column
var title = row[1]; // Second column
var tstart = new Date(row[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[3]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[4];
var desc = row[5];
var complete = row[6];
var status = row[7];
var id = row[8]; // Eight column == eventId
// Check if event already exists, update it if it does
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:"("+status+") "+desc,location:loc}).getId();
row[8] = newEvent; // Update the data array with event ID
}
else {
event.setTitle(title);
event.setDescription("("+status+") "+desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
// Record all event IDs to spreadsheet except for row 7
range.setValues(data);
}
There is no way to write "selectively" using setValues... I suggest you splice your array (vertically) in 2 new arrays and write it with 2 different setValues, leaving the formula's column untouched.
Note that the splice array method splices horizontally (for a 2D array) so you'll have to loop into the first level and do the splicing for each row but working with arrays is very fast so it won't be an issue.
example code :(I took data from a sheet to demonstrate)
function spliceVertically() {
var data = SpreadsheetApp.getActive().getActiveSheet().getDataRange().getValues();
Logger.log('data = '+JSON.stringify(data));
var data1 = [];
var data2 = [];
for(var n in data){
data2.push(data[n].splice(7,1));// cut the row at col 8 and keep 1
data1.push(data[n].splice(0,6));// cut at 0 and keep 6 , this method cut the array >> get data2 before data1
}
Logger.log('data1 = '+JSON.stringify(data1));
Logger.log('data2 = '+JSON.stringify(data2));
}
EDIT :
to insert it in your code simply use it like this :
sh.getRange(1,1,data1.length,data1[0].length).setValues(data1);// update col 1 to 6
sh.getRange(1,8,data2.length,data2[0].length).setValues(data2);// update col 8
Btw, you can also use slice method ... below is a complete test with sheet update :
function spliceVertically() {
var sh = SpreadsheetApp.getActive().getActiveSheet();
var range = sh.getDataRange();
var data = range.getValues();
Logger.log('data = '+JSON.stringify(data));
var data1 = [];
var data2 = [];
for(var n in data){
data1.push(data[n].slice(0,8));
data2.push(data[n].slice(9,10));
}
Logger.log('data1 = '+JSON.stringify(data1));
Logger.log('data2 = '+JSON.stringify(data2));
sh.getRange(1,1,data1.length,data1[0].length).setValues(data1);
sh.getRange(1,10,data2.length,data2[0].length).setValues(data2);
}
final edit : full code implemented in yours
since it seems you didn't get it working, below is a full implementation. tested on this sheet
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];
sheet.addMenu("Update Calendar", entries);
}
//Export events from spreadsheet to calendar//
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "h22nevo15tm0nojb6ul4hu7ft8#group.calendar.google.com"; //removed link on purpose
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[0]); // First column
var title = row[1]; // Second column
var tstart = new Date(row[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[3]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[4];
var desc = row[5];
var complete = row[6];
var status = row[7];
var id = row[8]; // Eight column == eventId
// Check if event already exists, update it if it does
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:"("+status+") "+desc,location:loc}).getId();
row[8] = newEvent; // Update the data array with event ID
}
else {
event.setTitle(title);
event.setDescription("("+status+") "+desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
data[i]=row;// update data with row values otherwise it is lost !
}
Logger.log(data);
var data1 = [];
var data2 = [];
for(var n in data){
data1.push(data[n].slice(0,8));
data2.push(data[n].slice(8,9));
}
Logger.log('data1 = '+JSON.stringify(data1));
Logger.log('data2 = '+JSON.stringify(data2));
sheet.getRange(1,1,data1.length,data1[0].length).setValues(data1); // write below to check where it writes !!!
sheet.getRange(1,9,data2.length,data2[0].length).setValues(data2); // change row6 to 1 whan copying in real code !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Record all event IDs to spreadsheet except for row 7
}
Related
I try to use a script from Create Google Calendar Events from Spreadsheet but prevent duplicates, however I can't make it work. It seems to me that there is a problem with the date format, though I use the standard one in my spreadsheet.
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];
sheet.addMenu("Calendar Actions", entries);
};
/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "YOUR_CALENDAR_ID";
var cal = CalendarApp.getCalendarById(calId);
for (i=0; i<data.length; i++) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[0]); // First column
var title = row[1]; // Second column
var tstart = new Date(row[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[3]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[4];
var desc = row[5];
var id = row[6]; // Sixth column == eventId
// Check if event already exists, update it if it does
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
row[6] = newEvent; // Update the data array with event ID
}
else {
event.setTitle(title);
event.setDescription(desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
// Record all event IDs to spreadsheet
range.setValues(data);
}
Please, could you have a look what is wrong (my spreadsheet: https://docs.google.com/spreadsheets/d/1OIZLOjG5cg32EbV-bI5c2qDWtbhbggDTTobPK_dYfyQ/edit?usp=sharing). The script works but there is no result in my Google Calendar.
I thought that when I saw your showing script, date.getYear() might be required to be modified to date.getFullYear(). I thought that this might be the reason for your current issue of The script works but there is no result in my Google Calendar..
And, in your script, var date = new Date(row[0]), var tstart = new Date(row[2]) and var tstop = new Date(row[3]) might be written as var date = row[0], var tstart = row[2] and var tstop = row[3]. Because the cell values are the date object. So, how about the following modification?
From:
var date = new Date(row[0]); // First column
var title = row[1]; // Second column
var tstart = new Date(row[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[3]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
To:
var date = row[0];
var title = row[1];
var tstart = row[2];
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getFullYear());
var tstop = row[3];
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getFullYear());
Note:
In the case of var event = cal.getEventSeriesById(id);, I think that even when id is empty and the invalid value, no error occurs. So, try - catch might not be required to be used.
Reference:
getFullYear()
I have created a basic Google sheet where staff will log meetings and then be able to export them to the google calendar.
The problem is that I have staff based in the US and in different timezones. I tried changing the spreadsheet settings but the timezones in Google seem a little unreliable (Pacific Time showing as GMT-8 when it is currently -7)...
I tried hardcoding the time difference as follows:
var tstart = new Date(tstart1.getTime() + 420 * 60000)
Now this works, except when it pushes the time past midnight. At this point it gets confused and states that end time must be later than start time. I guess therefore it is not pushing the date forward.
How can I stop this error occurring?
The rest of the code:
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];
sheet.addMenu("Calendar Actions", entries);
};
/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
// var calId = sheet.getRange("H2:H2").getValue();
var calId = "********";
var cal = CalendarApp.getCalendarById(calId);
for (i=0; i<data.length; i++) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[1]); // First column
var title = row[2]; // Second column
var initial = row[0];
var city = row[3];
var concatTitle = initial + " - " + title + ", " + city;
var tstart1 = new Date(row[4]);
var tstart = new Date(tstart1.getTime() + 420 * 60000)
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
//var tstop = new Date(row[4]);
var tstop = new Date(tstart.getTime() + row[5] * 60000);
// Logger.log(new Date(tstart.getTime() + 65 * 60000))
// var tstop = new Date(tstart + row[4]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[6];
var desc = row[7];
var id = row[8]; // Sixth column == eventId
// Check if event already exists, update it if it does
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(concatTitle, tstart, tstop, {description:desc,location:loc}).getId();
row[8] = newEvent; // Update the data array with event ID
}
else {
event.setTitle(concatTitle);
event.setDescription(desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
// Record all event IDs to spreadsheet
range.setValues(data);
}
I have attempted to create a google script that will create calendar events based on information within cells in google sheets. I have gotten to the point where everything is labeled and marked, but an error is occuring that states:
TypeError: Cannot find function createEvent in object Calendar. (line 18, file "Code")
Here is the code I have written:
function calInsert() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 25; // Number of rows to process
var dataRange = sheet.getRange(startRow, 2, numRows, 9);
var data = dataRange.getValues();
var cal = CalendarApp.getCalendarsByName( "EC Calendar" );
for (i in data) {
var row = data[i];
var title = row[1]; // First column
var tstart = row[2]; // Second column
var tstop = row[3];
var desc = row[4];
var loc = row[5];
var cmmail = row[6];
var leamail = row[7];
var event = cal.createEvent(title, new Date(tstart), new Date(tstop), {description:desc,location:loc,guests:cmmail,guests:leamail});
}
}
Any help you can provide would be appreciated.
var cal = CalendarApp.getCalendarsByName("EC Calendar");
This gives you an array of calendars with that name. Change this to:
var cal = CalendarApp.getCalendarsByName("EC Calendar")[0]; //Gets the correct calendar
This gives you the first Calendar with the name. I tried the below code:
function calInsert() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
var data = dataRange.getValues();
var cal = CalendarApp.getCalendarsByName( "calendar ID" )[0];
for (i in data) {
var row = data[i];
var title = row[0]; // First column
var tstart = row[2]; // Second column
var tstop = row[3];
Logger.log(tstop);
var desc = row[1];
var loc = row[4];
//var cmmail = row[6];
//var leamail = row[7];
cal.createEvent(title, new Date(tstart), new Date(tstop), {description:desc,location:loc});
}
}
I am able to create event in my calendar. If needed, you can send cmmail and leamail to createEvent.
I am trying to export events from google sheet to google calender using code I found Here
I have updated it to fit my sheet but the stock code replaced formulas in cells with the value, rendering the sheet useless. I tried replacing the last line
range.setValues(data);
with
range.setFormulas(data);
but this just made all cells blank.
Is there away to use the .setValues to just set the Id?
Coppy of my code forgot to add it
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];
sheet.addMenu("Calendar Actions", entries);
};
/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getValues();
var calId = "abeaqo4gf3of7u64sa8uufulpc#group.calendar.google.com";
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[21]); // First column
var title = row[22]; // Second column
var tstart = new Date(row[23]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[24]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[25];
var desc = row[26];
var id = row[27]; // Sixth column == eventId
var tep = row[28];
if (i > tep) continue;
// Check if event already exists, update it if it does
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
row[27] = newEvent; // Update the data array with event ID
}
else {
event.setTitle(title);
event.setDescription(desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
// Record all event IDs to spreadsheet
}
Instead of setting all the data outside the for loop, you can get the particular cell (where you want to update the event id) using range and set the value to that cell in each row.
Here is the code. you can just change the row and column values accordingly:
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
Logger.log(range.getLastRow());
var data = range.getValues();
Logger.log(data);
var calId = "your calendar id";
var cal = CalendarApp.getCalendarById(calId);
for (i in data) {
if (i < headerRows) continue; // Skip header row(s)
var row = data[i];
var date = new Date(row[0]); // First column
var title = row[1]; // Second column
var tstart = new Date(row[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(row[3]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[4];
var desc = row[5];
var id = row[6]; // Sixth column == eventId
// Check if event already exists, update it if it does
var event = cal.getEventSeriesById(id);
//Logger.log(id);
range = SpreadsheetApp.getActiveSheet().getRange(i, 6);
if (!event) {
var newEvent = cal.createEvent(title, tstart, tstop,{description:desc,location:loc}).getId();
//row[6] = newEvent; // Update the data array with event ID
range.setValue(newEvent);
}
else {
event.setTitle(title);
event.setDescription(desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
range.setValue(event.getId());
}
//sheet.getRange(i,6).setValue(newEvent);
}
}
I created a script that can update the Google Calender from Google Spreadsheet.My Spreadsheet is like
|A | B | C | ------ |AS|AT|AU|
in my code
function getRows(){
var data = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var sheet = SpreadsheetApp.getActiveSheet();
var date = new Date(data[44][1]);
var calId = "**************#group.calendar.google.com";
var cal = CalendarApp.getCalendarById(calId);
var range = sheet.getDataRange();
for (j=0,i=3;i<15;i++,j++) {
var title=data[44][i];
var tstart = new Date(data[9][i]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date(data[9][i+1]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var desc="adkd";
var loc="akskd";
var id = data[44][26+j];
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
}
if (!event) {
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
data[44][26+j] = newEvent;
}
else {
event.setTitle(title);
event.setDescription(desc);
event.setLocation(loc);
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
range.setValues(data);
}
}
In this i am getting an error as
Incorrect range width was 27 but should be 24
i increased the column numbers.But still i am getting this error.
instead of range.setValues(data); you should try
sheet.getRange(1,1,data.length,data[0].length).setValues(data);
so you'll be sure that the range has the right size (at least if data is homogeneous (same number of columns in each row)
EDIT
Here is a script to "normalize your output array so that it can be used as value in setValues().
In this example I push values 'Z' to see it more easily in the logger (for demo) but of course you should replace the 'Z' with '' so that it only adds empty cells.
I join a test function and the Logger result below.
function test(){
var array = [['xx','xx'],['xx','xx','xx'],['xx','xx','xx','xx','xx'],['xx','xx','xx','xx','xx','xx','xx']];
Logger.log('array '+JSON.stringify(array)+'\n becomes '+JSON.stringify(arrayNormalize(array)));
}
function arrayNormalize(array) {
var lenMax = 0;
for(var n in array){
if(array[n].length>lenMax){lenMax = array[n].length };
}
Logger.log('max array width = '+lenMax);
for(var n in array){
while(array[n].length<lenMax){
array[n].push('Z');
};
}
return array;
}
use this function as follows in your code :
var newData = arrayNormalize(data);
sheet.getRange(1,1,newData.length,newData[0].length).setValues(newData);