在 Python 中使用 wxPython 导出实体类列表数据到 Excel,通常可以借助 openpyxlpandas 库来实现。本篇随笔由浅入深,逐步介绍导出Excel文件的操作,然后结合跨平台项目的实现,根据抽象继承的方式,对不同业务模块的通用导出Excel文件功能,以及跨平台的打开处理方式的实现进行介绍。

以下是一个基本示例,展示如何将实体类的列表数据导出到 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 窗口展示如何导出数据
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)) # 创建一些实体类数据
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, "导出实体类数据到 Excel")
app.MainLoop()

实体类 (Person):包含一些字段,如 nameageemail,并定义了 to_dict 方法,将实体对象转换为字典格式,以便更容易处理。

export_to_excel:这个方法将实体类列表转换为字典列表,使用 pandas 库将数据导出为 Excel 文件。

如果你需要更多的功能(如自定义 Excel 格式,单元格样式等),可以进一步扩展 openpyxlxlsxwriter 来提供更复杂的导出选项。

2、使用 openpyxl 库导出Excel

要在 Excel 导出时为标题加粗并设置背景色,你可以使用 openpyxl 库,它提供了丰富的功能来设置单元格样式(如字体、背景色等)。

以下是一个更新的示例,演示如何在导出数据时,设置 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 窗口展示如何导出数据
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)) # 创建一些实体类数据
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] # 创建 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 # 填充数据
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, "导出实体类数据到 Excel")
app.MainLoop()

Excel 在 openpyxl 中可以设置自适应列宽或者指定具体的列宽,甚至可以设置框架(边框样式)。

虽然 openpyxl 本身并没有直接提供“自动调整列宽”的功能,但我们可以通过遍历列中的所有单元格来计算每列的最大宽度,然后动态调整列宽。

调整后的代码如下所示。

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 窗口展示如何导出数据
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)) # 创建一些实体类数据
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] # 创建 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 # 填充数据
for person in data:
ws.append([person["Name"], person["Age"], person["Email"]]) # 设置列宽(手动指定或根据内容自适应)
# 自动调整列宽
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, "导出实体类数据到 Excel")
app.MainLoop()

点击“导出到Excel”按钮后,程序将生成一个包含:

  • 自动调整列宽的 Excel 文件;
  • 每个单元格的边框;
  • 标题行加粗并带黄色背景色的 Excel 文件。

为了实现一个通用的导出函数,根据 display_columnscolumn_mapping 设置导出的字段,并映射标题名称,你可以设计一个灵活的函数,接收这些参数并根据需要导出数据到 Excel。

  • display_columns:一个字符串,指定需要导出的字段(如 name,age,email)。
  • column_mapping:一个字典,指定字段到显示名称的映射。
  • list:包含实体类数据的列表,每个实体类需要提供 to_dict() 方法,将数据转换为字典格式。
  • 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] # 创建 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 # 填充数据
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 函数并传递数据、要导出的字段(display_columns)、字段映射(column_mapping)和保存的文件名(filename)。它会生成一个 Excel 文件,并按要求设置样式。

openpyxl 中,自动调整列宽是通过检查列中内容的最大长度来实现的。如果你发现某一列(例如“年龄”列)的宽度过窄,可能是因为该列中的数据(例如数字)被视为较短的字符串,导致列宽过小。

为了解决这个问题,您可以通过设置列宽时为数字列提供额外的宽度补偿,或者通过在计算列宽时增加一个常量来确保列宽更合适。

    # 设置列宽(自动调整)
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)
# 增加补偿宽度:如果是数字列,增加额外宽度
if isinstance(cell.value, (int, float)):
max_length = max(max_length, len(cell_value) + 2) # 数字列增加 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
  • 列宽补偿:对于数字列(如 age 列),在计算最大长度时增加一个 +2 的补偿。这将确保数字列的列宽足够显示数字值。
  • 最小列宽:为了避免列过窄,我设置了 max(adjusted_width, 12),确保列宽至少为 12。如果计算出的列宽小于 12,将强制设置为 12。
  • 自动列宽:自动计算每列的最大长度,并为每列分配合适的宽度。

如果我们需要再实际业务中导出数据,如对于用户信息,实体类为UserDto,那么我们需要在导出数据之前,将 UserDto 类型的对象转换为字典格式。

