WxPython開發(fā)之實現(xiàn)表格數(shù)據(jù)導出到Excel并打開
在 Python 中使用 wxPython 導出實體類列表數(shù)據(jù)到 Excel,通??梢越柚?nbsp;openpyxl 或 pandas 庫來實現(xiàn)。本篇隨筆由淺入深,逐步介紹導出Excel文件的操作,然后結合跨平臺項目的實現(xiàn),根據(jù)抽象繼承的方式,對不同業(yè)務模塊的通用導出Excel文件功能,以及跨平臺的打開處理方式的實現(xiàn)進行介紹。
以下是一個基本示例,展示如何將實體類的列表數(shù)據(jù)導出到 Excel 文件。
1、使用pandas 庫導出Excel
import wx
import pandas as pd
# 假設這是你的實體類
class Person:
def __init__(self, name, age, email):
self.name = name
self.age = age
self.email = email
def to_dict(self):
return {"Name": self.name, "Age": self.age, "Email": self.email}
# 用一個 wxPython 窗口展示如何導出數(shù)據(jù)
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super().__init__(parent, title=title, size=(300, 200))
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label="導出到Excel", pos=(50, 50))
# 創(chuàng)建一些實體類數(shù)據(jù)
self.person_list = [
Person("Alice", 30, "alice@example.com"),
Person("Bob", 25, "bob@example.com"),
Person("Charlie", 35, "charlie@example.com")
]
self.Bind(wx.EVT_BUTTON, self.export_to_excel, self.button)
self.Show()
def export_to_excel(self, event):
# 將實體類列表轉換為字典列表
data = [person.to_dict() for person in self.person_list]
# 使用 pandas 導出到 Excel
df = pd.DataFrame(data)
df.to_excel("exported_data.xlsx", index=False)
wx.MessageBox("導出成功!", "信息", wx.OK | wx.ICON_INFORMATION)
# 啟動 wxPython 應用
app = wx.App(False)
frame = MyFrame(None, "導出實體類數(shù)據(jù)到 Excel")
app.MainLoop()實體類 (Person):包含一些字段,如 name、age 和 email,并定義了 to_dict 方法,將實體對象轉換為字典格式,以便更容易處理。
export_to_excel:這個方法將實體類列表轉換為字典列表,使用 pandas 庫將數(shù)據(jù)導出為 Excel 文件。
如果你需要更多的功能(如自定義 Excel 格式,單元格樣式等),可以進一步擴展 openpyxl 或 xlsxwriter 來提供更復雜的導出選項。
2、使用 openpyxl 庫導出Excel
要在 Excel 導出時為標題加粗并設置背景色,你可以使用 openpyxl 庫,它提供了豐富的功能來設置單元格樣式(如字體、背景色等)。
以下是一個更新的示例,演示如何在導出數(shù)據(jù)時,設置 Excel 標題行的加粗和背景色。
import wx
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill
# 假設這是你的實體類
class Person:
def __init__(self, name, age, email):
self.name = name
self.age = age
self.email = email
def to_dict(self):
return {"Name": self.name, "Age": self.age, "Email": self.email}
# 用一個 wxPython 窗口展示如何導出數(shù)據(jù)
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super().__init__(parent, title=title, size=(300, 200))
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label="導出到Excel", pos=(50, 50))
# 創(chuàng)建一些實體類數(shù)據(jù)
self.person_list = [
Person("Alice", 30, "alice@example.com"),
Person("Bob", 25, "bob@example.com"),
Person("Charlie", 35, "charlie@example.com")
]
self.Bind(wx.EVT_BUTTON, self.export_to_excel, self.button)
self.Show()
def export_to_excel(self, event):
# 將實體類列表轉換為字典列表
data = [person.to_dict() for person in self.person_list]
# 創(chuàng)建 Excel 工作簿和工作表
wb = Workbook()
ws = wb.active
ws.title = "People Data"
# 設置標題行并加粗背景色
titles = ["Name", "Age", "Email"]
ws.append(titles)
# 設置標題樣式:加粗和背景色
title_font = Font(bold=True)
title_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") # 黃色背景
for cell in ws[1]:
cell.font = title_font
cell.fill = title_fill
# 填充數(shù)據(jù)
for person in data:
ws.append([person["Name"], person["Age"], person["Email"]])
# 保存到文件
wb.save("exported_data_with_styles.xlsx")
wx.MessageBox("導出成功!", "信息", wx.OK | wx.ICON_INFORMATION)
# 啟動 wxPython 應用
app = wx.App(False)
frame = MyFrame(None, "導出實體類數(shù)據(jù)到 Excel")
app.MainLoop()Excel 在 openpyxl 中可以設置自適應列寬或者指定具體的列寬,甚至可以設置框架(邊框樣式)。
雖然 openpyxl 本身并沒有直接提供“自動調整列寬”的功能,但我們可以通過遍歷列中的所有單元格來計算每列的最大寬度,然后動態(tài)調整列寬。
調整后的代碼如下所示。
import wx
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Border, Side
# 假設這是你的實體類
class Person:
def __init__(self, name, age, email):
self.name = name
self.age = age
self.email = email
def to_dict(self):
return {"Name": self.name, "Age": self.age, "Email": self.email}
# 用一個 wxPython 窗口展示如何導出數(shù)據(jù)
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super().__init__(parent, title=title, size=(300, 200))
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label="導出到Excel", pos=(50, 50))
# 創(chuàng)建一些實體類數(shù)據(jù)
self.person_list = [
Person("Alice", 30, "alice@example.com"),
Person("Bob", 25, "bob@example.com"),
Person("Charlie", 35, "charlie@example.com")
]
self.Bind(wx.EVT_BUTTON, self.export_to_excel, self.button)
self.Show()
def export_to_excel(self, event):
# 將實體類列表轉換為字典列表
data = [person.to_dict() for person in self.person_list]
# 創(chuàng)建 Excel 工作簿和工作表
wb = Workbook()
ws = wb.active
ws.title = "People Data"
# 設置標題行并加粗背景色
titles = ["Name", "Age", "Email"]
ws.append(titles)
# 設置標題樣式:加粗和背景色
title_font = Font(bold=True)
title_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") # 黃色背景
for cell in ws[1]:
cell.font = title_font
cell.fill = title_fill
# 填充數(shù)據(jù)
for person in data:
ws.append([person["Name"], person["Age"], person["Email"]])
# 設置列寬(手動指定或根據(jù)內容自適應)
# 自動調整列寬
for col in ws.columns:
max_length = 0
column = col[0].column_letter # 獲取列字母
for cell in col:
try:
if len(str(cell.value)) > max_length:
max_length = len(cell.value)
except:
pass
adjusted_width = (max_length + 2)
ws.column_dimensions[column].width = adjusted_width
# 設置框架(邊框)
border = Border(
left=Side(border_style="thin"),
right=Side(border_style="thin"),
top=Side(border_style="thin"),
bottom=Side(border_style="thin")
)
for row in ws.iter_rows():
for cell in row:
cell.border = border
# 保存到文件
wb.save("exported_data_with_styles_and_borders.xlsx")
wx.MessageBox("導出成功!", "信息", wx.OK | wx.ICON_INFORMATION)
# 啟動 wxPython 應用
app = wx.App(False)
frame = MyFrame(None, "導出實體類數(shù)據(jù)到 Excel")
app.MainLoop()點擊“導出到Excel”按鈕后,程序將生成一個包含:
- 自動調整列寬的 Excel 文件;
- 每個單元格的邊框;
- 標題行加粗并帶黃色背景色的 Excel 文件。
為了實現(xiàn)一個通用的導出函數(shù),根據(jù) display_columns 和 column_mapping 設置導出的字段,并映射標題名稱,你可以設計一個靈活的函數(shù),接收這些參數(shù)并根據(jù)需要導出數(shù)據(jù)到 Excel。
display_columns:一個字符串,指定需要導出的字段(如name,age,email)。column_mapping:一個字典,指定字段到顯示名稱的映射。list:包含實體類數(shù)據(jù)的列表,每個實體類需要提供to_dict()方法,將數(shù)據(jù)轉換為字典格式。filename:保存的文件名。
import wx
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Border, Side
def export_to_excel(list_data, display_columns, column_mapping, filename):
# 解析 display_columns 為列表
display_columns = display_columns.split(',')
# 獲取映射后的標題
headers = [column_mapping.get(col, col) for col in display_columns]
# 創(chuàng)建 Excel 工作簿和工作表
wb = Workbook()
ws = wb.active
ws.title = "Data"
# 設置標題行并加粗背景色
ws.append(headers)
title_font = Font(bold=True)
title_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") # 黃色背景
for cell in ws[1]:
cell.font = title_font
cell.fill = title_fill
# 填充數(shù)據(jù)
for data_item in list_data:
row = [data_item.get(col) for col in display_columns]
ws.append(row)
# 設置列寬(自動調整)
for col in ws.columns:
max_length = 0
column = col[0].column_letter # 獲取列字母
for cell in col:
try:
if len(str(cell.value)) > max_length:
max_length = len(cell.value)
except:
pass
adjusted_width = (max_length + 2)
ws.column_dimensions[column].width = adjusted_width
# 設置框架(邊框)
border = Border(
left=Side(border_style="thin"),
right=Side(border_style="thin"),
top=Side(border_style="thin"),
bottom=Side(border_style="thin")
)
for row in ws.iter_rows():
for cell in row:
cell.border = border
# 保存到文件
wb.save(filename)
return f"導出成功!文件已保存為 {filename}"調用代碼如下所示
def export(self, event):
display_columns = "name,age,email" # 需要導出的字段
column_mapping = {
"age": "年齡",
"email": "電子郵箱",
"name": "顯示名稱"
}
filename = "exported_data.xlsx" # 保存的文件名
result = export_to_excel(
[person.to_dict() for person in self.person_list],
display_columns,
column_mapping,
filename
)
wx.MessageBox(result, "信息", wx.OK | wx.ICON_INFORMATION)你只需調用 export_to_excel 函數(shù)并傳遞數(shù)據(jù)、要導出的字段(display_columns)、字段映射(column_mapping)和保存的文件名(filename)。它會生成一個 Excel 文件,并按要求設置樣式。
在 openpyxl 中,自動調整列寬是通過檢查列中內容的最大長度來實現(xiàn)的。如果你發(fā)現(xiàn)某一列(例如“年齡”列)的寬度過窄,可能是因為該列中的數(shù)據(jù)(例如數(shù)字)被視為較短的字符串,導致列寬過小。
為了解決這個問題,您可以通過設置列寬時為數(shù)字列提供額外的寬度補償,或者通過在計算列寬時增加一個常量來確保列寬更合適。
# 設置列寬(自動調整)
for col in ws.columns:
max_length = 0
column = col[0].column_letter # 獲取列字母
for cell in col:
try:
if cell.value:
cell_value = str(cell.value)
# 增加補償寬度:如果是數(shù)字列,增加額外寬度
if isinstance(cell.value, (int, float)):
max_length = max(max_length, len(cell_value) + 2) # 數(shù)字列增加 2 的寬度
else:
max_length = max(max_length, len(cell_value))
except:
pass
adjusted_width = (max_length + 2) # 留出一些額外的空間
ws.column_dimensions[column].width = max(adjusted_width, 12) # 設置最小寬度為 12- 列寬補償:對于數(shù)字列(如
age列),在計算最大長度時增加一個+2的補償。這將確保數(shù)字列的列寬足夠顯示數(shù)字值。 - 最小列寬:為了避免列過窄,我設置了
max(adjusted_width, 12),確保列寬至少為 12。如果計算出的列寬小于 12,將強制設置為 12。 - 自動列寬:自動計算每列的最大長度,并為每列分配合適的寬度。
如果我們需要再實際業(yè)務中導出數(shù)據(jù),如對于用戶信息,實體類為UserDto,那么我們需要在導出數(shù)據(jù)之前,將 UserDto 類型的對象轉換為字典格式。
在每個 DTO 對象中,添加一個 to_dict 方法,用于將對象的屬性轉換為字典。to_dict 方法可以返回一個字典,其中每個鍵是類屬性的名稱,每個值是對應的屬性值。
不過我的跨平臺框架中的UserDto對象是與Pydantic模型的,因此它可以通過函數(shù) model_dump 進行通用處理為字典對象。
使用 model_dump 方法可以很方便地將 Python 類對象(特別是 Pydantic 模型或者具備 model_dump 方法的類)轉換為字典。如果你正在使用 Pydantic 或者使用了某些自定義實現(xiàn)了 model_dump 方法的類,可以直接調用該方法來完成對象到字典的轉換。
假設你有一個 UserDto 類,它是一個 Pydantic 模型:
from pydantic import BaseModel
class UserDto(BaseModel):
name: str
age: int
email: str
# 創(chuàng)建一個 UserDto 實例
user = UserDto(name="Alice", age=30, email="alice@example.com")
# 使用 model_dump 將對象轉換為字典
user_dict = user.model_dump()
print(user_dict)在這個例子中,model_dump 會自動將 Pydantic 模型實例轉換為字典,所有字段(即類的屬性)都會成為字典的鍵,屬性值成為字典的值。
如果你有嵌套的 Pydantic 模型,model_dump 會自動遞歸地將嵌套模型轉換為字典。如果你的項目中使用了 Pydantic,這種方法將非常簡便高效。
3、在項目列表基類中增加導出功能
通過上面的封裝測試,我們可以把導出Excel的功能做的很不錯了,因此把它整合到列表基類里面,通過基類界面中增加一個導出按鈕即可實現(xiàn)所有業(yè)務模塊的數(shù)據(jù)導出,不用每個頁面都實現(xiàn),簡化了操作。

