Builder Lesson 41 of 70 ⏱ 9 min ▶ Video

The calendar visualization — a month grid, colored or labeled by day

Lesson summary

The calendar drops every dated row onto its day in a month grid — then either colors the day by a value, so a season of days reads like a heatmap, or writes a label on it, so each day shows a status or an owner. It has exactly one hard requirement: a date the software can read. Get the date right — and there's a timezone twist the video glosses over — and the calendar is one of the fastest, most satisfying visualizations in DashboardFox to build.

By the end of this lesson

  • Build a numeric calendar heatmap with a color legend, and read the coverage strip to avoid gaps
  • Switch to text mode to label each day with a category — the top owner, the dominant status
  • Set up day- and year-level comparisons, and use a DTZ/DOZ date field so days never shift

You'll need

  • A report with detail rows and a date column, open in the Composer — one row per dated thing (a ticket, an order)
  • The date field built as a timezone-aware type (DTZ or DOZ) — how and why is the first step below. Type overrides live in Formula fields

Background

A calendar takes dated rows and lays them out the way a wall calendar does — a grid of months, every row on its own day. What each day shows is one of two things, and choosing between them is the first real decision:

  • Numeric (colored values) — each day is colored by a number against a legend you define. A month of days becomes a heatmap: quiet days one color, busy days another.
  • Text (labels) — each day is labeled with a category: the dominant status, the on-call owner, the busiest product line. An at-a-glance status calendar.

The calendar has one non-negotiable: a date column it can read. Without one, there's no calendar. Everything else — the legend, the roll-ups, the comparisons, the click-through — is a bonus your data may or may not unlock. It works best on detail rows: one row per dated thing — a ticket, an order, an event. The calendar gathers all the rows that fall on a day and combines them for you.

You have
Each day shows
A date + a numeric column
A value, colored by a legend. Roll-ups, week/month totals, drill-down.
A date + a text column
A label — a status, an owner, an outcome — chosen when a day has several rows.

If the value you point at is text, the calendar can still work — it just counts the rows ("how many tickets that day"), which is often exactly what you want.

Haven't watched the video yet? It's about nine minutes and builds the calendar four ways — a colored heatmap of daily ticket volume, a prior-period comparison, a text calendar naming each day's top operator, and an open-vs-closed category comparison. Worth the nine minutes; this page covers the same ground and adds the one thing the video skips: the timezone-aware date field that keeps your days from sliding.

Stuck before you've got dated rows to work with? Email [email protected] with the app and the date field you're using. Real human, same business day reply.

Do it

  1. Build the dataset and open the calendar

    Start with the simplest useful shape: in the Tickets app, pull in ticket number and the open time (your DTZ/DOZ date). That's enough to see how many tickets opened each day.

    Click Visualizations → Calendar. Set Display Type to Numeric (colored values). The Date Field is your open time; the Current Value Field is the ticket number. Because ticket number is text, the calendar sets Combining Same Day Rows to Count of records automatically — counting is the only thing that makes sense for text, and here it's exactly right.

  2. Make a legend — the color rule

    Open Color Legend. With a single value you build a Static legend: discrete color bands, each one a rule. Add a few:

    • Between 80 and 100 → a "normal" color.
    • Less Than 80 → a "low day" color.
    • Greater Than 100 → a "high day" color.

    Each band has a Threshold Type (Greater Than, Less Than, Between, Equal To, No Data), its value(s), a Label, and colors. Two things make bands easy to get right. Order is priority — a day takes the color of the first band it matches, so if two bands overlap, move the one you want to win up the list. And the coverage strip beneath the bands lays them across your range and flags gaps (values no band covers) and overlaps — it catches the classic 1–10 then 11–20 leaving 10–11 uncovered. A day matching no band takes the No Data color, so a catch-all band is a good habit.

    Save & Apply, then View Full Document — the sample only shows part of the picture — and your days are color-coded high / normal / low.

  3. Constrain the dates

    The first heatmap probably reached all the way back to 2024 — too much. A calendar shows a window of time, rarely every row ever recorded. Add a criterion on the date field with a predetermined range: Is Year to Date, or Is Last Year. When you're about to do comparisons, this year and last year is usually all you need — it keeps the report fast and the grid legible. (More on why this matters for speed in Make it real.)

  4. Add a comparison

    Back in Config, set a Comparison Type. Prior period unlocks a choice of what to compare each day against: Prior day, Same weekday last week, Same date last month, or Same date last year. Pick Same date last year for a year-over-year read.

    With two years of data in play, narrow what's drawn: under Display Options, set Display Range to This year so you see the current year colored, each day comparing against the same day last year. The comparison is calculated from all your data; the range just chooses which months are on screen.

    Once a comparison exists, the legend gains a second mode: alongside Static bands you can pick a Gradient, and compare in percent rather than absolute terms — handy for "how much up or down from last year" heatmaps.

  5. Switch to text mode — label each day

    Reset back to the data and try the other mode. Bring in a text field like assignee. In Config, change Display Type to Text (labels). Now each day writes a word instead of a color, and you choose which word with Choosing One Label — because a day usually has many rows:

    • Most frequent label — the label that appears most that day.
    • Top label by a measure — the label with the highest total of a measure you pick (set it under Rank By). Label = assignee, Rank By = ticket count → each day shows the operator who handled the most tickets.
    • First row's label / Last row's label — the first or last row of the day.

    View Full Document and each day names its top operator, with the month's leader called out. Ties break alphabetically, so a day always resolves the same way.

  6. Compare two categories

    One more comparison worth knowing. Back in numeric mode, bring in a status field, and set Comparison Type to Compare two categories. Pick the status field, then choose the two values — Open as the Base Member and Closed as the Comparison Member. Now each day shows how many tickets were opened versus closed that day — a running read on whether you're keeping up. Add a legend to interpret the colors, and save.

