¿Cómo centrar una tabla con respecto al ancho del documento?

publicado por: Anonymous

Estoy usando reportlab==3.2.0 y quiero saber la forma de poder centrar el Table de platypus. Tengo lo siguiente dentro de una función AJAX en Django:

# Response
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
# Crear PDF
pdf = SimpleDocTemplate(
    response,
    pagesize=A4,
    rightMargin=inch/2,
    leftMargin=inch/2,
    topMargin=inch,
    bottomMargin=inch/2
)
Story = []
# Estilos
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='Center', alignment=TA_CENTER))
# Cabecera
text = '''
    <strong><font size=14>REPORTE DE ASISTENCIA</font></strong>
'''
Story.append(Paragraph(text, styles['Center']))
Story.append(Spacer(1, 15))
data = [(
    Paragraph('<strong><font size=6>#</font></strong>', styles['Center']),
    Paragraph('<strong><font size=6>DNI</font></strong>', styles['Center']),
    Paragraph('<strong><font size=6>APELLIDO PATERNO</font></strong>', styles['Center']),
    Paragraph('<strong><font size=6>APELLIDO MATERNO</font></strong>', styles['Center']),
    Paragraph('<strong><font size=6>NOMBRES</font></strong>', styles['Center']),
    Paragraph('<strong><font size=6>JORNADA</font></strong>', styles['Center']),
    Paragraph('<strong><font size=6>HORA DE INGRESO</font></strong>', styles['Center']),
    Paragraph('<strong><font size=6>HORA DE SALIDA</font></strong>', styles['Center']),
)]
# Registros
for counter, record in enumerate(records, 1):
    nro_documento = record['nro_documento']
    apellido_paterno = record['apellido_paterno']
    apellido_materno = record['apellido_materno']
    nombres = record['nombres']
    jornada = record['fecha'].strftime('%d/%m/%Y')
    fecha_hora_entrada = ''
    fecha_hora_salida = ''
    if record['fecha_hora_entrada']:
        fecha_hora_entrada = record['fecha_hora_entrada'].strftime('%d/%m/%Y %H:%M:%S')
    if record['fecha_hora_salida']:
        fecha_hora_salida = record['fecha_hora_salida'].strftime('%d/%m/%Y %H:%M:%S')
    data.append((
        Paragraph('<font size=6>%s</font>' % counter, styles['Normal']),
        Paragraph('<font size=6>%s</font>' % nro_documento, styles['Normal']),
        Paragraph('<font size=6>%s</font>' % apellido_paterno, styles['Normal']),
        Paragraph('<font size=6>%s</font>' % apellido_materno, styles['Normal']),
        Paragraph('<font size=6>%s</font>' % nombres, styles['Normal']),
        Paragraph('<font size=6>%s</font>' % jornada, styles['Normal']),
        Paragraph('<font size=6>%s</font>' % fecha_hora_entrada, styles['Normal']),
        Paragraph('<font size=6>%s</font>' % fecha_hora_salida, styles['Normal'])
    ))
table = Table(
    data,
    colWidths=50 # Valor del ancho de las columnas
)
table.setStyle(
    TableStyle([
        ('VALIGN',(0, 0), (-1, -1),'MIDDLE'),
        ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black),
        ('BOX', (0, 0), (-1, -1), 0.25, colors.black),
    ])
)
Story.append(table)
pdf.build(Story)

Como pueden apreciar estoy usando un ancho estático de 50 ya que no encuentro la manera de centrar la tabla, la idea es que este ancho varíe por el tipo de columna. Asi es como se ve mi PDF, hay demasiado espacio libre en los bordes izquierdo y derecho y si aumento el ancho de la columna entonces excede el ancho del documento:

introducir la descripción de la imagen aquí

solución

Gracias a @AntonioBeamud pude llegar a mi respuesta definitiva, no tenía idea de que se podía pasar una lista en la definición de Table. Esta es la solución más óptima según mi parecer aunque estoy abierto a soluciones más eficientes.

En reporlab el valor para inch (pulgada) es de 72.0:

>>> from reportlab.lib.units import inch
>>> inch
72.0

Los márgenes que estoy usando son los siguientes:

pdf = SimpleDocTemplate(
    response,
    pagesize=A4,
    rightMargin=inch/2,
    leftMargin=inch/2,
    topMargin=inch,
    bottomMargin=inch/2
)

Con lo que tenemos en el margen izquierdo y derecho un valor de 36.0 (inch/2):

introducir la descripción de la imagen aquí

Ahora, el tamaño del papel en formato A4 según la siguiente tabla es de 8.3 x 11.7 (pulgadas):

introducir la descripción de la imagen aquí

Entonces, mediante un simple cálculo podemos determinar el ancho total de nuestro papel y el espacio total restante con respecto a los márgenes:

>>> from reportlab.lib.units import inch
>>> ancho = inch * 8.3
>>> ancho
597.6

El espacio total de los márgenes izquierdo y derecho es de 72.0 (inch / 2 * 2). Con lo que tendríamos para el espacio total:

>>> ancho -= (inch / 2 * 2)
>>> ancho
525.6

introducir la descripción de la imagen aquí

Aun asi, calcular el total del ancho de cada columna es un tema más de prueba y error que de otra cosa. Por lo que probando llegue al siguiente resultado final para mis columnas:

table = Table(
    data,
    colWidths=(30, 40, 90, 90, 90, 45, 70.3, 70.3)
)

La suma de las columnas:

>>> 30 + 40 + 90 + 90 + 90 + 45 + 70.3 + 70.3
525.6

El resultado es una tabla que aprovecha perfectamente el espacio del ancho total con respecto a los márgenes:

introducir la descripción de la imagen aquí

Espero les sirva a otros para futuras referencias y evitar dolores de cabeza.

Referencias:

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *