Horizontally merge and divide cells in an HTML Table for Timetable based on the Data in Python File

I am not much familiar with Jinja, so this answer might not be the most efficient one.

By using basic hard coding in your Template.HTML file, I was able to achieve the results you are trying to. For this, I used the same code that was given by D-E-N in your previous question.

I combined all the attributes of your object into a string

  • An attribute is differentiated from another with @ (like Course and Teacher)
  • Instead of using space character, I used a _ character to represent space character in the attributes.
  • If one slot contains multiple objects, they are differentiated with space character (just like in the code provided by D-E-N)

Here's the updated code of yours with these changes,

from typing import List
import pdfkit
from pdfkit.api import configuration
from jinja2 import FileSystemLoader, Environment
wkhtml_path = pdfkit.configuration(wkhtmltopdf = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe")  #by using configuration you can add path value.

class section:
    def __init__(self, id, course, section, instructor, room):
        self.id = id
        self.course = course
        self.section = section
        self.instructor = instructor
        self.room = room

def generate_data():
    data = {}

    # For CS-1A
    data["CS-1A"] = [["" for i in range(5)] for j in range(5)]
    data["CS-1A"][0][0] += "[email protected]@Room_#2 "
    data["CS-1A"][0][0] += "Applied_Physics@Bilal@Room_#1 "
    data["CS-1A"][0][1] += "Programming_Fundamentals@Muhammad_Bilal@Room_#1 "
    data["CS-1A"][0][3] += "Programming_Fundamentals_Lab@Mr._Abid@Lab_#01 "
    data["CS-1A"][0][4] += "Programming_Fundamentals_Lab@Mr._Abid@Lab_#01 "

    # You may change all these for testing purposes. 
    # data["CS-1A"][0][0].append(section(2, "Programming Fundamentals", "CS-1A", "Bilal", "Room #1"))
    # data["CS-1A"][0][1].append(section(3, "Applied Physics", "CS-1A", "Muhammad Bilal", "Room #5"))
    # obj = section(4, "Programming Lab", "CS-1A", "Mr. Abid", "Lab #01")
    # data["CS-1A"][0][1].append(obj)
    # data["CS-1A"][0][2].append(obj)
    # data["CS-1A"][0][4].append(section(5, "English Communication", "CS-1A1", "Ms. Ayeza", "Cal Lab"))
    # data["CS-1A"][0][4].append(section(6, "English Communication", "CS-1A2", "Ms. Ayesha", "GP Lab"))
    # data["CS-1A"][1][1].append(section(7, "Linear Algebra", "CS-1A", "Ms. Zain", "Romm #2"))
    # obj = section(8, "English Lab", "CS-1A", "Ms. Abida", "Lab #04")
    # data["CS-1A"][1][3].append(obj)
    # data["CS-1A"][1][4].append(obj)
    # data["CS-1A"][2][0].append(section(9, "Social Studies", "CS-1A", "Mr. Zain Iqbal", "Room #14"))
    # data["CS-1A"][2][4].append(section(10, "Programming Fundamentals", "CS-1A", "Bilal", "Room #15"))
    # # No lectures on Thursday i.e. 3rd index
    # obj = section(11, "English Lab", "CS-1A", "Ms. Abida", "Lab #03")
    # data["CS-1A"][4][1].append(obj)
    # data["CS-1A"][4][2].append(obj)
    # data["CS-1A"][4][2].append(section(12, "English Communication", "CS-1A1", "Ms. Ayeza", "Room #3"))
    # data["CS-1A"][4][2].append(section(13, "English Communication", "CS-1A2", "Ms. Ayesha", "GP Lab"))
    #
    #
    #
    # # For CS-1B
    # data["CS-1B"] = [[[] for i in range(5)] for j in range(5)]
    #
    # data["CS-1B"][0][1].append(section(14, "Advance Programming", "CS-1B", "Mr. Ali Hassan", "Room #2"))
    # data["CS-1B"][0][2].append(section(15, "English Comprehension and Communication", "CS-1B", "Mr. Bilal", "Room #1"))
    # obj = section(15, "Software for Mobile and Devices", "CS-1B", "Mr. Jacob", "Room #5")
    # data["CS-1B"][1][1].append(obj)
    # data["CS-1B"][1][2].append(obj)
    # data["CS-1B"][1][3].append(section(17, "Calculus and Geometrical Analytics", "CS-1B", "Ms. Nomi Khan", "Room #06"))
    # data["CS-1B"][2][3].append(section(18, "Introduction to Information and Communication Technology - Lab", "CS-1B1", "Ms. Sarah Niaz", "Lab #01"))
    # data["CS-1B"][2][3].append(section(19, "Introduction to Information and Communication Technology - Lab", "CS-1B2", "Ms. Julia John", "Lab #06"))
    # data["CS-1B"][2][4].append(section(20, "English Comprehenseion and Communication", "Cs-1B", "Mr. Lionel Boyle", "Room #02"))
    # data["CS-1B"][3][3].append(section(21, "Programming Fundamentals", "CS-1B", "Mr. Alex Niles", "Room #3"))
    # data["CS-1B"][4][2].append(section(22, "Linear Algebra", "CS-1B", "Ms. Ayesha", "GP Lab"))

    return data

def organise_input_data(elements: List[List[str]]) -> List[list]:
    """
    Organises the input data to find double courses for easier use in templates
    """
    new_elements = []
    for day in elements:
        last_course = None
        course_list = []
        index = 0
        for course in day:
            # cleanup data
            course = course.strip().replace(" ", "<hr>")
            # check if long course (and not lunch time)
            if course != "" and course == last_course and index != 3:
                course_list.remove((course, 1))
                course_list.append((course, 2))
                course_list.append(("none", 0))
            else:
                course_list.append((course.replace(" ", "<hr>"), 1))
            last_course = course
            index += 1
        new_elements.append(course_list)

    return new_elements


def generate_html(template, name: str, elements: List[list]) -> str:

    new_elements = organise_input_data(elements=elements)

    rendered = template.render(
        name=name,
        monday=new_elements[0],
        tuesday=new_elements[1],
        wednesday=new_elements[2],
        thursday=new_elements[3],
        friday=new_elements[4]
    )

    with open(f"out_{name}.html", "w+") as file:
        file.write(rendered)

    return rendered


def run(input_data):
    # Init jinja
    file_loader = FileSystemLoader('.')
    env = Environment(loader=file_loader)
    template = env.get_template('template.html')

    full_text = ""
    for name, elements in input_data.items():
        full_text += generate_html(template=template, name=name, elements=elements)

    pdfkit.from_string(full_text, "out.pdf", configuration = wkhtml_path)


if __name__ == '__main__':
    data = generate_data()
    run(data)

Major changes are done in the template.html file to achieve what you are trying to achieve. Here's the Code,

<!DOCTYPE html>

<html>
  <style>
.center
{
  text-align: center;

}
.left
{
    text-align: left;
    margin-left: 6px;
    /*margin-top: 10px;*/
}
.right
{
    text-align: right;  margin-right: 4px;
}
.teacher
{
    margin-left: 4px;
}
td{
  height:175px;
  width:150px;
}


  </style>
<body>
<!-- Heading -->
    <h1 class="center">{{name}}</h1>

<!-- Table -->
    <table border="5" cellspacing="5" align="center">

<!-- Day/Periods -->
        <tr>
            <td class="center" ><br>
                <b>Day/Period</b></br>
            </td>
            <td class="center" >
                <b>I</b>
            </td>
            <td class="center" >
                <b>II</b>
            </td>
            <td class="center">
                <b>III</b>
            </td>
            <td class="center">
                <b>1:15-1:45</b>
            </td>
            <td class="center" >
                <b>IV</b>
            </td>
            <td class="center" >
                <b>V</b>
            </td>

        </tr>
<!-- Monday -->
        <tr>
            <td class="center">
                <b>Monday</b></td>
            {% for course in monday %}
                {% if loop.index == 4 %}
                    <td rowspan="6" class="center">
                        <h2>L<br>U<br>N<br>C<br>H</h2>
                    </td>
                {% endif %}
                {% if course[1] != 0 %}
                    <td colspan={{course[1]}}>
                        {% set count = [] %}
                        {%- for y in range(0, 5) -%}
                            {%- if count|length < course[0]|length -%}
                                <p class="left">
                            
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}
                                    </p>
                                    {% set __ = count.append(1) %}
                                    <p class = "right">
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}

                                </p>
                            {% set __ = count.append(1) %}
                        <p class = "teacher">
                        {%- for z in range(count|length, course[0]|length) -%}
                            {%- if course[0][count|length] == '@' -%}
                            {%- else -%}
                                {% set __ = count.append(1) %}
                                {%- if course[0][count|length-1] == '_' -%}
                                    {{' '}}
                                {%- else -%}
                                    {{course[0][count|length-1]}}
                                {%- endif -%}
                            {%- endif -%}
                        {%- endfor -%}  
                        </p>
                        <!-- <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p> -->
                       {%- endif -%}
                      {%- endfor -%}    
                    </td>
                {% endif %}
            {% endfor %}

        </tr>
