Search code examples
pythonlistfor-loophtml-tablenested-for-loop

My python list is being printed entirely in one row in a HTML table


I am making a python script which makes a html table with a list (Without a module), but it keeps printing the entire list in one row instead of wrapping it like I need. My list is data = ['1', '2', '3', ... , '30']. Im trying to get it to 5 cells in each row (not counting the side header) but I keep getting the entire list being printed in every row:

Here is a blank table for a bit of reference:

My code,

classes = {"ILA":'#d0e2f3', "Math":'#f5cacc', "Science":'#d9ead3', "Social<br>Studies":'#ffe598', "Academy<br>Connect!":
    '#dad2e9', "Elective":'#f9cb9c'}

file = open("/Users/EhMehMan/PythonProjects/agenda/output.html", "w")

table = "<h3>Date:__________________________________________________________</h3>\n<head>\n<style>table, th, td" \
        " {\nborder: 3px solid black;\nborder-collapse: collapse;\n}\n</style>\n</head>\n<table style='width:100%'>\n"

#-----------------------------------------------------------------------------------

table += "  <tr>\n"
table += "    <th>{0}</th>\n".format(" ")
for z in days:
    table += "    <th style = 'height:74px;width:350px'>{text}</th>\n".format(text=z)
table += "  </tr>\n"


for x in classes.keys():
    table += "  <tr>\n"
    table += "    <th style='height:100px;width:100px' bgcolor='{color}'>{classes}</th>\n".format(color=classes[x],classes=x)
    for element in data:
        table += "    <td>{cell}</td>\n".format(cell = element)
    table += "  </tr>\n"
table += "</table>"
#-----------------------------------------------------------------------------------

file.writelines(table)

Any help would be great!


Solution

  • The loop for element in data: iterates over the entire dataset for every row. You need to adjust it to run in chunks of size len(days), incrementing for each row.

    There are a couple of ways of doing that. A complicated way would be to make an iterator that chunks up data and zip it with classes.keys in the outer loop. A much simpler approach would be to maintain a counter between runs of the outer loop:

    for index, subject in enumerate(classes):
        table += "  <tr>\n"
        table += f"    <th style='height:100px;width:100px' bgcolor='{classes[subject]}'>{subject}</th>\n"
        for i in range(len(days)):
            table += f"    <td>{data[index * len(days) + i]}</td>\n"
        table += "  </tr>\n"
    

    A faster way to do what you want would be to write to the file directly instead of accumulating a giant string in memory. Also, operate on files using a with block, so resources get freed up correctly in case of error. So for the example above:

    with open("/Users/EhMehMan/PythonProjects/agenda/output.html", "w") as file:
        file.write('<h3>Date:__________________________________________________________</h3>\n')
        file.write('<head>\n')
        file.write('  <style>table, th, td {\nborder: 3px solid black;\n')
        file.write('    border-collapse: collapse;\n}\n')
        file.write('  </style>\n')
        file.write('</head>\n\n')
        file.write('<table style='width:100%'>\n')
    
        ...
    
        for index, (subject, color) in enumerate(classes.items()):
            file.write('  <tr>\n')
            file.write(f'    <th style="height:100px;width:100px" bgcolor="{color}">{subject}</th>\n')
            for i in range(len(days)):
                file.write(f'    <td>{data[index * len(days) + i]}</td>\n')
            file.write('  </tr>\n')
        file.write('</table>')
    

    Notice that formatting gets a lot easier with f-strings.