Schedules are sometimes best understood in a “calendar page” format. A hypothetical scenario illustrates design considerations and code.
Your team runs daily events scheduled by a parent organization. Details about future events are sent to you every month or so via spreadsheet.
Each of your team members requires only a moment to sit down at a computer, open a spreadsheet, and find the rows and columns outlining the day’s work. However, you’d like to spare your people even this minor hassle, and more broadly, you have misgivings about spreadsheets for exchanging schedule data. While pondering these issues, an idea comes to mind…
Here is some random data for illustration. We’ll assume events are run on most, but not necessarily all business days, and that each event is characterized by a type and lead. An eventDirectory data structure something like this would normally be wrangled from spreadsheets or other external sources.
In[]:=
SeedRandom[123];​​eventDirectory=Module[{(*NotethereisnoneedtosorteventDays*)​​eventDays=RandomSample[#,400]&@DayRange[DateObject["1 January 2020"],DateObject["31 December 2021"],"BusinessDay"],​​eventTypes={"Alpha","Beta","Gamma","Delta"},​​eventLeads={"Ms Arial","Mr Baskerville","Ms Courier","Mr Helvetica","Ms Monaco","Mr Optima","Ms Palatino","Mr Tahoma"}​​},​​#​​"eventLead"RandomChoice[eventLeads],​​"eventType"RandomChoice[eventTypes],​​"eventDetails"ResourceFunction["RandomFortune"][](*RandomWord[RandomInteger[{3,6}]]*)​​&/@eventDays​​​​];
A look at the data is always worthwhile. In order to display both the keys and values, the eventDirectory has here been turned from an association into a list.
In[]:=
Manipulate[​​Column[Normal[eventDirectory]〚index;;index+5〛],​​Style["eventDirectory","Subsubsection"],{index,1,Length[eventDirectory]-5,1},​​SaveDefinitionsTrue]
Out[]=
​
eventDirectory
index
Fri 4 Dec 2020
eventLeadMr Optima,eventTypeGamma,eventDetailsI generally avoid temptation unless I can't resist it. ― Mae West
Mon 31 Aug 2020
eventLeadMs Arial,eventTypeAlpha,eventDetailsEen schip op het strand is een baken in zee.[A ship on the beach is a lighthouse to the sea.] ― Dutch Proverb
Thu 30 Jan 2020
eventLeadMr Baskerville,eventTypeAlpha,eventDetailsSaying that Java is nice because it works on all OSes is like saying thatanal sex is nice because it works on all genders. ― Alanna
Wed 24 Jun 2020
eventLeadMs Arial,eventTypeAlpha,eventDetailsThings are not as simple as they seems at first. ― Edward Thorp
Wed 20 Jan 2021
eventLeadMr Baskerville,eventTypeBeta,eventDetailsCorripe Cervisiam!
Fri 22 May 2020
eventLeadMr Optima,eventTypeDelta,eventDetailsEducation is what remains after one has forgotten what one has learned inschool. ― Albert Einstein
This rule converts a DateObject into a formatted Item that will represent a day in a calendar. Formatting includes a background color keyed to event type, and event details displayed as a tooltip.
Also, the ItemSize option for Item does not seem to work on the cloud; width is ok, but hight shrinks to remove whitespace beneath content. A couple of invisible Z's provide a fix, but will need to be removed when using this code on desktop.
In[]:=
do_DateObjectModule[{​​dayNumber=Style[DateValue[do,"Day"],12,Bold,GrayLevel[0.25]],​​moonPhase=MoonPhase[do,"Icon"]/.Graphics[{gl_,{__},mp__},opts__]Graphics[{gl,Disk[],mp},AspectRatio1,BaselinePositionBottom,ImageSize9],​​eventCharacteristics=Lookup[eventDirectory,do,"eventLead""N/A","eventType""N/A"],​​eventTypeToColor=​​MapThread[Rule,{​​{"Alpha","Beta","Gamma","Delta","N/A"},Lighter[ColorData[1,"ColorList"],0.8]〚1;;4〛~Join~{White}​​}](*endMapThread*)​​,​​tooltip=Tooltip[#,​​Lookup[eventDirectory,do,"eventDetails"{"No Event Today"}]["eventDetails"]]&​​},​​Item[​​tooltip@Column[{​​Row[{dayNumber,Spacer[8],moonPhase}],​​Row[{"Day of Year: ",DateValue[do,"ISOYearDay"]}],​​Row[{"Lead: ",eventCharacteristics["eventLead"]}],​​Row[{"Event Type: ",eventCharacteristics["eventType"]}],​​Invisible["z"],​​Invisible["z"],​​Invisible["z"]​​}/."N/A"Style["N/A",Gray],​​Alignment{Left,Center},​​BaseStyle{"Text",Small}](*endColumn*),​​Alignment{Left,Top},​​BackgroundeventTypeToColor[eventCharacteristics["eventType"]],​​FrameTrue,​​ItemSize{8,8}(*sizeofIteminemsandlineheights*)​​](*endItem*)​​](*endModule*);​​dateObjectToFormattedDay=%;
Functionality of dateObjectToFormattedDay is illustrated here.
In[]:=
{DateObject["1 March 2021"],Spacer[5],​​DateObject["9 March 2021"],Spacer[5],​​DateObject["11 March 2021"],Spacer[5],​​DateObject["16 March 2021"],Spacer[5],​​DateObject["18 March 2021"]}/.dateObjectToFormattedDay//Grid[{#}]&
Out[]=
1
Day of Year: 60
Lead: N/A
Event Type: N/A
z
z
z
9
Day of Year: 68
Lead: Ms Palatino
Event Type: Alpha
z
z
z
11
Day of Year: 70
Lead: Mr Optima
Event Type: Gamma
z
z
z
16
Day of Year: 75
Lead: Ms Arial
Event Type: Gamma
z
z
z
18
Day of Year: 77
Lead: Ms Arial
Event Type: Beta
z
z
z
A calendar page is simply a Grid populated with these formatted day Items. Note that Framed is used here only to prevent the bottom of the calendar from being chopped off; it seems not be needed on the desktop.
In[]:=
Clear[monthNames,dayOfWeekNames,createCalendarPage];​​monthNames=
month names
;​​dayOfWeekNames=
day of week names, formatted
;​​createCalendarPage[month_Integer,year_Integer]:=Module[{​​days=DateRange[#,DatePlus[#,{{1,"Month"},{-1,"Day"}}]]&[DateObject[{year,month,1}]],​​splitDays,formattedDays,​​monthName=monthNames〚month〛​​},​​splitDays=Split[days,DateValue[#2,"DayName"]≠Sunday&]/.{first_List,middle__,last_List}{PadLeft[first,7,""],middle,PadRight[last,7,""]};​​formattedDays=splitDays/.dateObjectToFormattedDay;​​Framed[#,FrameStyleNone]&@Column[{​​Style[Row[{monthName," ",year}],"Subsubsection"],​​Grid[Join[dayOfWeekNames,formattedDays],​​Alignment{Left,Top},​​FrameStyleThin]​​},Center](*endColumn*)​​](*endModule*)
In[]:=
monthNumberToNameRules=Rule@@@({Range[12],monthNames});​​Manipulate[Magnify[createCalendarPage[month,year],scale],​​{{scale,1},0.2,2},​​{year,{2020,2021}},​​{month,monthNumberToNameRules,ControlTypeSetterBar},​​SaveDefinitionsTrue]
Out[]=
​
scale
year
2020
2021
month
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
Jun 2020
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
Day of Year: 153
Lead: N/A
Event Type: N/A
z
z
z
2
Day of Year: 154
Lead: N/A
Event Type: N/A
z
z
z
3
Day of Year: 155
Lead: N/A
Event Type: N/A
z
z
z
4
Day of Year: 156
Lead: N/A
Event Type: N/A
z
z
z
5
Day of Year: 157
Lead: N/A
Event Type: N/A
z
z
z
6
Day of Year: 158
Lead: N/A
Event Type: N/A
z
z
z
7
Day of Year: 159
Lead: N/A
Event Type: N/A
z
z
z
8
Day of Year: 160
Lead: N/A
Event Type: N/A
z
z
z
9
Day of Year: 161
Lead: N/A
Event Type: N/A
z
z
z
10
Day of Year: 162
Lead: N/A
Event Type: N/A
z
z
z
11
Day of Year: 163
Lead: N/A
Event Type: N/A
z
z
z
12
Day of Year: 164
Lead: N/A
Event Type: N/A
z
z
z
13
Day of Year: 165
Lead: N/A
Event Type: N/A
z
z
z
14
Day of Year: 166
Lead: N/A
Event Type: N/A
z
z
z
15
Day of Year: 167
Lead: N/A
Event Type: N/A
z
z
z
16
Day of Year: 168
Lead: N/A
Event Type: N/A
z
z
z
17
Day of Year: 169
Lead: N/A
Event Type: N/A
z
z
z
18
Day of Year: 170
Lead: N/A
Event Type: N/A
z
z
z
19
Day of Year: 171
Lead: N/A
Event Type: N/A
z
z
z
20
Day of Year: 172
Lead: N/A
Event Type: N/A
z
z
z
21
Day of Year: 173
Lead: N/A
Event Type: N/A
z
z
z
22
Day of Year: 174
Lead: N/A
Event Type: N/A
z
z
z
23
Day of Year: 175
Lead: N/A
Event Type: N/A
z
z
z
24
Day of Year: 176
Lead: N/A
Event Type: N/A
z
z
z
25
Day of Year: 177
Lead: N/A
Event Type: N/A
z
z
z
26
Day of Year: 178
Lead: N/A
Event Type: N/A
z
z
z
27
Day of Year: 179
Lead: N/A
Event Type: N/A
z
z
z
28
Day of Year: 180
Lead: N/A
Event Type: N/A
z
z
z
29
Day of Year: 181
Lead: N/A
Event Type: N/A
z
z
z
30
Day of Year: 182
Lead: N/A
Event Type: N/A
z
z
z
Though calendar pages are not quite graphics, their quasi-graphic nature can open up display options: for example, they can work well on a large monitor in a common area, or on a website for quick reference on a cell phone. They, along with TimelinePlot for showing past and future milestones, can make schedules--is it possible?--somewhat interesting.
You use these ideas to present your team’s accomplishments at The Big Meeting, and everyone is so overwhelmingly impressed that you are promoted on the spot to Executive Head Honcho. Congratulations--you are a hero!