Skip to content

McRUN Attendance Documentation


About

Welcome to the McRUN Attendance codebase documentation. This project is a Google Apps Script-based solution designed to streamline attendance tracking for the McRUN club. It integrates with Google Sheets, Google Forms, and external tools to automate attendance submissions, formatting, and reporting.

The system also includes features for email notifications, data validation, and integration with the Points Ledger for tracking participation.

Files

Key Features

  • Attendance Management: Automates the processing of attendance submissions from Google Forms and the McRUN app.
  • Data Formatting: Ensures uniform formatting of names, headruns, and other attendance details.
  • Email Notifications: Sends reminders and attendance copies to headrunners and club executives.
  • Integration with Points Ledger: Transfers attendance data to a Points Ledger for tracking participation.
  • Custom Menus: Provides a user-friendly interface in Google Sheets for executing scripts.
  • Triggers and Scheduling: Automates tasks like checking for missing attendance and updating calendar-based triggers.

Note: This documentation is generated from a code search and may not include every function in the repository.
View all code on GitHub

Function Docs

This section provides a quick reference to all functions in the McRUN Attendance codebase. Click on a function name to jump to its detailed documentation.

# Formatting.gs


## addMissingPlatform()

Adds 'Google Form' as a platform source for a row.

addMissingPlatform(7);
Name Type Description
row Integer Row in attendance sheet (defaults to ATTENDANCE_SHEET.getLastRow()))

## toTitleCase()

Converts a string to title case.

toTitleCase("hello world");
Name Type Description
inputString String The string to title

Output: String


## cleanSheetData()

Runs all formatting functions for the sheet.

cleanSheetData();

## formatAllHeadRun()

Formats all headrun entries in the sheet.

formatAllHeadRun();

## formatAllConfirmations()

Formats all confirmation columns in the sheet.

formatAllConfirmations();

## formatConfirmationInRow(row)

Formats confirmation as a user-friendly string.

formatConfirmationInRow(10);
Name Type Description
row Integer Row in attendance sheet. Default: ATTENDANCE_SHEET.getLastRow()

# HeadRun-Attendance.gs


## onFormSubmission()

Runs after form submission; sorts, processes, transfers, and formats the new entry.

onFormSubmission();

## onFormSubmissionInRow()

Executes post-form-submission logic for a specific row.

onFormSubmissionInRow(15);
Name Type Description
row Integer Row in attendance sheet (1-index)

## onAppSubmission()

Processes app-based attendance submissions.

onAppSubmission(22);
Name Type Description
row Integer Row in attendance sheet (1-index). Defaults to ATTENDANCE_SHEET.getLastRow()

## bulkFormatting()

Bulk-formats a row: confirmation and names.

bulkFormatting(7);
Name Type Description
row Integer Row in attendance sheet

## transferAndFormat()

Transfers a row to the Points Ledger, triggers formatting.

transferAndFormat(7);
Name Type Description
row Integer Row in attendance sheet

## getLastSubmission()

Finds the last non-empty row in the attendance sheet.

getLastSubmission();
Name Type Description
sheet Sheet (Optional) Target sheet object. Defaults to GET_ATTENDANCE_SHEET()

Output: Integer (1-indexed row number)


# Headrun-Info.gs


## storeObject()

Stores obj in the document properties under key.

storeObject('headrunners', {...});
Name Type Description
key String Property key
obj Object Object to store

## getAllHeadruns()

Returns all stored headruns.

getAllHeadruns();

## getAllHeadrunners()

Returns all stored headrunners.

getAllHeadrunners();

## getWeekday()

Returns day string for the given index.

getWeekday(2); // returns 'tuesday'
Name Type Description
weekdayIndex Integer 0=Sunday, 6=Saturday

## getScheduleFromStore()

Returns run schedule for the specified weekday.

getScheduleFromStore('monday');
Name Type Description
currentWeekday String Int

## getMatchedTimeKey()

Finds the time key in runSchedule matching submission time ± offset.

getMatchedTimeKey(new Date(), scheduleObj, 2);
Name Type Description
submissionDate Date Date of the submission
runSchedule Object Schedule object
offsetHours Integer Offset window in hours (default 2)

