Skip to main content

Implementation Details

Modules

info

Unfortunately, the script is bound to the spreadsheet, and I can't share it directly without making the sheet open to the world. I'll share the code here, as a next-best effort.

In Google AppsScript, everything exists in the global scope. You can get the benefits of modules if you develop locally, and synchronize your changes with clasp, but that seemed a bit heavy-weight for this project. That said, I wanted to keep my code as organized as I could so, barring some utility functions and constants, I broke it up into the following chunks:


Code.gs is the entry point for the script, and performs high-level orchestration.

I would probably be wise to extract the late-added logic that writes the URL of the created (or updated) cover-letter to the spreadsheet into it's own module, but I've already invested a lot of time in this, and it's essentially a one-liner.

Code.gs
function generateCoverLetters() {
const sheet = SpreadsheetApp
// this is a bound script -- activeSpreadsheet is always the same sheet, and always non-null
.getActiveSpreadsheet()
.getSheetByName(JOB_LISTINGS_SHEET_NAME);

const effectiveRange = getEffectiveRange(sheet);
const jobListingRows = effectiveRange.getValues();

for ([i, listingRow] of jobListingRows.entries()){
if(listingRow.every(value => value === '')) continue;
const listing = mapDataRowToJobListingRecord(listingRow);

const coverLetterFile = createCoverLetterPathAndFile(listing);
updateCoverLetter(coverLetterFile, listing);

sheet.getRange(effectiveRange.getRow() + i, 7).setFormula(`=HYPERLINK("${coverLetterFile.getUrl()}", "Cover Letter")`);
};
}

function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Job Listing Tools')
.addItem('Generate Cover Letters', 'generateCoverLetters')
.addToUi();
}