I have set up the Google analytics API on Google sheets for reporting purposes, however have had some issues:
How to add titles to the table?
function myFunction() {
var tableId = 'ga:*******' // Your Google Analytics view ID
var startDate = '2daysAgo';
var endDate = '1daysAgo';
var metric = 'ga:pageviews';
var options = {
'dimensions': 'ga:pageTitle, ga:date',
'sort': '-ga:date',
'filters': 'ga:pageTitle==(EN) SignUp Page'
};
var result = Analytics.Data.Ga.get(tableId, startDate, endDate, metric, options); // Make the request
var total_sessions = result.totalsForAllResults['ga:sessions'];
var total_transactions = result.totalsForAllResults['ga:transactions'];
var doc = SpreadsheetApp.getActiveSpreadsheet(); // Current document
var sheet = doc.getSheetByName('Sheet1'); // Current sheet
//sheet.getRange('B3').setValue(total_sessions); // Write total sessions
//sheet.getRange('B4').setValue(total_transactions); // Write toal transactions
var rows = result.rows;
for (var k = 0; k < rows.length; k++) {
var pagetitle= rows[k][0];
var date= rows[k][1];
var pageviews= rows[k][2];
var result_row = [pagetitle, date, pageviews]; // Single row of results
sheet.appendRow(result_row); // Print single row of results
}
}
use sheet.appendRow to add desired header row before looping through report rows.
Related
I'm posting after having read different posts here in SO, and still, I didn't manage to solve my problem.
What I'm trying to do is basically to retrieve from Google Calendars the events from different calendars and have them listed in an excel file.
The script below correctly gets the events from the first calendar, but not from the others. From the others, I basically get an empty array.
Here is the code I'm working with:
function getEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var sheetsoptions = ss.getSheetByName("Options");
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
// var id_cal = sheet.getRange("C2").getValue();
var id_cal = sheetsoptions.getRange("A5:A6").getValues();
var arrayLength = id_cal.length;
var cell_events = 5;
for (var j = 0; j < arrayLength; j++) {
if (id_cal[j] == ""){
break;
}
else{
var cal = CalendarApp.getCalendarById(id_cal[j]);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
for (var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var loc = events[i].getLocation();
var des = events[i].getDescription();
var vis = events[i].getVisibility();
sheet.getRange(cell_events,1).setValue(title);
sheet.getRange(cell_events,2).setValue(start_time);
sheet.getRange(cell_events,3).setValue(end_time);
sheet.getRange(cell_events,4).setValue(loc);
sheet.getRange(cell_events,5).setValue(des);
sheet.getRange(cell_events,6).setValue(vis);
cell_events++;
}
}
}
Logger.log("Events have been added to the Spreadsheet");
}
Thanks in advance for your help.
Luca
I think you just had a small issue with your calid being a 2d array. Try this, it's almost the same thing that you had, written a little differently.
function getEvents() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Sheet1");
var sheetsoptions = ss.getSheetByName("Options");
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
var calid = sheetsoptions.getRange("A5:A6").getValues().flat().filter(id => id);//test for truthiness
var row = 5;
calid.forEach(id => {
var cal = CalendarApp.getCalendarById(id);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
events.forEach(ev => {
var title = ev.getTitle();
var start_time = ev.getStartTime();
var end_time = ev.getEndTime();
var loc = ev.getLocation();
var des = ev.getDescription();
var vis = ev.getVisibility();
sheet.getRange(row++, 1, 1, 6).setValues([[title, start_time, end_time, loc, des, vis]]);//this should save some time writing all five columns at the same time
});
});
Logger.log("Events have been added to the Spreadsheet");
}
Issue:
You are using the same variables for minimum and maximum dates when listing calendar events and for getting the start and end time of each event (start_time, end_time).
Because of this, after the first calendar iteration, start_time and end_time are not the times defined in cells A2 and B2, but the start and end times of the last event in the first calendar.
Solution:
Update one of the two sets of variables so there's no confusion. For example:
var event_start_time = events[i].getStartTime();
var event_end_time = events[i].getEndTime();
// ...
sheet.getRange(cell_events,2).setValue(event_start_time);
sheet.getRange(cell_events,3).setValue(event_end_time);
Note:
Consider using setValues to write all event values at once instead of setValue, in order to minimize calls to Sheets service and improve efficiency (see Use batch operations).
I have the following Google Sheets Apps Script to extract calendar invites to a Google Sheet, however, I am trying to make some adjustments that I am struggling to find a solution for:
function getEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
var id_cal = sheet.getRange("P5").getValue();
var cal = CalendarApp.getCalendarById(id_cal);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
for (var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var des = events[i].getDescription();
var vis = events[i].getVisibility();
var guestlist = events[i].getGuestList();
sheet.getRange(i+5,1).setValue(title);
sheet.getRange(i+5,2).setValue(start_time);
sheet.getRange(i+5,3).setValue(end_time);
sheet.getRange(i+5,4).setValue(des);
sheet.getRange(i+5,5).setValue(vis);
sheet.getRange(i+5,6).setValue(guestlist);
}
Logger.log("Events have been added to the Spreadsheet");
}
How do I amend this script to:
Extract from several calendars that I have the email addresses in a range of cells (Z1:Z25) instead of just 1 calendar. I have attempted changing the range, but it only pulls the calendar from the top cell.
Include all accepted/pending attendees (including the organiser). I have attempted to add .getGuestList, but this returns 'EventGuest'
Include the calendar that event was taken from
I believe your goal is as follows.
You want to retrieve the events from multiple Calendars by the calendar IDs which are retrieved from the cells "Z1:Z25" of the Spreadsheet.
As the data, from Include all accepted/pending attendees (including the organiser)., you want to add the user's email addresses.
You want to add the calendar IDs as the additional value.
Modification points:
In your script, only one Calendar ID is used. In order to achieve your goal, it is required to retrieve the calendar IDs from the cells "Z1:Z25".
About I have attempted to add .getGuestList, but this returns 'EventGuest', the method of getGuestList() returns EventGuest object. I think that this is the reason for your issue.
In your script, setValue is used in a loop. In this case, the process cost becomes high. Ref
When these points are reflected in your script, it becomes as follows.
Modified script:
function getEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var [start_time, end_time] = sheet.getRange("A2:B2").getValues()[0];
var dates = [new Date(start_time), new Date(end_time)]; // If the cell value is date object, you can also use [start_time, end_time]
var ids = sheet.getRange("Z1:Z25").getValues().reduce((ar, [z]) => {
if (z) ar.push(z);
return ar;
}, []);
var values = ids.flatMap(id_cal => {
var cal = CalendarApp.getCalendarById(id_cal);
if (!cal) return [];
var events = cal.getEvents(...dates);
return events.map(e => {
var title = e.getTitle();
var start = e.getStartTime();
var end = e.getEndTime();
var des = e.getDescription();
var vis = e.getVisibility().toString(); // or e.getVisibility()
var guestlist = e.getGuestList().map(f => f.getEmail()).join(",");
return [id_cal, title, start, end, des, vis, guestlist];
});
});
sheet.getRange(5, 1, values.length, values[0].length).setValues(values);
Logger.log("Events have been added to the Spreadsheet");
}
When this script is run, the calendar IDs are retrieved from "Z1:Z25" of "Sheet1". And, the events are retrieved, and the values are retrieved from each event. In this case, the calendar ID, event title, start time, end time, description, visibility, and guest email addresses are put on the sheet in order.
If you want to change the order of values, please modify return [id_cal, title, start, end, des, vis, guestlist];.
If you want to change the user's email to the user's name, please modify f.getEmail() to f.getName().
Note:
This modified script is a simple modification. So, please modify this for your actual situation.
References:
map()
Class EventGuest
Try something like this:
function getEvents() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName("Sheet1");
var start = sh.getRange("A2").getValue();
var end = sh.getRange("B2").getValue();
const ids = [];
CalendarApp.getAllCalendars().forEach(c => ids.push(c.getId()));
ids.forEach(id => {
let cal = CalendarApp.getCalendarById(id);
let events = cal.getEvents(new Date(start), new Date(end));
for (var i = 0; i < events.length; i++) {
var title = events[i].getTitle();
var start = events[i].getStartTime();
var end = events[i].getEndTime();
var des = events[i].getDescription();
var vis = events[i].getVisibility();
var guestlist = events[i].getGuestList();
let row = sh.getLastRow() + 1
sh.getRange(sh.getLastRow() + 1, 1,1,5).setValues([[title,start,end,des,vis,guestlist]]);
}
})
Logger.log("Events have been added to the Spreadsheet");
}
I'll leave it up to you to add the additional items as this is not a venue for getting free scripts.
I need help deleting the filtered row in a sheet without timing out. There are over 10,000 rows in the sheet so running a for loop with DeleteRow() is timing out.
The larger goal of the project is to basically archive data from the main sheet to an archive sheet automatically if the date is more than 31 days ago.
This is the current code I currently have to do this but the loop is working really slow with as much data as I have in the sheets. If there are any other major performance improvements feel free to make those suggestions as well. This is my first real time working with google app scripts
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copy_sheet = ss.getSheetByName("upload");
var paste_sheet = ss.getSheetByName("archive");
const day = 24 * 60 * 60 * 1000;
var date = new Date();
var remove_before_date = new Date()
remove_before_date.setDate(date.getDate()-31);
var prev_filter = copy_sheet.getFilter();
if (prev_filter !== null) {
prev_filter.remove();
return;
}
//create filter
var range = copy_sheet.getRange("A:I");
var filter = range.createFilter();
var Filter_Criteria = SpreadsheetApp.newFilterCriteria().whenDateBefore(remove_before_date);
var add_filter = filter.setColumnFilterCriteria(1,Filter_Criteria);
//copy and paste
var range = copy_sheet.getDataRange().offset(2,0);
var last_row_archive = paste_sheet.getDataRange().getNumRows();
var last_row_upload = copy_sheet.getDataRange().getNumRows();
paste_sheet.insertRowAfter(last_row_archive)
range.copyTo(paste_sheet.getRange(last_row_archive+1,1));
//delete from upload
for (var i = last_row_upload; i > 2; i--) {
if (!copy_sheet.isRowHiddenByFilter(i)) {
copy_sheet.deleteRow(i);
}
}
//remove filters
filter.remove();
}```
The execution will be much faster if you
get all values of source sheet
filter them as you wish
split them into two arrays: array to remove, array to stay
place values of these arrays to source sheet and target sheet respectively.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getSheetByName('upload');
var target = ss.getSheetByName('archive');
var data = source.getDataRange();
var range = source.getRange(3,1,data.getNumRows()-2, data.getNumColumns());
var values = range.getValues();
var datesCol = 'I'; //replace this with where your dates are
var datesColIndex = source.getRange(datesCol + ':' + datesCol).getColumn()-1;
var lastRowArchive = target.getDataRange().getNumRows();
//this filters data and gets all rows, the date of which earlier then 31 days.
var valuesToRemove = values.filter(function(row) {
var dayInMs= 24 * 60 * 60 * 1000;
return new Date().valueOf() - new Date(row[datesColIndex]).valueOf() >= dayInMs*31;
})
//this creates a new array containing only the remaining rows
var valuesToStay = values.filter(row => !valuesToRemove.includes(row));
//if there are values to remove
if (valuesToRemove.length) {
//clear the range in the source sheet
range.clearContent();
//place valuesToStay array to the source sheet
source.getRange(3,1,valuesToStay.length,valuesToStay[0].length)
.setValues(valuesToStay);
//place valuesToRemove array to end of the target sheet
target.getRange(lastRowArchive+1,1,valuesToRemove.length, valuesToRemove[0].length)
.setValues(valuesToRemove);
}
}
I want to copy the cell with the daily score from the sheets of all of my students in a spreadsheet where they are calculated and collected to another spreadsheet where they are used as currency to buy rewards. Both spreadsheets contain a sheet for every student that is named after that student, e.g. "John Smith"
The original google script that I created worked, but it was poor coding because I had to repeat the coding for every single name, and therefore add a new paragraph of code every time we get a new student. I would like to create a new google script that is more elegant and powerful and works without specifying the students' names so that it never needs to be amended. I can't quite get it and keep hitting a "Syntax error" with the last line.
function ImportDailyScore() {
var dailyinput = "J27"; // Mon=J3, Tue=J9, Wed=J15, Thu=J21, Fri=J27
var dollaroutput = "B2"; // Today=B2, Yesterday=B3, etc.
var dollarspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var checkinspreadsheet = SpreadsheetApp.openById('some id');
var checkinsheets = checkinspreadsheet.getSheets(); // get all the sheets from check in doc
var dollarsheets = dollarspreadsheet.getSheets(); // get all the sheets from dollar doc
for (var i=0; i<checkinsheets.length; i++){ // loop across all the checkin sheets
var checkindata = checkinsheets[i].getRange(dailyinput).getValue();
var namedcheckin = checkinsheets[i].getSheetName()
for (var j=0; j<dollarsheets.length; j++){
var nameddollar = dollarsheets[j].getSheetName();
if (namedcheckin = nameddollar, dollarsheets[j].getRange(dollaroutput).setValue(checkindata))
}
}
}
For reference, the original code (which works just as I would like it to) but needs to specify the name of every single student is:
function ImportDailyScore() {
var dollarspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var checkinspreadsheet = SpreadsheetApp.openById('1Y9Ys1jcm1xMaLSqmyl_pFnvIzbf-omSeIcaI2FgjFIs');
var dailyinput = "J3"; // Mon=J3, Tue=J9, Wed=J15, Thu=J21, Fri=J27
var dollaroutput = "B4"; // Today=B2, Yesterday=B3, etc.
var JohnCHECKIN = checkinspreadsheet.getSheetByName('John Smith');
var JohnCHECKINData = JohnCHECKIN.getRange(dailyinput).getValue();
var JohnDOLLAR = dollarspreadsheet.getSheetByName('John Smith');
JohnDOLLAR.getRange(dollaroutput).setValue(JohnCHECKINData);
var JenniferCHECKIN = checkinspreadsheet.getSheetByName('Jennifer Scott');
var JenniferCHECKINData = JenniferCHECKIN.getRange(dailyinput).getValue();
var JenniferDOLLAR = dollarspreadsheet.getSheetByName('Jennifer Scott');
JenniferDOLLAR.getRange(dollaroutput).setValue(JenniferCHECKINData);
etc.
Try this:
I don't have enough information to know how to handle the dollaroutput programmatically.
function ImportDailyScore() {
var inputA=['','J3','J9','J15','J21','J27',''];
var dailyinput = inputA[new Date().getDay()];
if(dailyinput) {
var dollaroutput = "B2"; // Today=B2, Yesterday=B3, etc. Not sure how to handle this programmatically I'd have to see the sheet
var dollarspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var checkinspreadsheet = SpreadsheetApp.openById('id');
var checkinsheets = checkinspreadsheet.getSheets(); // get all the sheets from check in doc
var dollarsheets = dollarspreadsheet.getSheets(); // get all the sheets from dollar doc
for (var i=0; i<checkinsheets.length; i++){ // loop across all the checkin sheets
var checkindata = checkinsheets[i].getRange(dailyinput).getValue();
var namedcheckin = checkinsheets[i].getSheetName();
for (var j=0; j<dollarsheets.length; j++){
var nameddollar = dollarsheets[j].getSheetName();
if (namedcheckin == nameddollar) {
dollarsheets[j].getRange(dollaroutput).setValue(checkindata);
}
}
}
}else{
SpreadsheetApp.getUi().alert(Utilities.formatString('Today is %s no school.', Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "E")));
}
}
I have been trying for days now, reading other posts, playing with other scripts that have been close to the same purpose and nothing works. I am trying to make a script that will take information from a web based google form, along with a month/day and turn it into a re-occuring event in the Calendar.
It is finally posting to the Calendar NOW but every event comes up undefined under December 31, 2015 - with no further information, altho at least it is reoccurring.
Any help would be greatly appreciated as I try to understand this coding and how to do it. Thank you!
//this is the ID of the calendar to add the event to, this is found on the calendar settings page of the calendar in question
var calendarId = "id#group.calendar.google.com";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 5;
var endDtId = 5;
var titleId = 2;
var descId = 3;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var startDt = sheet.getRange(lr,startDtId,1,1).getValue();
//set to first hour and minute of the day.
// startDt.setHours(0);
// startDt.setMinutes(00);
var endDt = sheet.getRange(lr,endDtId,1,1).getValue();
//set endDt to last hour and minute of the day
// endDt.setHours(23);
// endDt.setMinutes(59);
// var subOn = "Submitted on :"+sheet.getRange(lr,formTimeStampId,1,1).getValue();
var desc = sheet.getRange(lr,descId,1,1).getValue();
var title = sheet.getRange(lr,titleId,1,1).getValue();
createAllDayEvent(calendarId,title,startDt,endDt,recurrence,loc,desc);
}
function createAllDayEventSeries(calendarId,title,startDt,endDt,recurrence,loc,desc) {
var cal = CalendarApp.getCalendarById('id#group.calendar.google.com');
var start = new Date(startDt);
var end = new Date(endDt);
var loc = descId;
var desc = "Happy Birthday "+titleId+" of "+descId;
// Creates a rule that recurs every week for ten weeks.
var recurrence = CalendarApp.newRecurrence().addYearlyRule();
var event = cal.createAllDayEventSeries(title, start, recurrence, {
description : desc,
location : loc
});
};
I created a form and tested with the following code:
// Column data constants
var nameCol = 2;
var birthdayCol = 3;
var descriptionCol = 4;
var locationCol = 4;
var calendarId = '[id]#group.calendar.google.com';
/* Send Confirmation Email with Google Forms */
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("CreateCalendarEvent")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
function createEvent() {
var ss = SpreadsheetApp.getActiveSheet();
var rows = ss.getDataRange();
var lr = rows.getLastRow();
var start = ss.getRange(lr,birthdayCol,1,1).getValue();
start.setHours(0);
start.setMinutes(00);
var title = ss.getRange(lr,nameCol,1,1).getValue() + " Birthday";
var desc = ss.getRange(lr,descriptionCol,1,1).getValue();
var loc = ss.getRange(lr,locationCol,1,1).getValue();
var recurrence = CalendarApp.newRecurrence().addYearlyRule();
Logger.log("accessing calendar");
var externalCalendar = CalendarApp.getCalendarById(calendarId);
externalCalendar.createAllDayEventSeries(title, start, recurrence, {
description : desc,
location : loc
});
}
function getRelativeDate(daysOffset, hour) {
var date = new Date();
date.setDate(date.getDate() + daysOffset);
date.setHours(hour);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
}
function CreateCalendarEvent(e) {
try {
Logger.log("creating event");
createEvent();
} catch (e) {
Logger.log(e.toString());
}
}
This sets a trigger function when the form is submitted, make sure that you change the value of the calendar id to the one provided by your calendar.