# Import.gs


## processImportFromApp(importObj)

Processes the latest attendance submission imported via the McRUN app.
Verifies if the import is JSON or multi-column, appends to the import sheet, processes and transfers to semester sheet, and triggers post-import logic.

processImportFromApp('{"timestamp":"2025-05-25T13:00:00Z", ...}');
Name Type Description
importObj String (JSON) JSON string of the attendance submission

Output: None (side effects: rows added, triggers post-import)
Pitfalls: Import must be a valid JSON string; malformed data will throw.


## transferLastImport()

Transfers the last imported attendance submission (from Import Sheet) to the semester sheet.

transferLastImport();
Name Type Description
— — No parameters

Output: None (side effects: submission transferred)
Pitfalls: Only for use with valid import rows.


## transferThisRow(row)

Helper to transfer a specific row from the import sheet to the semester sheet.

transferThisRow(5);
Name Type Description
row Integer The row number in the import sheet to process

Output: None.
Pitfalls: Row must contain valid JSON string.


# Points-Ledger.gs


## appendMemberEmail()

Appends member emails to attendee names in a row.

appendMemberEmail(5, registeredArr, unregisteredArr);
Name Type Description
row Integer Row in attendance sheet
registered String[][] Registered attendees/emails
unregistered String[][] Unregistered attendees

## transferSubmissionToLedger()

Transfers a submission to the Points Ledger.

transferSubmissionToLedger(12);
Name Type Description
row Integer Row in attendance sheet (default: getLastSubmission())


# Triggers.gs


## updateWeeklyCalendarTriggers()

Adds/removes time-based triggers for events, ensures correct calendar is used.

updateWeeklyCalendarTriggers();

## addSingleEventTrigger()

Adds a trigger for all events today.

addSingleEventTrigger();

## createDailyAttendanceTrigger()

Creates time-based triggers for all relevant events in the current week.

createDailyAttendanceTrigger();

## getStartOfDay()

Returns start-of-day for a given date.

getStartOfDay(new Date());
Name Type Description
date Date The date object

Output: Date (start of the given day)


# Unregistered.gs


## getAllUnregisteredMembers()

Runs the unregistered member check for all rows in the attendance sheet.

getAllUnregisteredMembers();
Name Type Description
— — No parameters

## getUnregisteredMembersInRow(row)

Finds attendees in a specific row who are unregistered, sets in the NOT_FOUND_COL, and appends emails to registered attendees.

getUnregisteredMembersInRow(10);
Name Type Description
row Integer Row in the attendance sheet (1-indexed). Default: ATTENDANCE_SHEET.getLastRow()

Output: None; side effects on sheet.


# User-Menu.gs


## logMenuAttempt()

Logs a user's attempt to use the custom menu.

logMenuAttempt("someone@mail.com");
Name Type Description
email String Email address of the active user. Defaults to empty string.

## onOpen()

Creates the custom menu in the spreadsheet UI.

onOpen();

## helpUI()

Displays a help message for the custom menu.

helpUI();


Triggers

  1. Form Submission: Set up a trigger for onFormSubmission (From form).
  2. App Submission: Set up a trigger for onAppSubmission (From event or manual).
  3. Scheduled Checks:
  4. Use time-driven triggers (e.g., weekly, daily) for functions like updateWeeklyCalendarTriggers.
  5. Calendar event-based triggers for event-driven attendance checks.

Troubleshooting

Common Issues

Issue/Error Cause Solution
"Exception: No permission" Not authorized Ensure proper account and OAuth scopes
"Cannot read property 'getRange' of null" Sheet name or ID is wrong Double-check constants in Attendance-Variables.gs
"Trigger not firing" Trigger not set up Manually add the trigger in Apps Script UI
"Malformed JSON" Import data is not valid JSON Validate data before import

FAQ

Q: How do I add a new admin?
A: Add their email to PERM_USER_ in User-Menu.gs.

Q: How do I change the active semester?
A: Update ATTENDANCE_SHEET_NAME and related constants in Attendance-Variables.gs.

Q: Where are attendance logs stored?
A: In the Points Ledger Google Sheet (see constants).

See also