The goal of this project was to have students logging their practice on translation and a separate non-translation activity.1 It’s a neat idea and I proposed doing it via Google Forms/sheets because it was a really short timeline.
Here’s a walkthrough of how it ended up with version two. It’s likely we’ll have a more packaged third version that will integrate some more elements.
There’s not too much unique going on in the script but here are a few of the hassles and how I dealt with them.
Connect Weekly Data for Stacked Bar Chart
weekCell.setFormula("=ISOWEEKNUM(A"+ lastRow+")");
I needed a way to group the data logged per week. ISOWEEKNUM gives you the week number that a particular date occurs in. So this little bit sets the last row of column N to be the ISOWEEKNUM function and referneces the date the form was submitted. This is handy and I’d never run across it before.
Keep it Sorted
function sortByWeek(){ const sheet = SpreadsheetApp.getActiveSheet(); const range = sheet.getRange("A2:N"); range.sort(14); }
I was trying to figure out how to do the sorting on the QUERY but this seemed easier. This function just keeps the entire sheet ordered by the week number. That way if people enter data later, it doesn’t mess up the graph.
Authorizing IMPORTRANGE via Script
From the beautiful people at Stackoverflow comes this gem. Previously, I could create the sheet and put the IMPORTRANGE function in the cell but I had to go to each sheet and hand authorize the connection. That gets boring fast. This does it automatically which is so very nice.
//from https://stackoverflow.com/a/68498535 function addImportrangePermission(newStudentSheet) { // donor or source spreadsheet id const donorId = SpreadsheetApp.getActiveSpreadsheet().getId(); // adding permission by fetching this url const url = `https://docs.google.com/spreadsheets/d/${newStudentSheet}/externaldata/addimportrangepermissions?donorDocId=${donorId}`; const token = ScriptApp.getOAuthToken(); const params = { method: 'post', headers: { Authorization: 'Bearer ' + token, }, muteHttpExceptions: true }; UrlFetchApp.fetch(url, params); }
Whole Script
//runs on trigger form submit function newSubmission(){ let email = newEntryEmail(); checkExistingTab(email);//make the internal tab sheets w sub function to make separate view sheet for student } //add week count runs on trigger of form submit function setWeekCount(){ const sheet = SpreadsheetApp.getActiveSheet(); const rows = sheet.getDataRange(); const lastRow = rows.getLastRow(); const weekCell = sheet.getRange('N'+ lastRow); weekCell.setFormula("=ISOWEEKNUM(A"+ lastRow+")"); } //make sure it stays sorted by week even if things are entered late which was easier than doing a sort on the import at the student sheet level function sortByWeek(){ const sheet = SpreadsheetApp.getActiveSheet(); const range = sheet.getRange("A2:N"); range.sort(14); } //get email function newEntryEmail(){ const sheet = SpreadsheetApp.getActiveSheet(); const rows = sheet.getDataRange(); const lastRow = rows.getLastRow(); return sheet.getRange("B"+lastRow).getValue(); } //check for individual tab for student email function checkExistingTab(email){ const workbook = SpreadsheetApp.getActiveSpreadsheet(); if(workbook.getSheetByName(email)){ Logger.log('hooray, you exist') } else { let totalSheets = workbook.getSheets(); Logger.log(totalSheets.length) let newSheet = workbook.insertSheet(totalSheets.length); newSheet.setName(email); let cell = newSheet.getRange('A1'); cell.setFormula("=QUERY('Form Responses 1'!A:N, \"Select * WHERE (B ='"+email+"')\")"); cloneStudentSheet(email); } } //clone student sheet from template . . . keep in mind you have to manually approve data integration (importrange) with main sheet function cloneStudentSheet(email){ const studentTemplate = DriveApp.getFileById('YOURFILEID'); const destFolder = DriveApp.getFolderById('YOURFOLDERID'); const summarySheet = 'THESUMMARYSHEETURL'; const newStudentSheet = studentTemplate.makeCopy(email+' reflective practice log', destFolder).getId(); Logger.log(newStudentSheet); SpreadsheetApp.openById(newStudentSheet).getRange('A1').setFormula('=IMPORTRANGE("'+summarySheet+'","'+email+'!A:N")'); addImportrangePermission(newStudentSheet); } //from https://stackoverflow.com/a/68498535 function addImportrangePermission(newStudentSheet) { // id of the spreadsheet to add permission to import // donor or source spreadsheet id, you should get it somewhere const donorId = SpreadsheetApp.getActiveSpreadsheet().getId(); // adding permission by fetching this url const url = `https://docs.google.com/spreadsheets/d/${newStudentSheet}/externaldata/addimportrangepermissions?donorDocId=${donorId}`; const token = ScriptApp.getOAuthToken(); const params = { method: 'post', headers: { Authorization: 'Bearer ' + token, }, muteHttpExceptions: true }; UrlFetchApp.fetch(url, params); }
1 Jogging, juggling, some other j word . . .
One thought on “Parallel Practice Logging in Google Forms/Sheets”
Comments are closed.