<!-- Tuesday -->
        <tr>
            <td class="center">
                <b>Tuesday</b>
            </td>
            {% for course in tuesday %}
                {% if course[1] != 0 %}
                    <td colspan={{course[1]}}>
                        {% set count = [] %}
                        {%- for y in range(0, 5) -%}
                            {%- if count|length < course[0]|length -%}
                                <p class="left">
                            
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}
                                    </p>
                                    {% set __ = count.append(1) %}
                                    <p class = "right">
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}

                                </p>
                            {% set __ = count.append(1) %}
                        <p class = "teacher">
                        {%- for z in range(count|length, course[0]|length) -%}
                            {%- if course[0][count|length] == '@' -%}
                            {%- else -%}
                                {% set __ = count.append(1) %}
                                {%- if course[0][count|length-1] == '_' -%}
                                    {{' '}}
                                {%- else -%}
                                    {{course[0][count|length-1]}}
                                {%- endif -%}
                            {%- endif -%}
                        {%- endfor -%}  
                        </p>
                        <!-- <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p> -->
                       {%- endif -%}
                      {%- endfor -%}    
                    </td>
                {% endif %}
            {% endfor %}
        </tr>
<!-- Wednesday -->
        <tr>
            <td class="center">
                <b>Wednesday</b>
            </td>
            {% for course in wednesday %}
                {% if course[1] != 0 %}
                    <td colspan={{course[1]}}>
                        {% set count = [] %}
                        {%- for y in range(0, 5) -%}
                            {%- if count|length < course[0]|length -%}
                                <p class="left">
                            
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}
                                    </p>
                                    {% set __ = count.append(1) %}
                                    <p class = "right">
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}

                                </p>
                            {% set __ = count.append(1) %}
                        <p class = "teacher">
                        {%- for z in range(count|length, course[0]|length) -%}
                            {%- if course[0][count|length] == '@' -%}
                            {%- else -%}
                                {% set __ = count.append(1) %}
                                {%- if course[0][count|length-1] == '_' -%}
                                    {{' '}}
                                {%- else -%}
                                    {{course[0][count|length-1]}}
                                {%- endif -%}
                            {%- endif -%}
                        {%- endfor -%}  
                        </p>
                        <!-- <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p> -->
                       {%- endif -%}
                      {%- endfor -%}    
                    </td>
                {% endif %}
            {% endfor %}
        </tr>
