diff --git a/aleksis/apps/alsijil/util/alsijil_helpers.py b/aleksis/apps/alsijil/util/alsijil_helpers.py
index 479dc8dd599da170f6ae8e7c968cc8b52da8833c..bf51d47ec94880dbec6fe0813222931140ec209e 100644
--- a/aleksis/apps/alsijil/util/alsijil_helpers.py
+++ b/aleksis/apps/alsijil/util/alsijil_helpers.py
@@ -1,5 +1,6 @@
+from datetime import date
 from operator import itemgetter
-from typing import Any, Dict, List, Optional, Union
+from typing import Any, Dict, Iterable, List, Optional, Sequence, Union
 
 from django.db.models.expressions import Exists, OuterRef
 from django.db.models.query import Prefetch, QuerySet
@@ -12,15 +13,8 @@ from calendarweek import CalendarWeek
 
 from aleksis.apps.alsijil.forms import FilterRegisterObjectForm
 from aleksis.apps.alsijil.models import LessonDocumentation
-from aleksis.apps.chronos.models import (
-    Event,
-    ExtraLesson,
-    Holiday,
-    LessonPeriod,
-    LessonSubstitution,
-)
+from aleksis.apps.chronos.models import Event, ExtraLesson, Holiday, LessonPeriod
 from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk
