pythonlayoutprettytable

Pretty table layout to make title inside the dividing lines


I have the following code for pretty table which goes like this:

from prettytable import PrettyTable

myTable = PrettyTable(["Student Name", "Class", "Section", "Percentage"])
myTable.title = 'Big Bang Theory'
  
# Add rows
myTable.add_row(["Leanord", "X", "B", "91.2 %"])
myTable.add_row(["Penny", "X", "C", "63.5 %"])
myTable.add_row(["Howard", "X", "A", "90.23 %"])
myTable.add_row(["Bernadette", "X", "D", "92.7 %"])
myTable.add_row(["Sheldon", "X", "A", "98.2 %"])
myTable.add_row(["Raj", "X", "B", "88.1 %"])
myTable.add_row(["Amy", "X", "B", "95.0 %"])
print(myTable)

This produces the following table:

+---------------------------------------------+
|               Big Bang Theory               |
+--------------+-------+---------+------------+
| Student Name | Class | Section | Percentage |
+--------------+-------+---------+------------+
|   Leanord    |   X   |    B    |   91.2 %   |
|    Penny     |   X   |    C    |   63.5 %   |
|    Howard    |   X   |    A    |  90.23 %   |
|  Bernadette  |   X   |    D    |   92.7 %   |
|   Sheldon    |   X   |    A    |   98.2 %   |
|     Raj      |   X   |    B    |   88.1 %   |
|     Amy      |   X   |    B    |   95.0 %   |
+--------------+-------+---------+------------+

I was wondering if it possible for the following layout:

+--------------(Big Bang Theory)--------------+
| Student Name | Class | Section | Percentage |
+--------------+-------+---------+------------+
|   Leanord    |   X   |    B    |   91.2 %   |
|    Penny     |   X   |    C    |   63.5 %   |
|    Howard    |   X   |    A    |  90.23 %   |
|  Bernadette  |   X   |    D    |   92.7 %   |
|   Sheldon    |   X   |    A    |   98.2 %   |
|     Raj      |   X   |    B    |   88.1 %   |
|     Amy      |   X   |    B    |   95.0 %   |
+--------------+-------+---------+------------+

Kindly please advise if such a layout is possible

Edit 1

I added this:

table_txt = myTable.get_string()

enter image description here

table_txt = table_txt.replace("+---------------------------------------------+\n|               Big Bang Theory               |\n+--------------+-------+---------+------------+", "+--------------(Big Bang Theory)--------------+")

print(table_txt)
+--------------(Big Bang Theory)--------------+
| Student Name | Class | Section | Percentage |
+--------------+-------+---------+------------+
|   Leanord    |   X   |    B    |   91.2 %   |
|    Penny     |   X   |    C    |   63.5 %   |
|    Howard    |   X   |    A    |  90.23 %   |
|  Bernadette  |   X   |    D    |   92.7 %   |
|   Sheldon    |   X   |    A    |   98.2 %   |
|     Raj      |   X   |    B    |   88.1 %   |
|     Amy      |   X   |    B    |   95.0 %   |
+--------------+-------+---------+------------+

This approach assumes that table width is static thus if the width changes, the junction of the first line does not align with the rest of the table.


Solution

  • You can do something like this

    #! /usr/bin/env python3
    from prettytable import PrettyTable
    
    myTable = PrettyTable(["Student Name", "Class", "Section", "Percentage"])
    title = 'Big Bang Theory'
      
    # Add rows
    myTable.add_row(["Leanord", "X", "B", "91.2 %"])
    myTable.add_row(["Penny", "X", "C", "63.5 %"])
    myTable.add_row(["Howard", "X", "A", "90.23 %"])
    myTable.add_row(["Bernadette", "X", "D", "92.7 %"])
    myTable.add_row(["Sheldon", "X", "A", "98.2 %"])
    myTable.add_row(["Raj", "X", "B", "88.1 %"])
    myTable.add_row(["Amy", "X", "B", "95.0 %"])
    for n, l in enumerate(myTable.get_string().split('\n')):
        if n == 0:
            l = f"+{f'({title})'.center(len(l)-2, '-')}+"
        print(l)
    

    It is enumerating the lines of the table as a string and for the first line, center the title and replace it.

    +--------------(Big Bang Theory)--------------+
    | Student Name | Class | Section | Percentage |
    +--------------+-------+---------+------------+
    |   Leanord    |   X   |    B    |   91.2 %   |
    |    Penny     |   X   |    C    |   63.5 %   |
    |    Howard    |   X   |    A    |  90.23 %   |
    |  Bernadette  |   X   |    D    |   92.7 %   |
    |   Sheldon    |   X   |    A    |   98.2 %   |
    |     Raj      |   X   |    B    |   88.1 %   |
    |     Amy      |   X   |    B    |   95.0 %   |
    +--------------+-------+---------+------------+
    

    Works for any width.

    edit

    Not sure if I understood your comment, but I think you mean to have the table as string and not print it, then do this

    table_txt = ''
    for n, l in enumerate(myTable.get_string().split('\n')):
        if n == 0:
            l = f"+{f'({title})'.center(len(l)-2, '-')}+"
        table_txt = f'{table_txt}{l}\n'
    

    You may find other ways of concatenating strings here but you should not have performance problems with these kind of tables.