Can do it like this,it's a little tricky to get CSS placement right.
Generate a
Generate a
schedule.html
import pandas as pd df = pd.DataFrame({ 'courseid': ['CHEM1250', 'CHEM1250', 'CHEM1250', 'PHYS1200', 'PHYS1200', 'BIOL1150', 'BIOL1150'], 'coursesec': ['L01', 'L02', 'L03', 'L01', 'L02', 'L01', 'L01'], 'Day': ['Monday', 'Tuesday', 'Friday', 'Tuesday', 'Thursday', 'Wednesday', 'Wednesday'], 'starttime': ['8:00', '12:00', '13:00', '9:00', '11:00', '8:00', '13:00'], 'endtime': ['9:30', '12:30', '14:00', '10:30', '12:00', '9:30', '14:30'], 'instructorid':['John', 'John', 'Bob', 'Jenna', 'Michel', 'Michel', 'Alice'] }) # Create blank grid: index = 08:00–22:00 in 30-min steps, columns = Monday–Friday times = pd.date_range("08:00", "22:00", freq="30min").time time_slots = [t.strftime("%H:%M") for t in times] days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"] grid = pd.DataFrame("", index=time_slots, columns=days) # Fill each time slot with the course info for _, row in df.iterrows(): slots = pd.date_range(row.starttime, row.endtime, freq="30min").time # drop the end slot so that 9:30–10:00 goes into the 9:30 row, etc. slots = [t.strftime("%H:%M") for t in slots[:-1]] text = f"{row.courseid} {row.coursesec}<br>Instructor: {row.instructorid}" grid.loc[slots, row.Day] = text # Turn the time‐index into a real column named "Time" and hide the integer index grid = grid.rename_axis("Time").reset_index() def bg_color(val): if "CHEM" in val: return "background-color: #d1ecf1;" if "PHYS" in val: return "background-color: #f8d7da;" if "BIOL" in val: return "background-color: #fff3cd;" return "" # Define table & cell border styles table_styles = [ {"selector":"table", "props": [("border-collapse", "collapse"), ("width", "100%")]}, {"selector":"th, td", "props": [("border", "1px solid #ccc"), ("padding", "6px"), ("vertical-align", "top")]}, {"selector":"th", "props": [("background-color", "#fafafa"), ("font-weight", "bold")]}, ] # Build the Styler styler = ( grid.style .map(bg_color) .set_table_styles(table_styles) .set_caption("Weekly Schedule") .hide(axis="index") ) # Export to HTML html = styler.to_html(escape=False) with open("schedule.html", "w", encoding="utf-8") as f: f.write(html) print("✅ schedule.html generated")
![[Image: wmPysP.png]](https://imagizer.imageshack.com/v2/800x600q70/922/wmPysP.png)