1

This formula is in A2 and populates from data in my booking sheet

=QUERY(
   ImportRange("Sheet_Key","sheet1!A7:Z"),
   "Select Col7,Col2,Col8,Col9,Col12,Col19"
 )

The calendar event script https://stackoverflow.com/a/15790894/6400958 works perfectly and takes 5-10 seconds to run when data is entered directly but creates duplicates and exceeds run time when the import range formula is used with exactly the same amount of data.

Here is a Demo file. Note that there are only three rows of event data.

Below is the script:

 /**
  * Adds a custom menu to the active spreadsheet, containing a single menu item
  * for invoking the exportEvents() function.
  * The onOpen() function, when defined, is automatically invoked whenever the
  * spreadsheet is opened.
  * For more information on using the Spreadsheet API, see
  * https://developers.google.com/apps-script/service_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 = "My_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);
}
Community
  • 1
  • 1
  • Possible duplicate of [Exceeded maximum execution time in Google Apps Script](http://stackoverflow.com/questions/7854573/exceeded-maximum-execution-time-in-google-apps-script) – Rubén Jun 11 '16 at 11:15
  • I think that you should focus first on solving the exceeded maximum execution time as the last line in the code is the one that update the spreadsheet with the event ids that are required to prevent duplicate events. – Rubén Jun 11 '16 at 11:21
  • I don't believe this is the issue because without the formula when the data is entered manually the script runs and completes in about 5 seconds. – Jarrod Rapson Jun 11 '16 at 11:24
  • It is definitely preventing the creation of the eventID's I just don't know why, I've tried skipping an extra header row to avoid the script reading the first row containing the formula but had just the same result. – Jarrod Rapson Jun 11 '16 at 11:27
  • How many rows do you enter manually and how many are you importing? – Rubén Jun 11 '16 at 11:35
  • only 3 rows / events my apologies for not showing an image i don't have enough points yet. – Jarrod Rapson Jun 11 '16 at 11:37
  • Create a demo file with the minimum of sheets and other elements and add the link to it to the question. See [mcve]. – Rubén Jun 11 '16 at 11:41
  • https://docs.google.com/spreadsheets/d/1J1o3yXsJzRD05PF-YIjVD-vFyCwIIA1q8KdYbn8mV8M/edit?usp=sharing – Jarrod Rapson Jun 11 '16 at 11:52
  • ok the link above is the simplest demo file i could come up with and I've just ran the script with and without the formula and had exactly the same results using the 3 rows of data – Jarrod Rapson Jun 11 '16 at 12:01
  • Admittedly I am a compete amateur at coding but is there any obvious reason why the import range query should affect the script like this? – Jarrod Rapson Jun 11 '16 at 12:15
  • Just posted an answer. – Rubén Jun 11 '16 at 12:17

1 Answers1

1

It's very likely that the open ended reference ("sheet1!A7:Z") makes that the resulting range of var range = sheet.getDataRange(); includes a lot of blank rows. Add a where clause to filter out the blank rows, something like where Col2 <> ''. The final formula will look like the following

=QUERY(
  ImportRange("Sheet_Key","sheet1!A7:Z"),
  "Select Col7,Col2,Col8,Col9,Col12,Col19 where Col2 &lt> ''"
 )
Rubén
  • 34,714
  • 9
  • 70
  • 166
  • The script overwrite the source range with the values. Consider to spend some time to learn JavaScript and Google Apps Script at least deep enough to understand the scripts that you found before adopting them. – Rubén Jun 11 '16 at 12:47
  • mate i appreciate your help and i would have upvoted u already but I've been frantically trying to test this as i go, I'm a concrete cutter who has gotten way over his head in trying to improve the way he manages his business through google apps, mate I'm learning as fast as i can but i tell ya if i seen you onsite struggling to accomplish something i'd just help ya – Jarrod Rapson Jun 11 '16 at 12:51
  • Keep calm and enjoy programming :) – Rubén Jun 11 '16 at 13:01
  • I take my hat off to ya ;) I was hoping that by skipping the extra row the formula would not be in the source data but i must be wrong cause it deletes it all the same, the event id is not created in the row so it must be skipping it but still deleting the formula, i guess ill just keep learning :) – Jarrod Rapson Jun 11 '16 at 13:04
  • I am now using the script on my actual booking sheet and i have put all the columns with the relevant data to the left and selecting the active range to save my formulas but i can't figure out how to get only the active rows from a specified number of columns any Ideas? – Jarrod Rapson Jun 12 '16 at 09:44
  • function exportEvents() { var sheet = SpreadsheetApp.getActiveSheet(); var headerRows = 0; var ss = SpreadsheetApp.getActiveSpreadsheet(); var range = ss.getSheets()[0].getRange("A8:G10"); SpreadsheetApp.setActiveRange(range); var data = range.getValues(); @AuriellePerlmann – Jarrod Rapson Jun 12 '16 at 09:48
  • The last two comments looks to be a new question, but that should be done by filling up the [Ask a question](http://stackoverflow.com/questions/ask) form instead of using comments. – Rubén Jun 12 '16 at 12:58