Remove 47 number And give new list
| S.No | Roll No | Name of Student | Theory (100) | Practical (100) | Total (200) |
|---|---|---|---|---|---|
| 1 | 2 | AHIR HARSHAD SADULBHAI | 31 | 59 | 90 |
| 2 | 3 | AUSURA DEVANSH ASHVINBHAI | 14 | 38 | 52 |
| 3 | 6 | BALDANIYA PALAK KISHORBHAI | 22 | 50 | 72 |
| 4 | 7 | BANGAL SURAJBHAI GOPALBHAI | 20 | 47 | 67 |
| 5 | 9 | BHANVADIYA AAYUSHI DIPESH | 35 | 61 | 96 |
| 6 | 10 | BHATIYA HARRY VIJAY | 37 | 59 | 96 |
| 7 | 11 | BHATT YATRI SAMEER | 36 | 68 | 104 |
| 8 | 12 | BHURAWALA ADITI HITESH | 32 | 61 | 93 |
| 9 | 14 | CHAUDHARI ABHAYKUMAR VIPULBHAI | 28 | 52 | 80 |
| 10 | 15 | CHAUDHARI DIVYANSHIKUMARI PARESHBHAI | 20 | 49 | 69 |
| 11 | 16 | CHAUDHARI EKTAKUMARI NARESHBHAI | 32 | 63 | 95 |
| 12 | 17 | CHAUDHARI NIDHI | 31 | 60 | 91 |
| 13 | 18 | CHAUDHARY KAMLESHKUMAR HIRABHAI | 30 | 58 | 88 |
| 14 | 19 | CHAUDHARY PRINCE MAHESHBHAI | 26 | 53 | 79 |
| 15 | 22 | CHHOTALA DHRUVITA ASHOKBHAI | 36 | 60 | 96 |
| 16 | 26 | DABHI DIKSHITBHAI PRAKASHBHAI | 22 | 53 | 75 |
| 17 | 29 | DAVRA OM MUKESHBHAI | 24 | 59 | 83 |
| 18 | 33 | DHADUK ARYAN | 34 | 63 | 97 |
| 19 | 41 | GAMIT ADITI BRIJESHKUMAR | 32 | 60 | 92 |
| 20 | 42 | GAMIT DHRUVIKUMARI BIPINBHAI | 27 | 52 | 79 |
| 21 | 48 | GOTHANA PRAXI | 27 | 54 | 81 |
| 22 | 49 | GOTI DHRUV DILIPBHAI | 27 | 54 | 81 |
| 23 | 50 | GUJJAR PREET DILIPBHAI | 23 | 51 | 74 |
| 24 | 51 | HADA ABHIKUMAR RAJUBHAI | 30 | 56 | 86 |
| 25 | 52 | HADIYA BHAUTIKBHAI OGHADBHAI | 36 | 65 | 101 |
| 26 | 53 | HADIYA BHAVESHBHAI HAMIRBHAI | 26 | 56 | 82 |
| 27 | 54 | HADIYA HETVI VALLABHBHAI | 32 | 59 | 91 |
| 28 | 55 | ITALIYA JAIMINBHAI JAYSUKHBHAI | 31 | 60 | 91 |
| 29 | 58 | KAKADIYA AKSHIT VINODBHAI | 38 | 65 | 103 |
| 30 | 59 | KALOLA NILKUMAR DIPAKBHAI | 27 | 54 | 81 |
| 31 | 62 | KATARIYA VISHAL MEGHJIBHAI | 21 | 51 | 72 |
| 32 | 64 | KELAWALA PARTH | 31 | 57 | 88 |
| 33 | 70 | KORADIYA HETVI RASIKLAL | 28 | 57 | 85 |
| 34 | 72 | KUBAVAT MAHEE MAYANKKUMAR | 34 | 60 | 94 |
| 35 | 73 | LIMBANI PROMISE | 34 | 65 | 99 |
| 36 | 76 | MAKADIA TIRTH HEMAL | 30 | 59 | 89 |
| 37 | 77 | MAKVANA BANSIBHAI SANJAYBHAI | 26 | 50 | 76 |
| 38 | 78 | MAKVANA JAYDIP ANANDBHAI | 31 | 57 | 88 |
| 39 | 79 | MALAKIYA PRADIPKUMAR NARSHIHBHAI | 31 | 59 | 90 |
| 40 | 81 | MOBH MITALBEN TAKHUBHAI | 0 | 0 | 0 |
| 41 | 84 | MOHAMMAD ASHHAD KHANJI | 33 | 66 | 99 |
| 42 | 87 | PADVI ANIKETBHAI ARVINDBHAI | 22 | 47 | 69 |
| 43 | 92 | PATEL AMEY HEMANG | 39 | 64 | 103 |
| 44 | 97 | PATEL ISMABANU FIROZBHAI | 23 | 47 | 70 |
| 45 | 98 | PATEL KASHTI VASUDEV | 37 | 63 | 100 |
| 46 | 99 | PATEL KRISH HIRENKUMAR | 25 | 54 | 79 |
| 47 | 103 | PATEL SHIVANI INDRAVADAN | 33 | 66 | 99 |
| 48 | 104 | PATHAN ADNAN PATHAN NAZIR KHAN | 5 | 7 | 12 |
| 49 | 110 | RAM KRISH GOVINDBHAI | 25 | 52 | 77 |
| 50 | 111 | RAMANUJ PAVAN KISHORBHAI | 24 | 47 | 71 |
| 51 | 114 | RATHVA KIRANBHAI BAKABHAI | 21 | 49 | 70 |
| 52 | 115 | RATHVA SUNILBHAI VECHATBHAI | 23 | 49 | 72 |
| 53 | 120 | SHAH VIDHI ASHISHBHAI | 36 | 65 | 101 |
| 54 | 126 | SOLANKI VRUNDA BHAVENDRASINH | 33 | 60 | 93 |
| 55 | 131 | SUTARIYA KHUSH DINESHBHAI | 22 | 20 | 42 |
| 56 | 135 | TARSARIYA RIDDHI KIRANBHAI | 34 | 20 | 54 |
| 57 | 137 | THORAT ZARA RAMANBHAI | 7 | 0 | 7 |
| 58 | 139 | TRIVEDI AASTHA PARESH | 33 | 49 | 82 |
| 59 | 141 | VAGHELA RISHI MAHESHBHAI | 23 | 48 | 71 |
| 60 | 143 | GURJAR SUMIT RANJEETBHAI | 25 | 51 | 76 |
| 61 | 144 | VANIYA ROSHISH RAMESHBHAI | 30 | 57 | 87 |
| 62 | 146 | VASAVA JAYSHREEBEN RAYSINGBHAI | 23 | 52 | 75 |
Remove completeley And give list in image form
mkdir -p /tmp/workspace/kiran-list && ls /tmp/workspace/kiran-list/
~/kiran-list/generate_list.py
from PIL import Image, ImageDraw, ImageFont
import os
# All 62 students (S.No 47 - Roll 102 PATEL PRINCEKUMAR SANJAYBHAI removed, renumbered)
students = [
(1, 2, "AHIR HARSHAD SADULBHAI", 31, 59, 90),
(2, 3, "AUSURA DEVANSH ASHVINBHAI", 14, 38, 52),
(3, 6, "BALDANIYA PALAK KISHORBHAI", 22, 50, 72),
(4, 7, "BANGAL SURAJBHAI GOPALBHAI", 20, 47, 67),
(5, 9, "BHANVADIYA AAYUSHI DIPESH", 35, 61, 96),
(6, 10, "BHATIYA HARRY VIJAY", 37, 59, 96),
(7, 11, "BHATT YATRI SAMEER", 36, 68, 104),
(8, 12, "BHURAWALA ADITI HITESH", 32, 61, 93),
(9, 14, "CHAUDHARI ABHAYKUMAR VIPULBHAI", 28, 52, 80),
(10, 15, "CHAUDHARI DIVYANSHIKUMARI PARESHBHAI", 20, 49, 69),
(11, 16, "CHAUDHARI EKTAKUMARI NARESHBHAI", 32, 63, 95),
(12, 17, "CHAUDHARI NIDHI", 31, 60, 91),
(13, 18, "CHAUDHARY KAMLESHKUMAR HIRABHAI", 30, 58, 88),
(14, 19, "CHAUDHARY PRINCE MAHESHBHAI", 26, 53, 79),
(15, 22, "CHHOTALA DHRUVITA ASHOKBHAI", 36, 60, 96),
(16, 26, "DABHI DIKSHITBHAI PRAKASHBHAI", 22, 53, 75),
(17, 29, "DAVRA OM MUKESHBHAI", 24, 59, 83),
(18, 33, "DHADUK ARYAN", 34, 63, 97),
(19, 41, "GAMIT ADITI BRIJESHKUMAR", 32, 60, 92),
(20, 42, "GAMIT DHRUVIKUMARI BIPINBHAI", 27, 52, 79),
(21, 48, "GOTHANA PRAXI", 27, 54, 81),
(22, 49, "GOTI DHRUV DILIPBHAI", 27, 54, 81),
(23, 50, "GUJJAR PREET DILIPBHAI", 23, 51, 74),
(24, 51, "HADA ABHIKUMAR RAJUBHAI", 30, 56, 86),
(25, 52, "HADIYA BHAUTIKBHAI OGHADBHAI", 36, 65, 101),
(26, 53, "HADIYA BHAVESHBHAI HAMIRBHAI", 26, 56, 82),
(27, 54, "HADIYA HETVI VALLABHBHAI", 32, 59, 91),
(28, 55, "ITALIYA JAIMINBHAI JAYSUKHBHAI", 31, 60, 91),
(29, 58, "KAKADIYA AKSHIT VINODBHAI", 38, 65, 103),
(30, 59, "KALOLA NILKUMAR DIPAKBHAI", 27, 54, 81),
(31, 62, "KATARIYA VISHAL MEGHJIBHAI", 21, 51, 72),
(32, 64, "KELAWALA PARTH", 31, 57, 88),
(33, 70, "KORADIYA HETVI RASIKLAL", 28, 57, 85),
(34, 72, "KUBAVAT MAHEE MAYANKKUMAR", 34, 60, 94),
(35, 73, "LIMBANI PROMISE", 34, 65, 99),
(36, 76, "MAKADIA TIRTH HEMAL", 30, 59, 89),
(37, 77, "MAKVANA BANSIBHAI SANJAYBHAI", 26, 50, 76),
(38, 78, "MAKVANA JAYDIP ANANDBHAI", 31, 57, 88),
(39, 79, "MALAKIYA PRADIPKUMAR NARSHIHBHAI", 31, 59, 90),
(40, 81, "MOBH MITALBEN TAKHUBHAI", 0, 0, 0),
(41, 84, "MOHAMMAD ASHHAD KHANJI", 33, 66, 99),
(42, 87, "PADVI ANIKETBHAI ARVINDBHAI", 22, 47, 69),
(43, 92, "PATEL AMEY HEMANG", 39, 64, 103),
(44, 97, "PATEL ISMABANU FIROZBHAI", 23, 47, 70),
(45, 98, "PATEL KASHTI VASUDEV", 37, 63, 100),
(46, 99, "PATEL KRISH HIRENKUMAR", 25, 54, 79),
(47, 103, "PATEL SHIVANI INDRAVADAN", 33, 66, 99),
(48, 104, "PATHAN ADNAN PATHAN NAZIR KHAN", 5, 7, 12),
(49, 110, "RAM KRISH GOVINDBHAI", 25, 52, 77),
(50, 111, "RAMANUJ PAVAN KISHORBHAI", 24, 47, 71),
(51, 114, "RATHVA KIRANBHAI BAKABHAI", 21, 49, 70),
(52, 115, "RATHVA SUNILBHAI VECHATBHAI", 23, 49, 72),
(53, 120, "SHAH VIDHI ASHISHBHAI", 36, 65, 101),
(54, 126, "SOLANKI VRUNDA BHAVENDRASINH", 33, 60, 93),
(55, 131, "SUTARIYA KHUSH DINESHBHAI", 22, 20, 42),
(56, 135, "TARSARIYA RIDDHI KIRANBHAI", 34, 20, 54),
(57, 137, "THORAT ZARA RAMANBHAI", 7, 0, 7),
(58, 139, "TRIVEDI AASTHA PARESH", 33, 49, 82),
(59, 141, "VAGHELA RISHI MAHESHBHAI", 23, 48, 71),
(60, 143, "GURJAR SUMIT RANJEETBHAI", 25, 51, 76),
(61, 144, "VANIYA ROSHISH RAMESHBHAI", 30, 57, 87),
(62, 146, "VASAVA JAYSHREEBEN RAYSINGBHAI", 23, 52, 75),
]
# Layout settings
PAGE_W = 1400
MARGIN = 40
TOP_MARGIN = 40
# Column widths and x positions
col_sno_w = 50
col_roll_w = 60
col_name_w = 480
col_theory_w = 130
col_prac_w = 130
col_total_w = 150
col_sno_x = MARGIN
col_roll_x = col_sno_x + col_sno_w
col_name_x = col_roll_x + col_roll_w
col_theory_x = col_name_x + col_name_w
col_prac_x = col_theory_x + col_theory_w
col_total_x = col_prac_x + col_prac_w
TABLE_RIGHT = col_total_x + col_total_w
ROW_H = 28
HEADER_H = 90
TITLE_H = 100
SUB_TITLE_H = 30
COL_HEADER_H = 70
# Estimate total height
ROWS_PER_PAGE = 35
n_pages = (len(students) + ROWS_PER_PAGE - 1) // ROWS_PER_PAGE
images = []
try:
font_title = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 22)
font_sub = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 16)
font_header = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 13)
font_body = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 13)
font_body_bold = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 13)
except:
font_title = ImageFont.load_default()
font_sub = font_title
font_header = font_title
font_body = font_title
font_body_bold = font_title
def draw_page(draw, img_w, y_start, rows, page_num, total_pages, is_first):
y = y_start
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
LIGHT_GRAY = (230, 230, 230)
HEADER_BG = (200, 210, 230)
TITLE_BG = (255, 255, 255)
if is_first:
# Title
draw.text((img_w // 2, y + 10), "KIRAN MEDICAL COLLEGE, SURAT", fill=BLACK, font=font_title, anchor="mt")
draw.text((img_w // 2, y + 38), "DEPARTMENT OF MICROBIOLOGY", fill=BLACK, font=font_title, anchor="mt")
y += 70
draw.text((img_w // 2, y), "List of Students to appear for Remedial Examination AUGUST, 2026", fill=BLACK, font=font_sub, anchor="mt")
y += 24
draw.text((img_w // 2, y), "Based on Aggregated Internal Assessment (IA) Marks", fill=BLACK, font=font_sub, anchor="mt")
y += 30
note = "*IA marks are aggregated marks of all the examinations, daily assessments, attendance, recordbooks etc."
draw.text((MARGIN, y), note, fill=BLACK, font=ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 11) if True else font_body)
y += 22
else:
draw.text((img_w // 2, y + 10), "KIRAN MEDICAL COLLEGE, SURAT", fill=BLACK, font=font_title, anchor="mt")
draw.text((img_w // 2, y + 38), "DEPARTMENT OF MICROBIOLOGY", fill=BLACK, font=font_title, anchor="mt")
y += 70
# Draw column header background
draw.rectangle([MARGIN, y, TABLE_RIGHT, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
# Internal Assessment Marks spanning header
ia_x1 = col_theory_x
ia_x2 = TABLE_RIGHT
draw.rectangle([ia_x1, y, ia_x2, y + 22], fill=HEADER_BG, outline=BLACK)
draw.text(((ia_x1 + ia_x2) // 2, y + 4), "Internal Assessment Marks", fill=BLACK, font=font_header, anchor="mt")
# S.No header
draw.rectangle([col_sno_x, y, col_roll_x, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
draw.text(((col_sno_x + col_roll_x) // 2, y + COL_HEADER_H // 2), "S.\nno.", fill=BLACK, font=font_header, anchor="mm")
# Roll No header
draw.rectangle([col_roll_x, y, col_name_x, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
draw.text(((col_roll_x + col_name_x) // 2, y + COL_HEADER_H // 2), "Roll\nno.", fill=BLACK, font=font_header, anchor="mm")
# Name header
draw.rectangle([col_name_x, y, col_theory_x, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
draw.text(((col_name_x + col_theory_x) // 2, y + COL_HEADER_H // 2), "Name of student", fill=BLACK, font=font_header, anchor="mm")
# Theory header
draw.rectangle([col_theory_x, y + 22, col_prac_x, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
draw.text(((col_theory_x + col_prac_x) // 2, y + 22 + (COL_HEADER_H - 22) // 2),
"Total\n(Theory)\n(Minimum\ncut off 40%)", fill=BLACK, font=font_header, anchor="mm")
# Practical header
draw.rectangle([col_prac_x, y + 22, col_total_x, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
draw.text(((col_prac_x + col_total_x) // 2, y + 22 + (COL_HEADER_H - 22) // 2),
"Total\n(Practical)\n(Minimum\ncut off 40%)", fill=BLACK, font=font_header, anchor="mm")
# Total header
draw.rectangle([col_total_x, y + 22, TABLE_RIGHT, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
draw.text(((col_total_x + TABLE_RIGHT) // 2, y + 22 + (COL_HEADER_H - 22) // 2),
"Theory + Practical\n(Minimum cut off\n50% = 100 marks)", fill=BLACK, font=font_header, anchor="mm")
y += COL_HEADER_H
# Max marks row
draw.rectangle([MARGIN, y, TABLE_RIGHT, y + ROW_H], fill=LIGHT_GRAY, outline=BLACK)
draw.text(((col_theory_x + col_prac_x) // 2, y + ROW_H // 2), "100", fill=BLACK, font=font_body_bold, anchor="mm")
draw.text(((col_prac_x + col_total_x) // 2, y + ROW_H // 2), "100", fill=BLACK, font=font_body_bold, anchor="mm")
draw.text(((col_total_x + TABLE_RIGHT) // 2, y + ROW_H // 2), "200", fill=BLACK, font=font_body_bold, anchor="mm")
# Draw vertical lines for max row
for x in [col_sno_x, col_roll_x, col_name_x, col_theory_x, col_prac_x, col_total_x, TABLE_RIGHT]:
draw.line([(x, y), (x, y + ROW_H)], fill=BLACK, width=1)
y += ROW_H
# Data rows
for i, (sno, roll, name, theory, prac, total) in enumerate(rows):
bg = WHITE if i % 2 == 0 else (245, 245, 250)
draw.rectangle([MARGIN, y, TABLE_RIGHT, y + ROW_H], fill=bg, outline=BLACK)
# Draw cell borders
for x in [col_sno_x, col_roll_x, col_name_x, col_theory_x, col_prac_x, col_total_x, TABLE_RIGHT]:
draw.line([(x, y), (x, y + ROW_H)], fill=BLACK, width=1)
draw.line([(MARGIN, y + ROW_H), (TABLE_RIGHT, y + ROW_H)], fill=BLACK, width=1)
cy = y + ROW_H // 2
draw.text(((col_sno_x + col_roll_x) // 2, cy), str(sno), fill=BLACK, font=font_body, anchor="mm")
draw.text(((col_roll_x + col_name_x) // 2, cy), str(roll), fill=BLACK, font=font_body, anchor="mm")
draw.text((col_name_x + 8, cy), name, fill=BLACK, font=font_body, anchor="lm")
draw.text(((col_theory_x + col_prac_x) // 2, cy), str(theory), fill=BLACK, font=font_body, anchor="mm")
draw.text(((col_prac_x + col_total_x) // 2, cy), str(prac), fill=BLACK, font=font_body, anchor="mm")
draw.text(((col_total_x + TABLE_RIGHT) // 2, cy), str(total), fill=BLACK, font=font_body, anchor="mm")
y += ROW_H
return y
# Generate pages
output_images = []
for p in range(n_pages):
batch = students[p * ROWS_PER_PAGE: (p + 1) * ROWS_PER_PAGE]
is_first = (p == 0)
extra_top = 170 if is_first else 80
page_h = extra_top + COL_HEADER_H + ROW_H + len(batch) * ROW_H + 60
img = Image.new("RGB", (PAGE_W, page_h), "white")
draw = ImageDraw.Draw(img)
draw_page(draw, PAGE_W, TOP_MARGIN, batch, p + 1, n_pages, is_first)
output_images.append(img)
# Save each page as PNG
for i, img in enumerate(output_images):
img.save(f"/tmp/workspace/kiran-list/page_{i+1}.png", "PNG")
print(f"Saved page_{i+1}.png size={img.size}")
print("Done!")
cd /tmp/workspace/kiran-list && python generate_list.py
find /usr/share/fonts -name "*.ttf" 2>/dev/null | head -20
~/kiran-list/generate_list.py
Error: String not found in file: 'FONT_REG = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" FONT_BOLD = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"'
~/kiran-list/generate_list.py
from PIL import Image, ImageDraw, ImageFont
import os
FONT_REG = "/usr/share/fonts/google-droid-sans-fonts/DroidSans.ttf"
FONT_BOLD = "/usr/share/fonts/google-droid-sans-fonts/DroidSans-Bold.ttf"
# All 62 students (S.No 47 Roll 102 PATEL PRINCEKUMAR SANJAYBHAI removed, renumbered)
students = [
(1, 2, "AHIR HARSHAD SADULBHAI", 31, 59, 90),
(2, 3, "AUSURA DEVANSH ASHVINBHAI", 14, 38, 52),
(3, 6, "BALDANIYA PALAK KISHORBHAI", 22, 50, 72),
(4, 7, "BANGAL SURAJBHAI GOPALBHAI", 20, 47, 67),
(5, 9, "BHANVADIYA AAYUSHI DIPESH", 35, 61, 96),
(6, 10, "BHATIYA HARRY VIJAY", 37, 59, 96),
(7, 11, "BHATT YATRI SAMEER", 36, 68, 104),
(8, 12, "BHURAWALA ADITI HITESH", 32, 61, 93),
(9, 14, "CHAUDHARI ABHAYKUMAR VIPULBHAI", 28, 52, 80),
(10, 15, "CHAUDHARI DIVYANSHIKUMARI PARESHBHAI", 20, 49, 69),
(11, 16, "CHAUDHARI EKTAKUMARI NARESHBHAI", 32, 63, 95),
(12, 17, "CHAUDHARI NIDHI", 31, 60, 91),
(13, 18, "CHAUDHARY KAMLESHKUMAR HIRABHAI", 30, 58, 88),
(14, 19, "CHAUDHARY PRINCE MAHESHBHAI", 26, 53, 79),
(15, 22, "CHHOTALA DHRUVITA ASHOKBHAI", 36, 60, 96),
(16, 26, "DABHI DIKSHITBHAI PRAKASHBHAI", 22, 53, 75),
(17, 29, "DAVRA OM MUKESHBHAI", 24, 59, 83),
(18, 33, "DHADUK ARYAN", 34, 63, 97),
(19, 41, "GAMIT ADITI BRIJESHKUMAR", 32, 60, 92),
(20, 42, "GAMIT DHRUVIKUMARI BIPINBHAI", 27, 52, 79),
(21, 48, "GOTHANA PRAXI", 27, 54, 81),
(22, 49, "GOTI DHRUV DILIPBHAI", 27, 54, 81),
(23, 50, "GUJJAR PREET DILIPBHAI", 23, 51, 74),
(24, 51, "HADA ABHIKUMAR RAJUBHAI", 30, 56, 86),
(25, 52, "HADIYA BHAUTIKBHAI OGHADBHAI", 36, 65, 101),
(26, 53, "HADIYA BHAVESHBHAI HAMIRBHAI", 26, 56, 82),
(27, 54, "HADIYA HETVI VALLABHBHAI", 32, 59, 91),
(28, 55, "ITALIYA JAIMINBHAI JAYSUKHBHAI", 31, 60, 91),
(29, 58, "KAKADIYA AKSHIT VINODBHAI", 38, 65, 103),
(30, 59, "KALOLA NILKUMAR DIPAKBHAI", 27, 54, 81),
(31, 62, "KATARIYA VISHAL MEGHJIBHAI", 21, 51, 72),
(32, 64, "KELAWALA PARTH", 31, 57, 88),
(33, 70, "KORADIYA HETVI RASIKLAL", 28, 57, 85),
(34, 72, "KUBAVAT MAHEE MAYANKKUMAR", 34, 60, 94),
(35, 73, "LIMBANI PROMISE", 34, 65, 99),
(36, 76, "MAKADIA TIRTH HEMAL", 30, 59, 89),
(37, 77, "MAKVANA BANSIBHAI SANJAYBHAI", 26, 50, 76),
(38, 78, "MAKVANA JAYDIP ANANDBHAI", 31, 57, 88),
(39, 79, "MALAKIYA PRADIPKUMAR NARSHIHBHAI", 31, 59, 90),
(40, 81, "MOBH MITALBEN TAKHUBHAI", 0, 0, 0),
(41, 84, "MOHAMMAD ASHHAD KHANJI", 33, 66, 99),
(42, 87, "PADVI ANIKETBHAI ARVINDBHAI", 22, 47, 69),
(43, 92, "PATEL AMEY HEMANG", 39, 64, 103),
(44, 97, "PATEL ISMABANU FIROZBHAI", 23, 47, 70),
(45, 98, "PATEL KASHTI VASUDEV", 37, 63, 100),
(46, 99, "PATEL KRISH HIRENKUMAR", 25, 54, 79),
(47, 103, "PATEL SHIVANI INDRAVADAN", 33, 66, 99),
(48, 104, "PATHAN ADNAN PATHAN NAZIR KHAN", 5, 7, 12),
(49, 110, "RAM KRISH GOVINDBHAI", 25, 52, 77),
(50, 111, "RAMANUJ PAVAN KISHORBHAI", 24, 47, 71),
(51, 114, "RATHVA KIRANBHAI BAKABHAI", 21, 49, 70),
(52, 115, "RATHVA SUNILBHAI VECHATBHAI", 23, 49, 72),
(53, 120, "SHAH VIDHI ASHISHBHAI", 36, 65, 101),
(54, 126, "SOLANKI VRUNDA BHAVENDRASINH", 33, 60, 93),
(55, 131, "SUTARIYA KHUSH DINESHBHAI", 22, 20, 42),
(56, 135, "TARSARIYA RIDDHI KIRANBHAI", 34, 20, 54),
(57, 137, "THORAT ZARA RAMANBHAI", 7, 0, 7),
(58, 139, "TRIVEDI AASTHA PARESH", 33, 49, 82),
(59, 141, "VAGHELA RISHI MAHESHBHAI", 23, 48, 71),
(60, 143, "GURJAR SUMIT RANJEETBHAI", 25, 51, 76),
(61, 144, "VANIYA ROSHISH RAMESHBHAI", 30, 57, 87),
(62, 146, "VASAVA JAYSHREEBEN RAYSINGBHAI", 23, 52, 75),
]
# Layout
PAGE_W = 1400
MARGIN = 40
TOP_MARGIN = 30
col_sno_w = 50
col_roll_w = 60
col_name_w = 480
col_theory_w = 130
col_prac_w = 130
col_total_w = 150
col_sno_x = MARGIN
col_roll_x = col_sno_x + col_sno_w
col_name_x = col_roll_x + col_roll_w
col_theory_x = col_name_x + col_name_w
col_prac_x = col_theory_x + col_theory_w
col_total_x = col_prac_x + col_prac_w
TABLE_RIGHT = col_total_x + col_total_w
ROW_H = 28
COL_HEADER_H = 70
ROWS_PER_PAGE = 35
try:
font_title = ImageFont.truetype(FONT_BOLD, 22)
font_sub = ImageFont.truetype(FONT_BOLD, 15)
font_note = ImageFont.truetype(FONT_REG, 11)
font_header = ImageFont.truetype(FONT_BOLD, 12)
font_body = ImageFont.truetype(FONT_REG, 13)
font_bbold = ImageFont.truetype(FONT_BOLD, 13)
except Exception as e:
print(f"Font error: {e}")
font_title = font_sub = font_note = font_header = font_body = font_bbold = ImageFont.load_default()
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
LIGHT_GRAY = (235, 235, 235)
HEADER_BG = (200, 215, 235)
ALT_ROW = (245, 248, 255)
def cell_text(draw, x1, x2, y1, y2, text, font, multiline=False):
cx = (x1 + x2) // 2
cy = (y1 + y2) // 2
if multiline:
lines = text.split("\n")
lh = 15
total = lh * len(lines)
sy = cy - total // 2
for line in lines:
bbox = draw.textbbox((0,0), line, font=font)
tw = bbox[2] - bbox[0]
draw.text((cx - tw//2, sy), line, fill=BLACK, font=font)
sy += lh
else:
bbox = draw.textbbox((0,0), text, font=font)
tw = bbox[2] - bbox[0]
th = bbox[3] - bbox[1]
draw.text((cx - tw//2, cy - th//2), text, fill=BLACK, font=font)
def draw_vlines(draw, y1, y2, xs):
for x in xs:
draw.line([(x, y1), (x, y2)], fill=BLACK, width=1)
def draw_page(draw, page_w, rows, is_first):
y = TOP_MARGIN
if is_first:
draw.text((page_w//2, y), "KIRAN MEDICAL COLLEGE, SURAT", fill=BLACK, font=font_title, anchor="mt")
y += 30
draw.text((page_w//2, y), "DEPARTMENT OF MICROBIOLOGY", fill=BLACK, font=font_title, anchor="mt")
y += 36
draw.text((page_w//2, y), "List of Students to appear for Remedial Examination AUGUST, 2026", fill=BLACK, font=font_sub, anchor="mt")
y += 22
draw.text((page_w//2, y), "Based on Aggregated Internal Assessment (IA) Marks", fill=BLACK, font=font_sub, anchor="mt")
y += 24
note = "*IA marks are aggregated marks of all the examinations, daily assessments, attendance, recordbooks etc."
draw.text((MARGIN, y), note, fill=BLACK, font=font_note)
y += 18
else:
draw.text((page_w//2, y), "KIRAN MEDICAL COLLEGE, SURAT", fill=BLACK, font=font_title, anchor="mt")
y += 30
draw.text((page_w//2, y), "DEPARTMENT OF MICROBIOLOGY", fill=BLACK, font=font_title, anchor="mt")
y += 44
xs = [col_sno_x, col_roll_x, col_name_x, col_theory_x, col_prac_x, col_total_x, TABLE_RIGHT]
# Column header
draw.rectangle([MARGIN, y, TABLE_RIGHT, y + COL_HEADER_H], fill=HEADER_BG, outline=BLACK)
# "Internal Assessment Marks" spanning top of last 3 cols
draw.rectangle([col_theory_x, y, TABLE_RIGHT, y + 22], fill=HEADER_BG, outline=BLACK)
cell_text(draw, col_theory_x, TABLE_RIGHT, y, y+22, "Internal Assessment Marks", font_header)
draw.line([(col_theory_x, y+22), (TABLE_RIGHT, y+22)], fill=BLACK, width=1)
# Sub-headers
cell_text(draw, col_sno_x, col_roll_x, y, y+COL_HEADER_H, "S.\nno.", font_header, multiline=True)
cell_text(draw, col_roll_x, col_name_x, y, y+COL_HEADER_H, "Roll\nno.", font_header, multiline=True)
cell_text(draw, col_name_x, col_theory_x, y, y+COL_HEADER_H, "Name of student", font_header)
cell_text(draw, col_theory_x, col_prac_x, y+22, y+COL_HEADER_H, "Total\n(Theory)\n(Minimum\ncut off 40%)", font_header, multiline=True)
cell_text(draw, col_prac_x, col_total_x, y+22, y+COL_HEADER_H, "Total\n(Practical)\n(Minimum\ncut off 40%)", font_header, multiline=True)
cell_text(draw, col_total_x, TABLE_RIGHT, y+22, y+COL_HEADER_H, "Theory + Practical\n(Minimum cut off\n50% = 100 marks)", font_header, multiline=True)
draw_vlines(draw, y, y+COL_HEADER_H, xs)
draw.line([(MARGIN, y+COL_HEADER_H), (TABLE_RIGHT, y+COL_HEADER_H)], fill=BLACK, width=1)
y += COL_HEADER_H
# Max marks row
draw.rectangle([MARGIN, y, TABLE_RIGHT, y+ROW_H], fill=LIGHT_GRAY, outline=BLACK)
cell_text(draw, col_theory_x, col_prac_x, y, y+ROW_H, "100", font_bbold)
cell_text(draw, col_prac_x, col_total_x, y, y+ROW_H, "100", font_bbold)
cell_text(draw, col_total_x, TABLE_RIGHT, y, y+ROW_H, "200", font_bbold)
draw_vlines(draw, y, y+ROW_H, xs)
draw.line([(MARGIN, y+ROW_H), (TABLE_RIGHT, y+ROW_H)], fill=BLACK, width=1)
y += ROW_H
# Data rows
for i, (sno, roll, name, theory, prac, total) in enumerate(rows):
bg = WHITE if i % 2 == 0 else ALT_ROW
draw.rectangle([MARGIN, y, TABLE_RIGHT, y+ROW_H], fill=bg)
draw_vlines(draw, y, y+ROW_H, xs)
draw.line([(MARGIN, y+ROW_H), (TABLE_RIGHT, y+ROW_H)], fill=BLACK, width=1)
cell_text(draw, col_sno_x, col_roll_x, y, y+ROW_H, str(sno), font_body)
cell_text(draw, col_roll_x, col_name_x, y, y+ROW_H, str(roll), font_body)
# Name left-aligned
bbox = draw.textbbox((0,0), name, font=font_body)
th = bbox[3] - bbox[1]
draw.text((col_name_x + 8, y + ROW_H//2 - th//2), name, fill=BLACK, font=font_body)
cell_text(draw, col_theory_x, col_prac_x, y, y+ROW_H, str(theory), font_body)
cell_text(draw, col_prac_x, col_total_x, y, y+ROW_H, str(prac), font_body)
cell_text(draw, col_total_x, TABLE_RIGHT, y, y+ROW_H, str(total), font_body)
y += ROW_H
return y
n_pages = (len(students) + ROWS_PER_PAGE - 1) // ROWS_PER_PAGE
for p in range(n_pages):
batch = students[p * ROWS_PER_PAGE:(p+1) * ROWS_PER_PAGE]
is_first = (p == 0)
extra_top = 165 if is_first else 80
page_h = extra_top + COL_HEADER_H + ROW_H + len(batch) * ROW_H + 40
img = Image.new("RGB", (PAGE_W, page_h), "white")
d = ImageDraw.Draw(img)
draw_page(d, PAGE_W, batch, is_first)
out = f"/tmp/workspace/kiran-list/page_{p+1}.png"
img.save(out, "PNG")
print(f"Saved {out} size={img.size}")
print("All done!")
cat > /tmp/workspace/kiran-list/generate_list.py << 'PYEOF' from PIL import Image, ImageDraw, ImageFont FONT_REG = "/usr/share/fonts/google-droid-sans-fonts/DroidSans.ttf" FONT_BOLD = "/usr/share/fonts/google-droid-sans-fonts/DroidSans-Bold.ttf" students = [ (1,2,"AHIR HARSHAD SADULBHAI",31,59,90), (2,3,"AUSURA DEVANSH ASHVINBHAI",14,38,52), (3,6,"BALDANIYA PALAK KISHORBHAI",22,50,72), (4,7,"BANGAL SURAJBHAI GOPALBHAI",20,47,67), (5,9,"BHANVADIYA AAYUSHI DIPESH",35,61,96), (6,10,"BHATIYA HARRY VIJAY",37,59,96), (7,11,"BHATT YATRI SAMEER",36,68,104), (8,12,"BHURAWALA ADITI HITESH",32,61,93), (9,14,"CHAUDHARI ABHAYKUMAR VIPULBHAI",28,52,80), (10,15,"CHAUDHARI DIVYANSHIKUMARI PARESHBHAI",20,49,69), (11,16,"CHAUDHARI EKTAKUMARI NARESHBHAI",32,63,95), (12,17,"CHAUDHARI NIDHI",31,60,91), (13,18,"CHAUDHARY KAMLESHKUMAR HIRABHAI",30,58,88), (14,19,"CHAUDHARY PRINCE MAHESHBHAI",26,53,79), (15,22,"CHHOTALA DHRUVITA ASHOKBHAI",36,60,96), (16,26,"DABHI DIKSHITBHAI PRAKASHBHAI",22,53,75), (17,29,"DAVRA OM MUKESHBHAI",24,59,83), (18,33,"DHADUK ARYAN",34,63,97), (19,41,"GAMIT ADITI BRIJESHKUMAR",32,60,92), (20,42,"GAMIT DHRUVIKUMARI BIPINBHAI",27,52,79), (21,48,"GOTHANA PRAXI",27,54,81), (22,49,"GOTI DHRUV DILIPBHAI",27,54,81), (23,50,"GUJJAR PREET DILIPBHAI",23,51,74), (24,51,"HADA ABHIKUMAR RAJUBHAI",30,56,86), (25,52,"HADIYA BHAUTIKBHAI OGHADBHAI",36,65,101), (26,53,"HADIYA BHAVESHBHAI HAMIRBHAI",26,56,82), (27,54,"HADIYA HETVI VALLABHBHAI",32,59,91), (28,55,"ITALIYA JAIMINBHAI JAYSUKHBHAI",31,60,91), (29,58,"KAKADIYA AKSHIT VINODBHAI",38,65,103), (30,59,"KALOLA NILKUMAR DIPAKBHAI",27,54,81), (31,62,"KATARIYA VISHAL MEGHJIBHAI",21,51,72), (32,64,"KELAWALA PARTH",31,57,88), (33,70,"KORADIYA HETVI RASIKLAL",28,57,85), (34,72,"KUBAVAT MAHEE MAYANKKUMAR",34,60,94), (35,73,"LIMBANI PROMISE",34,65,99), (36,76,"MAKADIA TIRTH HEMAL",30,59,89), (37,77,"MAKVANA BANSIBHAI SANJAYBHAI",26,50,76), (38,78,"MAKVANA JAYDIP ANANDBHAI",31,57,88), (39,79,"MALAKIYA PRADIPKUMAR NARSHIHBHAI",31,59,90), (40,81,"MOBH MITALBEN TAKHUBHAI",0,0,0), (41,84,"MOHAMMAD ASHHAD KHANJI",33,66,99), (42,87,"PADVI ANIKETBHAI ARVINDBHAI",22,47,69), (43,92,"PATEL AMEY HEMANG",39,64,103), (44,97,"PATEL ISMABANU FIROZBHAI",23,47,70), (45,98,"PATEL KASHTI VASUDEV",37,63,100), (46,99,"PATEL KRISH HIRENKUMAR",25,54,79), (47,103,"PATEL SHIVANI INDRAVADAN",33,66,99), (48,104,"PATHAN ADNAN PATHAN NAZIR KHAN",5,7,12), (49,110,"RAM KRISH GOVINDBHAI",25,52,77), (50,111,"RAMANUJ PAVAN KISHORBHAI",24,47,71), (51,114,"RATHVA KIRANBHAI BAKABHAI",21,49,70), (52,115,"RATHVA SUNILBHAI VECHATBHAI",23,49,72), (53,120,"SHAH VIDHI ASHISHBHAI",36,65,101), (54,126,"SOLANKI VRUNDA BHAVENDRASINH",33,60,93), (55,131,"SUTARIYA KHUSH DINESHBHAI",22,20,42), (56,135,"TARSARIYA RIDDHI KIRANBHAI",34,20,54), (57,137,"THORAT ZARA RAMANBHAI",7,0,7), (58,139,"TRIVEDI AASTHA PARESH",33,49,82), (59,141,"VAGHELA RISHI MAHESHBHAI",23,48,71), (60,143,"GURJAR SUMIT RANJEETBHAI",25,51,76), (61,144,"VANIYA ROSHISH RAMESHBHAI",30,57,87), (62,146,"VASAVA JAYSHREEBEN RAYSINGBHAI",23,52,75), ] PAGE_W = 1400 MARGIN = 40 col_sno_x = MARGIN col_roll_x = col_sno_x + 50 col_name_x = col_roll_x + 60 col_theory_x = col_name_x + 480 col_prac_x = col_theory_x + 130 col_total_x = col_prac_x + 130 TABLE_RIGHT = col_total_x + 150 ROW_H = 28 COL_H = 70 ROWS_PP = 35 try: ft = ImageFont.truetype(FONT_BOLD, 22) fs = ImageFont.truetype(FONT_BOLD, 15) fn = ImageFont.truetype(FONT_REG, 11) fh = ImageFont.truetype(FONT_BOLD, 12) fb = ImageFont.truetype(FONT_REG, 13) fbb = ImageFont.truetype(FONT_BOLD, 13) except Exception as e: print("Font load error:", e) ft=fs=fn=fh=fb=fbb=ImageFont.load_default() BK=(0,0,0); WH=(255,255,255); LG=(235,235,235); HB=(200,215,235); AR=(245,248,255) xs = [col_sno_x, col_roll_x, col_name_x, col_theory_x, col_prac_x, col_total_x, TABLE_RIGHT] def ct(d, x1, x2, y1, y2, txt, font, multi=False): cx=(x1+x2)//2; cy=(y1+y2)//2 if multi: lines=txt.split("\n"); lh=15; sy=cy-lh*len(lines)//2 for l in lines: bb=d.textbbox((0,0),l,font=font); tw=bb[2]-bb[0] d.text((cx-tw//2,sy),l,fill=BK,font=font); sy+=lh else: bb=d.textbbox((0,0),txt,font=font) d.text((cx-(bb[2]-bb[0])//2, cy-(bb[3]-bb[1])//2),txt,fill=BK,font=font) def vlines(d,y1,y2): for x in xs: d.line([(x,y1),(x,y2)],fill=BK,width=1) def hline(d,y): d.line([(MARGIN,y),(TABLE_RIGHT,y)],fill=BK,width=1) def draw_page(d, rows, is_first): y = 30 if is_first: d.text((PAGE_W//2,y),"KIRAN MEDICAL COLLEGE, SURAT",fill=BK,font=ft,anchor="mt"); y+=30 d.text((PAGE_W//2,y),"DEPARTMENT OF MICROBIOLOGY",fill=BK,font=ft,anchor="mt"); y+=36 d.text((PAGE_W//2,y),"List of Students to appear for Remedial Examination AUGUST, 2026",fill=BK,font=fs,anchor="mt"); y+=22 d.text((PAGE_W//2,y),"Based on Aggregated Internal Assessment (IA) Marks",fill=BK,font=fs,anchor="mt"); y+=24 d.text((MARGIN,y),"*IA marks are aggregated marks of all the examinations, daily assessments, attendance, recordbooks etc.",fill=BK,font=fn); y+=18 else: d.text((PAGE_W//2,y),"KIRAN MEDICAL COLLEGE, SURAT",fill=BK,font=ft,anchor="mt"); y+=30 d.text((PAGE_W//2,y),"DEPARTMENT OF MICROBIOLOGY",fill=BK,font=ft,anchor="mt"); y+=44 # col header d.rectangle([MARGIN,y,TABLE_RIGHT,y+COL_H],fill=HB,outline=BK) d.rectangle([col_theory_x,y,TABLE_RIGHT,y+22],fill=HB,outline=BK) ct(d,col_theory_x,TABLE_RIGHT,y,y+22,"Internal Assessment Marks",fh) d.line([(col_theory_x,y+22),(TABLE_RIGHT,y+22)],fill=BK,width=1) ct(d,col_sno_x,col_roll_x,y,y+COL_H,"S.\nno.",fh,multi=True) ct(d,col_roll_x,col_name_x,y,y+COL_H,"Roll\nno.",fh,multi=True) ct(d,col_name_x,col_theory_x,y,y+COL_H,"Name of student",fh) ct(d,col_theory_x,col_prac_x,y+22,y+COL_H,"Total\n(Theory)\n(Minimum\ncut off 40%)",fh,multi=True) ct(d,col_prac_x,col_total_x,y+22,y+COL_H,"Total\n(Practical)\n(Minimum\ncut off 40%)",fh,multi=True) ct(d,col_total_x,TABLE_RIGHT,y+22,y+COL_H,"Theory + Practical\n(Minimum cut off\n50% = 100 marks)",fh,multi=True) vlines(d,y,y+COL_H); hline(d,y+COL_H); y+=COL_H # max row d.rectangle([MARGIN,y,TABLE_RIGHT,y+ROW_H],fill=LG) ct(d,col_theory_x,col_prac_x,y,y+ROW_H,"100",fbb) ct(d,col_prac_x,col_total_x,y,y+ROW_H,"100",fbb) ct(d,col_total_x,TABLE_RIGHT,y,y+ROW_H,"200",fbb) vlines(d,y,y+ROW_H); hline(d,y+ROW_H); y+=ROW_H for i,(sno,roll,name,theory,prac,total) in enumerate(rows): bg=WH if i%2==0 else AR d.rectangle([MARGIN,y,TABLE_RIGHT,y+ROW_H],fill=bg) vlines(d,y,y+ROW_H); hline(d,y+ROW_H) ct(d,col_sno_x,col_roll_x,y,y+ROW_H,str(sno),fb) ct(d,col_roll_x,col_name_x,y,y+ROW_H,str(roll),fb) bb=d.textbbox((0,0),name,font=fb); th=bb[3]-bb[1] d.text((col_name_x+8,y+ROW_H//2-th//2),name,fill=BK,font=fb) ct(d,col_theory_x,col_prac_x,y,y+ROW_H,str(theory),fb) ct(d,col_prac_x,col_total_x,y,y+ROW_H,str(prac),fb) ct(d,col_total_x,TABLE_RIGHT,y,y+ROW_H,str(total),fb) y+=ROW_H return y n_pages = (len(students)+ROWS_PP-1)//ROWS_PP for p in range(n_pages): batch=students[p*ROWS_PP:(p+1)*ROWS_PP] is_first=(p==0) extra=165 if is_first else 82 ph=extra+COL_H+ROW_H+len(batch)*ROW_H+40 img=Image.new("RGB",(PAGE_W,ph),"white") draw_page(ImageDraw.Draw(img),batch,is_first) out=f"/tmp/workspace/kiran-list/page_{p+1}.png" img.save(out,"PNG") print(f"Saved {out} {img.size}") print("Done") PYEOF python /tmp/workspace/kiran-list/generate_list.py
page 1
Image · PNG
page 2
Image · PNG