添加按鈕采用通用輔助函數(shù)參加按鈕及圖標,并增加導出的處理函數(shù),如下代碼所示。
btn_export = ControlUtil.create_button(
pane, "導出Excel", "xls", handler=self.OnExport, is_async=True
)OnExport函數(shù)的實現(xiàn)如下所示。
async def OnExport(self, event: wx.Event) -> None:
"""導出數(shù)據(jù)"""
# 檢查數(shù)據(jù)是否是一個 Pydantic 實體
export_list = []
for item in self.data:
if hasattr(item, "model_dump"):
export_item = item.model_dump()
export_list.append(export_item)
else:
export_list.append(item)
# print(export_list)
filename = FileDialogUtil.save_excel(self)
if not filename:
return
result = ExcelUtil.export_to_excel(
export_list, self.display_columns, self.column_mapping, filename
)
if result:
if (
MessageUtil.show_confirm(self, "導出成功,是否打開文件?", "導出成功")
== wx.ID_YES
):
ExcelUtil.open_file(filename)
else:
MessageUtil.show_error(self, "導出失敗")在MacOS上彈出導出提示,如下所示。

確認后提示,是否打開文件如下。

導出的文件打開后,可以看到效果如下所示

4、文件的打開方式和跨平臺打開實現(xiàn)
注意,不同平臺打開文件進行查看,操作方式有所不同。
如果你想用默認應用(如 Excel 或 Numbers)直接打開 .xls 文件,你可以通過 Python 的 subprocess 模塊調用 macOS 上的應用程序來打開文件。
在 macOS 中,open 命令可以用來打開任何文件。如果你希望在默認的應用程序中打開 .xls 文件(例如 Excel 或 Numbers),可以使用如下方法:
import subprocess # 打開 .xls 文件 subprocess.run(["open", "your_file.xls"])
macOS 支持通過 os 模塊調用系統(tǒng)命令來打開文件??梢酝ㄟ^ os.system() 或 subprocess.run() 來調用 open 命令,在 macOS 上打開文件。
import os
# 打開 .xls 文件
os.system("open your_file.xls")通過 os.system("open your_file.xls") 或 subprocess.run(["open", "your_file.xls"]),你可以在 macOS 上使用默認的應用程序(如 Excel 或 Numbers)打開 .xls 文件。這些方法非常簡單且不需要依賴外部庫。
os.startfile() 是 Windows 系統(tǒng)中的一個特定方法,用于打開文件并在關聯(lián)的默認應用程序中顯示它。然而,os.startfile() 在 macOS 和 Linux 系統(tǒng)中不可用。因此,在 macOS 上使用該方法會導致錯誤。
為了使代碼在不同平臺上都能工作,您可以編寫一個條件判斷,區(qū)分操作系統(tǒng)并使用合適的命令來打開文件。
import os
import subprocess
import platform
def open_file(file_path):
system = platform.system()
if system == "Darwin": # macOS
subprocess.run(["open", file_path])
elif system == "Windows":
os.startfile(file_path)
elif system == "Linux":
subprocess.run(["xdg-open", file_path])
else:
raise NotImplementedError(f"Unsupported operating system: {system}")
# 示例調用
open_file("your_file.xls")說明:
- macOS (Darwin):使用
open命令。 - Windows:使用
os.startfile(),這是 Windows 特有的方法。 - Linux:使用
xdg-open命令,適用于大多數(shù) Linux 發(fā)行版。
對于跨平臺執(zhí)行系統(tǒng)命令,推薦使用 subprocess 模塊,它提供了更強大的功能,并且更靈活和安全。subprocess.run() 方法是一個更通用的替代方案。
因此結合通用的導出Excel和打開文件,就可以實現(xiàn)Excel文件的導出打開操作了,各個業(yè)務列表模塊度是基于列表基礎頁面的,因此自動具有導出的功能,當然,我們也可以根據(jù)一些條件進行判斷是否使用導出按鈕即可。
列表界面繼承基類,從而可以大幅度的利用相應的規(guī)則和實現(xiàn)。

如對于兩個例子窗體:系統(tǒng)類型定義,客戶信息,其中傳如對應的DTO信息和參數(shù)即可。


子類繼承基類列表頁面,并傳入對應的參數(shù)即可具體化相關的業(yè)務功能了。

以上就是根據(jù)抽象繼承的方式,對不同業(yè)務模塊的通用導出Excel文件功能,以及跨平臺的打開處理方式的實現(xiàn)。
以上就是WxPython開發(fā)之實現(xiàn)表格數(shù)據(jù)導出到Excel并打開的詳細內容,更多關于WxPython數(shù)據(jù)導出到Excel的資料請關注腳本之家其它相關文章!
相關文章
深度定制Python的Flask框架開發(fā)環(huán)境的一些技巧總結
現(xiàn)在越來越多的人使用virtualenv虛擬環(huán)境部署Python項目,包括針對框架的實例文件夾與版本控制布置,這里我們就來整理關于深度定制Python的Flask框架開發(fā)環(huán)境的一些技巧總結2016-07-07

