Task guide
Create Calendar events from Sheet rows
Turn rows on an Events tab into events on your Google Calendar. The script creates an event for each row that has no event ID yet, then writes the new ID back into the row so a later run skips it.
1 · Prepare
Put these pieces in place
- Create a Sheet tab named Events with headers in row 1.
- Put the event title in column A, the start in column B, the end in column C, and leave column D empty for the event ID.
- Format the start and end cells as a date with a time. Select them, then choose Format, Number, Date time. A cell holding plain text cannot be read as a date.
- Run the script from an account whose main Google Calendar should get these events. Only one person should run it at a time. Wait for each run to finish, and do not edit or sort the rows while it runs.
Change these values
- Sheet tab name
EventsThis must match the tab that holds one planned event per row.
- Calendar
CalendarApp.getDefaultCalendar()This is the main calendar of the account running the script. Swap it for CalendarApp.getCalendarById to use a different calendar.
- Event ID column
4Column D is column number 4. The script writes the new event ID there, and that is what makes a second run skip the row.
2 · Review before running
What the script can access and change
Permissions you approve
- See, edit, create, and delete all your Google Sheets spreadsheets. The code only reads the Events tab and writes event IDs into column D of this spreadsheet.
- See, edit, share, and permanently delete all the calendars you can access using Google Calendar. The code only adds new events to your default calendar.
Effects of one run
- Creates one calendar event for each row that has a title, a start, and an empty column D.
- Writes the new event ID to column D right after creating each event, so a later run skips that row. The script writes one row at a time, instead of all rows at the end, because each event already exists in Calendar as soon as it is created. If the run stops between creating an event and writing its ID, or before Sheets saves the write, the event exists but column D stays empty.
- Only creates events. It never deletes or edits an event that already exists on your calendar.
3 · Copy
Paste this into the Apps Script editor
Create or open a script file, replace the example values marked above, then save the project.
function createCalendarEventsFromSheetRows() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Events');
if (!sheet) throw new Error('Add a Sheet tab named Events before running this function.');
const firstDataRow = 2;
const lastRow = sheet.getLastRow();
if (lastRow < firstDataRow) return;
const calendar = CalendarApp.getDefaultCalendar();
const rows = sheet.getRange(firstDataRow, 1, lastRow - firstDataRow + 1, 4).getValues();
rows.forEach((row, index) => {
const [title, start, end, eventId] = row;
if (!title || !start || eventId) return;
const rowNumber = firstDataRow + index;
const startTime = start instanceof Date ? start : new Date(String(start));
const endTime = end instanceof Date ? end : new Date(String(end));
if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) {
throw new Error('Row ' + rowNumber + ' needs a date with a time in both the start cell and the end cell.');
}
const event = calendar.createEvent(String(title), startTime, endTime);
sheet.getRange(rowNumber, 4).setValue(event.getId());
});
} 4 · Run
Follow these steps in order
Start with one test row
Put headers in row 1. Add a single row below it with a title, a start, and an end, and leave column D empty. Pick a time later today so the new event is easy to find.
Add the script
Choose Extensions, then Apps Script. Paste the function over the starter code and save.
Run it once and approve access
Choose createCalendarEventsFromSheetRows in the function dropdown above the code, then click Run. A dialog says Authorization required. Click Review permissions and allow access to your spreadsheets and your calendars. Then open Google Calendar and look for the test event.
Add the remaining rows
When the test event looks right, fill in the other rows and run the function again. Rows that already show an ID in column D are left alone.
5 · Confirm
How to tell it worked
Each finished row shows a long event ID in column D, and the matching events appear on your calendar at the times from columns B and C.
If the result is different
Troubleshooting
- The run stops with "Add a Sheet tab named Events before running this function."
- Rename your tab to Events, or change the tab name in the code to the name of your tab.
- The run stops with "Row 2 needs a date with a time in both the start cell and the end cell."
- Select the start and end cells in that row and choose Format, Number, Date time, then enter the date and time again. Text such as March 4 at 9 is not a date to the script.
- The same event was created twice, or a run failed and a row has no ID.
- Do not run the script again yet. In Google Calendar, go to the date and time from that row and compare each event title and time with the row. When you find the matching event, get its ID with CalendarEvent.getId() in a script and paste it into column D. The event link in your browser is not that ID. If several events match, or you cannot tell whether any of them came from this row, decide what to keep before you run again. Duplicates come from clearing IDs in column D, from two runs at the same time, and from a run that fails after creating an event.
- The event landed on the wrong calendar.
- Replace CalendarApp.getDefaultCalendar() with CalendarApp.getCalendarById and the calendar ID from Google Calendar settings. getDefaultCalendar() is the main calendar of the account running the script.
Technical details
Names used in this script
Open these details when you want to adapt the example or look up an exact service or method name.
Show Apps Script symbols and service pages
Apps Script symbols
Service pages
Keep going
Related tasks, basics, and apps
- Task guide Email yourself tomorrow's calendar agenda
Get an email each evening listing tomorrow's events on your main Google Calendar. Run the setup function once to install the daily trigger.
- Task guide Send an email for each row in a Google Sheet
Send one email to each person listed on a Customers tab. The script marks each row Sent as it goes, so a later run sends only to rows that are not marked yet.
- Object reference Sheet
A Sheet is one tab inside a Google spreadsheet. Get it with getSheetByName() or getActiveSheet(). Use getLastRow() to find the last row with content, or getRange() to select cells to read.
- Object reference Range
A Range represents one cell such as A2 or a rectangular block of rows and columns in a Sheet. Use getValue() for one cell and getValues() or setValues() for a 2D array of rows.
- Object reference Calendar
A calendar holds a set of events. Most scripts use your default calendar, but you can also open another calendar you have access to by its ID.
- Object reference Calendar event
A calendar event is one entry on a calendar, such as a meeting or a reminder. It carries a title, a start and end time, and an optional guest list.
- Basics Dates, time zones, and Utilities.formatDate
A Date holds one instant in time. Use Utilities.formatDate(date, timeZone, pattern) and Session.getScriptTimeZone() to format it in the right time zone.
- Google app Google Sheets
SpreadsheetApp lets a Google Sheets script read a Sheet or Range, add a custom menu or formula, and act on each row, such as sending one email per row.
- Google app Google Calendar
CalendarApp scripts read events on a date with getEventsForDay() and add new CalendarEvent entries with createEvent() after you approve Calendar access.