-from aleksis.core.models import SchoolTerm
 
 
 def get_register_object_by_pk(
@@ -112,72 +106,260 @@ def register_objects_sorter(register_object: Union[LessonPeriod, Event, ExtraLes
         return 0
 
 
-def generate_list_of_all_register_objects(filter_dict: Dict[str, Any]) -> List[dict]:
-    # Get data for filtering
+def _filter_register_objects_by_dict(
+    filter_dict: Dict[str, Any],
+    register_objects: QuerySet[Union[LessonPeriod, Event, ExtraLesson]],
+    label_: str,
+) -> QuerySet[Union[LessonPeriod, Event, ExtraLesson]]:
+    if label_ == LessonPeriod.label_:
+        register_objects = register_objects.filter(
+            lesson__validity__school_term=filter_dict.get("school_term")
+        )
+    else:
+        register_objects = register_objects.filter(school_term=filter_dict.get("school_term"))
+    register_objects = register_objects.distinct()
+
+    if (
+        filter_dict.get("date_start")
+        and filter_dict.get("date_end")
+        and label_ != LessonPeriod.label_
+    ):
+        register_objects = register_objects.within_dates(
+            filter_dict.get("date_start"), filter_dict.get("date_end")
+        )
+
+    if filter_dict.get("person"):
+        if label_ == LessonPeriod.label_:
+            register_objects = register_objects.filter(
+                Q(lesson__teachers=filter_dict.get("person"))
+                | Q(substitutions__teachers=filter_dict.get("person"))
+            )
+        else:
+            register_objects = register_objects.filter_teacher(filter_dict.get("person"))
+
+    if filter_dict.get("group"):
+        register_objects = register_objects.filter_group(filter_dict.get("group"))
+
+    if filter_dict.get("groups"):
+        register_objects = register_objects.filter_groups(filter_dict.get("groups"))
+
+    if filter_dict.get("subject"):
+        if label_ == LessonPeriod.label_:
+            register_objects = register_objects.filter(
+                Q(lesson__subject=filter_dict.get("subject"))
+                | Q(substitutions__subject=filter_dict.get("subject"))
+            )
+        elif label_ == Event.label_:
+            # As events have no subject, we exclude them at all
+            register_objects = register_objects.none()
+        else:
+            register_objects = register_objects.filter(subject=filter_dict.get("subject"))
+
+    return register_objects
+
+
+def _generate_dicts_for_lesson_periods(
+    filter_dict: Dict[str, Any],
+    lesson_periods: QuerySet[LessonPeriod],
+    documentations: Optional[Iterable[LessonDocumentation]] = None,
+    holiday_days: Optional[Sequence[date]] = None,
+) -> List[Dict[str, Any]]:
+    """Generate a list of dicts for use with ``RegisterObjectTable``."""
+    if not holiday_days:
+        holiday_days = []
+    date_start = lesson_periods.first().lesson.validity.date_start
+    date_end = lesson_periods.last().lesson.validity.date_end
+    if (
+        filter_dict["filter_date"]
+        and filter_dict.get("date_start") > date_start
+        and filter_dict.get("date_start") < date_end
+    ):
+        date_start = filter_dict.get("date_start")
+    if (
+        filter_dict["filter_date"]
+        and filter_dict.get("date_end") < date_end
+        and filter_dict.get("date_end") > date_start
+    ):
+        date_end = filter_dict.get("date_end")
+    weeks = CalendarWeek.weeks_within(date_start, date_end)
+
+    register_objects = []
+    for lesson_period in lesson_periods:
+        for week in weeks:
+            day = week[lesson_period.period.weekday]
+
+            # Skip all lesson periods in holidays
+            if day in holiday_days:
+                continue
+            # Ensure that the lesson period is in filter range and validity range
+            if (
+                lesson_period.lesson.validity.date_start
+                <= day
+                <= lesson_period.lesson.validity.date_end
+            ) and (
+                not filter_dict.get("filter_date")
+                or (filter_dict.get("date_start") <= day <= filter_dict.get("date_end"))
+            ):
+                sub = lesson_period.get_substitution()
+
+                # Skip lesson period if the person isn't a teacher
+                # or substitution teacher of this lesson period
+                if filter_dict.get("person") and (
+                    filter_dict.get("person") not in lesson_period.lesson.teachers.all() and not sub
+                ):
+                    continue
+
+                teachers = (
+                    sub.teacher_names
+                    if sub and sub.teachers.all()
+                    else lesson_period.lesson.teacher_names
+                )
+                if (
+                    filter_dict.get("subject")
+                    and filter_dict.get("subject") != lesson_period.get_subject()
+                ):
+                    continue
+
+                # Filter matching documentations and annotate if they exist
+                filtered_documentations = list(
+                    filter(
+                        lambda d: d.week == week.week
+                        and d.year == week.year
+                        and d.lesson_period_id == lesson_period.pk,
+                        documentations
+                        if documentations is not None
+                        else lesson_period.documentations.all(),
+                    )
+                )
+                has_documentation = bool(filtered_documentations)
+
+                if filter_dict.get(
+                    "has_documentation"
+                ) is not None and has_documentation != filter_dict.get("has_documentation"):
+                    continue
+
+                # Build table entry
+                entry = {
+                    "pk": f"lesson_period_{lesson_period.pk}_{week.year}_{week.week}",
+                    "week": week,
+                    "has_documentation": has_documentation,
+                    "substitution": sub,
+                    "register_object": lesson_period,
+                    "date": date_format(day),
+                    "date_sort": day,
+                    "period": f"{lesson_period.period.period}.",
+                    "period_sort": lesson_period.period.period,
+                    "groups": lesson_period.lesson.group_names,
+                    "teachers": teachers,
+                    "subject": lesson_period.get_subject().name,
+                }
+                if has_documentation:
+                    doc = filtered_documentations[0]
+                    entry["topic"] = doc.topic
+                    entry["homework"] = doc.homework
+                    entry["group_note"] = doc.group_note
+                register_objects.append(entry)
+    return register_objects
+
+
+def _generate_dicts_for_events_and_extra_lessons(
+    filter_dict: Dict[str, Any],
+    register_objects_start: Sequence[Union[Event, ExtraLesson]],
+    documentations: Optional[Iterable[LessonDocumentation]] = None,
+) -> List[Dict[str, Any]]:
+    """Generate a list of dicts for use with ``RegisterObjectTable``."""
+    register_objects = []
+    for register_object in register_objects_start:
+        filtered_documentations = list(
+            filter(
+                lambda d: getattr(d, f"{register_object.label_}_id") == register_object.pk,
+                documentations
+                if documentations is not None
+                else register_object.documentations.all(),
+            )
+        )
+        has_documentation = bool(filtered_documentations)
+
+        if filter_dict.get(
+            "has_documentation"
+        ) is not None and has_documentation != filter_dict.get("has_documentation"):
+            continue
+
+        if isinstance(register_object, ExtraLesson):
+            day = date_format(register_object.day)
+            day_sort = register_object.day
+            period = f"{register_object.period.period}."
+            period_sort = register_object.period.period
+        else:
+            day = (
+                f"{date_format(register_object.date_start)}"
+                f"–{date_format(register_object.date_end)}"
+            )
+            day_sort = register_object.date_start
+            period = f"{register_object.period_from.period}.–{register_object.period_to.period}."
+            period_sort = register_object.period_from.period
+
+        # Build table entry
+        entry = {
+            "pk": f"{register_object.label_}_{register_object.pk}",
+            "has_documentation": has_documentation,
+            "register_object": register_object,
+            "date": day,
+            "date_sort": day_sort,
+            "period": period,
+            "period_sort": period_sort,
+            "groups": register_object.group_names,
+            "teachers": register_object.teacher_names,
+            "subject": register_object.subject.name
+            if isinstance(register_object, ExtraLesson)
+            else _("Event"),
+        }
+        if has_documentation:
+            doc = filtered_documentations[0]
+            entry["topic"] = doc.topic
+            entry["homework"] = doc.homework
+            entry["group_note"] = doc.group_note
+        register_objects.append(entry)
+
+    return register_objects
+
+
+def generate_list_of_all_register_objects(filter_dict: Dict[str, Any]) -> List[Dict[str, Any]]:
+    """Generate a list of all register objects.
+
+    This list can be filtered using ``filter_dict``. The following keys are supported:
+    - ``school_term`` (defaults to the current school term)
+    - ``date_start`` and ``date_end`` (defaults to the last thirty days)
+    - ``groups`` and/or ``groups``
+    - ``person``
+    - ``subject``
+    """
+    # Always force a value for school term, start and end date so that queries won't get too big
     initial_filter_data = FilterRegisterObjectForm.get_initial()
-    # Always force a selected school term so that queries won't get to big
-    filter_school_term = filter_dict.get("school_term", SchoolTerm.current)
-    filter_person = filter_dict.get("person")
-    should_have_documentation = filter_dict.get("has_documentation")
-    filter_group = filter_dict.get("group")
-    filter_groups = filter_dict.get("groups")
-    filter_subject = filter_dict.get("subject")
-    filter_date_start = filter_dict.get("date_start", initial_filter_data.get("date_start"))
-    filter_date_end = filter_dict.get("date_end", initial_filter_data.get("date_end"))
-    filter_date = filter_date_start and filter_date_end
+    filter_dict["school_term"] = filter_dict.get("school_term", initial_filter_data["school_term"])
+    filter_dict["date_start"] = filter_dict.get("date_start", initial_filter_data["date_start"])
+    filter_dict["date_end"] = filter_dict.get("date_end", initial_filter_data["date_end"])
+    filter_dict["filter_date"] = bool(filter_dict.get("date_start")) and bool(
+        filter_dict.get("date_end")
+    )
 
     # Get all holidays in the selected school term to sort all data in holidays out
     holidays = Holiday.objects.within_dates(
-        filter_school_term.date_start, filter_school_term.date_end
+        filter_dict["school_term"].date_start, filter_dict["school_term"].date_end
     )
-    event_q = Q()
-    extra_lesson_q = Q()
-    holiday_days = []
-    for holiday in holidays:
-        event_q = event_q | Q(date_start__lte=holiday.date_end, date_end__gte=holiday.date_start)
-        extra_lesson_q = extra_lesson_q | Q(day__gte=holiday.date_start, day__lte=holiday.date_end)
-        holiday_days += list(holiday.get_days())
-
-    lesson_periods = (
-        LessonPeriod.objects.select_related("lesson")
-        .prefetch_related("lesson__teachers", "lesson__groups")
-        .filter(lesson__validity__school_term=filter_school_term)
-        .distinct()
-        .order_by("lesson__validity__school_term__date_start")
+    holiday_days = holidays.get_all_days()
+
+    lesson_periods = _filter_register_objects_by_dict(
+        filter_dict,
+        LessonPeriod.objects.order_by("lesson__validity__date_start"),
+        LessonPeriod.label_,
     )
-    events = Event.objects.filter(school_term=filter_school_term).exclude(event_q).distinct()
-    extra_lessons = (
-        ExtraLesson.objects.annotate_day()
-        .filter(school_term=filter_school_term)
-        .exclude(extra_lesson_q)
-        .distinct()
+    events = _filter_register_objects_by_dict(
+        filter_dict, Event.objects.exclude_holidays(holidays), Event.label_
+    )
+    extra_lessons = _filter_register_objects_by_dict(
+        filter_dict, ExtraLesson.objects.exclude_holidays(holidays), ExtraLesson.label_
     )
-
-    # Do filtering by date, by person, by group and by subject (if activated)
-    if filter_date:
-        events = events.within_dates(filter_date_start, filter_date_end)
-        extra_lessons = extra_lessons.filter(day__gte=filter_date_start, day__lte=filter_date_end)
-    if filter_person:
-        lesson_periods = lesson_periods.filter(
-            Q(lesson__teachers=filter_person) | Q(substitutions__teachers=filter_person)
-        )
-        events = events.filter_teacher(filter_person)
-        extra_lessons = extra_lessons.filter_teacher(filter_person)
-    if filter_group:
-        lesson_periods = lesson_periods.filter_group(filter_group)
-        events = events.filter_group(filter_group)
-        extra_lessons = extra_lessons.filter_group(filter_group)
-    if filter_groups:
-        lesson_periods = lesson_periods.filter_groups(filter_groups)
-        events = events.filter_groups(filter_groups)
-        extra_lessons = extra_lessons.filter_groups(filter_groups)
-    if filter_subject:
-        lesson_periods = lesson_periods.filter(
-            Q(lesson__subject=filter_subject) | Q(substitutions__subject=filter_subject)
-        )
-        # As events have no subject, we exclude them at all
-        events = []
-        extra_lessons = extra_lessons.filter(subject=filter_subject)
 
     # Prefetch documentations for all register objects and substitutions for all lesson periods
     # in order to prevent extra queries
@@ -186,151 +368,14 @@ def generate_list_of_all_register_objects(filter_dict: Dict[str, Any]) -> List[d
         | Q(extra_lesson__in=extra_lessons)
         | Q(lesson_period__in=lesson_periods)
     )
-    substitutions = LessonSubstitution.objects.filter(lesson_period__in=lesson_periods)
-    if filter_person:
-        substitutions = substitutions.filter(teachers=filter_person)
 
     if lesson_periods:
-        # Get date range for which lesson periods should be added
-        date_start = lesson_periods.first().lesson.validity.school_term.date_start
-        date_end = lesson_periods.last().lesson.validity.school_term.date_end
-        if filter_date and filter_date_start > date_start and filter_date_start < date_end:
-            date_start = filter_date_start
-        if filter_date and filter_date_end < date_end and filter_date_start > date_start:
-            date_end = filter_date_end
-        print(date_start, date_end)
-        weeks = CalendarWeek.weeks_within(date_start, date_end)
-
-        register_objects = []
-        for lesson_period in lesson_periods:
-            for week in weeks:
-                day = week[lesson_period.period.weekday]
-
-                # Skip all lesson periods in holidays
-                if day in holiday_days:
-                    continue
-
-                # Ensure that the lesson period is in filter range and validity range
-                if (
-                    lesson_period.lesson.validity.date_start
-                    <= day
-                    <= lesson_period.lesson.validity.date_end
-                ) and (not filter_date or (filter_date_start <= day <= filter_date_end)):
-
-                    filtered_substitutions = list(
-                        filter(lambda s: s.lesson_period_id == lesson_period.id, substitutions)
-                    )
-                    # Skip lesson period if the person isn't a teacher
-                    # or substitution teacher of this lesson period
-                    if filter_person and (
-                        filter_person not in lesson_period.lesson.teachers.all()
-                        and not filtered_substitutions
-                    ):
-                        continue
-
-                    # Annotate substitution to lesson period
-                    sub = filtered_substitutions[0] if filtered_substitutions else None
-
-                    subject = sub.subject if sub and sub.subject else lesson_period.lesson.subject
-                    teachers = (
-                        sub.teacher_names
-                        if sub and sub.teachers.all()
-                        else lesson_period.lesson.teacher_names
-                    )
-                    if filter_subject and filter_subject != subject:
-                        continue
-
-                    # Filter matching documentations and annotate if they exist
-                    filtered_documentations = list(
-                        filter(
-                            lambda d: d.week == week.week
-                            and d.year == week.year
-                            and d.lesson_period_id == lesson_period.pk,
-                            documentations,
-                        )
-                    )
-                    has_documentation = bool(filtered_documentations)
-
-                    if (
-                        should_have_documentation is not None
-                        and has_documentation != should_have_documentation
-                    ):
-                        continue
-
-                    # Build table entry
-                    entry = {
-                        "pk": f"lesson_period_{lesson_period.pk}_{week.year}_{week.week}",
-                        "week": week,
-                        "has_documentation": has_documentation,
-                        "substitution": sub,
-                        "register_object": lesson_period,
-                        "date": date_format(day),
-                        "date_sort": day,
-                        "period": f"{lesson_period.period.period}.",
-                        "period_sort": lesson_period.period.period,
-                        "groups": lesson_period.lesson.group_names,
-                        "teachers": teachers,
-                        "subject": subject.name,
-                    }
-                    if has_documentation:
-                        doc = filtered_documentations[0]
-                        entry["topic"] = doc.topic
-                        entry["homework"] = doc.homework
-                        entry["group_note"] = doc.group_note
-                    register_objects.append(entry)
-
-        for register_object in list(extra_lessons) + list(events):
-            filtered_documentations = list(
-                filter(
-                    lambda d: getattr(d, f"{register_object.label_}_id") == register_object.pk,
-                    documentations,
-                )
-            )
-            has_documentation = bool(filtered_documentations)
-
-            if (
-                should_have_documentation is not None
-                and has_documentation != should_have_documentation
-            ):
-                continue
-
-            if isinstance(register_object, ExtraLesson):
-                day = date_format(register_object.day)
-                day_sort = register_object.day
-                period = f"{register_object.period.period}."
-                period_sort = register_object.period.period
-            else:
-                day = (
-                    f"{date_format(register_object.date_start)}"
-                    f"–{date_format(register_object.date_end)}"
-                )
-                day_sort = register_object.date_start
-                period = (
-                    f"{register_object.period_from.period}.–{register_object.period_to.period}."
-                )
-                period_sort = register_object.period_from.period
-
-            # Build table entry
-            entry = {
-                "pk": f"{register_object.label_}_{register_object.pk}",
-                "has_documentation": has_documentation,
-                "register_object": register_object,
-                "date": day,
-                "date_sort": day_sort,
-                "period": period,
-                "period_sort": period_sort,
-                "groups": register_object.group_names,
-                "teachers": register_object.teacher_names,
-                "subject": register_object.subject.name
-                if isinstance(register_object, ExtraLesson)
-                else _("Event"),
-            }
-            if has_documentation:
-                doc = filtered_documentations[0]
-                entry["topic"] = doc.topic
-                entry["homework"] = doc.homework
-                entry["group_note"] = doc.group_note
-            register_objects.append(entry)
+        register_objects = _generate_dicts_for_lesson_periods(
+            filter_dict, lesson_periods, documentations, holiday_days
+        )
+        register_objects += _generate_dicts_for_events_and_extra_lessons(
+            filter_dict, list(events) + list(extra_lessons), documentations
+        )
 
         # Sort table entries by date and period and configure table
         register_objects = sorted(register_objects, key=itemgetter("date_sort", "period_sort"))