在每个 DTO 对象中,添加一个 to_dict 方法,用于将对象的属性转换为字典。to_dict 方法可以返回一个字典,其中每个键是类属性的名称,每个值是对应的属性值。

不过我的跨平台框架中的UserDto对象是与Pydantic模型的,因此它可以通过函数 model_dump  进行通用处理为字典对象。

使用 model_dump 方法可以很方便地将 Python 类对象(特别是 Pydantic 模型或者具备 model_dump 方法的类)转换为字典。如果你正在使用 Pydantic 或者使用了某些自定义实现了 model_dump 方法的类,可以直接调用该方法来完成对象到字典的转换。

假设你有一个 UserDto 类,它是一个 Pydantic 模型:

from pydantic import BaseModel

class UserDto(BaseModel):
name: str
age: int
email: str # 创建一个 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的功能做的很不错了,因此把它整合到列表基类里面,通过基类界面中增加一个导出按钮即可实现所有业务模块的数据导出,不用每个页面都实现,简化了操作。

添加按钮采用通用辅助函数参加按钮及图标,并增加导出的处理函数,如下代码所示。

  btn_export = ControlUtil.create_button(
pane, "导出Excel", "xls", handler=self.OnExport, is_async=True
)

OnExport函数的实现如下所示。

    async def OnExport(self, event: wx.Event) -> None:
"""导出数据"""
# 检查数据是否是一个 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、文件的打开方式和跨平台打开实现

注意,不同平台打开文件进行查看,操作方式有所不同。

如果你想用默认应用(如 Excel 或 Numbers)直接打开 .xls 文件,你可以通过 Python 的 subprocess 模块调用 macOS 上的应用程序来打开文件。

在 macOS 中,open 命令可以用来打开任何文件。如果你希望在默认的应用程序中打开 .xls 文件(例如 Excel 或 Numbers),可以使用如下方法:

import subprocess

# 打开 .xls 文件
subprocess.run(["open", "your_file.xls"])

macOS 支持通过 os 模块调用系统命令来打开文件。可以通过 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 系统中的一个特定方法,用于打开文件并在关联的默认应用程序中显示它。然而,os.startfile()macOSLinux 系统中不可用。因此,在 macOS 上使用该方法会导致错误。

为了使代码在不同平台上都能工作,您可以编写一个条件判断,区分操作系统并使用合适的命令来打开文件。

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 命令,适用于大多数 Linux 发行版。

对于跨平台执行系统命令,推荐使用 subprocess 模块,它提供了更强大的功能,并且更灵活和安全。subprocess.run() 方法是一个更通用的替代方案。

因此结合通用的导出Excel和打开文件,就可以实现Excel文件的导出打开操作了,各个业务列表模块度是基于列表基础页面的,因此自动具有导出的功能,当然,我们也可以根据一些条件进行判断是否使用导出按钮即可。

列表界面继承基类,从而可以大幅度的利用相应的规则和实现。

如对于两个例子窗体:系统类型定义,客户信息,其中传如对应的DTO信息和参数即可。

子类继承基类列表页面,并传入对应的参数即可具体化相关的业务功能了。

以上就是根据抽象继承的方式,对不同业务模块的通用导出Excel文件功能,以及跨平台的打开处理方式的实现。

