I found this old question about synchronizing Google Sheets and Google Calendar and tried to download the template and then edit it accordingly.
When I try to run the script it prompts this error ReferenceError: calenderId is not defined.
Since I can only see one line, 9, where to to enter the calendarId I can not make the script work.
Did I miss a line in my example? I am aware that I need to write my cal-id in line 9.
// Script to synchronize a calendar to a spreadsheet and vice versa.
//
// See https://github.com/Davepar/gcalendarsync for instructions on setting this up.
//
// Set this value to match your calendar!!!
// Calendar ID can be found in the "Calendar Address" section of the Calendar Settings.
//var calendarId = '<your-calendar-id>#group.calendar.google.com';
var calendarId = 'Her er min kalender-adresse, naturligvis';
// Set the beginning and end dates that should be synced. beginDate can be set to Date() to use
// today. The numbers are year, month, date, where month is 0 for Jan through 11 for Dec.
var beginDate = new Date(1970, 0, 1); // Default to Jan 1, 1970
var endDate = new Date(2500, 0, 1); // Default to Jan 1, 2500
// Date format to use in the spreadsheet.
var dateFormat = 'M/d/yyyy H:mm';
var titleRowMap = {
'title': 'Title',
'description': 'Description',
'location': 'Location',
'starttime': 'Start Time',
'endtime': 'End Time',
'guests': 'Guests',
'color': 'Color',
'id': 'Id'
};
var titleRowKeys = ['title', 'description', 'location', 'starttime', 'endtime', 'guests', 'color', 'id'];
var requiredFields = ['id', 'title', 'starttime', 'endtime'];
// This controls whether email invites are sent to guests when the event is created in the
// calendar. Note that any changes to the event will cause email invites to be resent.
var SEND_EMAIL_INVITES = false;
// Setting this to true will silently skip rows that have a blank start and end time
// instead of popping up an error dialog.
var SKIP_BLANK_ROWS = false;
// Updating too many events in a short time period triggers an error. These values
// were successfully used for deleting and adding 240 events. Values in milliseconds.
var THROTTLE_SLEEP_TIME = 200;
var MAX_RUN_TIME = 5.75 * 60 * 1000;
// Special flag value. Don't change.
var EVENT_DIFFS_WITH_GUESTS = 999;
// Adds the custom menu to the active spreadsheet.
function onOpen() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [
{
name: "Update from Calendar",
functionName: "syncFromCalendar"
}, {
name: "Update to Calendar",
functionName: "syncToCalendar"
}
];
spreadsheet.addMenu('Calendar Sync', menuEntries);
}
// Creates a mapping array between spreadsheet column and event field name
function createIdxMap(row) {
var idxMap = [];
for (var idx = 0; idx < row.length; idx++) {
var fieldFromHdr = row[idx];
for (var titleKey in titleRowMap) {
if (titleRowMap[titleKey] == fieldFromHdr) {
idxMap.push(titleKey);
break;
}
}
if (idxMap.length <= idx) {
// Header field not in map, so add null
idxMap.push(null);
}
}
return idxMap;
}
// Converts a spreadsheet row into an object containing event-related fields
function reformatEvent(row, idxMap, keysToAdd) {
var reformatted = row.reduce(function(event, value, idx) {
if (idxMap[idx] != null) {
event[idxMap[idx]] = value;
}
return event;
}, {});
for (var k in keysToAdd) {
reformatted[keysToAdd[k]] = '';
}
return reformatted;
}
// Converts a calendar event to a psuedo-sheet event.
function convertCalEvent(calEvent) {
convertedEvent = {
'id': calEvent.getId(),
'title': calEvent.getTitle(),
'description': calEvent.getDescription(),
'location': calEvent.getLocation(),
'guests': calEvent.getGuestList().map(function(x) {return x.getEmail();}).join(','),
'color': calEvent.getColor()
};
if (calEvent.isAllDayEvent()) {
convertedEvent.starttime = calEvent.getAllDayStartDate();
var endtime = calEvent.getAllDayEndDate();
if (endtime - convertedEvent.starttime === 24 * 3600 * 1000) {
convertedEvent.endtime = '';
} else {
convertedEvent.endtime = endtime;
if (endtime.getHours() === 0 && endtime.getMinutes() == 0) {
convertedEvent.endtime.setSeconds(endtime.getSeconds() - 1);
}
}
} else {
convertedEvent.starttime = calEvent.getStartTime();
convertedEvent.endtime = calEvent.getEndTime();
}
return convertedEvent;
}
// Converts calendar event into spreadsheet data row
function calEventToSheet(calEvent, idxMap, dataRow) {
convertedEvent = convertCalEvent(calEvent);
for (var idx = 0; idx < idxMap.length; idx++) {
if (idxMap[idx] !== null) {
dataRow[idx] = convertedEvent[idxMap[idx]];
}
}
}
// Returns empty string or time in milliseconds for Date object
function getEndTime(ev) {
return ev.endtime === '' ? '' : ev.endtime.getTime();
}
// Determines the number of field differences between a calendar event and
// a spreadsheet event
function eventDifferences(convertedCalEvent, sev) {
var eventDiffs = 0 + (convertedCalEvent.title !== sev.title) +
(convertedCalEvent.description !== sev.description) +
(convertedCalEvent.location !== sev.location) +
(convertedCalEvent.starttime.toString() !== sev.starttime.toString()) +
(getEndTime(convertedCalEvent) !== getEndTime(sev)) +
(convertedCalEvent.guests !== sev.guests) +
(convertedCalEvent.color !== ('' + sev.color));
if (eventDiffs > 0 && convertedCalEvent.guests) {
// Use a special flag value if an event changed, but it has guests.
eventDiffs = EVENT_DIFFS_WITH_GUESTS;
}
return eventDiffs;
}
// Determine whether required fields are missing
function areRequiredFieldsMissing(idxMap) {
return requiredFields.some(function(val) {
return idxMap.indexOf(val) < 0;
});
}
// Returns list of fields that aren't in spreadsheet
function missingFields(idxMap) {
return titleRowKeys.filter(function(val) {
return idxMap.indexOf(val) < 0;
});
}
// Set up formats and hide ID column for empty spreadsheet
function setUpSheet(sheet, fieldKeys) {
sheet.getRange(1, fieldKeys.indexOf('starttime') + 1, 999).setNumberFormat(dateFormat);
sheet.getRange(1, fieldKeys.indexOf('endtime') + 1, 999).setNumberFormat(dateFormat);
sheet.hideColumns(fieldKeys.indexOf('id') + 1);
}
// Display error alert
function errorAlert(msg, evt, ridx) {
var ui = SpreadsheetApp.getUi();
if (evt) {
ui.alert('Skipping row: ' + msg + ' in event "' + evt.title + '", row ' + (ridx + 1));
} else {
ui.alert(msg);
}
}
// Updates a calendar event from a sheet event.
function updateEvent(calEvent, convertedCalEvent, sheetEvent){
var numChanges = 0;
sheetEvent.sendInvites = SEND_EMAIL_INVITES;
if (convertedCalEvent.starttime.toString() !== sheetEvent.starttime.toString() ||
getEndTime(convertedCalEvent) !== getEndTime(sheetEvent)) {
if (sheetEvent.endtime === '') {
calEvent.setAllDayDate(sheetEvent.starttime);
} else {
calEvent.setTime(sheetEvent.starttime, sheetEvent.endtime);
}
numChanges++;
}
if (convertedCalEvent.title !== sheetEvent.title) {
calEvent.setTitle(sheetEvent.title);
numChanges++;
}
if (convertedCalEvent.description !== sheetEvent.description) {
calEvent.setDescription(sheetEvent.description);
numChanges++;
}
if (convertedCalEvent.location !== sheetEvent.location) {
calEvent.setLocation(sheetEvent.location);
numChanges++;
}
if (convertedCalEvent.color !== ('' + sheetEvent.color)) {
if (sheetEvent.color > 0 && sheetEvent.color < 12) {
calEvent.setColor('' + sheetEvent.color);
numChanges++;
}
}
if (convertedCalEvent.guests !== sheetEvent.guests) {
var guestCal = calEvent.getGuestList().map(function (x) {
return {
email: x.getEmail(),
added: false
};
});
var sheetGuests = sheetEvent.guests || '';
var guests = sheetGuests.split(',').map(function (x) {
return x ? x.trim() : '';
});
// Check guests that are already invited.
for (var gIx = 0; gIx < guestCal.length; gIx++) {
var index = guests.indexOf(guestCal[gIx].email);
if (index >= 0) {
guestCal[gIx].added = true;
guests.splice(index, 1);
}
}
guests.forEach(function (guest) {
if (guest) {
calEvent.addGuest(guest);
numChanges++;
}
});
guestCal.forEach(function (guest) {
if (!guest.added) {
calEvent.removeGuest(guest.email);
numChanges++;
}
});
}
// Throttle updates.
Utilities.sleep(THROTTLE_SLEEP_TIME * numChanges);
return numChanges;
}
// Synchronize from calendar to spreadsheet.
function syncFromCalendar() {
console.info('Starting sync from calendar');
// Get calendar and events
var calendar = CalendarApp.getCalendarById(calendarId);
var calEvents = calendar.getEvents(beginDate, endDate);
// Get spreadsheet and data
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
var eventFound = new Array(data.length);
// Check if spreadsheet is empty and add a title row
var titleRow = [];
for (var idx = 0; idx < titleRowKeys.length; idx++) {
titleRow.push(titleRowMap[titleRowKeys[idx]]);
}
if (data.length < 1) {
data.push(titleRow);
range = sheet.getRange(1, 1, data.length, data[0].length);
range.setValues(data);
setUpSheet(sheet, titleRowKeys);
}
if (data.length == 1 && data[0].length == 1 && data[0][0] === '') {
data[0] = titleRow;
range = sheet.getRange(1, 1, data.length, data[0].length);
range.setValues(data);
setUpSheet(sheet, titleRowKeys);
}
// Map spreadsheet headers to indices
var idxMap = createIdxMap(data[0]);
var idIdx = idxMap.indexOf('id');
// Verify header has all required fields
if (areRequiredFieldsMissing(idxMap)) {
var reqFieldNames = requiredFields.map(function(x) {return titleRowMap[x];}).join(', ');
errorAlert('Spreadsheet must have ' + reqFieldNames + ' columns');
return;
}
// Array of IDs in the spreadsheet
var sheetEventIds = data.slice(1).map(function(row) {return row[idIdx];});
// Loop through calendar events
for (var cidx = 0; cidx < calEvents.length; cidx++) {
var calEvent = calEvents[cidx];
var calEventId = calEvent.getId();
var ridx = sheetEventIds.indexOf(calEventId) + 1;
if (ridx < 1) {
// Event not found, create it
ridx = data.length;
var newRow = [];
var rowSize = idxMap.length;
while (rowSize--) newRow.push('');
data.push(newRow);
} else {
eventFound[ridx] = true;
}
// Update event in spreadsheet data
calEventToSheet(calEvent, idxMap, data[ridx]);
}
// Remove any data rows not found in the calendar
var rowsDeleted = 0;
for (var idx = eventFound.length - 1; idx > 0; idx--) {
//event doesn't exists and has an event id
if (!eventFound[idx] && sheetEventIds[idx - 1]) {
data.splice(idx, 1);
rowsDeleted++;
}
}
// Save spreadsheet changes
range = sheet.getRange(1, 1, data.length, data[0].length);
range.setValues(data);
if (rowsDeleted > 0) {
sheet.deleteRows(data.length + 1, rowsDeleted);
}
}
// Synchronize from spreadsheet to calendar.
function syncToCalendar() {
console.info('Starting sync to calendar');
var scriptStart = Date.now();
// Get calendar and events
var calendar = CalendarApp.getCalendarById(calendarId);
if (!calendar) {
errorAlert('Cannot find calendar. Check instructions for set up.');
}
var calEvents = calendar.getEvents(beginDate, endDate);
var calEventIds = calEvents.map(function(val) {return val.getId();});
// Get spreadsheet and data
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
if (data.length < 2) {
errorAlert('Spreadsheet must have a title row and at least one data row');
return;
}
// Map headers to indices
var idxMap = createIdxMap(data[0]);
var idIdx = idxMap.indexOf('id');
var idRange = range.offset(0, idIdx, data.length, 1);
var idData = idRange.getValues()
// Verify header has all required fields
if (areRequiredFieldsMissing(idxMap)) {
var reqFieldNames = requiredFields.map(function(x) {return titleRowMap[x];}).join(', ');
errorAlert('Spreadsheet must have ' + reqFieldNames + ' columns');
return;
}
var keysToAdd = missingFields(idxMap);
// Loop through spreadsheet rows
var numAdded = 0;
var numUpdates = 0;
var eventsAdded = false;
for (var ridx = 1; ridx < data.length; ridx++) {
var sheetEvent = reformatEvent(data[ridx], idxMap, keysToAdd);
// If enabled, skip rows with blank/invalid start and end times
if (SKIP_BLANK_ROWS && !(sheetEvent.starttime instanceof Date) &&
!(sheetEvent.endtime instanceof Date)) {
continue;
}
// Do some error checking first
if (!sheetEvent.title) {
errorAlert('must have title', sheetEvent, ridx);
continue;
}
if (!(sheetEvent.starttime instanceof Date)) {
errorAlert('start time must be a date/time', sheetEvent, ridx);
continue;
}
if (sheetEvent.endtime !== '') {
if (!(sheetEvent.endtime instanceof Date)) {
errorAlert('end time must be empty or a date/time', sheetEvent, ridx);
continue;
}
if (sheetEvent.endtime < sheetEvent.starttime) {
errorAlert('end time must be after start time for event', sheetEvent, ridx);
continue;
}
}
// Ignore events outside of the begin/end range desired.
if (sheetEvent.starttime > endDate) {
continue;
}
if (sheetEvent.endtime === '') {
if (sheetEvent.starttime < beginDate) {
continue;
}
} else {
if (sheetEvent.endtime < beginDate) {
continue;
}
}
// Determine if spreadsheet event is already in calendar and matches
var addEvent = true;
if (sheetEvent.id) {
var eventIdx = calEventIds.indexOf(sheetEvent.id);
if (eventIdx >= 0) {
calEventIds[eventIdx] = null; // Prevents removing event below
addEvent = false;
var calEvent = calEvents[eventIdx];
var convertedCalEvent = convertCalEvent(calEvent);
var eventDiffs = eventDifferences(convertedCalEvent, sheetEvent);
if (eventDiffs > 0) {
// When there are only 1 or 2 event differences, it's quicker to
// update the event. For more event diffs, delete and re-add the event. The one
// exception is if the event has guests (eventDiffs=99). We don't
// want to force guests to re-confirm, so go through the slow update
// process instead.
if (eventDiffs < 3 && eventDiffs !== EVENT_DIFFS_WITH_GUESTS) {
numUpdates += updateEvent(calEvent, convertedCalEvent, sheetEvent);
} else {
addEvent = true;
calEventIds[eventIdx] = sheetEvent.id;
}
}
}
}
console.info('%d updates, time: %d msecs', numUpdates, Date.now() - scriptStart);
if (addEvent) {
var newEvent;
sheetEvent.sendInvites = SEND_EMAIL_INVITES;
if (sheetEvent.endtime === '') {
newEvent = calendar.createAllDayEvent(sheetEvent.title, sheetEvent.starttime, sheetEvent);
} else {
newEvent = calendar.createEvent(sheetEvent.title, sheetEvent.starttime, sheetEvent.endtime, sheetEvent);
}
// Put event ID back into spreadsheet
idData[ridx][0] = newEvent.getId();
eventsAdded = true;
// Set event color
if (sheetEvent.color > 0 && sheetEvent.color < 12) {
newEvent.setColor('' + sheetEvent.color);
}
// Throttle updates.
numAdded++;
Utilities.sleep(THROTTLE_SLEEP_TIME);
if (numAdded % 10 === 0) {
console.info('%d events added, time: %d msecs', numAdded, Date.now() - scriptStart);
}
}
// If the script is getting close to timing out, save the event IDs added so far to avoid lots
// of duplicate events.
if ((Date.now() - scriptStart) > MAX_RUN_TIME) {
idRange.setValues(idData);
}
}
// Save spreadsheet changes
if (eventsAdded) {
idRange.setValues(idData);
}
// Remove any calendar events not found in the spreadsheet
var numToRemove = calEventIds.reduce(function(prevVal, curVal) {
if (curVal !== null) {
prevVal++;
}
return prevVal;
}, 0);
if (numToRemove > 0) {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Delete ' + numToRemove + ' calendar event(s) not found in spreadsheet?',
ui.ButtonSet.YES_NO);
if (response == ui.Button.YES) {
var numRemoved = 0;
calEventIds.forEach(function(id, idx) {
if (id != null) {
calEvents[idx].deleteEvent();
Utilities.sleep(THROTTLE_SLEEP_TIME);
numRemoved++;
if (numRemoved % 10 === 0) {
console.info('%d events removed, time: %d msecs', numRemoved, Date.now() - scriptStart);
}
}
});
}
}
}
// Set up a trigger to automatically update the calendar when the spreadsheet is
// modified. See the instructions for how to use this.
function createSpreadsheetEditTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger('syncToCalendar')
.forSpreadsheet(ss)
.onEdit()
.create();
}
// Delete the trigger. Use this to stop automatically updating the calendar.
function deleteTrigger() {
// Loop over all triggers.
var allTriggers = ScriptApp.getProjectTriggers();
for (var idx = 0; idx < allTriggers.length; idx++) {
if (allTriggers[idx].getHandlerFunction() === 'syncToCalendar') {
ScriptApp.deleteTrigger(allTriggers[idx]);
}
}
}
The ReferenceError: calenderId is not defined error message you are getting is due to the fact that you are declaring calenderId instead of calendarId and you are using calendarId all over your code.
So in order to fix your error you might want to check the line at which you are declaring the variable and declare it with the appropriate name.
Related
I have created a trigger which will first execute after 5 minutes, the when the trigger function starts executing, the trigger is deleted at first place , then the required code executes, and then new trigger is created which executes in 1 minutes. Also I have a condition where in the trigger is deleted and never created.. but the trigger still continues to execute.
I get total_uploads value as 29393, but it ended up adding nearly 100k records.
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Fetch CoA')
.addItem('Fetch CoA', 'main')
.addToUi();
}
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var config = ss.getSheetByName("Config");
var hostname = config.getRange(2, 2).getValue();
var authorization = config.getRange(3, 2).getValue();
var coaID = config.getRange(4, 2).getValue();
var documentProperties = PropertiesService.getDocumentProperties();
documentProperties.setProperties({
'hostname': hostname,
'authorization': authorization,
'coaID': coaID,
'offset': '0',
'is_last_set': 0
});
var coaSheet = ss.getSheetByName("COA");
if (coaSheet.getLastRow() > 1) {
coaSheet.deleteRows(1, coaSheet.getLastRow() - 1);
}
console.log("Getting CoA Validaton");
writeCOA();
}
function writeCOA() {
var documentProperties = PropertiesService.getDocumentProperties();
var hostname = documentProperties.getProperty('hostname');
var authorization = documentProperties.getProperty('authorization');
var coaID = documentProperties.getProperty('coaID');
var offset = parseInt(documentProperties.getProperty('offset'));
var is_last_set = parseInt(documentProperties.getProperty('is_last_set'));
var options = {
"method": "GET",
"headers": {
"Authorization": "Token token=" + authorization
}
};
var today = new Date();
console.log("Writing the uploads array");
var ss = SpreadsheetApp.getActiveSpreadsheet();
var coaSheet = ss.getSheetByName("COA");
coaSheet.getRange("A1:D1").setValues([["id", "account_number", "created_at", "updated_at"]]);
var rowNum = 2;
var uploads = [];
var next_page = true;
var total_uploads = "...";
console.log("Getting all Account numbers for CoA: " + coaID);
while (next_page) {
documentProperties.setProperty('next_page', next_page);
if (isTimeUp(today) && is_last_set == 0) {
console.log("RepeatWriteCoA triggered");
// schedule a trigger for a different function
ScriptApp.newTrigger("repeatWriteCoA")
.timeBased()
.everyMinutes(5)
.create();
break;
}
console.log(`Getting uploads ${offset} to ${offset + 500} of ${total_uploads}`);
var platformUrl = `${hostname}/api/v3/chart_of_accounts/${coaID}/account_numbers?limit=500&offset=${offset}`;
//console.log(platformUrl);
var response = UrlFetchApp.fetch(platformUrl, options);
var jsonResponse = response.getContentText();
var page_of_uploads = JSON.parse(jsonResponse);
total_uploads = page_of_uploads['meta']['total'];
documentProperties.setProperty('total_uploads', total_uploads);
uploads = page_of_uploads['account_numbers'];
try {
offset = page_of_uploads['meta']['next']['offset'];
documentProperties.setProperty('offset', offset);
} catch (Exception) {
next_page = false;
documentProperties.setProperty('next_page', next_page);
console.log("Exception in getting the next page offset hence stopping the loop");
deleteTriggers();
// For last set of records that needs to added in our spreadsheet
console.log("Adding Last set of Records..");
for (i = 0; i < uploads.length; i++) {
acc_number = uploads[i].account_number.replace(/[^a-zA-Z0-9\s\p{P}]/g, '-');
coaSheet.getRange("A" + rowNum + ":D" + rowNum).setValues([[uploads[i].id, acc_number, uploads[i].created_at, uploads[i].updated_at]]);
rowNum += 1;
documentProperties.setProperty('rowNum', rowNum);
}
console.log("End of Last set of Records..");
is_last_set = 1;
}
console.log("Adding to spreadsheet");
for (i = 0; i < uploads.length; i++) {
acc_number = uploads[i].account_number.replace(/[^a-zA-Z0-9\s\p{P}]/g, '-');
coaSheet.getRange("A" + rowNum + ":D" + rowNum).setValues([[uploads[i].id, acc_number, uploads[i].created_at, uploads[i].updated_at]]);
rowNum += 1;
documentProperties.setProperty('rowNum', rowNum);
}
console.log("End of adding rows");
if (offset >= total_uploads) {
deleteTriggers();
}
}
documentProperties.setProperty('is_last_set', is_last_set);
}
function repeatWriteCoA() {
console.log("Triggered RepeatFunction... Running from Repeat function");
// Delete trigger , so that new function wont be trigger untill this function ends
deleteTriggers();
var documentProperties = PropertiesService.getDocumentProperties();
var hostname = documentProperties.getProperty('hostname');
var authorization = documentProperties.getProperty('authorization');
var coaID = documentProperties.getProperty('coaID');
var offset = parseInt(documentProperties.getProperty('offset'));
var next_page = documentProperties.getProperty('next_page');
var rowNum = parseInt(documentProperties.getProperty('rowNum'));
var total_uploads = parseInt(documentProperties.getProperty('total_uploads'));
var options = {
"method": "GET",
"headers": {
"Authorization": "Token token=" + authorization
}
};
var today = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var coaSheet = ss.getSheetByName("COA");
var is_last_set = parseInt(documentProperties.getProperty('is_last_set'));
console.log("Getting all Account numbers for CoA: " + coaID);
while (next_page) {
if (is_last_set == 1) {
console.log('last set already executed');
break;
}
console.log(`Getting uploads ${offset} to ${offset + 500} of ${total_uploads}`);
var platformUrl = `${hostname}/api/v3/chart_of_accounts/${coaID}/account_numbers?limit=500&offset=${offset}`;
var response = UrlFetchApp.fetch(platformUrl, options);
var jsonResponse = response.getContentText();
var page_of_uploads = JSON.parse(jsonResponse);
total_uploads = page_of_uploads['meta']['total'];
uploads = page_of_uploads['account_numbers'];
try {
offset = page_of_uploads['meta']['next']['offset'];
documentProperties.setProperty('offset', offset);
} catch (Exception) {
next_page = false;
documentProperties.setProperty('next_page', next_page);
console.log("Exception in getting the next page offset hence stopping the loop");
// For last set of records that needs to added in our spreadsheet
console.log("Adding Last set of Records..");
for (i = 0; i < uploads.length; i++) {
acc_number = uploads[i].account_number.replace(/[^a-zA-Z0-9\s\p{P}]/g, '-');
coaSheet.getRange("A" + rowNum + ":D" + rowNum).setValues([[uploads[i].id, acc_number, uploads[i].created_at, uploads[i].updated_at]]);
rowNum += 1;
documentProperties.setProperty('rowNum', rowNum);
}
console.log("End of Last set of Records..");
is_last_set = 1;
}
for (i = 0; i < uploads.length; i++) {
acc_number = uploads[i].account_number.replace(/[^a-zA-Z0-9\s\p{P}]/g, '-');
coaSheet.getRange("A" + rowNum + ":D" + rowNum).setValues([[uploads[i].id, acc_number, uploads[i].created_at, uploads[i].updated_at]]);
rowNum += 1;
documentProperties.setProperty('rowNum', rowNum);
}
// Creating new trigger so that it will trigger this function next time ,
// this time we are creating the trigger with 1 min
if (offset <= total_uploads && isTimeUp(today) && is_last_set == 0) {
console.log("RepeatWriteCoA triggered");
// schedule a trigger for a different function
ScriptApp.newTrigger("repeatWriteCoA")
.timeBased()
.everyMinutes(1)
.create();
break;
}
}
documentProperties.setProperty('is_last_set', is_last_set);
}
function isTimeUp(today) {
var now = new Date();
console.log(now.getTime() - today.getTime());
return now.getTime() - today.getTime() > 240000;
// 240000 = 4 mins; this is the threshold limit
// you are free to setup your own threshold limit
}
function deleteTriggers() {
// Loop over all triggers.
var allTriggers = ScriptApp.getProjectTriggers();
if (allTriggers.length > 0) {
console.log("Deleting trigger....");
for (var i = 0; i < allTriggers.length; i++) {
// If the current trigger is the correct one, delete it.
ScriptApp.deleteTrigger(allTriggers[i]);
}
}
}
I am using this code to retrieve the User Usage Report. I am able to get the 7 parameters out of 12.
Questions:
Is it okay to combine accounts and gmail parameters? If yes, how would I fix the code to display the same format as the "Last Login"?
All shows "undefined":
'gmail:timestamp_last_access',
'gmail:timestamp_last_imap',
'gmail:timestamp_last_pop',
'gmail:timestamp_last_webmail'
What is the parameter reference for Account Status = Active, Suspended, Deleted...etc.? I have tried searching but no luck.
I am using this code below. Thanks in advance for your time and help!
function generateUserReport() {
var today = new Date();
var twoDaysAgo = new Date(today.getTime() - 2 * 24 * 60 * 60 * 1000);
var timezone = Session.getScriptTimeZone();
var date = Utilities.formatDate(twoDaysAgo, timezone, "yyyy-MM-dd");
var parameters = [
'accounts:first_name',
'accounts:last_name',
'accounts:is_super_admin',
'accounts:last_login_time',
'accounts:gmail_used_quota_in_mb',
'accounts:drive_used_quota_in_mb',
'gmail:timestamp_last_access',
'gmail:timestamp_last_imap',
'gmail:timestamp_last_pop',
'gmail:timestamp_last_webmail'
];
var rows = [];
var pageToken;
var page;
do {
page = AdminReports.UserUsageReport.get('all',date, {
parameters: parameters.join(','),
maxResults: 500,
pageToken: pageToken
});
if (page.warnings) {
for (var i = 0; i < page.warnings.length; i++) {
var warning = page.warnings[i];
Logger.log(warning.message);
}
}
var reports = page.usageReports;
if (reports) {
for (var i = 0; i < reports.length; i++) {
var report = reports[i];
var parameterValues = getParameterValues(report.parameters);
var row = [
report.date,
report.entity.userEmail,
parameterValues['accounts:first_name'],
parameterValues['accounts:last_name'],
parameterValues['accounts:is_super_admin'],
parameterValues['accounts:last_login_time'],
parameterValues['accounts:gmail_used_quota_in_mb'],
parameterValues['accounts:drive_used_quota_in_mb'],
parameterValues['gmail:timestamp_last_access'],
parameterValues['gmail:timestamp_last_imap'],
parameterValues['gmail:timestamp_last_pop'],
parameterValues['gmail:timestamp_last_webmail']
];
rows.push(row);
}
}
pageToken = page.nextPageToken;
} while (pageToken);
if (rows.length > 0) {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('UserSheet');
sheet.clear();
// Append the headers.
var headers = ['Date','User','First Name', 'Last Name','Admin Account Status', 'Last Login', 'Email Usage', 'Drive Usage','Last Access Date',
'IMAP','POP','WEBMAIL'];
sheet.appendRow(headers);
// Append the results.
sheet.getRange(2, 1, rows.length, headers.length).setValues(rows);
Logger.log('Report spreadsheet created: %s', spreadsheet.getUrl());
} else {
Logger.log('No results returned.');
}
}
/**
* Gets a map of parameter names to values from an array of parameter objects.
* #param {Array} parameters An array of parameter objects.
* #return {Object} A map from parameter names to their values.
*/
function getParameterValues(parameters) {
return parameters.reduce(function(result, parameter) {
var name = parameter.name;
var value;
if (parameter.intValue !== undefined) {
value = parameter.intValue;
} else if (parameter.stringValue !== undefined) {
value = parameter.stringValue;
} else if (parameter.datetimeValue !== undefined) {
value = new Date(parameter.datetimeValue);
} else if (parameter.boolValue !== undefined) {
value = parameter.boolValue;
}
result[name] = value;
return result;
}, {});
}
I would be very appreciative of any input. Thank you;
I'm using the G Suite Developer Quickstart for a Meet attendance script
https://developers.google.com/gsuite/add-ons/editors/sheets/quickstart/attendance
Unfortunately, upon using the provided code, and having made adjustments, I either always get "Absent" or "Present" for all students (regardless of whether they were present or not) depending on if I use "null" of "false" in an if statement for activities for applicationName 'meet'.
Here is the code I'm using as a superuser:
...
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Opciones SG')
.addItem("Importar Curso", 'importCourses')
.addItem('Verificar Asistencia', 'checkAll')
.addToUi();
}
function importCourses() {
var optionalArgs = {
teacherId: 'me',
pageSize: 5
};
var response = Classroom.Courses.list();
var courses = response.courses;
for (var i = 0; i < 1; i++) {
var courseName = courses[i].name;
var courseId = courses[i].id;
insertCourse(courseName, courseId)
}
}
function insertCourse(courseName, courseId) {
var spreadsheetName = courseName + "(" + courseId + ")"
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var yourNewSheet = activeSpreadsheet.getSheetByName(spreadsheetName);
if (yourNewSheet != null) {
return
}
yourNewSheet = activeSpreadsheet.insertSheet();
yourNewSheet.setName(spreadsheetName);
yourNewSheet.appendRow(['Nombre', 'Email', 'Asistencia'])
yourNewSheet.setFrozenRows(1)
var studentNames = getRoster(courseId)["studentNames"]
var studentEmails = getRoster(courseId)["studentEmails"]
for (var i = 0; i < studentNames.length; i++) {
yourNewSheet.appendRow([studentNames[i],studentEmails[i]])
}
yourNewSheet.autoResizeColumns(1, 2)
yourNewSheet.setFrozenColumns(2)
}
function getRoster(courseId) {
var studentNames = []
var studentEmails = []
var optionalArgs = {
pageSize: 100
};
var response = Classroom.Courses.Students.list(courseId, optionalArgs)
var students = response.students
for (var i = 0; i < 100; i++) {
try {
studentNames.push(students[i].profile.name.fullName)
studentEmails.push(students[i].profile.emailAddress)
} catch (err) {
return { "studentNames":studentNames, "studentEmails":studentEmails }
}
}
}
function checkAll() {
var ss = SpreadsheetApp.getActiveSheet();
var sheet = ss.getDataRange().getValues();
for (var i = 2; i < sheet.length * 100; i++){
var meetCode = getCleanCode(sheet[0][i])
// No Meet code given
if (meetCode == null) {
break;
}
else {
// check whether each student was present in Meet
checkMeet(meetCode, i+1);
}
}
}
function checkMeet(meetCode, index) {
// universal settings - static
var userKey = 'all';
var applicationName = 'meet';
var ss = SpreadsheetApp.getActiveSheet();
var sheet = ss.getDataRange().getValues();
for (var i = 0; i < sheet.length-1; i++) {
var emailAddress = sheet[i+1][1]
var optionalArgs = {
event_name: "call_ended",
filters: "identifier==" + emailAddress + ",meeting_code==" + meetCode
};
try {
var response = AdminReports.Activities.list(userKey, applicationName, optionalArgs);
var activities = response.items;
if (activities == false) {
markAbsent(ss,i+2,index)
}
else {
markPresent(ss,i+2,index)
}
} catch (err) {
continue
}
}
}
function getCleanCode(meetCode) {
try{
return meetCode.replace("/-/g","")
} catch (err) { return meetCode; }
}
function markAbsent(sheet, i, j) {
var cell = sheet.getRange(i, j);
cell.setValue("Absent");
}
function markPresent(sheet, i, j) {
var cell = sheet.getRange(i, j);
cell.setValue("Present");
}
...
For the correct functionality of the code, check for if (activities == null) or if (activities == undefined) - NOT if (activities == false)
If there are no response items (that is no items have been found for a given user and meeting code) - activities will be undefined, but not false.
if (activities == false) will never be fulfilled and if you use it - all participants will be marked as present
On the other hand, if activities == undefined for other reasons - for example because you introduced the wrong meet code (don't forget to replace 'Asistencia' through a valid meet code), all participants will be marked as absent
Note that the Reports API has some delay, so do not expect to retrieve participation data in live time.
If all participants are marked as absent - probably the data did not propagate yet, wait some time and try again.
Make sure you pass the correct meet code to the script. Your meet code should look something like xxx-xxxx-xxx.
The script needs to remove the - for correct functionality. For this please change in function getCleanCode(meetCode) the line return meetCode.replace("/-/g","") to return meetCode.replace(/-/g, "");
As for the question in your comment: here you can see all available Hangouts Meet Audit Activity Events that you can use for filtering instead of the meeting_code. Unfortunately the timestamp is not one of possible query parameters.
Here is the code we have been using for a few months now, no glitches:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Asistencia')
.addItem('Asistencia', 'checkAll')
.addItem('*Crear*', 'createNewSheets')
.addToUi();
}
function createNewSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Get the range of cells that store employee data.
var employeeDataRange = ss.getRangeByName("A:A");
var employeeObjects = employeeDataRange.getValues();
var template = ss.getSheetByName('Template');
for (var i=0; i < employeeObjects.length; i++) {
// Put the sheet you want to create in a variable
var sheet = ss.getSheetByName(employeeObjects[i]);
// Check if the sheet you want to create already exists. If so,
// log this and loop back. If not, create the new sheet.
if (sheet) {
Logger.log("Sheet " + employeeObjects[i] + "already exists");
} else {
template.copyTo(ss).setName(employeeObjects[i]);
}
}
return;
}
function importCourses() {
var optionalArgs = {
teacherId: 'me',
pageSize: 5
};
var response = Classroom.Courses.list(optionalArgs);
var courses = response.courses;
for (var i = 0; i < 2; i++) {
var courseName = courses[i].name;
var courseId = courses[i].id;
insertCourse(courseName, courseId)
}
}
function insertCourse(courseName, courseId) {
var spreadsheetName = courseName + "(" + courseId + ")"
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var yourNewSheet = activeSpreadsheet.getSheetByName(spreadsheetName);
if (yourNewSheet != null) {
return
}
yourNewSheet = activeSpreadsheet.insertSheet();
yourNewSheet.setName(spreadsheetName);
yourNewSheet.appendRow(['Nombre', 'Email', 'Asistencia'])
yourNewSheet.setFrozenRows(1)
var studentNames = getRoster(courseId)["studentNames"]
var studentEmails = getRoster(courseId)["studentEmails"]
for (var i = 0; i < studentNames.length; i++) {
yourNewSheet.appendRow([studentNames[i],studentEmails[i]])
}
yourNewSheet.autoResizeColumns(1, 2)
yourNewSheet.setFrozenColumns(2)
}
function getRoster(courseId) {
var studentNames = []
var studentEmails = []
var optionalArgs = {
pageSize: 100
};
var response = Classroom.Courses.Students.list(courseId, optionalArgs)
var students = response.students
for (var i = 0; i < 100; i++) {
try {
studentNames.push(students[i].profile.name.fullName)
studentEmails.push(students[i].profile.emailAddress)
} catch (err) {
return { "studentNames":studentNames, "studentEmails":studentEmails }
}
}
}
function checkAll() {
var ss = SpreadsheetApp.getActiveSheet();
var sheet = ss.getDataRange().getValues();
for (var i = 2; i < sheet.length * 100; i++){
var meetCode = getCleanCode(sheet[0][i])
// No Meet code given
if (meetCode == null) {
break;
}
else {
// check whether each student was present in Meet
checkMeet(meetCode, i+1);
}
}
}
function checkMeet(meetCode, index) {
// universal settings - static
var userKey = 'all';
var applicationName = 'meet';
var ss = SpreadsheetApp.getActiveSheet();
var sheet = ss.getDataRange().getValues();
//let today = new Date()
//var staringTime = new Date().toISOString();
// var DateValue = ss.getRange(1, 1).getValues();
for (var i = 0; i < sheet.length-1; i++) {
var emailAddress = sheet[i+1][1]
var optionalArgs = {
startTime: formatStartDate(),
event_name: "call_ended",
filters: "identifier==" + emailAddress + ",meeting_code==" + meetCode
};
try {
var response = AdminReports.Activities.list(userKey, applicationName, optionalArgs);
var activities = response.items;
if (activities == undefined) {
markAbsent(ss,i+2,index)
}
else {
markPresent(ss,i+2,index)
}
} catch (err) {
continue
}
}
}
function getCleanCode(meetCode) {
try{
return meetCode.replace(/-/g, "");
} catch (err) { return meetCode; }
}
function markAbsent(sheet, i, j) {
var cell = sheet.getRange(i, j);
cell.setValue("A");
}
function markPresent(sheet, i, j) {
var cell = sheet.getRange(i, j);
cell.setValue("");
}
function formatStartDate(){
let date = new Date();
const offset = date.getTimezoneOffset();
let offsetDate = new Date(date.getTime() - (offset*145*1000));
return offsetDate.toISOString();
}
I have the below script in place (1st script implemented 1 year ago) to move a row form 1 sheet to another (within a google sheet/workbook). The problem is that is does not take the comments with it. Does anyone know how I can include any unresolved comments in the transition from sheet to sheet?
var objSettings = {
sheets : ['CHECK', 'STAGE2', 'READY', 'SCHEDULED', 'ARCHIVE', 'WASTE'],
shActive : [1, 1, 1, 1, 1, 1],
column : 1,} function onEdit(e) {try{var sh = e.range.getSheet();if (e.range.getNumRows() == 1 && e.range.getNumColumns() == 1 && e.range.getColumn() == objSettings.column) {
var sheetName = '';
for (var i = 0; i < objSettings.sheets.length; i++) {
if (objSettings.sheets[i] == sh.getName().trim().toUpperCase()) {
if (objSettings.shActive[i] == 1) {
Logger.log(('' + e.value).trim().toUpperCase() );
Logger.log(sh.getName().trim().toUpperCase());
if (('' + e.value).trim().toUpperCase() != sh.getName().trim().toUpperCase()) {
var shDest = e.source.getSheetByName(e.value);
if (!(shDest)) {
var shDest = e.source.getSheetByName(('' + e.value).trim().toProperCase());
}
if (!(shDest)) {
var shDest = e.source.getSheetByName(('' + e.value).trim().toLowerCase());
}
if (!(shDest)) {
var shDest = e.source.getSheetByName(('' + e.value).trim().toUpperCase());
}
Logger.log(shDest);
if (shDest) {
var currRow = e.range.getRow();
var dataDest = shDest.getDataRange().getValues();
for (var j = 3; j < dataDest.length; j++) {
if (('' + dataDest[j][objSettings.column - 1]).length == 0) {
break;
}
}
var lastRow = j;
for (var k = 0; k < objSettings.sheets.length; k++) {
if (('' + e.value).trim().toUpperCase() == objSettings.sheets[k]) {
var type = objSettings.shActive[k];
break;
}
}
var dataR = sh.getRange(currRow, 1, 1, sh.getLastColumn()).getValues();
if (type == 1) {
shDest.getRange(lastRow + 1, 1, 1, dataR[0].length).setValues(dataR);
} else {
var dataR0 = dataR[0];
dataR0.shift();
shDest.getRange(lastRow + 1, 1, 1, dataR[0].length).setValues([dataR0]);
}
sh.deleteRow(currRow);
Logger.log(currRow);
Logger.log(lastRow + 1);
Logger.log(type);
sh.getParent().toast('The row has been moved!', 'Info');
}
}
}
break;
}
}
}}catch(e){
SpreadsheetApp.getUi().alert(e); } }
Alternatively, if you think there is a better more stable way of accomplishing this, please do let me know.
Use moveTo() to cut and paste ranges with comments.
Comments are a part of the Drive API.
Enable the Advanced Drive Service to use Drive.Comments.{}
Then you can check the status property for "open" || "resolved"
function moveComments () {
var ss = SpreadsheetApp.getActive();
var range_one = ss.getSheets()[0].getRange("A10");
var range_two = ss.getSheets()[1].getRange("A10");
// Get a list of all comments in the workbook
var workbook_comments = Drive.Comments.list(ss.getId());
/*
var comment_cell_value = workbook_comments.items[0].context.value;
var check_status = workbook_comments.items[0].status; // "open" || "resolved"
*/
// Move the range with comments to another sheet.range
range_one.moveTo(range_two);
}
See also Manage Comments and Discussions
I'm about to bulk update multiple users email domaine in g-suite using the code below - found it here https://support.google.com/a/answer/7068037
// Cell Colors
COLOR_GRAY = '#434343';
COLOR_GREEN = '#B5D5A7';
COLOR_RED = '#E89898';
COLOR_YELLOW = '#FDE398';
COLOR_WHITE = '#FFFFFF';
// Sheet Columns
COLUMN_PARAMETER = 1;
COLUMN_RESULT = 2;
COLUMN_USER = 1;
COLUMN_VALUE = 2;
// Header Labels
HEADER_PARAMETER = 'Parameter';
HEADER_RESULT = 'Result';
HEADER_USER = 'Username';
HEADER_VALUE = 'Value';
// Status Messages
MESSAGE_COMPLETE = 'User renamed to: ';
MESSAGE_PAUSE = 'Select "Start Rename" from the "Actions" menu to continue';
MESSAGE_RUNTIME = 'Runtime exceeded. Will resume automatically in a few minutes';
MESSAGE_STOP = 'Select "Start Rename" from the "Actions" menu to continue';
// Parameter Labels
PARAMETER_DOMAIN = 'Domain Name';
PARAMETER_CURRENT = 'Current Row';
PARAMETER_RUN = 'Run Number';
// Parameter Dimensions
PARAMETER_COLUMNS = 2;
PARAMETER_ROWS = 4;
// Result Dimensions
RESULT_COLUMNS = 2;
// Sheet Rows
ROW_DOMAIN = 2;
ROW_HEADER = 1;
ROW_CURRENT = 4;
ROW_RUN = 3;
// Runtime Settings
RUNTIME_MAX = 270000;
RUNTIME_PAUSE = 60000;
// Sheet Names
SHEET_PARAMETERS = 'Parameters';
SHEET_RESULTS = 'Results';
// Status Labels
STATUS_ABORT = '[ABORTED]';
STATUS_ERROR = '[ERROR]';
STATUS_PAUSE = '[PAUSED]';
STATUS_COMPLETE = '[COMPLETED]';
// Cell Sizes
WIDTH_SMALL = 200;
WIDTH_MEDIUM = 400;
WIDTH_LARGE = 800;
// Parameter Values
VALUE_CURRENT = 2;
VALUE_NULL = '';
VALUE_RUN = 1;
// Clears all triggers from current project.
function clearTriggers() {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
}
// Returns currently active sheet
function getCurrentSheet() {
return SpreadsheetApp.getActiveSheet();
}
// Returns currently active spreadsheet
function getCurrentSpreadsheet() {
return SpreadsheetApp.getActiveSpreadsheet();
}
// Returns value of specified cell in a sheet
function getCellValue(sheet, row, column) {
return sheet.getRange(row, column).getValue();
}
// Returns value of the specified parameter
function getParameter(parameter) {
return getCellValue(getSheet(SHEET_PARAMETERS), parameter, COLUMN_VALUE);
}
// Returns sheet with the specified name (if one exists)
function getSheet(name) {
return getCurrentSpreadsheet().getSheetByName(name);
}
// Returns true if 'haystack' contains 'needle'.
function hasString(haystack, needle) {
return String(haystack).indexOf(needle) != -1;
}
// Returns true if script is nearing the max run time (4.5 min).
function isRuntimeExpired(start, currentTime) {
return currentTime - start >= RUNTIME_MAX;
}
// Adds custom items to "Actions" menu of spreadsheet
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Actions')
.addItem('Start Rename', 'startRename')
.addItem('Pause Rename', 'pauseRename')
.addItem('Stop Rename', 'stopRename')
.addItem('Reset Spreadsheet', 'resetSpreadsheet')
.addToUi();
}
// Pause rename process (manually)
function pauseRename() {
clearTriggers();
var results = getSheet(SHEET_RESULTS);
var lastRow = results.getLastRow();
var row = getParameter(ROW_CURRENT);
var currentResult = getCellValue(results, row, COLUMN_RESULT);
if (!hasString(currentResult, STATUS_ABORT) &&
!hasString(currentResult, STATUS_ERROR) &&
!hasString(currentResult, STATUS_PAUSE)) {
row = row + 1;
}
if (row < lastRow) {
setResult(row, COLOR_YELLOW, STATUS_PAUSE, MESSAGE_PAUSE);
}
}
// Formats layout of "Parameters" sheet
function formatParameters() {
var parameters = getSheet(SHEET_PARAMETERS);
var lastColumn = parameters.getMaxColumns();
var lastRow = parameters.getMaxRows();
if (lastColumn > PARAMETER_COLUMNS) {
parameters.deleteColumns(
PARAMETER_COLUMNS + 1, lastColumn - PARAMETER_COLUMNS);
}
parameters.getRange(ROW_HEADER, COLUMN_PARAMETER, lastRow).clear();
parameters.getRange(ROW_HEADER, COLUMN_VALUE, lastRow).clear();
parameters.getRange(ROW_HEADER, COLUMN_RESULT).setFontColor(COLOR_WHITE);
parameters.setColumnWidth(COLUMN_PARAMETER, WIDTH_SMALL);
parameters.setColumnWidth(COLUMN_VALUE, WIDTH_SMALL);
parameters.getRange(ROW_HEADER, COLUMN_PARAMETER)
.setBackground(COLOR_GRAY)
.setFontColor(COLOR_WHITE)
.setValue(HEADER_PARAMETER);
parameters.getRange(ROW_HEADER, COLUMN_VALUE)
.setBackground(COLOR_GRAY)
.setFontColor(COLOR_WHITE)
.setValue(HEADER_VALUE);
parameters.getRange(ROW_DOMAIN, COLUMN_PARAMETER).setValue(PARAMETER_DOMAIN);
parameters.getRange(ROW_RUN, COLUMN_PARAMETER).setValue(PARAMETER_RUN);
parameters.getRange(ROW_CURRENT, COLUMN_PARAMETER)
.setValue(PARAMETER_CURRENT);
parameters.setFrozenRows(ROW_HEADER);
}
// Formats layout of "Results" sheet
function formatResults() {
var results = getSheet(SHEET_RESULTS);
var userHeader = results.getRange(ROW_HEADER, COLUMN_USER);
var lastColumn = results.getMaxColumns();
var lastRow = results.getLastRow();
if (hasString(userHeader.getValue(), '#')) {
results.insertRowBefore(1);
}
if (lastColumn > RESULT_COLUMNS) {
results.deleteColumns(RESULT_COLUMNS + 1, lastColumn - RESULT_COLUMNS);
}
if (lastColumn < RESULT_COLUMNS) {
results.insertColumnAfter(COLUMN_USER);
}
results.getRange(ROW_HEADER, COLUMN_USER, lastRow).clearFormat();
results.getRange(ROW_HEADER, COLUMN_RESULT, lastRow).clear();
userHeader.setFontColor(COLOR_WHITE);
results.getRange(ROW_HEADER, COLUMN_RESULT).setFontColor(COLOR_WHITE);
userHeader.setValue(HEADER_USER);
results.setColumnWidth(COLUMN_USER, WIDTH_MEDIUM);
results.setColumnWidth(COLUMN_RESULT, WIDTH_LARGE);
results.setFrozenRows(ROW_HEADER);
setResult(ROW_HEADER, COLOR_GRAY, HEADER_RESULT, '');
}
// Renames email address of each user in "Results" sheet
function renameUsers(start) {
var results = getSheet(SHEET_RESULTS);
SpreadsheetApp.setActiveSheet(results);
var lastRow = results.getLastRow();
var firstRow = getParameter(ROW_CURRENT);
var domain = getParameter(ROW_DOMAIN);
if (firstRow && firstRow <= lastRow) {
setResult(firstRow, COLOR_WHITE, VALUE_NULL, VALUE_NULL);
for (var row = firstRow; row <= lastRow; row++) {
setCurrentRow(row);
var currentEmail = getCellValue(results, row, COLUMN_USER);
var currentResult = getCellValue(results, row, COLUMN_RESULT);
var userExists = false;
if (row != lastRow) {
if (isRuntimeExpired(start, new Date().getTime())) {
setTrigger(RUNTIME_PAUSE);
setTrigger(RUNTIME_PAUSE + RUNTIME_MAX);
setResult(row, COLOR_YELLOW, STATUS_PAUSE, MESSAGE_RUNTIME);
return;
}
}
if (hasString(currentResult, STATUS_PAUSE)) {
return;
}
if (hasString(currentResult, STATUS_ABORT)) {
var parameters = getSheet(SHEET_PARAMETERS);
setCurrentRow(row);
getCurrentSpreadsheet().deleteSheet(parameters);
return;
}
if (hasString(currentResult, STATUS_COMPLETE)) continue;
setResult(row, COLOR_RED, STATUS_ABORT, VALUE_NULL);
if (!hasString(currentEmail, '#')) continue;
var delimiter = currentEmail.indexOf('#');
var currentUsername = currentEmail.substring(0, delimiter);
var newUsername = currentUsername + '#' + domain;
var user = {'primaryEmail': newUsername};
try {
AdminDirectory.Users.update(user, currentEmail);
message = MESSAGE_COMPLETE + user.primaryEmail;
setResult(row, COLOR_GREEN, STATUS_COMPLETE, message);
} catch (err) {
setResult(row, COLOR_RED, STATUS_ERROR, err.message);
}
Utilities.sleep(100);
parameters = getSheet(SHEET_PARAMETERS);
}
}
getCurrentSpreadsheet().deleteSheet(parameters);
return;
}
//Resets layout of "Results" sheet; removes "Parameters" sheet
function resetSpreadsheet() {
clearTriggers();
var parameters = getSheet(SHEET_PARAMETERS);
if (parameters) {
getCurrentSpreadsheet().deleteSheet(parameters);
}
formatResults();
}
//Sets background color of specified cell in a sheet
function setCellColor(sheet, row, column, color) {
sheet.getRange(row, column).setBackground(color);
}
//Sets value of specified cell in a sheet
function setCellValue(sheet, row, column, value) {
sheet.getRange(row, column).setValue(value);
}
//Sets value of "Row Number" parameter
function setCurrentRow(row) {
var parameters = getSheet(SHEET_PARAMETERS);
Utilities.sleep(50);
setCellValue(parameters, ROW_CURRENT, COLUMN_VALUE, row);
Utilities.sleep(50);
}
//Sets value of "Domain Name" parameter
function setDomainName(domain) {
var parameters = getSheet(SHEET_PARAMETERS);
setCellValue(parameters, ROW_DOMAIN, COLUMN_VALUE, domain);
}
//Sets result of specified row in "Results" sheet
function setResult(row, color, status, message) {
var results = getSheet(SHEET_RESULTS);
results.getRange(row, COLUMN_USER).setBackground(color);
results.getRange(row, COLUMN_RESULT).setBackground(color);
if (message == VALUE_NULL) {
results.getRange(row, COLUMN_RESULT).setValue(status);
} else {
results.getRange(row, COLUMN_RESULT).setValue(status + ' ' + message);
}
}
//Sets value of "Run Number" parameter
function setRunNumber(count) {
var parameters = getSheet(SHEET_PARAMETERS);
setCellValue(parameters, ROW_RUN, COLUMN_VALUE, count);
}
function setTrigger(pause) {
ScriptApp.newTrigger('startRename').timeBased().after(pause).create();
}
//Starts rename process
function startRename() {
clearTriggers();
var start = new Date().getTime();
if (getSheet(SHEET_PARAMETERS)) {
var results = getSheet(SHEET_RESULTS);
var parameters = getSheet(SHEET_PARAMETERS);
setRunNumber(getParameter(ROW_RUN) + 1);
} else {
getCurrentSheet().setName(SHEET_RESULTS);
formatResults();
var domains = AdminDirectory.Domains.list('my_customer').domains;
var ui = SpreadsheetApp.getUi();
var input = ui.prompt('Rename users to which domain?', ui.ButtonSet.OK_CANCEL);
if (input.getSelectedButton() == ui.Button.OK) {
var valid = false;
var domain = input.getResponseText().toLowerCase();
for (var i in domains) {
if (domain == domains[i].domainName.toLowerCase()) {
valid = true;
}
}
if (!valid) {
ui.alert(
'The specified domain is invalid! Please try again.',
ui.ButtonSet.OK);
return;
}
} else {
return;
}
var results = getSheet(SHEET_RESULTS);
var parameters = getCurrentSpreadsheet().insertSheet(SHEET_PARAMETERS);
formatParameters();
setDomainName(domain);
setCurrentRow(VALUE_CURRENT);
setRunNumber(VALUE_RUN);
}
renameUsers(start);
}
//Stop rename process
function stopRename() {
clearTriggers();
var results = getSheet(SHEET_RESULTS);
var lastRow = results.getLastRow();
var row = getParameter(ROW_CURRENT);
var currentResult = getCellValue(results, row, COLUMN_RESULT);
if (hasString(currentResult, STATUS_ABORT) ||
hasString(currentResult, STATUS_ERROR) ||
hasString(currentResult, STATUS_PAUSE)) {
var parameters = getSheet(SHEET_PARAMETERS);
if (parameters) {
getCurrentSpreadsheet().deleteSheet(parameters);
}
} else {
row = row + 1;
}
setResult(row, COLOR_RED, STATUS_ABORT, MESSAGE_STOP);
}
Since I'm changing the domain I will like also to update different fields, like Department....
Is there a simplest way to do it rather then using a script?
Where do I find the users fields?
Regards
Hugo L
I wrote a script for managing G suite user email signatures which you might want to check out.
python set-signatures.py
It allows you to set the signature for every user in your organization using an HTML template, a CSV of users and the Google Service Account API.