<!-- Thursday -->
        <tr>
            <td class="center">
                <b>Thursday</b>
            </td>
            {% for course in thursday %}
                {% if course[1] != 0 %}
                    <td colspan={{course[1]}}>
                        {% set count = [] %}
                        {%- for y in range(0, 5) -%}
                            {%- if count|length < course[0]|length -%}
                                <p class="left">
                            
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}
                                    </p>
                                    {% set __ = count.append(1) %}
                                    <p class = "right">
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}

                                </p>
                            {% set __ = count.append(1) %}
                        <p class = "teacher">
                        {%- for z in range(count|length, course[0]|length) -%}
                            {%- if course[0][count|length] == '@' -%}
                            {%- else -%}
                                {% set __ = count.append(1) %}
                                {%- if course[0][count|length-1] == '_' -%}
                                    {{' '}}
                                {%- else -%}
                                    {{course[0][count|length-1]}}
                                {%- endif -%}
                            {%- endif -%}
                        {%- endfor -%}  
                        </p>
                        <!-- <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p> -->
                       {%- endif -%}
                      {%- endfor -%}    
                    </td>
                {% endif %}
            {% endfor %}

        </tr>
<!-- Friday -->
        <tr>
            <td class="center">
                <b>Friday</b>
            </td>
            {% for course in friday %}
                {% if course[1] != 0 %}
                    <td colspan={{course[1]}}>
                        {% set count = [] %}
                        {%- for y in range(0, 5) -%}
                            {%- if count|length < course[0]|length -%}
                                <p class="left">
                            
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}
                                    </p>
                                    {% set __ = count.append(1) %}
                                    <p class = "right">
                                    {%- for z in range(count|length, course[0]|length) -%}
                                        {%- if course[0][count|length] == '@' -%}
                                        {%- else -%}
                                            {% set __ = count.append(1) %}
                                            {%- if course[0][count|length-1] == '_' -%}
                                                {{' '}}
                                            {%- else -%}
                                                {{course[0][count|length-1]}}
                                            {%- endif -%}
                                        {%- endif -%}
                                    {%- endfor -%}

                                </p>
                            {% set __ = count.append(1) %}
                        <p class = "teacher">
                        {%- for z in range(count|length, course[0]|length) -%}
                            {%- if course[0][count|length] == '@' -%}
                            {%- else -%}
                                {% set __ = count.append(1) %}
                                {%- if course[0][count|length-1] == '_' -%}
                                    {{' '}}
                                {%- else -%}
                                    {{course[0][count|length-1]}}
                                {%- endif -%}
                            {%- endif -%}
                        {%- endfor -%}  
                        </p>
                        <!-- <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p> -->
                       {%- endif -%}
                      {%- endfor -%}    
                    </td>
                {% endif %}
            {% endfor %}

        </tr>

    </table>
</body>

</html>

This produces the following result,

enter image description here