WxPython跨平台开发框架之表格数据导出到Excel并打开的更多相关文章

  1. Vue+element UI实现表格数据导出Excel组件

    介绍 这是一个可以将页面中的表格数据导出为Excel文件的功能组件,该组件一般与表格一起使用,将表格数据传给组件,然后通过点击组件按钮可将表格中的数据导出成Excel文件. 使用方法 由于封装该组件内 ...

  2. 将页面中表格数据导出excel格式的文件(vue)

    近期由于项目需要,需要将页面中的表格数据导出excel格式的文件,折腾了许久,在网上各种百度,虽然资料不少,但是大都不全,踩了许多坑,总算是皇天不负有心人,最后圆满解决了. 1.安装相关依赖(npm安 ...

  3. 前端 vue表格数据导出Excel 文件实现

    实现思路 使用json2csv将后台json数据转化为csv格式数据 采用创建Blob(二进制大对象)的方式来存放缓存数据: 生成下载链接: 创建一个a标签,设置href和download属性 触发a ...

  4. 学习笔记 DataGridView数据导出为Excel

    DataGridView数据导出为Excel   怎样把WinForm下的“DGV”里的绑定数据库后的数据导出到Excel中. 比如:在窗体里有个一“DGV”,DataGridView1,绑定了数据源 ...

  5. asp.net将数据导出到excel

    本次应用datatable导出,若用gridview(假设gridview设为了分页显示)会出现只导出当前页的情况. protected void btnPrn_Click(object sender ...

  6. 机房收费系统——在VB中将MSHFlexGrid控件中的数据导出到Excel

    机房收费系统中,好多查询的窗体都包含同一个功能:将数据库中查询到的数据显示在MSHFlexGrid控件中,然后再把MSHFlexGrid控件中的数据导出到Excel表格中. 虽然之前做过学生信息管理系 ...

  7. 将Datagridview中的数据导出至Excel中

        首先添加一个模块ImportToExcel,并添加引用         然后导入命名空间: Imports Microsoft.Office.Interop Imports System.Da ...

  8. C#大量数据导出到Excel(转)

    工作过程中经常会用到将数据导出到Excel中,一般情况下需要导出的数据都是几百几千条或者上万条,这都没有什么问题,但有时候会遇到特殊的需求,客户要求把几十万条甚至上百万条的数据导出到Excel中,这就 ...

  9. Java利用Apache POI将数据库数据导出为excel

    将数据库中的数据导出为excel文件,供其他人查看 public class POITest { public static void main(String[] args) { POITest te ...

  10. Magic xpa 3.x很容易将数据导出到Excel中

    Magic xpa 3.x很方便的将表中数据导出到Excel文件中,还可以自动将表中数据生成各种图表. 通过使用自带的打印数据内部事即可实现. 1.首先将打印数据任务属性设置为“是”. 2.可使用主程 ...

随机推荐

  1. 3.1 migration to 5.0

    记入我遇到的问题 : 1. localizer.WithCulture 废弃了 https://github.com/dotnet/aspnetcore/issues/7756 其实讨论很久了, 只是 ...

  2. SuperMap iDesktopX创建HBase数据源并导入数据

    需提前部署HBase集群,HBase环境搭建请查看文章https://www.cnblogs.com/zhangyongli2011/p/12034628.html 本文基于10.1.1 win版本s ...

  3. 离线安装Redis

    redis 直接去官网下载tar包就可以 主要是gcc 环境的安装包不太好找,我下载的还缺少 make 如果服务器比较干净,还得预装一下lrzsz-0.12.20.tar.gz 上传下载文件,unzi ...

  4. Spark集群的安装及高可用配置

    spark官网学习文档 Spark集群的安装及高可用配置 前期需求:Hadoop和Scala必须已经安装完成 步骤: ①进入spark下载网站中https://spark.apache.org/dow ...

  5. UEFI原理与编程(三)

    1 开发UEFI服务 本质Protocol 就是包含属性和函数指针的结构体,功能上来说就是提供者和使用者对服务的一种约定. 2 开发UEFI驱动 一个设备/总线驱动程序在安装时首要找到对应的硬件设备( ...

  6. Newstar_week1-2_wp

    week1 wp crypto 一眼秒了 n费马分解再rsa flag: import libnum import gmpy2 from Crypto.Util.number import * p = ...

  7. C++ 命令行传参 参数使用 坐标参数的转换

    目录 1. 什么是命令行传参 2. 如何传参 3. 应用实例 4. 问题 1. 什么是命令行传参 命令行传参就是在 cmd 命令提示符, 或者 Linux shell 中使用可执行程序时, 可以添加 ...

  8. 使用 vscode 编译+运行 typescropt Mac win同理

    一..d.ts文件最好在src/typings 目录下,可在tsconfig.json 文件配置 二.vs 监听文件变化,自动编译ts文件 tsconfig.json { "compiler ...

  9. 教程:搭建一个我的世界模组服务器(Linux)

    首先给自己的服务器打个广告 服务器版本1.12.2 地址:www.verysucksminecraftserver.top(好像只有一个月) 所需Mod网盘:https://pan.quark.cn/ ...

  10. layui laydate日期时间范围,时间默认设定为23:59:59

    在Layui中,如果你想设置日期时间选择器(datetime)的默认结束时间为当天的23:59:59,你可以使用如下代码(红色部分): laydate.render({ elem: '#test10' ...