diff --git a/timetabling/timetable-ics.py b/timetabling/timetable-ics.py
index 224a5ff686f4dbc5e6d493994a155ba06798e5b8..a5e7592fe3b848e047a775918645b25b03e28c65 100644
--- a/timetabling/timetable-ics.py
+++ b/timetabling/timetable-ics.py
@@ -8,7 +8,7 @@ import sys
 from icalendar import Calendar, Event
 from datetime import datetime, timedelta
 
-from typing import Dict, Generator, Set
+from typing import Dict, Generator, Optional, Set
 
 TIMEZONE = "Europe/London"
 BASE_DATE = datetime(2024, 9, 23, 0, 0, 0, 0, pytz.timezone(TIMEZONE))
@@ -67,10 +67,13 @@ def get_day_offset(day : str) -> int:
     except ValueError:
         return -1
 
-def get_time(week : int, day_offset : int, start : str) -> datetime:
-    day = BASE_DATE + timedelta(days=7 * (week - 1) + day_offset)
-    hour = int(start.split(":")[0])
-    return day + timedelta(hours=hour)
+def get_time(week : int, day_offset : int, start : str) -> Optional[datetime]:
+    try:
+        day = BASE_DATE + timedelta(days=7 * (week - 1) + day_offset)
+        hour = int(start.split(":")[0])
+        return day + timedelta(hours=hour)
+    except ValueError:
+        return None
 
 def get_end_time(start : datetime, duration : str) -> datetime:
     hours = int(duration.split(":")[0])
@@ -83,7 +86,12 @@ def iter_rows(ttfile : str) -> Generator[Dict[str, str], None, None]:
             for row in csv.DictReader(f):
                 yield row
     else: # try any excel
-        df = pd.read_excel(ttfile, dtype=str, na_filter=False)
+        df = pd.read_excel(
+            ttfile,
+            dtype=str,
+            na_filter=False,
+            sheet_name="Activities 2025_26",
+        )
         for row in df.to_dict(orient="records"):
             yield row
 
@@ -105,7 +113,13 @@ for ttfile in timetable_files:
         elif "Start Time" in row:
             start = row["Start Time"]
         duration_hours = row["Duration"]
-        weeks = list(get_weeks(row["Teaching Week Pattern"]))
+
+        try:
+            weeks = list(get_weeks(row["Teaching Week Pattern"]))
+        except ValueError:
+            mod_name = row["Module Name"]
+            print(f"Warning: ignore because bad weeks for {mod_name}")
+            continue
 
         location = ""
         if "PROVISIONAL Location Name" in row:
@@ -131,6 +145,9 @@ for ttfile in timetable_files:
                     print(f"Warning: ignoring day {day} of {row}")
                 else:
                     start_time = get_time(week, offset, start)
+                    if start_time is None:
+                        print(f"Warning: ignore because no time for {name}")
+                        continue
                     end_time = get_end_time(start_time, duration_hours)
                     event = Event()
                     event.add("summary", name)
@@ -159,6 +176,10 @@ for ttfile in timetable_files:
                 print(f"Warning: ignoring day {day} of {row}")
             else:
                 start_time = get_time(weeks[0], offset, start)
+                if start_time is None:
+                    print(f"Warning: ignore because no time for {name}")
+                    continue
+
                 end_time = get_end_time(start_time, duration_hours)
 
                 year_weeks = list(map(