I want creat discharge summary for my hospital I want model in word from one with one page another with 2 page
mkdir -p /tmp/workspace/discharge-summary && ls /tmp/workspace/discharge-summary/
~/discharge-summary/build_templates.py
"""
Build two hospital discharge summary Word templates:
- discharge_summary_1page.docx (compact, fits on one A4 page)
- discharge_summary_2page.docx (detailed, spreads over two A4 pages)
"""
from docx import Document
from docx.shared import Pt, Inches, RGBColor, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
import copy
# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE = RGBColor(0x0A, 0x47, 0x7E) # header background / section bars
MID_BLUE = RGBColor(0x1A, 0x73, 0xBB) # sub-header
LIGHT_BLUE = RGBColor(0xD6, 0xE8, 0xF7) # table header fill / alternating row
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
DARK_GREY = RGBColor(0x33, 0x33, 0x33)
MID_GREY = RGBColor(0x66, 0x66, 0x66)
# ── Low-level XML helpers ────────────────────────────────────────────────────
def set_cell_bg(cell, hex_color: str):
"""Fill a table cell with a solid colour (hex without #)."""
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
shd = OxmlElement("w:shd")
shd.set(qn("w:val"), "clear")
shd.set(qn("w:color"), "auto")
shd.set(qn("w:fill"), hex_color)
tcPr.append(shd)
def set_cell_borders(cell, top=None, bottom=None, left=None, right=None):
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
tcBorders = OxmlElement("w:tcBorders")
for side, val in [("top", top), ("bottom", bottom),
("left", left), ("right", right)]:
if val:
el = OxmlElement(f"w:{side}")
el.set(qn("w:val"), val.get("val", "single"))
el.set(qn("w:sz"), val.get("sz", "4"))
el.set(qn("w:space"), val.get("space", "0"))
el.set(qn("w:color"), val.get("color", "auto"))
tcBorders.append(el)
tcPr.append(tcBorders)
def no_space_before(para):
pPr = para._p.get_or_add_pPr()
spacing = OxmlElement("w:spacing")
spacing.set(qn("w:before"), "0")
spacing.set(qn("w:after"), "0")
pPr.append(spacing)
def set_table_no_spacing(table):
tbl = table._tbl
tblPr = tbl.find(qn("w:tblPr"))
if tblPr is None:
tblPr = OxmlElement("w:tblPr")
tbl.insert(0, tblPr)
tblCellMar = OxmlElement("w:tblCellMar")
for side in ["top", "bottom", "left", "right"]:
el = OxmlElement(f"w:{side}")
el.set(qn("w:w"), "60")
el.set(qn("w:type"), "dxa")
tblCellMar.append(el)
tblPr.append(tblCellMar)
def keep_together(para):
pPr = para._p.get_or_add_pPr()
kl = OxmlElement("w:keepLines")
pPr.append(kl)
def page_break(doc):
para = doc.add_paragraph()
run = para.add_run()
run.add_break(docx_break_type())
no_space_before(para)
def docx_break_type():
from docx.oxml.ns import qn as _qn
from docx.oxml import OxmlElement as _OE
br = _OE("w:br")
br.set(_qn("w:type"), "page")
return br
# ── Reusable building blocks ─────────────────────────────────────────────────
def add_hospital_header(doc, hospital_name="City General Hospital",
tagline="Excellence in Healthcare",
address="123 Medical Drive, Health City | Tel: +1 234 567 8900 | www.citygeneralhospital.com"):
"""Dark-blue banner header with hospital name."""
tbl = doc.add_table(rows=1, cols=1)
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
cell = tbl.cell(0, 0)
set_cell_bg(cell, "0A477E")
p1 = cell.paragraphs[0]
p1.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p1.add_run(hospital_name.upper())
run.font.color.rgb = WHITE
run.font.size = Pt(18)
run.font.bold = True
run.font.name = "Arial"
no_space_before(p1)
p2 = cell.add_paragraph()
p2.alignment = WD_ALIGN_PARAGRAPH.CENTER
r2 = p2.add_run(tagline)
r2.font.color.rgb = RGBColor(0xCC, 0xDD, 0xEE)
r2.font.size = Pt(9)
r2.font.italic = True
r2.font.name = "Arial"
no_space_before(p2)
p3 = cell.add_paragraph()
p3.alignment = WD_ALIGN_PARAGRAPH.CENTER
r3 = p3.add_run(address)
r3.font.color.rgb = RGBColor(0xCC, 0xDD, 0xEE)
r3.font.size = Pt(7.5)
r3.font.name = "Arial"
no_space_before(p3)
# bottom padding inside header cell
tcPr = cell._tc.get_or_add_tcPr()
tcMar = OxmlElement("w:tcMar")
for side, val in [("top","80"),("bottom","80"),("left","120"),("right","120")]:
el = OxmlElement(f"w:{side}")
el.set(qn("w:w"), val); el.set(qn("w:type"), "dxa")
tcMar.append(el)
tcPr.append(tcMar)
# Title row
p_title = doc.add_paragraph()
p_title.alignment = WD_ALIGN_PARAGRAPH.CENTER
pPr = p_title._p.get_or_add_pPr()
sp = OxmlElement("w:spacing")
sp.set(qn("w:before"), "60")
sp.set(qn("w:after"), "60")
pPr.append(sp)
rt = p_title.add_run("DISCHARGE SUMMARY")
rt.font.color.rgb = DARK_BLUE
rt.font.size = Pt(13)
rt.font.bold = True
rt.font.name = "Arial"
def add_section_bar(doc, title: str, font_size=9):
"""Coloured section title bar."""
tbl = doc.add_table(rows=1, cols=1)
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
cell = tbl.cell(0, 0)
set_cell_bg(cell, "1A73BB")
p = cell.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
run = p.add_run(f" {title.upper()}")
run.font.color.rgb = WHITE
run.font.size = Pt(font_size)
run.font.bold = True
run.font.name = "Arial"
no_space_before(p)
tcPr = cell._tc.get_or_add_tcPr()
tcMar = OxmlElement("w:tcMar")
for side, val in [("top","40"),("bottom","40"),("left","80"),("right","80")]:
el = OxmlElement(f"w:{side}")
el.set(qn("w:w"), val); el.set(qn("w:type"), "dxa")
tcMar.append(el)
tcPr.append(tcMar)
return tbl
def add_info_table(doc, rows_data, col_widths=None, header=False):
"""
Create a neat 2-column label/value table.
rows_data: list of (label, placeholder) tuples
Can be split into 2 side-by-side logical pairs using 4-col layout.
"""
cols = 4
n = len(rows_data)
half = (n + 1) // 2
tbl = doc.add_table(rows=half, cols=cols)
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
set_table_no_spacing(tbl)
if col_widths is None:
col_widths = [Inches(1.1), Inches(2.3), Inches(1.1), Inches(2.3)]
for i, row in enumerate(tbl.rows):
for j, cell in enumerate(row.cells):
w = col_widths[j] if j < len(col_widths) else Inches(1.5)
cell.width = w
for idx, (label, value) in enumerate(rows_data):
r = idx % half
c = (idx // half) * 2 # 0 or 2
label_cell = tbl.cell(r, c)
value_cell = tbl.cell(r, c + 1)
set_cell_bg(label_cell, "D6E8F7")
lp = label_cell.paragraphs[0]
lrun = lp.add_run(label)
lrun.font.bold = True
lrun.font.size = Pt(8)
lrun.font.name = "Arial"
lrun.font.color.rgb = DARK_BLUE
lp.alignment = WD_ALIGN_PARAGRAPH.LEFT
no_space_before(lp)
vp = value_cell.paragraphs[0]
vrun = vp.add_run(value)
vrun.font.size = Pt(8)
vrun.font.name = "Arial"
vrun.font.color.rgb = MID_GREY
vp.alignment = WD_ALIGN_PARAGRAPH.LEFT
no_space_before(vp)
# light bottom border between rows
for cell in [label_cell, value_cell]:
set_cell_borders(cell,
bottom={"val":"single","sz":"2","color":"CCCCCC"})
return tbl
def add_text_box(doc, label, placeholder, font_size=8, lines=2):
"""Single-row label above a lined placeholder area."""
tbl = doc.add_table(rows=1, cols=1)
set_table_no_spacing(tbl)
cell = tbl.cell(0, 0)
ph_text = placeholder + ("\n" * (lines - 1))
lp = cell.paragraphs[0]
r1 = lp.add_run(label + ":\n")
r1.font.bold = True
r1.font.size = Pt(font_size)
r1.font.name = "Arial"
r1.font.color.rgb = DARK_BLUE
no_space_before(lp)
r2 = lp.add_run(ph_text)
r2.font.size = Pt(font_size)
r2.font.name = "Arial"
r2.font.color.rgb = MID_GREY
set_cell_borders(cell,
top={"val":"single","sz":"4","color":"1A73BB"},
bottom={"val":"single","sz":"4","color":"1A73BB"},
left={"val":"single","sz":"4","color":"1A73BB"},
right={"val":"single","sz":"4","color":"1A73BB"})
return tbl
def add_meds_table(doc, compact=True):
"""Discharge medications table."""
headers = ["#", "Medication", "Dose", "Route", "Frequency", "Duration"]
col_w = [Inches(0.25), Inches(2.1), Inches(0.7), Inches(0.6), Inches(0.85), Inches(0.8)]
rows = 4 if compact else 7
tbl = doc.add_table(rows=rows + 1, cols=len(headers))
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
set_table_no_spacing(tbl)
for j, (h, w) in enumerate(zip(headers, col_w)):
cell = tbl.cell(0, j)
cell.width = w
set_cell_bg(cell, "0A477E")
p = cell.paragraphs[0]
run = p.add_run(h)
run.font.bold = True
run.font.size = Pt(7.5)
run.font.name = "Arial"
run.font.color.rgb = WHITE
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
no_space_before(p)
for i in range(1, rows + 1):
bg = "FFFFFF" if i % 2 == 1 else "EDF4FB"
for j in range(len(headers)):
cell = tbl.cell(i, j)
set_cell_bg(cell, bg)
p = cell.paragraphs[0]
run = p.add_run("")
run.font.size = Pt(8)
run.font.name = "Arial"
no_space_before(p)
set_cell_borders(cell, bottom={"val":"single","sz":"2","color":"CCCCCC"})
return tbl
def add_signature_block(doc, compact=True):
"""Three-column signature row."""
tbl = doc.add_table(rows=2, cols=3)
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
set_table_no_spacing(tbl)
labels = ["Attending Physician", "Consultant / Specialist", "Ward Nurse / Co-signer"]
subs = ["Name / Signature / Date", "Name / Signature / Date", "Name / Signature / Date"]
for j in range(3):
top_cell = tbl.cell(0, j)
set_cell_bg(top_cell, "0A477E")
tp = top_cell.paragraphs[0]
tr = tp.add_run(f" {labels[j]}")
tr.font.bold = True
tr.font.size = Pt(7.5)
tr.font.name = "Arial"
tr.font.color.rgb = WHITE
tp.alignment = WD_ALIGN_PARAGRAPH.LEFT
no_space_before(tp)
bot_cell = tbl.cell(1, j)
set_cell_bg(bot_cell, "F0F5FB")
bp = bot_cell.paragraphs[0]
br = bp.add_run(f"\n\n {subs[j]}")
br.font.size = Pt(7.5)
br.font.name = "Arial"
br.font.color.rgb = MID_GREY
bp.alignment = WD_ALIGN_PARAGRAPH.LEFT
no_space_before(bp)
set_cell_borders(bot_cell,
bottom={"val":"single","sz":"4","color":"1A73BB"})
return tbl
def small_gap(doc, pts=40):
p = doc.add_paragraph()
pPr = p._p.get_or_add_pPr()
sp = OxmlElement("w:spacing")
sp.set(qn("w:before"), "0")
sp.set(qn("w:after"), str(pts))
pPr.append(sp)
# ══════════════════════════════════════════════════════════════════════════════
# TEMPLATE 1 — ONE PAGE (compact)
# ══════════════════════════════════════════════════════════════════════════════
def build_1page():
doc = Document()
section = doc.sections[0]
section.page_height = Cm(29.7)
section.page_width = Cm(21.0)
section.top_margin = Cm(1.0)
section.bottom_margin = Cm(1.0)
section.left_margin = Cm(1.5)
section.right_margin = Cm(1.5)
# ── Header ───────────────────────────────────────────────────────────────
add_hospital_header(doc)
small_gap(doc, 30)
# ── Patient Demographics ──────────────────────────────────────────────────
add_section_bar(doc, "Patient Information")
small_gap(doc, 10)
add_info_table(doc, [
("Patient Name:", "_______________________________"),
("Date of Birth:", "__ / __ / ____"),
("MRN / ID:", "_______________________________"),
("Age:", "____ yrs"),
("Gender:", "☐ Male ☐ Female ☐ Other"),
("Nationality:", "_______________________________"),
("Admission Date:", "__ / __ / ____"),
("Discharge Date:", "__ / __ / ____"),
("Ward / Room:", "_______________________________"),
("Length of Stay:", "____ days"),
])
small_gap(doc, 20)
# ── Diagnosis ─────────────────────────────────────────────────────────────
add_section_bar(doc, "Diagnosis")
small_gap(doc, 10)
add_info_table(doc, [
("Admission Diagnosis:", "_______________________________"),
("Final Diagnosis:", "_______________________________"),
("ICD-10 Code:", "_______________________________"),
("Procedure(s):", "_______________________________"),
], col_widths=[Inches(1.3), Inches(2.1), Inches(1.3), Inches(2.1)])
small_gap(doc, 20)
# ── Clinical Summary (compact 2-col layout) ───────────────────────────────
add_section_bar(doc, "Clinical Summary")
small_gap(doc, 10)
# Two side-by-side boxes
tbl = doc.add_table(rows=1, cols=2)
set_table_no_spacing(tbl)
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
for j, (lbl, ph) in enumerate([
("History & Examination", "Brief presenting history and key examination findings..."),
("Investigations", "Key labs, imaging, ECG results..."),
]):
cell = tbl.cell(0, j)
set_cell_bg(cell, "F7FBFF")
set_cell_borders(cell,
top={"val":"single","sz":"4","color":"1A73BB"},
bottom={"val":"single","sz":"4","color":"1A73BB"},
left={"val":"single","sz":"4","color":"1A73BB"},
right={"val":"single","sz":"4","color":"1A73BB"})
p = cell.paragraphs[0]
r1 = p.add_run(lbl + ":\n")
r1.font.bold = True; r1.font.size = Pt(7.5); r1.font.name = "Arial"
r1.font.color.rgb = DARK_BLUE
r2 = p.add_run(ph + "\n\n")
r2.font.size = Pt(7.5); r2.font.name = "Arial"; r2.font.color.rgb = MID_GREY
no_space_before(p)
small_gap(doc, 20)
# Treatment & Condition
tbl2 = doc.add_table(rows=1, cols=2)
set_table_no_spacing(tbl2)
tbl2.alignment = WD_TABLE_ALIGNMENT.CENTER
for j, (lbl, ph) in enumerate([
("Treatment Given / Procedures", "Medications, procedures, surgeries performed..."),
("Condition at Discharge", "☐ Stable ☐ Improved ☐ Unchanged ☐ Transferred\n\nNotes: _______________________"),
]):
cell = tbl2.cell(0, j)
set_cell_bg(cell, "F7FBFF")
set_cell_borders(cell,
top={"val":"single","sz":"4","color":"1A73BB"},
bottom={"val":"single","sz":"4","color":"1A73BB"},
left={"val":"single","sz":"4","color":"1A73BB"},
right={"val":"single","sz":"4","color":"1A73BB"})
p = cell.paragraphs[0]
r1 = p.add_run(lbl + ":\n")
r1.font.bold = True; r1.font.size = Pt(7.5); r1.font.name = "Arial"
r1.font.color.rgb = DARK_BLUE
r2 = p.add_run(ph + "\n")
r2.font.size = Pt(7.5); r2.font.name = "Arial"; r2.font.color.rgb = MID_GREY
no_space_before(p)
small_gap(doc, 20)
# ── Discharge Medications ────────────────────────────────────────────────
add_section_bar(doc, "Discharge Medications")
small_gap(doc, 10)
add_meds_table(doc, compact=True)
small_gap(doc, 20)
# ── Follow-up & Instructions ─────────────────────────────────────────────
add_section_bar(doc, "Follow-Up & Discharge Instructions")
small_gap(doc, 10)
tbl3 = doc.add_table(rows=1, cols=2)
set_table_no_spacing(tbl3)
tbl3.alignment = WD_TABLE_ALIGNMENT.CENTER
for j, (lbl, ph) in enumerate([
("Follow-Up Appointment", "Date: ___________ Dept: ___________\nPhysician: ___________________________"),
("Discharge Instructions", "Activity restrictions, diet, wound care, warning signs..."),
]):
cell = tbl3.cell(0, j)
set_cell_bg(cell, "F7FBFF")
set_cell_borders(cell,
top={"val":"single","sz":"4","color":"1A73BB"},
bottom={"val":"single","sz":"4","color":"1A73BB"},
left={"val":"single","sz":"4","color":"1A73BB"},
right={"val":"single","sz":"4","color":"1A73BB"})
p = cell.paragraphs[0]
r1 = p.add_run(lbl + ":\n")
r1.font.bold = True; r1.font.size = Pt(7.5); r1.font.name = "Arial"
r1.font.color.rgb = DARK_BLUE
r2 = p.add_run(ph + "\n")
r2.font.size = Pt(7.5); r2.font.name = "Arial"; r2.font.color.rgb = MID_GREY
no_space_before(p)
small_gap(doc, 20)
# ── Signatures ───────────────────────────────────────────────────────────
add_section_bar(doc, "Authorisation & Signatures")
small_gap(doc, 10)
add_signature_block(doc)
# footer note
small_gap(doc, 30)
fp = doc.add_paragraph()
fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
fr = fp.add_run("CONFIDENTIAL — This document is intended solely for the named patient and authorised healthcare providers. Page 1 of 1")
fr.font.size = Pt(6.5)
fr.font.name = "Arial"
fr.font.color.rgb = MID_GREY
no_space_before(fp)
out = "/tmp/workspace/discharge-summary/Discharge_Summary_1Page.docx"
doc.save(out)
print(f"Saved: {out}")
# ══════════════════════════════════════════════════════════════════════════════
# TEMPLATE 2 — TWO PAGES (detailed)
# ══════════════════════════════════════════════════════════════════════════════
def build_2page():
doc = Document()
section = doc.sections[0]
section.page_height = Cm(29.7)
section.page_width = Cm(21.0)
section.top_margin = Cm(1.5)
section.bottom_margin = Cm(1.5)
section.left_margin = Cm(2.0)
section.right_margin = Cm(2.0)
# ═══════════════ PAGE 1 ══════════════════════════════════════════════════
# ── Header ───────────────────────────────────────────────────────────────
add_hospital_header(doc)
small_gap(doc, 40)
# ── Patient Demographics ──────────────────────────────────────────────────
add_section_bar(doc, "Patient Information", font_size=10)
small_gap(doc, 15)
add_info_table(doc, [
("Patient Full Name:", "___________________________________"),
("Date of Birth:", "__ / __ / ____"),
("Medical Record No.:", "___________________________________"),
("Age:", "____ years"),
("Gender:", "☐ Male ☐ Female ☐ Other"),
("Blood Group:", "_______"),
("Nationality:", "___________________________________"),
("Contact No.:", "___________________________________"),
("Referring Physician:","___________________________________"),
("Payer / Insurance:", "___________________________________"),
], col_widths=[Inches(1.4), Inches(2.4), Inches(1.4), Inches(2.4)])
small_gap(doc, 25)
# ── Admission Details ─────────────────────────────────────────────────────
add_section_bar(doc, "Admission & Discharge Details", font_size=10)
small_gap(doc, 15)
add_info_table(doc, [
("Admission Date:", "__ / __ / ____"),
("Admission Time:", "__ : __ ☐ AM ☐ PM"),
("Discharge Date:", "__ / __ / ____"),
("Discharge Time:", "__ : __ ☐ AM ☐ PM"),
("Ward / Unit:", "___________________________________"),
("Room / Bed No.:", "___________________________________"),
("Length of Stay:", "____ days"),
("Type of Admission:", "☐ Elective ☐ Emergency ☐ Transfer"),
], col_widths=[Inches(1.4), Inches(2.4), Inches(1.4), Inches(2.4)])
small_gap(doc, 25)
# ── Diagnosis ─────────────────────────────────────────────────────────────
add_section_bar(doc, "Diagnosis", font_size=10)
small_gap(doc, 15)
add_info_table(doc, [
("Admission Diagnosis:", "___________________________________"),
("ICD-10 (Admission):", "___________________________________"),
("Final / Principal Dx:", "___________________________________"),
("ICD-10 (Final):", "___________________________________"),
("Secondary Diagnoses:", "___________________________________"),
("Comorbidities:", "___________________________________"),
("Procedure(s):", "___________________________________"),
("ICD-10-PCS / CPT:", "___________________________________"),
], col_widths=[Inches(1.5), Inches(2.3), Inches(1.5), Inches(2.3)])
small_gap(doc, 25)
# ── History & Examination ─────────────────────────────────────────────────
add_section_bar(doc, "History & Physical Examination", font_size=10)
small_gap(doc, 15)
add_text_box(doc,
"Presenting Complaint & History of Present Illness",
"Document the patient's chief complaint, onset, duration, associated symptoms, "
"relevant past medical / surgical / family / social history...\n\n\n",
lines=5)
small_gap(doc, 10)
add_text_box(doc,
"Physical Examination Findings",
"Vital signs: BP ___ / ___ HR ___ RR ___ Temp ___°C SpO₂ ___%\n"
"General: ___________ Systemic: ______________________________________\n\n",
lines=4)
small_gap(doc, 25)
# ── Investigations ────────────────────────────────────────────────────────
add_section_bar(doc, "Investigations & Results", font_size=10)
small_gap(doc, 15)
# Labs sub-table
inv_tbl = doc.add_table(rows=1, cols=2)
inv_tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
set_table_no_spacing(inv_tbl)
for j, (lbl, ph) in enumerate([
("Laboratory Results",
"CBC: ___________________\nLFT / RFT: ______________\n"
"Electrolytes: ___________\nOther: __________________\n"),
("Imaging & Special Investigations",
"X-Ray: _________________\nCT/MRI: ________________\n"
"Echo/ECG: ______________\nOther: __________________\n"),
]):
cell = inv_tbl.cell(0, j)
set_cell_bg(cell, "F7FBFF")
set_cell_borders(cell,
top={"val":"single","sz":"4","color":"1A73BB"},
bottom={"val":"single","sz":"4","color":"1A73BB"},
left={"val":"single","sz":"4","color":"1A73BB"},
right={"val":"single","sz":"4","color":"1A73BB"})
p = cell.paragraphs[0]
r1 = p.add_run(lbl + ":\n"); r1.font.bold = True
r1.font.size = Pt(9); r1.font.name = "Arial"; r1.font.color.rgb = DARK_BLUE
r2 = p.add_run(ph)
r2.font.size = Pt(9); r2.font.name = "Arial"; r2.font.color.rgb = MID_GREY
no_space_before(p)
# ═══════════════ PAGE 2 ══════════════════════════════════════════════════
# Explicit page break
pb_para = doc.add_paragraph()
pb_run = pb_para.add_run()
from docx.oxml import OxmlElement as _OE
from docx.oxml.ns import qn as _qn
br = _OE("w:br"); br.set(_qn("w:type"), "page")
pb_run._r.append(br)
no_space_before(pb_para)
# ── Page 2 Header (smaller) ───────────────────────────────────────────────
# Compact repeat header
ph2_tbl = doc.add_table(rows=1, cols=3)
ph2_tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
set_table_no_spacing(ph2_tbl)
for j, (lbl, val) in enumerate([
("Patient Name:", "________________________________"),
("MRN:", "________________"),
("Discharge Date:", "__ / __ / ____"),
]):
cell = ph2_tbl.cell(0, j)
set_cell_bg(cell, "D6E8F7")
p = cell.paragraphs[0]
r1 = p.add_run(lbl + " "); r1.font.bold = True
r1.font.size = Pt(8); r1.font.name = "Arial"; r1.font.color.rgb = DARK_BLUE
r2 = p.add_run(val)
r2.font.size = Pt(8); r2.font.name = "Arial"; r2.font.color.rgb = MID_GREY
no_space_before(p)
small_gap(doc, 20)
p_sub = doc.add_paragraph()
p_sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
rs = p_sub.add_run("DISCHARGE SUMMARY — Page 2 of 2")
rs.font.bold = True; rs.font.size = Pt(11)
rs.font.name = "Arial"; rs.font.color.rgb = DARK_BLUE
no_space_before(p_sub)
small_gap(doc, 20)
# ── Treatment ─────────────────────────────────────────────────────────────
add_section_bar(doc, "Treatment Given During Admission", font_size=10)
small_gap(doc, 15)
add_text_box(doc,
"Medical Management",
"Medications, IV fluids, oxygen therapy, and other conservative measures administered...\n\n\n",
lines=4)
small_gap(doc, 10)
add_text_box(doc,
"Surgical / Procedural Interventions",
"Operation name, date, surgeon, anaesthesia type, findings, and intraoperative notes...\n\n\n",
lines=4)
small_gap(doc, 10)
add_text_box(doc,
"Course in Hospital",
"Progress during admission, response to treatment, complications, consultations...\n\n\n",
lines=4)
small_gap(doc, 20)
# ── Condition at Discharge ────────────────────────────────────────────────
add_section_bar(doc, "Condition at Discharge", font_size=10)
small_gap(doc, 15)
add_info_table(doc, [
("Discharge Condition:", "☐ Stable ☐ Improved ☐ Unchanged ☐ Deteriorated"),
("Vital Signs at D/C:", "BP: ___ / ___ HR: ___ Temp: ___°C SpO₂: ___%"),
("Discharge Disposition:","☐ Home ☐ Rehab ☐ Nursing Home ☐ Transfer ☐ AMA"),
("Functional Status:", "☐ Independent ☐ Partial Assist ☐ Full Assist"),
], col_widths=[Inches(1.5), Inches(5.7)])
small_gap(doc, 20)
# ── Discharge Medications ────────────────────────────────────────────────
add_section_bar(doc, "Discharge Medications", font_size=10)
small_gap(doc, 15)
add_meds_table(doc, compact=False)
small_gap(doc, 20)
# ── Follow-up ─────────────────────────────────────────────────────────────
add_section_bar(doc, "Follow-Up Plan & Discharge Instructions", font_size=10)
small_gap(doc, 15)
add_info_table(doc, [
("Follow-Up Date:", "__ / __ / ____"),
("Department / Clinic:", "___________________________________"),
("Treating Physician:", "___________________________________"),
("Contact for Concerns:", "___________________________________"),
], col_widths=[Inches(1.5), Inches(2.3), Inches(1.5), Inches(2.3)])
small_gap(doc, 10)
add_text_box(doc,
"Discharge Instructions (Diet, Activity, Wound Care, Warning Signs)",
"• Diet: _______________\n• Activity: ____________\n"
"• Wound care: __________\n• Return to ER if: _______\n• Other: _______________",
lines=5)
small_gap(doc, 20)
# ── Allergy Alert ─────────────────────────────────────────────────────────
add_info_table(doc, [
("Known Allergies:", "☐ NKDA Drug: ____________ Food: ____________ Other: ____________"),
("Pending Results:", "___________________________________________________________________"),
], col_widths=[Inches(1.5), Inches(5.7)])
small_gap(doc, 20)
# ── Signatures ───────────────────────────────────────────────────────────
add_section_bar(doc, "Authorisation & Signatures", font_size=10)
small_gap(doc, 15)
add_signature_block(doc, compact=False)
# footer note
small_gap(doc, 40)
fp = doc.add_paragraph()
fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
fr = fp.add_run(
"CONFIDENTIAL — This document is intended solely for the named patient and authorised healthcare providers.\n"
"Retain as part of the permanent medical record. | City General Hospital | Page 2 of 2")
fr.font.size = Pt(7)
fr.font.name = "Arial"
fr.font.color.rgb = MID_GREY
no_space_before(fp)
out = "/tmp/workspace/discharge-summary/Discharge_Summary_2Page.docx"
doc.save(out)
print(f"Saved: {out}")
# ── Main ─────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
build_1page()
build_2page()
print("Done.")
cd /tmp/workspace/discharge-summary && python build_templates.py
python3 -c " from docx import Document for fname in [ '/tmp/workspace/discharge-summary/Discharge_Summary_1Page.docx', '/tmp/workspace/discharge-summary/Discharge_Summary_2Page.docx' ]: doc = Document(fname) texts = [p.text.strip() for p in doc.paragraphs if p.text.strip()] print(f'--- {fname.split(\"/\")[-1]} ---') for t in texts[:10]: print(' ', t) print() "
Discharge Summary 1Page
Word Document · DOCX
Discharge Summary 2Page
Word Document · DOCX