技术求助:如何将Pandas DataFrame或QTableWidget转换为PDF?
Hey Daniel, let's fix that PDF generation issue for your product reports. I've got two solid approaches for you—one leveraging your Pandas DataFrame (which is straightforward since you're already querying the DB into it) and another that works directly from your QTableWidget. Both use pure Python libraries so you won't run into external tool dependencies like wkhtmltopdf.
This method uses fpdf2 (a modern PDF generation library) and tabulate to format your DataFrame into a clean table for the PDF.
First, install the required packages:
pip install fpdf2 tabulate pandas sqlalchemy
Then update your gerarRelatorio function to add PDF generation:
import sqlite3 import pandas as pd from sqlalchemy import create_engine from fpdf import FPDF from tabulate import tabulate def gerarRelatorio(self): self.banco = sqlite3.connect('Vendas.db') engine = create_engine('sqlite:///Vendas.db') df = pd.read_sql_table("Produtos", engine) print(df) # Initialize PDF object pdf = FPDF() pdf.add_page() # Set font for the document pdf.set_font("Arial", size=12) # Extract headers and data from DataFrame table_headers = df.columns.tolist() table_data = df.values.tolist() # Format data into a grid-style table using tabulate formatted_table = tabulate(table_data, headers=table_headers, tablefmt="grid") # Write the table to PDF (multi_cell handles line breaks) pdf.multi_cell(0, 10, txt=formatted_table, align='L') # Save the final PDF pdf.output("Relatorio_Produtos_DataFrame.pdf") print("PDF generated successfully from DataFrame!")
This will create a neatly formatted PDF with your product data, including proper grid lines and headers.
If you prefer to use the data already loaded into your QTableWidget, we can extract the data first then generate the PDF the same way.
Update or add this function to your code:
from fpdf import FPDF def gerarRelatorioDesdeTabela(self): table = self.listaprodutos row_count = table.rowCount() col_count = table.columnCount() # Extract table headers (make sure your QTableWidget has headers set!) try: table_headers = [table.horizontalHeaderItem(col).text() for col in range(col_count)] except AttributeError: # Fallback if headers aren't set—use database column names instead self.banco = sqlite3.connect('Vendas.db') cursor = self.banco.execute("SELECT * FROM Produtos LIMIT 0") table_headers = [description[0] for description in cursor.description] # Extract all row data from the table table_data = [] for row_idx in range(row_count): current_row = [] for col_idx in range(col_count): table_item = table.item(row_idx, col_idx) current_row.append(table_item.text() if table_item else "") table_data.append(current_row) # Generate PDF pdf = FPDF() pdf.add_page() pdf.set_font("Arial", size=12) # Write headers with a separator line header_line = " | ".join(table_headers) pdf.cell(0, 10, txt=header_line, ln=True, align='L') pdf.cell(0, 5, txt="-" * len(header_line), ln=True, align='L') # Write each row of data for row in table_data: row_line = " | ".join(row) pdf.cell(0, 10, txt=row_line, ln=True, align='L') # Save the PDF pdf.output("Relatorio_Produtos_Tabela.pdf") print("PDF generated successfully from QTableWidget!")
A quick note: If your QTableWidget doesn't have headers configured, this code will fall back to fetching column names directly from the SQLite database—so you don't have to worry about missing headers.
Either of these methods should work reliably for your product report needs. Let me know if you run into any small tweaks needed for your specific data format!
内容的提问来源于stack exchange,提问作者Daniel Oliveira

