Forum Discussion
Dynamic Calendar in Excel 365
DaeyunPablo Looks pretty good. Just one comment for now... monthly calendars should contain 6 rows of data (not 5). Months beginning on a Friday or Saturday take up 6 weeks on the grid. There are a number of months on your sample calendar that are missing the last day or two (Mar-2024, Jun-2024, Mar-2025, Aug-2025, etc.). 😉
I'll work on an array manipulation alternative to the REDUCE / STACK method when I have some spare time. Cheers!
- djclementsAug 09, 2024Bronze Contributor
DaeyunPablo Here's my array manipulation variant, using TOCOL, IF, SORTBY and WRAPROWS:
=LET( wrap_count, 3, start_date, MIN(B7:B15), end_date, MAX(B7:B15), months, CEILING.MATH((YEAR(end_date) - YEAR(start_date)) * 12 + MONTH(end_date) - MONTH(start_date) + 1, wrap_count), month_start, DATE(YEAR(start_date), MONTH(start_date) + SEQUENCE(months,, 0), 1), period_start, month_start - WEEKDAY(month_start) - 13, period_end, period_start + 55, seq_start, MIN(period_start), all_dates, SEQUENCE(, MAX(period_end) - seq_start + 1, seq_start), test, (period_start > all_dates) + (period_end < all_dates), period_dates, TOCOL(IF(test, NA(), all_dates), 2), first_dates, TOCOL(IF(test, NA(), month_start), 2), wrap_ID, INT(SEQUENCE(ROWS(period_dates),, 0) / (wrap_count * 56)), week_ID, TOCOL(IF(SEQUENCE(months), TOROW(IF(SEQUENCE(, 7), SEQUENCE(8))))), sort_ID, wrap_ID * 8 + week_ID, output, IF(week_ID = 1, IF(WEEKDAY(period_dates) = 4, TEXT(first_dates, "mmm-yyyy"), ""), IF(week_ID = 2, TEXT(period_dates, "ddd"), IF(MONTH(period_dates) = MONTH(first_dates), period_dates, 0))), WRAPROWS(SORTBY(output, sort_ID), wrap_count * 7) )
Change the wrap_count if you want to output 2 or 4 months across, for example. I expanded the conditional formatting rules to accommodate up to 4 months across for demonstration purposes, but you could expand them further, if desired.
EDIT: after testing it with a larger date range (with the conditional formatting rules removed), it didn't hold up as well as I'd hoped. The REDUCE / STACK method was actually faster... so sad 😞
- DaeyunPabloAug 11, 2024Copper ContributorUnfortunate, I was hoping to see an alternative which can be used in general instead of REDUCE/STACK method... But nice version of yours, looking at it I updated my formula which has the 3rd input 'mth_in_row_num' to expand/shrink the calendar horizontally.
Please do let us know if you come up with a faster alternative later!- djclementsMay 24, 2025Bronze Contributor
Better late than never... I revisited this today with improved methods, which can handle a date range spanning hundreds of years efficiently:
=LET( wrap_count, 3, low, MIN(B7:B15), upp, MAX(B7:B15), num, CEILING.MATH((YEAR(upp) - YEAR(low)) * 12 + MONTH(upp) - MONTH(low) + 1, wrap_count), beg, DATE(YEAR(low), MONTH(low) + SEQUENCE(num,, 0), 1), pad, EXPAND("", ROWS(beg), 3, ""), lbl, EXPAND(TEXT(beg, "mmm-e"),, 4, ""), hdr, IFNA(TEXT(SEQUENCE(, 7), "ddd"), beg), bdy, beg - WEEKDAY(beg) + SEQUENCE(, 42), arr, HSTACK(pad, lbl, hdr, (MONTH(bdy) = MONTH(beg)) * bdy), h, 8, w, 7, n, wrap_count * w, i, SEQUENCE(COUNTA(arr) / n,, 0), j, SEQUENCE(, n, 0), INDEX(arr, 1 + QUOTIENT(j, w) + wrap_count * QUOTIENT(i, h), 1 + MOD(j, w) + w * MOD(i, h)) )
Adjust the wrap_count as desired. Cheers!