Make it real

The calendar is quick to build; these are the things that keep it honest and fast — starting with the one that fixes the most mystifying bug.

DTZ/DOZ, again — because it fixes the "wrong day" bug

If days ever look shifted one earlier than your data, the date field is a plain type (DAT/DPO) and the browser's time zone is offsetting it. Rebuild it as DTZ or DOZ (Add Formula → change the type). Do it on the calendar's report and on any drill-down target, or the drilled report opens on the wrong day even when the calendar is right. This is the single most common calendar surprise, and it's a two-click fix.

Roll-ups are computed from the data, not the rounded days

Under Display Options you can add running figures down the side: Show Week Totals, Show Week Average, Show Monthly Average, plus layout choices — Number Of Months (1 or 2 columns), Week Start (Monday or Sunday), and Show Today. The nice detail: totals and averages are calculated from your underlying data, not from the rounded number printed on each day. So you can show a daily average in each cell and a weekly total down the side, and both are correct. In text mode, the roll-up reports the period's most common label.

Drill-down — click a day, open the detail

Under Drilldown Options, set a Target Report and each day becomes clickable — click a day, open that report filtered to that day. Select Date Field tells the calendar which field in the target to filter on (the target must contain that same date field, or the filter is ignored), and Use Criterias passes the calendar's own filters through too, so the drilled report stays scoped the way the calendar is. And the reason it's back in this lesson: the target report's date field must also be DTZ/DOZ, or the day you click and the day that opens won't match. Drilldowns covers the pattern in full.

Non-visible fields become dashboard filters — and keep you fast

You don't have to bake every filter into the report. Include a field but set it non-visible, and it can still power a dashboard filter or a report prompt — so a viewer can segment the calendar by product line, region, or customer on the fly, without that column crowding the days. With Use Criterias on, that live choice even travels through a drill-down. Those same non-visible fields are also the performance tip: a calendar reads detail rows, so on a busy source, constrain the dates (Year to Date / Last Year), filter to the subset that matters, and if there are many rows per day, pre-aggregate to the day in the report (keeping the date DTZ/DOZ). A visible column you don't need is a column the database has to group by — turn it off. See Criteria and prompts and Report formulas.

If you're stuck

The calendar stumbles, roughly in the order they bite. The first one accounts for most support emails about this visualization.

Days are shifted one day earlier than the data

The date field is a plain type (DAT / DPO), so the viewer's browser time zone offsets it and pushes rows onto the day before. Rebuild the field as DTZ or DOZ (Add Formula → change the type). This is the big one — do it before anything else.

My date column isn't in the Date Field list

Its values aren't consistently readable as dates — mixed formats, blanks, or a date buried in text. Clean the column, or build one consistent date with a formula. ISO (2026-03-15) is the safest format.

The value won't Sum or Average — only Count

The Current Value Field is typed as text, so the calendar can only count rows. Override its data type to a number (see Formula fields), or lean into Count of records if a count is what you actually want.

Every day is the "No Data" color

No band matches those values, so every day falls through to No Data. Check the coverage strip for gaps and add a catch-all band that covers everything else.

Two bands seem to fight over a value

They overlap, and the top band wins (order is priority). Reorder the bands with the row arrows, or fix the overlap the coverage strip is flagging.

A drill-down opens on the wrong day

The target report's date field isn't DTZ/DOZ, so it offsets even though the calendar is correct. Rebuild the target's date field as DTZ or DOZ too — the fix has to be on both sides.

The calendar is slow to load

It's reading every detail row. Constrain the dates (Year to Date / Last Year), filter to the subset it's about, and if a lot happens per day, pre-aggregate the report to one row per day — keeping the date DTZ/DOZ and filter-only columns non-visible.

None of these match my situation

Email [email protected] with the app, the date field you're using, and a screenshot. Real human, same business day reply. The full control-by-control reference is the visualization options reference.

7-day free trial — no credit card

Built lean. Priced fairly. Supported by humans.

Full access to all features. No credit card required.

Prefer no subscriptions & full control? Self-hosted from $4,995 one-time →

Click once to extend to 14 days — need more time? Just reach out.

25+ years building BI tools Support from the team that builds it Available in US & EU regions
DashboardFox mascot