我正在尝试使用 fpdf 在 Python 中构建 pdf 报告。我想从存储在 DataFrame 中的分析中获取一些数据并创建表格和图表。就像您在 Excel 中所做的那样。我的问题是,如果您在创建表格,则无法像在 Excel 中使用“换行文本”功能那样获得标题换行文本。我尝试了多次迭代,我想出的最好的如下:
data1 = {
'Category': ['A', 'B', 'C', 'D'],
'Values': [10.1234, 20.5678, 15.9101, 25.1121]
}
data2 = {
'Category': ['E', 'F', 'G', 'H'],
'I expect this to wrap': [30.2345, 40.6789, 35.3456, 45.7890]
}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
# Create a PDF class
class PDF(FPDF):
def header(self):
self.set_font('Arial', 'B', 12)
self.cell(0, 10, 'PDF Report with Charts and Tables', 0, 1, 'C')
self.ln(10)
def chapter_title(self, title):
self.set_font('Arial', 'B', 12)
self.cell(0, 10, title, 0, 1, 'L')
self.ln(5)
def table(self, df):
self.set_font('Helvetica', '', 10)
# Calculate column widths
index_col_width = max(self.get_string_width(str(index)) for index in df.index) + 10
col_widths = {col: self.get_string_width(col) + 10 for col in df.columns}
max_col_width = max(col_widths.values())
# Row height
row_height = self.font_size + 5
# Header
self.set_fill_color(255, 255, 255)
self.set_draw_color(0, 0, 0)
# Wrap headers
x_start = self.get_x()
y_start = self.get_y()
self.multi_cell(index_col_width, row_height, 'Member', border=1, align='C', fill=True)
self.set_xy(x_start + index_col_width, y_start)
for col_name in df.columns:
x_start = self.get_x()
y_start = self.get_y()
self.multi_cell(max_col_width, row_height, col_name, border=1, align='C', fill=True)
self.set_xy(x_start + max_col_width, y_start)
self.ln(row_height)
# Data
fill = False
for index, row in df.iterrows():
fill = not fill
self.set_fill_color(240, 240, 240) if fill else self.set_fill_color(255, 255, 255)
self.cell(index_col_width, row_height, str(index), border=1, fill=True, align='L')
for cell in row:
formatted_cell = f"{cell:.2f}" if isinstance(cell, float) else str(cell)
self.cell(max_col_width, row_height, formatted_cell, border=1, fill=True, align='L')
self.ln(row_height)
# Create a PDF document
pdf = PDF()
pdf.set_auto_page_break(auto=True, margin=15)
# Add first table
pdf.add_page(orientation='L')
pdf.chapter_title('Table 1: Category vs Values')
pdf.table(df1)
# Add second table
pdf.add_page(orientation='L')
pdf.chapter_title('Table 2: Category vs Values')
pdf.table(df2)
# Create chart for demonstration
plt.figure(figsize=(10, 5.63)) # Adjust figure size to fit within page
plt.bar(df1['Category'], df1['Values'], color='skyblue')
plt.title('Sample Bar Chart')
plt.xlabel('Category')
plt.ylabel('Values')
plt.savefig('bar_chart.png') # Save the figure
plt.close()
# Add chart
pdf.add_page(orientation='L')
pdf.chapter_title('Sample Bar Chart')
pdf.image('bar_chart.png', x=10, y=30, w=250) # Adjust the positioning and size as needed
# Output the PDF
pdf.output('report_test_2_check.pdf')
这给了我以下内容:
下面是我对第二个表的期望的 Excel 示例:
尝试使用FPDF2:
pip 安装 fpdf2
这个版本是今天最后一个版本,它解决了包装问题。
这是解释这一点的代码:
from fpdf import FPDF
TABLE_DATA = (
("wrap this text wrap this text", "wrap this text wrap this text", "wrap this text wrap this text", "wrap this text wrap this text"),
("Jules", "Smith", "34", "San Juan"),
("Mary", "Ramos", "45", "Orlando"),
("Carlson", "Banks", "19", "Los Angeles"),
("Lucas", "Cimon", "31", "Saint-Mathurin-sur-Loire"),
)
pdf = FPDF()
pdf.add_page()
pdf.set_font("Times", size=16)
with pdf.table() as table:
for data_row in TABLE_DATA:
row = table.row()
for datum in data_row:
row.cell(datum)
pdf.output('table.pdf')
上面的代码将给出以下结果: