How to createEvent based on form submit? - google-apps-script

A question I've seen a few times on the major coding support fora, how to add an event to a calendar based on a form submit. Nevertheless, I'm struggling.
Timestamp form
Date
name
startTime
endTime
descr
25/05/2021 13:05:05
=to_date(A2)
Meeting
15:05:00
15:42:00
garden
The event would always take place on the date of the form submit. Nothing seems to come of the following code.
var spreadsheet = SpreadsheetApp.getActive().getSheetByName("Form1");
var data = spreadsheet.getRange("A2:F").getValues();
function toCal() {
let [, date, name, startTime, endTime, descr] = data;
var calen = CalendarApp.getCalendarById("examplecal#group.calendar.google.com");
calen.createEvent(name,
new Date(date + startTime),
new Date(date + endTime),
{location: "Brandenburger Tor", description: descr});
}
}
The event just needs to be based on the last submission, so I can put it on a "on form submit" trigger.
I think the trouble comes from the date time. However if I just put in new Date("25/05/2021 15:05:00") instead of a the current thing, nothing appears in my calendar as well.
Any help would be appreciated.

Format B2 to 2021-05-25
and try:
function toCal() {
var spreadsheet = SpreadsheetApp.getActive().getSheetByName("Form1");
var data = spreadsheet.getRange("A2:F2").getDisplayValues();
start = new Date(data[0][1] + " " + data[0][3]);
end = new Date(data[0][1] + " " + data[0][4]);
var calen = CalendarApp.getCalendarById("examplecal#group.calendar.google.com");
calen.createEvent(data[0][2], start, end,
{location: "Brandenburger Tor", description: data[0][5]});
}

Related

How to trigger google sheets function on specific cell change (or triggered by time)

I'm trying to trigger a function (send email) when a cell changes on sheets.
At present, my code looks like this.
function RealtimeFeedbackdue() {
var remainingHoursRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("F5");
var remainingHours = remainingHoursRange.getValue();
var studentNameRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("B1");
var studentName = studentNameRange.getValue();
// Check total hours
if (remainingHours < 6){
// Fetch the email address
var emailAddressRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("B5");
var emailAddress = emailAddressRange.getValue();
var emailAddressRange2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("B6");
var emailAddress2 = emailAddressRange2.getValue();
// Send Alert Email for teacher.
var message = studentName + ' has ' + remainingHours + ' hours left of their course. This means their realtime feedback report is due. ' +
'This is an automatically generated email.' ;
var subject = 'Realtime feedback report due for ' + studentName;
MailApp.sendEmail(emailAddress, subject, message);
// Send Alert Email for course consultant.
var message2 = studentName + ' has ' + remainingHours + ' hours left of their course. Their teacher will be completing the realtime feedback report this week. Please speak to them regarding course renewal etc. This is an automatically generated email.' ;
var subject2 = 'Private student ' + studentName + ' has nearly completed their hours';
MailApp.sendEmail(emailAddress2, subject2, message2);
}
}
I would settle for having a weekly trigger but I can't work out how to program that either. I've tried this.
function RealtimeFeedbackdue() {
ScriptApp.newTrigger('RealtimeFeedbackdue')
.timeBased()
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.atHour(9)
.create();
var remainingHoursRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("F5");
var remainingHours = remainingHoursRange.getValue();
var studentNameRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("B1");
var studentName = studentNameRange.getValue();
// Check total hours
if (remainingHours < 6) {
// Fetch the email address
var emailAddressRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("B5");
var emailAddress = emailAddressRange.getValue();
var emailAddressRange2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Attendance").getRange("B6");
var emailAddress2 = emailAddressRange2.getValue();
// Send Alert Email for teacher.
var message = studentName + ' has ' + remainingHours + ' hours left of their course. This means their realtime feedback report is due. ' +
'This is an automatically generated email.';
var subject = 'Realtime feedback report due for ' + studentName;
MailApp.sendEmail(emailAddress, subject, message);
// Send Alert Email for course consultant.
var message2 = studentName + ' has ' + remainingHours + ' hours left of their course. Their teacher will be completing the realtime feedback report this week. Please speak to them regarding course renewal etc. This is an automatically generated email.';
var subject2 = 'Private student ' + studentName + ' has nearly completed their hours';
MailApp.sendEmail(emailAddress2, subject2, message2);
}
}
}
Since you want to trigger the execution of the function based on an edit of the cell, the most appropriate trigger in this situation is the onEdit one.
Therefore, you can use something similar to this:
Snippet
function onEdit(e){
var row = e.range.getRow();
var col = e.range.getColumn();
var sheet = e.range.getSheet();
if (sheet.getName() == 'NAME_OF_THE_SHEET' && row == NUMBER_OF_ROW && col == NUMBER_OF_COL)
// if the edit was made in the wanted cell
// add the instructions here
}
Explanation
The above function makes use of the e event in object in order to get the data needed about the edited cell.
Snippet 2
However, you can also use a time-based trigger, but this won't have anything to do with the edited cell - it will just trigger every Monday at the time you chose.
function theTimeTrigger() {
ScriptApp.newTrigger('RealtimeFeedbackdue')
.timeBased()
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.atHour(9)
.create();
}
Explanation
For this, a new function was needed in order to create the time-based trigger and associate it to the function you already have.
Create triggers from the UI
You can also create triggers using the Apps Script's UI. This can be done by clicking this icon which will redirect you to the current project's triggers.
Afterwards, you can click this button in order to create a new trigger and you customize it in the way you want.
Reference
I also suggest you to take a look at these links below since they might be of help to you in your future development.
Event Objects Apps Script;
Installable Triggers Apps Script;
ClockTriggerBuilder Class Apps Script.

Export all events from a shared calendar, including events added by non-owners

I'm trying to extract Google Calendar event data into a spreadsheet, which works. However, the code I use only exports data which has been created by the owner of the Google Account/Calendar, not events that have been added by other users.
Below is a sample of some of the code I am using to get to the calendar and to retrieve events details.
Is there any way of achieving the above with details added by all users..?
var cal = CalendarApp.getCalendarById("name of calendar");
var events = cal.getEvents(new Date("18/08/2018 12:00 AM"), new Date("30/08/2018 12:00 AM"))
Edit:
Further to my original post, this may help..
Thanks for the replies so far... I'm not entirely sure what is going on in the code that has just been quoted, my full function is below. It may also help too if I give the practical example of what I'm trying to do.
A warehouse moves in /out a number of pallets each day. Details of these various in/outs are added as events on the "in" and "out" calendars. One calendar for each type of operation. Details are only entered into the "Title" section (e.g. PO numbers, etc.) and a time given. I had the idea of putting the number of pallets into the "Description" section so that when we extract events into a spreadsheet, we get a count of pallets in and out, each day, hour, etc.
function goodsin() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var cal = CalendarApp.getCalendarById("name of calendar");
var events = cal.getEvents(new Date("18/08/2018 12:00 AM"), new Date("30/08/2018 12:00 AM"));
for (var i = 0; i < events.length; i++) {
var title = events[i].getTitle();
var sd = events[i].getStartTime();
var ed = events[i].getEndTime();
var des = events[i].getDescription();
ss.getRange(i+2, 1).setValue(title)
ss.getRange(i+2, 2).setValue(sd);
ss.getRange(i+2, 2).setNumberFormat("dd/mm/yyyy h:mm:ss AM/PM")
ss.getRange(i+2, 3).setValue(ed);
ss.getRange(i+2, 3).setNumberFormat("dd/mm/yyyy h:mm:ss AM/PM")
ss.getRange(i+2, 4).setValue(des);
}
}
I can't reproduce your issue.
Events in "default" calendars
Using account A, I created an event on its default calendar, and invited account B. Account B has not accepted the invitation.
From account B, if I run the following code, I get the event information in my Stackdriver logs:
function getNextEvent_(calendars) {
if (!calendars)
calendars = CalendarApp.getAllCalendars();
const now = new Date();
const end = new Date();
return calendars.map(function (cal) {
var weeks = 4;
end.setTime(now.getTime());
do {
end.setDate(end.getDate() + 7)
var e = cal.getEvents(now, end, {max: 1}).pop();
} while (!e && --weeks);
return cal.getName() + ': ' +
(!e
? 'No visible events up to ' + end.toLocaleString()
: e.getTitle() + ' (Org. by ' + e.getCreators().join(',') + ')'
);
});
}
function logNextEvents() {
console.log({
message: "Upcoming Events",
events: getNextEvent_()
});
}
If I dig deeper, the event is found for the default calendar of Account B, i.e. CalendarApp.getDefaultCalendar().getEvents(...) contains the event owned and organized by Account A.
Events in a shared calendar
Setup:
Account A makes a new Google Calendar.
Account B is added with the permission to make changes to events.
Account C is added with the permission to make changes to events.
All accounts create an event on the calendar (3 events created).
Code:
function querySharedCal() {
const id = 'notarealgroupid#group.calendar.google.com';
const cal = CalendarApp.getCalendarById(id);
if (!cal) throw new Error("no calendar");
const now = new Date();
const end = new Date();
end.setDate(end.getDate() + 4);
const events = cal.getEvents(now, end).map(function (e) {
return cal.getName() + ': ' + e.getTitle() +
' (Org. by ' + e.getCreators().join(',') + ')';
});
console.log({message:"search result by " + Session.getTemporaryActiveUserKey(), events: events});
}
Cases:
Account A runs the above code
Account B runs the above code
Account C runs the above code
Results:
All cases return the 3 events. Even if each of the accounts a, b, c writes their own code (rather than having a single project which each can execute), all queries are successful.
Perhaps there is something you aren't sharing with us regarding the permission levels of the calendar, the accounts that create the events, the event visibilities, and the account from which you perform the queries.

