I'm a complete noob at coding but, with some help, I have written a Google Apps Script.
I get teachers to submit student reports via a Google Form. On the form, they select their name (out of 15 faculty members), the student's name (out of 60 students), whether the student is in Middle School or High School, which subject they are reporting on (out of 50 subjects), the grade (type, percent and letter) and their remarks.
As our students take, on average, 6 or 7 subjects, we end up with around 400 form responses. We then need to generate student reports containing the school's logo, the Principal's signature, and all the data for each of the 60 individual students.
To generate the reports in PDF format, I have made a crude attempt at writing a script. I wait until all faculty have submitted all of their form responses and I then take the Form Responses 1 sheet and copy it into another sheet named mainSheet. I also have a detailsSheet which contains values of items which need to be inserted into the reports (school logo image, principal signature image, semester, year and the Folder ID where I want the generated report PDF files to be stored).
The script works and does generate all the correctly formatted and named PDF reports for the students, but it takes around 6 minutes, and I can't help thinking that it's execution time is down to my crude attempt at coding and my code's inefficiency.
Here's the code, and, if required, I can share a sample MainSheet and detailsSheet for testing purposes.
Thank you for whatever insight you can provide on how I could get my code to be more efficient and use less of Google's resources to achieve what I need to do.
function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{ name: 'Generate Reports...', functionName: 'createDocuments' }
];
spreadsheet.addMenu('Reports', menuItems);
}
function createDocuments() {
// Enable the Advanced Drive Service
function enableAdvancedDriveService() {
return DriveApp.getStorageUsed();
}
// Access the active Google Sheet
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// Access the main sheet containing student data
var mainSheet = spreadsheet.getSheetByName("MainSheet");
// Access the sheet containing additional details
var detailsSheet = spreadsheet.getSheetByName("DetailsSheet");
// Get the data range for the main sheet
var dataRange = mainSheet.getDataRange();
// Get all data from the main sheet
var data = dataRange.getValues();
// Create an object to store data for each student
var studentData = {};
// Loop through each row of data (skipping header row)
for (var i = 1; i < data.length; i++) {
var row = data[i];
// Extract data from the row
var studentName = row[1];
var program = row[2];
var teacherName = row[0];
var subject = row[3];
var typeGrade = row[4]; // Assuming Grade Type is in column 8 (change as needed)
var percentageGrade = row[5];
var letterGrade = row[6];
var remarks = row[7];
// Check if student data exists in the object
if (!studentData[studentName]) {
// Initialize student data object if it doesn't exist
studentData[studentName] = {
"program": program,
"subjects": []
};
}
// Add subject data to the student's subjects array
studentData[studentName]["subjects"].push({
"teacherName": teacherName,
"subject": subject,
"typeGrade": typeGrade,
"percentageGrade": percentageGrade,
"letterGrade": letterGrade,
"remarks": remarks
});
}
// Loop through each student in the student data object
for (var studentName in studentData) {
if (studentData.hasOwnProperty(studentName)) {
var student = studentData[studentName];
// Create filename for the report
var programInitials = (student["program"] === "High School") ? "HS" : "MS";
var semester = detailsSheet.getRange("B1").getValue();
var semesterShort = semester.slice(0, 2); // Extract first two letters of semester
var year = detailsSheet.getRange("B2").getValue();
var yearShort = year.toString().slice(-2); // Extract last two digits of year
var typeReport = detailsSheet.getRange("B5").getValue(); // Assuming Report Type is in cell B6 (change as needed)
var filename = studentName + " " + programInitials + " " + semesterShort + yearShort + " " + typeReport + " Report.pdf";
// Create a new Google Doc
var doc = DocumentApp.create(filename);
// Access the body of the document
var body = doc.getBody();
// Access the header of the document
var header = doc.addHeader();
// Insert School Logo image
var logoImageFileId = detailsSheet.getRange("B3").getValue();
var logoFile = DriveApp.getFileById(logoImageFileId);
var logoImg = header.appendImage(logoFile.getBlob());
var styles = {};
styles[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.CENTER;
logoImg.getParent().setAttributes(styles);
// Insert student details
var reportHeader = studentName.toUpperCase() + "\n" +
student["program"].toUpperCase() + " - " + typeReport.toUpperCase() + " REPORT\n" +
semester.toUpperCase() + ", " + year;
body.appendParagraph(reportHeader).setHeading(DocumentApp.ParagraphHeading.HEADING2).setAlignment(DocumentApp.HorizontalAlignment.CENTER).setBold(true);
// Loop through each subject for the student
for (var j = 0; j < student["subjects"].length; j++) {
var subjectData = student["subjects"][j];
// Insert subject and teacher details on the same line
body.appendParagraph(""); // Add an empty paragraph
body.appendParagraph(subjectData["subject"] + " - " + subjectData["teacherName"]).setFontSize(12).setBold(true);
body.appendParagraph(subjectData["typeGrade"] + ": " + subjectData["percentageGrade"] + "% (" + subjectData["letterGrade"] + ")").setFontSize(12).setBold(false);
body.appendParagraph("Remarks: " + subjectData["remarks"]);
body.appendParagraph(""); // Add an empty paragraph
}
// Insert Principal's signature and stamp image
var signatureImageFileId = detailsSheet.getRange("B4").getValue();
var signatureFile = DriveApp.getFileById(signatureImageFileId);
body.appendImage(signatureFile.getBlob());
// Insert disclaimer below Principal's signature and stamp image
var disclaimer = "Please note that this document has no official validity and is solely for informative purposes.";
body.appendParagraph(""); // Add an empty paragraph
body.appendParagraph(disclaimer).setFontSize(8).setAlignment(DocumentApp.HorizontalAlignment.LEFT);
// Save the document
doc.saveAndClose();
// Convert the document to PDF
var pdf = DriveApp.getFileById(doc.getId()).getAs('application/pdf');
// Get the folder ID where you want to store the generated reports
var folderId = detailsSheet.getRange("B6").getValue();
// Access the specified folder
var folder = DriveApp.getFolderById(folderId);
// Create the PDF file in the specified folder
var pdfFile = folder.createFile(pdf);
// Delete the temporary Google Doc
DriveApp.getFileById(doc.getId()).setTrashed(true);
}
}
}