如何使用 python reportalab 生成自定义表

问题描述 投票:0回答:2

我有下面的数据框,我正在尝试用这些数据生成表格格式的报告。

import pandas as pd
data = {'MonthString': ['January', 'February', 'March'],
        'sachin': [98.08, 99.27, 100.00],
        'saurav': ['96.77', '99.85', '98.86']}
df = pd.DataFrame(data)

我想使用 python 的报告实验室库生成以下格式的表格并将其另存为 pdf

| Customer |           %Uptime 
|----------|--------|--------|---------|
|          | Jan    | Feb    | March   |
|          |--------|--------|---------|
| Schin    | 98.08% | 99.27% | 100.00% |
| Saurav   | 96.77% | 99.85  | 98.86%  |

下面是我试过的代码

from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.pdfgen import canvas
from reportlab.lib import colors
from reportlab.platypus import Table, TableStyle
import pandas as pd

# create the DataFrame
data = {'MonthString': ['January', 'February', 'March'],
        'sachin': [98.08, 99.27, 100.00],
        'saurav': ['96.77', '99.85', '98.86']}

df = pd.DataFrame(data)
df = df.rename(columns={'MonthString': 'Month'})
df = df.set_index('Month').T.reset_index().rename(columns={'index': 'Customer'})

# create the table
table_data = [list(df.columns)]
for i in range(len(df)):
    table_data.append([df.iloc[i][0], *df.iloc[i][1:]])

table = Table(table_data)
table.setStyle(TableStyle([('BACKGROUND', (0,0), (-1,0), colors.gray),
                           ('TEXTCOLOR',(0,0),(-1,0),colors.whitesmoke),
                           ('ALIGN', (0,0), (-1,-1), 'CENTER'),
                           ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
                           ('FONTSIZE', (0,0), (-1,0), 14),
                           ('BOTTOMPADDING', (0,0), (-1,0), 12),
                           ('BACKGROUND',(0,1),(-1,-1),colors.beige),
                           ('GRID',(0,0),(-1,-1),1,colors.black)]))

# create the PDF
pdf_file = 'table.pdf'
c = canvas.Canvas(pdf_file, pagesize=letter)
table.wrapOn(c, inch*7, inch*2)
table.drawOn(c, x=50, y=650)
c.save()

但是我无法正确设置表格格式。谁能帮忙?

python python-3.x reportlab
2个回答
1
投票

我稍微改变了你的输入数据框:

df = pd.DataFrame(data)
cols = df.columns.tolist()
for prsn in range(1, df.shape[1]):
    df[cols[prsn]] = df[cols[prsn]].apply(lambda x: f'{"{:.2f}".format(float(x))}%')
df = df.T.reset_index()
my_list = [['Customer', '%Uptime']] + df.values.tolist()
my_list[1][0] = my_list[2][0]

并更改了 reportlab TableStyle:

table = Table(my_list)
table.setStyle(TableStyle([('SPAN', (0, 1), (0, 2)),
                       ('SPAN', (1, 0), (-1, 0)),
                       ('BACKGROUND', (0,0), (-1,0), colors.gray),
                       ('TEXTCOLOR',(0,0),(-1,0),colors.whitesmoke),
                       ('ALIGN', (0,0), (-1,-1), 'CENTER'),
                       ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
                       ('FONTSIZE', (0,0), (-1,0), 14),
                       ('BOTTOMPADDING', (0,0), (-1,0), 12),
                       ('BACKGROUND',(0,1),(-1,-1),colors.beige),
                       ('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
                       ('GRID',(1, 1), (-1,1),1,colors.black),
                       ('GRID',(0, 0), (-1,0),1,colors.black)] +
                          [('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])]))

我认为pdf视图是您现在需要的。

在我看来这张表应该是这样的:

这是获取它的代码:

df = pd.DataFrame(data)
cols = df.columns.tolist()
for prsn in range(1, df.shape[1]):
    df[cols[prsn]] = df[cols[prsn]].apply(lambda x: f'{"{:.2f}".format(float(x))}%')
df = df.T.reset_index()
my_list = [['Customer', '%Uptime']] + df.values.tolist()
table = Table(my_list)
table.setStyle(TableStyle([('SPAN', (0, 0), (0, 1)),
                   ('SPAN', (1, 0), (-1, 0)),
                   ('BACKGROUND', (0,0), (-1,0), colors.gray),
                   ('BACKGROUND',(0,1),(-1,-1),colors.beige),
                   ('BACKGROUND', (0,0), (0,1), colors.gray),
                   ('TEXTCOLOR',(0,0),(-1,0),colors.whitesmoke),
                   ('ALIGN', (0,0), (-1,-1), 'CENTER'),
                   ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
                   ('FONTSIZE', (0,0), (-1,0), 14),
                   ('BOTTOMPADDING', (0,0), (-1,0), 12),
                   ('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
                   ('GRID',(0, 0), (-1,-1),1,colors.black)]))

0
投票

第一个代码的更多客户(它像我在评论中写的那样工作):

第二个代码的更多客户(它也像我在评论中写的那样工作):

此链接可帮助您了解表格样式在 reportlab 中的工作原理: https://docs.reportlab.com/reportlab/userguide/ch7_tables/ 我认为这是很好的解释

几个例子:

  • ('LINEABOVE', (start col, start row), (stop col, stop row), 1, colors.black)

这只是基本水平线,在本例中位于第 2 行上方(这意味着第三行,因为 0、1、2)。它是从第 1 列(从一月开始)到最后一列(五月),因为 -1 表示最后一列

                       ('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
                   # ('GRID',(1, 1), (-1,1),1,colors.black),
                   # ('GRID',(0, 0), (-1,0),1,colors.black)] +
                   #    [('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])
                       ]))

  • ('GRID',(start col, start row), (stop col, stop row),1,colors.black)

它是从第 1 列(第二列因为 0、1)到最后一列因为 -1 的网格。此网格仅在第 1 行(第二行)中,因为开始行 = 1 和停止行 = 1.

                       #('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
                   ('GRID',(1, 1), (-1,1),1,colors.black),
                   # ('GRID',(0, 0), (-1,0),1,colors.black)] +
                   #    [('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])
                       ]))

  • ('BOX', (start col, start row), (stop col, stop row), 1, colors.black)

它是 box ,所以如果我们有例如一个单元格,它将与网格相同。如果我们有整张桌子,我们只会在边框上画线。在我们的例子中,我们有一个包含框的列表,其长度取决于

df.shape[1]
,这意味着从月数+带有客户名称的第一列。由于 -1,我们案例中的每个框都基于一列,从第 1 行(第二行)到最后一行。因此,如果
df.shape[1] == 6
这意味着我们在表中有 6 列,代码创建 6 个从 0 到 5 的框。

                       #('LINEABOVE', (1, 2), (-1, 2), 1, colors.black),
                   #('GRID',(1, 1), (-1,1),1,colors.black),
                   #('GRID',(0, 0), (-1,0),1,colors.black),
                       ] + [('BOX', (x, 1), (x, -1), 1, colors.black) for x in range(df.shape[1])]))

© www.soinside.com 2019 - 2024. All rights reserved.