Google Apps Script - Creating Calendar Events with Appointment Color

So I have a script that creates calendar events just fine, I am now trying to have the appointment color red without success. What is the best way to do this? Here is a portion of the code that I am currently using.
Here is the revised code that is now working!
function createCalendarEvent(eventObject) {
//Get a calendar object by opening the calendar using the
//calendar id stored in the GLOBAL variable object
//var startTime = eventObject.startDate+" "+eventObject.startTime
//var endTime = eventObject.endDate+" "+eventObject.endTime
var calendar = CalendarApp.getCalendarById(GLOBAL.calendarId),
//The title for the event that will be created
title = eventObject.eventTitle,
//The start time and date of the event that will be created
startTime1 = moment(eventObject.startDate+" "+eventObject.startTime).toDate(),
//The end time and date of the event that will be created ---moved up
APLength = eventObject.AppLength1;
//an options object containing the description and guest list
//for the event that will be created
var comboDescription = title+" in "+ eventObject.county +" is interested in a "+eventObject.deckStyle+". The referral source was "+eventObject.referral+". "+" Their email address is "+eventObject.Cemail+"."+" They can be reached at "+eventObject.phone1+" "+eventObject.phone2+" "+eventObject.Gdescription+" "+eventObject.Qdescription;
var options = {
description : comboDescription,
guests: eventObject.Cemail,
location: eventObject.location,
};
if(APLength=="1 hour") {var endTime1 = moment(eventObject.startDate+" "+eventObject.startTime).add(1, 'h').toDate()};
if(APLength=="2 hour") {var endTime1 = moment(eventObject.startDate+" "+eventObject.startTime).add(2, 'h').toDate()};
//////Send a reminder email
//MailApp.sendEmail ("-----------", "New Appointment with "+title, "I have added the following information to your calender. The appointment range is "+moment(startTime1).format("dddd, MMM Do YYYY, h:mm:ss a")+" till "+ moment(endTime1).format("dddd, MMM Do YYYY, h:mm:ss a")+" See the following appointment details....."+comboDescription);
try {
//create a calendar event with given title, start time,
//end time, and description and guests stored in an
//options argument
//calendarEvent.setColor(11);
//eventObject.colorId: 11
var event = calendar.createEvent(title, startTime1, endTime1, options)
event.setColor("11")
//var event = Calendar.Events.insert(title, startTime1, endTime1, options)
//CalendarApp.event.setColor("10")
} catch (e) {
//delete the guest property from the options variable,
//as an invalid email address with cause this method to
//throw an error.
delete options.guests
//create the event without including the guest
//var eventObject.colorId = 11
//var event = calendar.createEvent(title, startTime1, endTime1, options)
var event = calendar.createEvent(title, startTime1, endTime1, options)
event.setColor("11")
//CalendarApp.event.setColor("10")
//var event = calendarEvent.setColor(11);
//colorId: Red
}
return event;
}
Does calendarEvent.setColor not work for you?
https://developers.google.com/apps-script/reference/calendar/calendar-event#setColor(String)
In your code above, have you tried adding:
event.setColor(CalendarEvent.EventColor.RED)?

Google Forms Script Editor to send emails based on answer

I use a Google Form to track employee hours and jobs completed for a mechanical services small business. The guys want to be able to get an email of their responses to track their own hours and ensure they put everything in correctly. I don't want them to have to enter their email every time or log in - they complete this on their phones and want to keep it as simple and less repetitive as possible.
I've looked on a lot of places around here and have (what I think) is the basis of a good code in Google Script Editor. I had it working to send an automated email, but when I added the information in the message it didn't work. I used some other examples out there and tried to put a few together to make it work. I'd appreciate any help critiquing this code and helping me figure out why it isn't working. I'm new to this and can't seem to figure it out. Thanks.
function EmailTimeSheetCMS(e){
var name = e.values [1];
var ReplyEmail = "__________#yahoo.com"
var Email1 = "__________#gmail.com"
var WorkOrder = e.values[2];
var date = e.values[3];
var location = e.values[4];
var jobdescription = e.values[5];
var notes = e.values[6];
var vendors = e.values[7];
var starttime = e.values[8];
var endtime = e.values[9];
var otherworkers = e.values[10]
var status = e.values [11];
var reghrs = e.values[12];
var othrs = e.values[13];
var tools = e.values[15];
var message = "You entered the following information" + "\nDate " + date + "\nWork Order # " + WorkOrder + "\nLocation " + location + "\nStart Time" + starttime + "\nEnd Time " + endtime + "\nRegular Hours worked" + reghrs + "\nOvertime Hours " + othrs + "\nJob Description " + jobdescription + "\nNotes " + notes + "\nVendors and Invoices " + vendors + "\nOther Workers Present " + otherworkers + "\nTools Used " + tools + "\nJob Status " + status ;
if(name = 'Bill')
{MailApp.sendEmail(Email1, ReplyEmail, "CMS Time Submission - Bill", message) }
else if(name = 'Scott')
{MailApp.sendEmail(ReplyEmail, ReplyEmail, "CMS Time Submission - Scott", message)
} }
On a first glance I see a potential flaw.
In the if condition i.e when you say
if (name = 'Bill')
it assigns 'Bill' to the variable name.
could you try writing it as
if(name == 'Bill')
and see if it works.
And when posting a question next time, it is always a good practice to enter the error message you get. Or at least the 'Execution transcript' available under the View in menu bar

Google app script - how to count number of google form response

It is my first time writing google app script and I am desperately need help.
The purpose is to set up a workshop sign up form. Based on how many people already signed up, an email is sent out to inform if sign up was successful, or was put in the wait list.
I copied code from a tutorial. But need help to get the count of form responses. Here is how it looks like now:
function onFormSubmit(e) {
var timestamp = e.values[0];
var yourName = e.values[1];
var toAddress = e.values[2];
var subject = "Workshop Confirmation";
var emailBody = "Thank you for your submitted on " + timestamp
var num_response = COUNT_NUMBER_OF_RESPONSE // <-- need help here
var LIMIT = 15
if (num_response <= LIMIT) {
emailBody = emailBody + "\n\nYou are enrolled in the workshop";
}
else {
var wait = num_response - LIMIT
emailBody = emailBody + "\n\nThe workshop is full. You are #" + wait + " in the waiting list"
}
emailBody = emailBody + "\n\nThe details you entered were as follows: " +
"\nYour Name: " + yourName +
"\nYour Email: " + toAddress ;
MailApp.sendEmail(toAddress, subject,
emailBody, optAdvancedArgs);
}
I have no clue how to find right answer in the google app document. Any help would be greatly appreciated!
How about the composite function
FormApp.getActiveForm().getResponses().length
no need to go around looking for the spreadsheet (since in my experience, the spreadsheet is not always up to date, whereas the form is)
From what I see in the tutorial, this script is embedded in a spreadsheet so the easiest would be to count the number of rows and substract 1 because of the headers...
There is a method for that : getLastRow(), the doc refered in this link should give you enough information to write the few lines of code you need...
test :
function xx(){
var lr = SpreadsheetApp.getActiveSheet().getLastRow()-1;
Logger.log(lr);
}
Script on form (not spreadsheet)
function onFormSubmit(e) {
var num_response = FormApp.getActiveForm().getResponses().length
var LIMIT = 20 //or whatever
if (num_response < LIMIT) {
}
else {
var form = FormApp.getActiveForm();
form.setAcceptingResponses(false);
}
}