import docx
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.oxml import OxmlElement, parse_xml
from docx.oxml.ns import nsdecls, qn
def create_boleta_doc():
doc = docx.Document()
# Configuración de márgenes
sections = doc.sections
for section in sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
# Estilo general
style = doc.styles['Normal']
font = style.font
font.name = 'Arial'
font.size = Pt(9)
font.color.rgb = RGBColor(0x33, 0x33, 0x33)
# Funciones de apoyo para celdas y bordes
def set_cell_background(cell, hex_color):
shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{hex_color}"/>')
cell._tc.get_or_add_tcPr().append(shading_elm)
def set_cell_margins(cell, top=60, bottom=60, left=100, right=100):
tcPr = cell._tc.get_or_add_tcPr()
tcMar = OxmlElement('w:tcMar')
for m, val in [('top', top), ('bottom', bottom), ('left', left), ('right', right)]:
node = OxmlElement(f'w:{m}')
node.set(qn('w:w'), str(val))
node.set(qn('w:type'), 'dxa')
tcMar.append(node)
tcPr.append(tcMar)
def set_table_borders(table, color="D3D3D3", sz="4", val="single"):
tblPr = table._tbl.tblPr
borders = parse_xml(
f'<w:tblBorders {nsdecls("w")}>\n'
f' <w:top w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
f' <w:left w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
f' <w:bottom w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
f' <w:right w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
f' <w:insideH w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
f' <w:insideV w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
f'</w:tblBorders>'
)
tblPr.append(borders)
# Encabezado (Título y Datos de Empresa)
t_head = doc.add_table(rows=1, cols=2)
t_head.alignment = WD_TABLE_ALIGNMENT.CENTER
t_head.autofit = False
cell_left = t_head.rows[0].cells[0]
cell_right = t_head.rows[0].cells[1]
cell_left.width = Inches(3.8)
cell_right.width = Inches(3.4)
p1 = cell_left.paragraphs[0]
r1 = p1.add_run("Boleta de Pago\n")
r1.bold = True
r1.font.size = Pt(18)
r1.font.color.rgb = RGBColor(0x1B, 0x2A, 0x4A)
r2 = p1.add_run("Mes: septiembre de 2026")
r2.bold = True
r2.font.size = Pt(11)
p_info = cell_left.add_paragraph()
p_info.paragraph_format.space_before = Pt(10)
p_info.add_run("VÍCTOR RAUL CARBAJAL INCA\n").bold = True
p_info.add_run("DNI: 43453964\n")
p_info.add_run("Fecha de Ingreso: 2 de agosto de 2021\n")
p_info.add_run("Cargo: Supervisor Técnico")
# Bloque Empresa
set_cell_background(cell_right, "BDD7EE")
p_emp_title = cell_right.paragraphs[0]
r_emp = p_emp_title.add_run("INFORMACIÓN EMPRESA\n")
r_emp.bold = True
r_emp.font.color.rgb = RGBColor(0x1B, 0x2A, 0x4A)
p_emp_body = cell_right.add_paragraph()
p_emp_body.add_run("RUC: 20604354219\n")
p_emp_body.add_run("Razón Social: NETAXION PERU S.A.C.")
doc.add_paragraph() # Espaciador
# Tabla 1: Datos Laborales
t1_data = [
["Tipo de Trabajador", "Regimen Pensionario", "CUSPP", "Situacion"],
["Empleado", "Habitat PE", "614271VCIBA4", "Vigente"],
["Días Laborados", "Días Subsidiados", "Días No Laborados", "Horas Trabajadas"],
["30.00", "0", "0", "198.00"],
["Sueldo Contractual", "Comprobantes de Vacaciones", "", ""],
["4,350.00", "", "", ""]
]
t1 = doc.add_table(rows=len(t1_data), cols=4)
t1.alignment = WD_TABLE_ALIGNMENT.CENTER
set_table_borders(t1)
for i, row_data in enumerate(t1_data):
row = t1.rows[i]
is_header = (i % 2 == 0)
for j, val in enumerate(row_data):
cell = row.cells[j]
cell.text = val
set_cell_margins(cell, 80, 80, 100, 100)
p = cell.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
if is_header:
set_cell_background(cell, "F2F2F2")
p.runs[0].font.bold = True
p.runs[0].font.size = Pt(8.5)
doc.add_paragraph()
# Tabla 2: Remuneraciones y Descuentos
t2_headers = ["Detalle Remuneracion", "Haberes", "Descuentos"]
t2_rows = [
("Haberes", "", ""),
(" Básico", "S/ 4,350.00", ""),
(" Horas Extras 100% ( 4.0 Horas )", "S/ 148.77", ""),
(" Asignación Familiar", "S/ 113.00", ""),
(" Viáticos", "S/ 260.00", ""),
("Descuentos Legales", "", ""),
(" SPP - Aportación Obligatoria", "", "S/ 461.18"),
(" SPP - Prima De Seguro", "", "S/ 63.18"),
(" Retención Impuesto mensual", "", "S/ 249.07"),
("Totales:", "S/ 4,871.77", "S/ 773.43"),
("NETO A PAGO:", "", "S/ 4,098.34")
]
t2 = doc.add_table(rows=len(t2_rows) + 1, cols=3)
t2.alignment = WD_TABLE_ALIGNMENT.CENTER
set_table_borders(t2)
# Cabecera T2
hdr_cells = t2.rows[0].cells
for j, name in enumerate(t2_headers):
hdr_cells[j].text = name
set_cell_background(hdr_cells[j], "D9D9D9")
set_cell_margins(hdr_cells[j], 100, 100, 100, 100)
p = hdr_cells[j].paragraphs[0]
p.runs[0].font.bold = True
if j > 0:
p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
# Cuerpo T2
for i, (col1, col2, col3) in enumerate(t2_rows):
row_cells = t2.rows[i+1].cells
row_cells[0].text = col1
row_cells[1].text = col2
row_cells[2].text = col3
for j, cell in enumerate(row_cells):
set_cell_margins(cell, 60, 60, 100, 100)
p = cell.paragraphs[0]
if j > 0:
p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
# Formato de secciones especiales
if col1 in ["Haberes", "Descuentos Legales", "Totales:", "NETO A PAGO:"]:
for cell in row_cells:
if p.runs:
p.runs[0].font.bold = True
if col1 == "NETO A PAGO:":
set_cell_background(row_cells[0], "F2F2F2")
set_cell_background(row_cells[1], "F2F2F2")
set_cell_background(row_cells[2], "F2F2F2")
doc.save("Boleta_Pago_Sep2026.docx")
create_boleta_doc()
To embed this project on your website, copy the following code and paste it into your website's HTML: