title: Google Sheets installable onEdit() Trigger not authorized to add calendar event
body: <p>I'm working on a script attached to a Google Spreadsheet that helps me generate a shift schedule for employees, create a google calendar, and update the calendar when people swap shifts.  I have an onEdit() installable trigger attached to the spreadsheet that checks if a user changed a cell in a certain range (to swap shifts), then finds the cells on the calendar in the Spreadsheet, swaps them, and calls and updateGoogleCalendar.</p>
  
  <p>It runs perfectly when executed from the script editor.  But when executed from the trigger on the spreadsheet, I get this error:  </p>
  
  <blockquote>
    <p>"Execution failed: You do not have permission to call getOwnedCalendarsByName (line 204, file "Code") [1.021 seconds total runtime]"</p>
  </blockquote>
  
  <p>In the google apps permissions, it says this for the script: "Google Calendar
  Manage your calendars" so it should be authorized.</p>
  
  <p>Here's the function called by the installable trigger OnEdit</p>
  
  <pre class="lang-js prettyprint-override"><code>function onEdit(e) {
    var sheets = SpreadsheetApp.getActive();
    var dutySwitchSheet = sheets.getSheetByName('Duty Switches');
  
    if(!e){
      var e = {};
      e.range = dutySwitchSheet.getRange(30, 9);
    }
    Logger.log(e.range.getValue());
  
    var changedRow = e.range.getRow();
    var changedCol = e.range.getColumn();
    var RAInitials = sheets.getRangeByName("dutySwitchRAInitials");
    var rangeTop = RAInitials.getRow();
    var rangeBottom = RAInitials.getLastRow();
    var rangeLeft = RAInitials.getColumn();
    var rangeRight = RAInitials.getLastColumn();
    Logger.log("changedRow: %s, changedCol: %s, rangeTop: %s, rangeBottom: %s, rangeLeft: %s, rangeRight: %s", changedRow, changedCol, rangeTop, rangeBottom, rangeLeft, rangeRight);
    if( changedRow &gt;= rangeTop &amp;&amp; changedRow &lt;= rangeBottom &amp;&amp; changedCol &gt;= rangeLeft &amp;&amp; changedCol &lt;= rangeRight &amp;&amp; e.range.getSheet().getName().toUpperCase() === dutySwitchSheet.getName().toUpperCase()){
      Logger.log("event sheet name: %s, Duty Switch Sheet Name: %S", e.range.getSheet().getName().toUpperCase(), dutySwitchSheet.getName().toUpperCase());
      var relRow = changedRow - rangeTop + 1;
      Logger.log("Checking if both initials are present");
      if(RAInitials.getCell(relRow, 1).getValue() &amp;&amp; RAInitials.getCell(relRow,2).getValue()){
        var ui = SpreadsheetApp.getUi()
        ui.showModalDialog(HtmlService.createHtmlOutput(""), "Checking Your input, please wait..");
        Logger.log("updating");
        var RA1Range = sheets.getRangeByName("dutySwitchRA1");
        var RA2Range = sheets.getRangeByName("dutySwitchRA2");
        var calendarRange = sheets.getRangeByName("dutyDays");
        var startDate = new Date(sheets.getRangeByName("startDate").getValue());
        var startDay = startDate.getDay();
  
        var RA1 = {name: RA1Range.getCell(relRow, 1).getValue(), shiftNum: RA1Range.getCell(relRow, 2).getValue(), date: new Date(RA1Range.getCell(relRow, 3).getValue()) };
        if(RA1.shiftNum != "N/A"){
          RA1.day = Math.floor( (RA1.date.getTime() - startDate.getTime())/(24*60*60*1000) ) + startDay;
          RA1.SwappedCell = calendarRange.getCell( Math.floor(RA1.day / 7) * 3 + Number(RA1.shiftNum) + 1, (RA1.day % 7) + 1 );
          RA1.cellValue = String(RA1.SwappedCell.getValue());
        }
  
        var RA2 = {name: RA2Range.getCell(relRow, 1).getValue(), shiftNum: RA2Range.getCell(relRow, 2).getValue(), date: new Date(RA2Range.getCell(relRow, 3).getValue()) };
        if(RA2.shiftNum != "N/A"){
          RA2.day = Math.floor( (RA2.date.getTime() - startDate.getTime())/(24*60*60*1000) ) + startDay;
          RA2.SwappedCell = calendarRange.getCell( Math.floor(RA2.day / 7) * 3 + Number(RA2.shiftNum) + 1, (RA2.day % 7) + 1 );
          RA2.cellValue = String(RA2.SwappedCell.getValue());
        }
        Logger.log("RA1 name: %s, date: %s, cellValue: %s; RA2 name: %s, date: %s, cellValue: %s" , RA1.name, RA1.date, RA1.cellValue, RA2.name, RA2.date, RA2.cellValue);
        Logger.log("RA1 name matches: %s, RA2 name matches: %s", RA1.cellValue.indexOf(RA1.name) != -1, RA2.cellValue.indexOf(RA2.name) != -1);
        if(RA1.cellValue.indexOf(RA1.name) != -1 || RA1.shiftNum == "N/A" &amp;&amp; RA2.cellValue.indexOf(RA2.name) != -1 || RA2.shiftNum == "N/A" ){
          Logger.log("Swapping Cells");
          if(RA1.shiftNum != "N/A"){
            RA1.SwappedCell.setValue( String(RA1.SwappedCell.getValue()).replace(RA1.name, RA2.name) );
          }
          if(RA2.shiftNum != "N/A"){
            RA2.SwappedCell.setValue( String(RA2.SwappedCell.getValue()).replace(RA2.name, RA1.name) );
          }
          Logger.log("Syncing Google Calendar");
          syncGoogleCalendar();
          ui.showModalDialog(HtmlService.createHtmlOutput(""), "The Google Calendar has been updated! :)");
          Logger.log("Done Updating!");
        } 
        else {
          Logger.log("Did Not Swap Cells");
          ui.showModalDialog(HtmlService.createHtmlOutput(""), "The info input does not match the spreadsheet.  Couldn't update :(");
        }
      }
    }
  }
  </code></pre>
  
  <p>And here's the updateGoogleCalendar() function untill it throws the error </p>
  
  <pre class="lang-js prettyprint-override"><code>function syncGoogleCalendar(){
  
    var dutyCalendars = CalendarApp.getOwnedCalendarsByName("RA Duty Calendar");
  </code></pre>