Reputation: 1
So I used an importGoogleCalendar code to pull my workers' names and hours from Google Calendar to Google Sheets. However, I pulled EVEYRTHING. The names are duplicated a numerous amount of times in multiple rows for each day with their corresponding hours. How can I get one unique name for each worker along with their added up hours for each time their name appears on the sheet to another sheet so that it looks cleaner and easier to look at?
Example: I would like
Name | Hours |
---|---|
Sam | 5 |
Sam | 7 |
Bob | 3 |
Sam | 5 |
Sam | 7 |
Bob | 6 |
Joe | 4 |
To look like
Name | Hours |
---|---|
Sam | 24 |
Bob | 9 |
Joe | 4 |
Here is the code:
function importGoogleCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var calendarId = sheet.getRange('B1').getValue().toString();
var calendar = CalendarApp.getCalendarById(calendarId);
// Set filters
var startDate = sheet.getRange('B2').getValue();
var endDate = sheet.getRange('B3').getValue();
var searchText = '';
// Print header
var header = [["Title", "Description", "Start", "End", "Duration"]];
var range = sheet.getRange("A6:E6");
range.setValues(header);
range.setFontWeight("bold")
// Get events based on filters
var events = (searchText == '') ? calendar.getEvents(startDate, endDate) : calendar.getEvents(startDate, endDate, {search: searchText});
// Display events
for (var i=0; i<events.length; i++) {
var row = i+7;
var details = [[events[i].getTitle(), events[i].getDescription(), events[i].getStartTime(), events[i].getEndTime(), '']];
range = sheet.getRange(row,1,1,5);
range.setValues(details);
// Format the Start and End columns
var cell = sheet.getRange(row, 3);
cell.setNumberFormat('mm/dd/yyyy hh:mm');
cell = sheet.getRange(row, 4);
cell.setNumberFormat('mm/dd/yyyy hh:mm');
// Fill the Duration column
cell = sheet.getRange(row, 5);
cell.setFormula('=(HOUR(D' + row + ')+(MINUTE(D' +row+ ')/60))-(HOUR(C' +row+ ')+(MINUTE(C' +row+ ')/60))');
cell.setNumberFormat('0.00');
}
}
I am willing to make another function if need be
Thank You and Stay Safe
Upvotes: 0
Views: 190
Reputation: 22011
I like the approach of using a pivot table (since they are perfect for handling such data). You get totals, and other features for free.
But if you only want to write summary data to your spreadsheet, you can use the following approach:
My starting point follows on from this line in your existing script:
// Get events based on filters
var events = (searchText == '') ? calendar.getEvents(startDate, endDate) : calendar.getEvents(startDate, endDate, {search: searchText});
From there I pass your events
array to a new function:
function summarize(events) {
var totalsByName = new Map();
events.forEach((event) => {
let name = event.getTitle();
// duration in seconds (from milliseconds / 1000):
let duration = Math.abs(event.getEndTime() - event.getStartTime()) / 1000.0;
if (totalsByName.has(name)) {
// increment the existing duration for this person:
totalsByName.set(name, totalsByName.get(name) + duration);
} else {
// add the first entry for this person:
totalsByName.set(name, duration);
}
} );
// iterate over each entry in the map:
for (let [name, duration] of totalsByName) {
console.log(name + ' = ' + (duration / 3600.0));
}
}
The function populates a map
of results - one entry per person's name.
In my example, all I do is print the data to the console.
console.log(name + ' = ' + (duration / 3600.0)); // convert seconds to hours
But you can instead adapt all your existing code to write this data to the spreadsheet instead, using my name
and duration
values.
You can apply additional logic to sort by names, if you wish, and round the numeric data to a preferred number of decimal places.
Upvotes: 1