Skip to content

Instantly share code, notes, and snippets.

@aakashrshah
Last active December 23, 2020 21:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aakashrshah/2a01e675d5f16c55ee3bbb9c0334ca60 to your computer and use it in GitHub Desktop.
Save aakashrshah/2a01e675d5f16c55ee3bbb9c0334ca60 to your computer and use it in GitHub Desktop.
Google App Script to generate Calendar and Habit Tracker in Google Sheets.
// https://bit.ly/2021_habit_tracker
var monthName = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
'January',
]
var configurationMap = {
"YEAR": "B2",
"TIMEZONE": "B3",
"THEME": "B4",
"JANUARY": "B5",
"FEBRUARY": "B6",
"MARCH": "B7",
"APRIL": "B8",
"MAY": "B9",
"JUNE": "B10",
"JULY": "B11",
"AUGUST": "B12",
"SEPTEMBER": "B13",
"OCTOBER": "B14",
"NOVEMBER": "B15",
"DECEMBER": "B16",
}
var daysOfWeekArray = [[
"S", "M", "T", "W" ,"T", "F" , "S"
]]
const configurationSheet = SpreadsheetApp.getActive().getSheetByName('Configuration ⚙️');
const habitsSheet = SpreadsheetApp.getActive().getSheetByName('Habits ⛹🏻‍♂️');
const themeColor = String(configurationSheet.getRange(configurationMap["THEME"]).getBackground());
const timeZone = String(configurationSheet.getRange(configurationMap["TIMEZONE"]).getValue());
const startColumn = "A"
const endColumn = "AN"
const totalColumn = "AO"
function authorize(){
var user = Session.getActiveUser().getEmail();
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('AuthTo', user);
var msg = "Hi, " + user + "\nYou are now authorized."
SpreadsheetApp.getUi().alert(msg);
}
function getCalendarSheet() {
var calendarSheet = SpreadsheetApp.getActive().getSheetByName('Calendar 📆');
if (calendarSheet === null) {
calendarSheet = SpreadsheetApp.getActive().insertSheet('Calendar 📆');
}
return calendarSheet;
}
function getHabits() {
var lastRow = habitsSheet.getRange("A:A").getValues().filter(String).length + 1;
var habits = habitsSheet.getRange("A2:A" + lastRow).getValues();
return habits;
}
function getCalendarYear(){
var year = Number(configurationSheet.getRange(configurationMap["YEAR"]).getValue());
if (year < 2020 || year > 2100){
var currentYear = Number(Utilities.formatDate(new Date(), timeZone, "yyyy"));
year = currentYear;
}
return year;
}
function getEmoji(monthName) {
var emoji = configurationSheet.getRange(configurationMap[monthName.toUpperCase()]).getDisplayValue();
return emoji || "☃️";
}
function clearCalendar() {
var sheet = getCalendarSheet();
sheet.getRange(startColumn + ":" + totalColumn).clearDataValidations().clearFormat().clearContent().clearNote().clear();
sheet.setColumnWidths(1, 8, 25)
sheet.setColumnWidths(9, 1, 150);
sheet.setColumnWidths(10, 31, 25);
sheet.setColumnWidths(41, 1, 100);
}
function displayMonthCalendar(sheet, theme, habits, startRow, monthIndex, monthName, year, startDate, startDay, endDate){
console.log(monthIndex, monthName, year, startDate, startDay, endDate);
var daysOfWeekRow = startRow + 2;
var datesOfMonthRow = daysOfWeekRow + 1;
// Display Days
sheet.getRange("A" + startRow).setValue(getEmoji(monthName));
sheet.getRange("A" + startRow + ":H" + startRow).setFontFamily("Century Gothic")
.setFontSize(10)
.setFontColor("black")
.setBackground(theme)
.setHorizontalAlignment("center");
sheet.getRange("B" + startRow).setValue(monthName + " - " + year).setFontWeight("bold");
sheet.getRange("B" + startRow + ":H" + startRow).merge();
sheet.getRange("B" + daysOfWeekRow + ":H" + daysOfWeekRow).setValues(daysOfWeekArray)
.setFontWeight("bold")
.setFontFamily("Century Gothic")
.setFontSize(10)
.setFontColor("black")
.setHorizontalAlignment("center");
// Display Dates
var dateColumn = startDay + 2;
for (var dateIndex = startDate; dateIndex <= endDate; dateIndex++) {
sheet.getRange(datesOfMonthRow, dateColumn).setValue(dateIndex)
.setNumberFormat("#")
.setFontFamily("Century Gothic")
.setFontSize(10)
.setFontColor("black")
.setHorizontalAlignment("center");
if (dateColumn++ === 8) {
datesOfMonthRow = datesOfMonthRow + 1;
dateColumn = 2;
}
}
}
function displayMonthBreakdown(sheet, theme, habits, startRow, monthIndex, monthName, year, startDate, startDay, endDate){
// console.log(sheet, monthIndex, monthName, year, startDate, startDay, endDate);
var habitsColumn = "I"
var totalColumn = 41
var startDatesColumn = 10
var datesOfMonthRow = startRow + 1;
var checkBoxStartRow = datesOfMonthRow + 1;
var date = 0;
var datesArray = [Array(endDate)];
var i = 0;
var day = startDay;
var daysArray = [Array(endDate)];
while(date<endDate) datesArray[0][date++]=date;
while(i<endDate){
daysArray[0][i++]=daysOfWeekArray[0][day++ % 6];
if(day === 7){
day = 0;
}
}
// Display Habits Row I - Dates
sheet.getRange(habitsColumn + startRow + ":AO" + startRow)
.setFontWeight("bold")
.setFontFamily("Century Gothic")
.setFontSize(10)
.setFontColor("black")
.setBackground(theme)
.setHorizontalAlignment("center");
sheet.getRange(habitsColumn + startRow).setValue("Habits");
sheet.getRange(startRow, startDatesColumn, 1, endDate).setValues(datesArray);
sheet.getRange(startRow, totalColumn).setValue("Total");
// Display Habits Row II - Days
sheet.getRange(datesOfMonthRow, startDatesColumn, 1, endDate).setValues(daysArray)
.setFontWeight("bold")
.setFontFamily("Century Gothic")
.setFontSize(10)
.setFontColor("black")
.setBackground(theme)
.setHorizontalAlignment("center");
// Display Habits Columns - Habits Array
var query = "=ARRAYFORMULA('Habits ⛹🏻‍♂️'!A2:A" + habits.length + ")";
sheet.getRange(checkBoxStartRow, startDatesColumn -1).setFormula(query);
sheet.getRange(checkBoxStartRow, startDatesColumn - 1, habits.length, 1)
.setFontWeight("bold")
.setFontFamily("Century Gothic")
.setFontSize(10)
.setFontColor("black")
.setHorizontalAlignment("center");
// Display Habits Rows - Checkboxes
sheet.getRange(checkBoxStartRow, startDatesColumn, habits.length - 1, endDate).insertCheckboxes()
.setHorizontalAlignment("center");
// Display Habits Rows - Checkboxes
for (var x=checkBoxStartRow; x < checkBoxStartRow + habits.length - 1; x++) {
var totalDoneFormula = "=COUNTIF(J"+x+":AN"+x+", TRUE)";
sheet.getRange(x, totalColumn).setFormula(totalDoneFormula);
}
}
function buildHabitTracker() {
clearCalendar()
var sheet = getCalendarSheet();
var habits = getHabits()
var year = getCalendarYear()
var defaultStartDate = 1;
var previousMonth = monthName[0];
var startDateString = previousMonth + ' ' + defaultStartDate + ', '+ year;
var currentMonthStart = new Date(startDateString)
var startDate = new Date(currentMonthStart.setDate(1));
var startRow = 0;
var interval = 1;
for (var monthIndex = 1; monthIndex <= 12; monthIndex++) {
var currentMonthFullName = monthName[monthIndex];
var endDateString = currentMonthFullName + ' ' + defaultStartDate + ', '+ year;
var currentMonthEnd = new Date(endDateString);
var endDate = new Date(currentMonthEnd.setDate(0));
var startRow = startRow + interval;
displayMonthCalendar(
sheet,
themeColor,
habits,
startRow,
monthIndex - 1,
previousMonth,
year,
1,
Number(startDate.getDay()),
Number(endDate.getDate())
);
displayMonthBreakdown(
sheet,
themeColor,
habits,
startRow,
monthIndex - 1,
previousMonth,
year,
1,
Number(startDate.getDay()),
Number(endDate.getDate())
);
previousMonth = currentMonthFullName;
var startDateString = previousMonth + ' ' + defaultStartDate + ', '+ year;
var currentMonthStart = new Date(startDateString)
var startDate = new Date(currentMonthStart.setDate(1));
var interval = habits.length + 3;
console.log("\n==============================\n")
}
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Habit Tracker ⛳️')
.addItem('Authorize ✍🏻', 'authorize')
.addSeparator()
.addItem('Build Habit Tracker 🎬', 'buildHabitTracker')
.addItem('Clear Calendar 🆑', 'clearCalendar')
.addToUi();
}
@aakashrshah
Copy link
Author

aakashrshah commented Dec 21, 2020

2021 Habit Tracker

2021_Habit_Tracker_ASCII

Introducing the habit tracker that can be used for the entire lifetime. Just configure the year annually and you are good to go to be able to track your new habits every year. You may feel free to change the code or keep a record of your habits.

The Kaizen Effect: Get 1% Better Each Day

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment