Last active
December 23, 2020 21:52
-
-
Save aakashrshah/2a01e675d5f16c55ee3bbb9c0334ca60 to your computer and use it in GitHub Desktop.
Google App Script to generate Calendar and Habit Tracker in Google Sheets.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
2021 Habit Tracker
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.