在日常办公、测试或数据报告中,你是否也曾被批量生成格式化的Excel文件所困扰?手动复制粘贴不仅效率低下,还极易出错。本文将深入探讨如何利用Python,打造一个强大的Excel模板自动化填充工具,实现数据与模板的智能结合,一键生成上百份标准化报告,彻底解放你的双手。
一、工具概览:Python驱动的Excel自动化利器
我们构建的这个工具,其核心是一个基于Python的脚本,它能够读取一个预设的Excel模板文件和一个包含多行数据的信息文件。工具的核心任务是:为信息文件中的每一行数据,在输出文件中创建一个独立的工作表(Sheet),并将模板中特定的占位符(如{姓名}、{部门})替换为对应行的实际数据。最终,所有个性化的工作表会被整合到一个新的Excel文件中。
例如,信息表中有10个人的信息,工具就会生成一个包含10个工作表的Excel文件,每个工作表都以对应人员的姓名命名,并填充了其专属信息。这对于批量生成测试用例、员工报告、客户合同等场景极具价值。
工具界面简洁直观:

用户只需导入模板文件和信息文件,选择输出路径,点击“生成”按钮即可。下面,我们来看看实现这一功能所需的核心技术与关键细节。掌握这些技巧,你不仅能使用现成工具,更能理解其背后的原理,甚至进行定制化开发。
二、核心技术解析:Pandas与Openpyxl的强强联合
本工具主要依赖Python的两个强大库:Pandas用于高效的数据读取和处理,Openpyxl用于精细化的Excel文件读写和格式控制。这种组合兼顾了数据处理的速度和对Excel文件格式的完全控制力。
1. 数据读取与基础操作
使用Pandas的read_excel函数可以轻松将Excel文件加载为DataFrame,这是进行所有数据操作的基础。
# 读取Excel文件
df = pd.read_excel('文件.xlsx', sheet_name='Sheet1')
遍历数据行是核心操作之一。Pandas的iterrows()方法返回一个迭代器,方便我们逐行处理数据。
import pandas as pd
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c']})
for idx,row in df.iterrows():
print(f"索引:{idx},行数据:{row['A']},{row['B']}")
有时我们只关心行数据,不关心索引,可以使用下划线_忽略索引变量:
for _,row in df.iterrows():
print(f"行数据:{row['A']},{row['B']}")
精确定位和修改DataFrame中的值,.loc[]方法是首选。它通过行标签和列标签进行访问,语义清晰。
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
}, index=['row1', 'row2', 'row3'])
# 使用.loc - 基于标签
print(df.loc['row2', 'B']) # 输出: 5
# 使用.iloc - 基于位置(整数索引)
print(df.iloc[1, 1]) # 输出: 5 (第2行第2列)
获取DataFrame的列名同样简单:
import pandas as pd
# 创建一个DataFrame
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五'],
'年龄': [25, 30, 28],
'城市': ['北京', '上海', '广州']
})
# .columns 返回列名
print(df.columns)
# 输出: Index(['姓名', '年龄', '城市'], dtype='object')
print(type(df.columns)) #
2. 工作表名称的规范化处理
Excel对工作表名称有严格限制(如不能超过31字符、不能包含[]:*?/\等字符)。直接使用数据中的字段(如姓名)作为Sheet名可能存在风险。因此,我们需要一个清洗函数clean_sheet_name()来确保名称合规。
该函数的核心逻辑包括:clean_sheet_name()
- 长度截断:使用切片操作确保名称不超过31个字符。
- 空格处理:使用
strip()移除首尾空格,并检查是否为空。 - 非法字符替换:将Excel不允许的字符替换为下划线。
字符串切片操作示例:
name = 'Hello world'
print(name[:3])
print(name[0:3])
print(name[slice(0,3)])
使用strip()处理空格:
name = ' 12Hello world34 '
print(f"移除首尾空格:",name.strip())
print(f"移除左边空格:",name.lstrip())
print(f"移除右边空格:",name.rstrip())
# 先移除首端的空白再移除数字
print(f"移除指定字符:",name.lstrip().strip('12'))
这里涉及一个Python的布尔逻辑:空字符串在条件判断中为False。因此if not name.strip()可以有效地检查去除空格后是否为空。
# 确保名称不为空
# 方法1
if not name.strip():
name = "Sheet"
# 方法2
if name.strip() == "":
name = "Sheet"
# 方法3
if len(name.strip()) == 0:
name = "Sheet"
完整的清洗函数还需要处理可能的缺失值(NaN),可以使用Pandas的pd.isna()进行判断。pd.isna()
import pandas as pd
def clean_sheet_name(name, max_length=31):
"""
清理sheet名称,确保符合Excel命名规则
参数:
name: 原始sheet名称
max_length: 最大长度限制(Excel限制为31个字符)
"""
if pd.isna(name):
name = "Sheet"
else:
name = str(name)
# 移除非法字符
illegal_chars = [':', '\\', '/', '?', '*', '[', ']']
for char in illegal_chars:
name = name.replace(char, '')
# 截断到最大长度
if len(name) > max_length:
name = name[:max_length]
# 确保名称不为空
if not name.strip():
name = "Sheet"
return name
# 测试各种情况
test_cases = [
None, # 空值
"销售数据:2024年/第一季度", # 包含非法字符
"这是一个非常非常非常长的Excel工作表名称超过了31个字符llll", # 超长
" ", # 只有空白
"正常名称", # 正常情况
]
for test in test_cases:
print(f"原始Sheet名称:{test} -> 清理后名称:{clean_sheet_name(test)}")
[AFFILIATE_SLOT_1]
三、核心实现:模板填充与文件生成
这是工具的“心脏”部分。我们使用pd.ExcelWriter作为上下文管理器来创建和写入Excel文件,这是最推荐的方式,它能确保文件被正确关闭。
# 等价写法(不推荐,因为需要手动关闭)
writer = pd.ExcelWriter(output_file, engine='openpyxl')
try:
# 写入操作
total_rows = len(info_df)
# ...
finally:
writer.save() # 必须手动保存
writer.close() # 必须手动关闭
# 使用 with 语句(推荐)
# 自动处理资源的打开和关闭,即使出错也会正确关闭
with pd.ExcelWriter(...) as writer:
# 写入操作
pass
# 退出 with 块时自动调用 writer.save() 和 writer.close()
参数指定输出路径,output_file指定使用openpyxl引擎。engine='openpyxl'writer就是这个写入器对象。writer
核心的替换逻辑经历了优化。最初的朴素方法是多层循环遍历模板每个单元格,与信息表每列比对,效率较低。优化后的策略是:
- 提取占位符:一次性扫描模板,使用正则表达式提取所有形如
{xxx}的占位符,并去重。 - 映射替换:遍历信息表每一行数据时,只需将去重后的占位符列表与当前行数据的列名进行匹配,一致的则进行替换。
- 性能提升:通过占位符去重减少了不必要的比对次数;在可能的地方使用Pandas的向量化操作;采用流式处理和模板复用来控制内存使用峰值。
关键替换代码逻辑如下:
# 4. 为信息表中的每一行生成一个sheet
for index, row in info_df.iterrows():
# 获取编号(用于sheet名称)
sheet_name = clean_sheet_name(row.get('编号'))
print(f"正在处理第 {index + 1}/{total_rows} 行: {sheet_name}")
# 复制模板
test_case_df = template_df.copy()
# 5. 替换模板中的占位符
for col in test_case_df.columns:
for idx in test_case_df.index:
cell_value = clean_value(test_case_df.loc[idx, col])
# 提取实际存在的占位符-- 非贪婪匹配,匹配 { 和 } 之间的所有内容
placeholders = re.findall(r'\{(.*?)\}', cell_value)
if placeholders: # 只有存在占位符时才处理
for placeholder in set(placeholders): # 去重
if placeholder in info_df.columns:
replacement = clean_value(row.get(placeholder, ""))
cell_value = cell_value.replace(f"{{{placeholder}}}", replacement)
test_case_df.loc[idx, col] = cell_value
生成文件后,我们还可以利用openpyxl自动调整列宽,让报告更加美观:
def auto_adjust_column_width(worksheet, df):
"""
自动调整Excel列的宽度以适应内容
参数:
worksheet: openpyxl的worksheet对象
df: 对应的DataFrame
"""
try:
# 遍历DataFrame的每一列
for column in df:
# 获取列索引(从1开始)
column_letter = openpyxl.utils.get_column_letter(df.columns.get_loc(column) + 1)
# 计算列的最大宽度
# 考虑列名本身的宽度
max_length = max(
len(str(column)), # 列名宽度
df[column].astype(str).map(len).max() # 该列数据最大宽度
)
# 添加一些边距(增加20%的宽度或至少5个字符)
adjusted_width = max_length * 1.2 + 5
# 设置列宽,限制在5到50之间
adjusted_width = max(5, min(adjusted_width, 50))
# 应用列宽
worksheet.column_dimensions[column_letter].width = adjusted_width
最终生成的效果如下图所示,每个人拥有独立且格式规范的工作表:


四、常见问题与进阶技巧
1. 占位符格式的严格性
最初版本的工具可能要求占位符必须是简单的{字段名}形式。如果包含空格或冒号等,如{姓名:},正则表达式可能无法正确匹配。这要求我们在设计模板时保持占位符的简洁性,或者修改正则表达式模式以兼容更复杂的格式。
原始正则可能只匹配字母、数字和下划线:
# 提取实际存在的占位符
placeholders = re.findall(r'\{(\w+)\}', cell_value)
为了兼容空格和中文,可以调整模式:
import re
# 示例1
cell_value = "Hello {name}, your score is {score_2023}"
placeholders = re.findall(r'\{(\w+)\}', cell_value)
# 结果: ['name', 'score_2023']
# 示例2 - 不匹配的情况
cell_value = "No placeholders here"
placeholders = re.findall(r'\{(\w+)\}', cell_value)
# 结果: []
技术延伸:这种基于模板和数据的生成思想,在JavaScript(如Node.js的xlsx库)、Go(如excelize库)乃至C++中都有对应的实现。选择Python是因为其生态丰富、开发效率高,但对于追求极致性能或需要集成到特定系统的场景,TypeScript或Go也是优秀的选择。
2. 字符串格式化中的花括号转义
在Python的f-string或.format()中,花括号{}有特殊含义。如果模板中需要保留字面意义上的花括号,需要进行转义,使用双花括号{{}}。
name = "张三"
age = 25
print(f"{name}") # 张三
print(f"{{name}}") # {name}
print(f"{{{name}}}") # {张三}
print(f"{{{{{name}}}}}") # {{张三}}
[AFFILIATE_SLOT_2]
五、从脚本到可执行文件:打包与分发
为了让不懂Python的同事也能方便地使用这个工具,我们需要将其打包成一个独立的可执行文件(.exe)。PyInstaller是完成这项任务的最佳工具之一。
首先安装PyInstaller:
pip install pyinstaller
创建一个简单的打包脚本(如build.spec)可以更精细地控制打包过程,例如添加数据文件、设置图标等。build_exe.py
# build_exe.py - 打包脚本
import PyInstaller.__main__
import os
import shutil
import sys
def build_executable():
"""构建可执行文件"""
# 主程序入口文件
main_script = "panel.py" # 假设您的主程序是 panel.py
# PyInstaller 配置参数
args = [
main_script, # 主脚本
'--name=TestCaseGenerator', # 程序名称
'--onefile', # 打包成单个exe文件
'--windowed', # 如果是GUI程序(控制台程序去掉这个)
'--icon=icon.ico', # 图标文件(可选)
'--add-data=templates;templates', # 包含模板文件夹
'--add-data=*.xlsx;.', # 包含Excel文件
'--hidden-import=pandas',
'--hidden-import=openpyxl',
'--hidden-import=numpy',
'--clean', # 清理临时文件
]
# 运行打包
PyInstaller.__main__.run(args)
print("打包完成!可执行文件在 dist/TestCaseGenerator.exe")
if __name__ == "__main__":
build_executable()
然后执行打包命令:
# 1. 将panel.py修改为可执行入口(如果需要)
# 2. 执行打包命令
pyinstaller --onefile --name=TestTool panel.py
打包成功后,你会得到一个独立的.exe文件,可以在没有Python环境的Windows电脑上直接运行。

实践建议:打包时注意将模板文件、配置文件等作为“数据文件”包含进去,或者让程序在运行时从指定目录读取,以增强工具的灵活性。
六、总结与源码
通过本文的探讨,我们完成了一个从需求分析、技术选型(Pandas+Openpyxl)、核心功能实现(数据读取、模板替换、文件写入)、问题解决(名称规范、占位符匹配)到最终打包分发的完整项目流程。这个Excel模板填充工具的核心价值在于:
- 提升效率:将重复的手工劳动转化为秒级的自动化操作。
- 保证准确:杜绝人工复制粘贴可能带来的错误。
- 标准化输出:确保每一份生成的文件都遵循统一的格式规范。
- 灵活可扩展:通过修改模板和信息表,可以轻松适配各种报告生成场景。
理解其原理后,你可以轻松地将其改造成批量生成Word文档、PDF报告或邮件的工具,自动化思维是相通的。以下是两个核心模块的源码参考,它们构成了这个工具的骨架:
主逻辑模块 (CaseOutput.py):
import pandas as pd
import openpyxl
import warnings
import re # 正则表达式模块,用于提取占位符
warnings.filterwarnings('ignore')
def clean_sheet_name(name, max_length=31):
"""
清理sheet名称,确保符合Excel命名规则
参数:
name: 原始sheet名称
max_length: 最大长度限制(Excel限制为31个字符)
"""
if pd.isna(name):
name = "Sheet"
else:
name = str(name)
# 移除非法字符
illegal_chars = [':', '\\', '/', '?', '*', '[', ']']
for char in illegal_chars:
name = name.replace(char, '')
# 截断到最大长度
if len(name) > max_length:
name = name[:max_length]
# 确保名称不为空
if not name.strip():
name = "Sheet"
return name
def clean_value(value):
"""
清理单元格值,处理NaN和None
参数:
value: 原始值
返回: 清理后的字符串
"""
if pd.isna(value):
return ""
return str(value)
def auto_adjust_column_width(worksheet, df):
"""
自动调整Excel列的宽度以适应内容
参数:
worksheet: openpyxl的worksheet对象
df: 对应的DataFrame
"""
try:
# 遍历DataFrame的每一列
for column in df:
# 获取列索引(从1开始)
column_letter = openpyxl.utils.get_column_letter(df.columns.get_loc(column) + 1)
# 计算列的最大宽度
# 考虑列名本身的宽度
max_length = max(
len(str(column)), # 列名宽度
df[column].astype(str).map(len).max() # 该列数据最大宽度
)
# 添加一些边距(增加20%的宽度或至少5个字符)
adjusted_width = max_length * 1.2 + 5
# 设置列宽,限制在5到50之间
adjusted_width = max(5, min(adjusted_width, 50))
# 应用列宽
worksheet.column_dimensions[column_letter].width = adjusted_width
except Exception as e:
print(f"自动调整列宽时发生错误: {e}")
# 如果出错,设置默认列宽
for column in df.columns:
column_letter = openpyxl.utils.get_column_letter(df.columns.get_loc(column) + 1)
worksheet.column_dimensions[column_letter].width = 20
def generate_test_cases_from_files(template_file, info_file, output_file):
"""
处理文件生成测试用例
参数:
template_file: 模板文件路径
info_file: 信息表文件路径
output_file: 输出文件路径
返回: 生成的测试用例数量
"""
try:
print("正在读取模板文件...")
# 1. 读取模板文件,保持空单元格为空字符串
template_df = pd.read_excel(
template_file,
dtype=str, # 所有列都读取为字符串类型
keep_default_na=False
)
print("正在读取信息表...")
# 2. 读取信息表,保持空单元格为空字符串
info_df = pd.read_excel(
info_file,
dtype=str,
keep_default_na=False
)
print("正在生成Excel文件...")
# 3. 创建Excel写入对象
with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
total_rows = len(info_df)
# 4. 为信息表中的每一行生成一个sheet
for index, row in info_df.iterrows():
# 获取编号(用于sheet名称)
sheet_name = clean_sheet_name(row.get('编号'))
print(f"正在处理第 {index + 1}/{total_rows} 行: {sheet_name}")
# 复制模板
test_case_df = template_df.copy()
# 5. 替换模板中的占位符
for col in test_case_df.columns:
for idx in test_case_df.index:
cell_value = clean_value(test_case_df.loc[idx, col])
# 提取实际存在的占位符-- 非贪婪匹配,匹配 { 和 } 之间的所有内容
placeholders = re.findall(r'\{(.*?)\}', cell_value)
if placeholders: # 只有存在占位符时才处理
for placeholder in set(placeholders): # 去重
if placeholder in info_df.columns:
replacement = clean_value(row.get(placeholder, ""))
cell_value = cell_value.replace(f"{{{placeholder}}}", replacement)
test_case_df.loc[idx, col] = cell_value
# 6. 将当前指示灯的测试用例保存到sheet
test_case_df.to_excel(
writer,
sheet_name=sheet_name,
index=False
)
# 获取当前sheet的worksheet对象
worksheet = writer.sheets[sheet_name]
# 调用自动调整列宽函数
auto_adjust_column_width(worksheet, test_case_df)
print(f" 已自动调整 {sheet_name} 的列宽")
print(f"Excel文件生成完成,共生成 {total_rows} 个测试用例")
return total_rows
except KeyError as e:
raise Exception(f"Excel文件中缺少必要的列: {e}")
except PermissionError as e:
raise Exception(f"文件访问权限错误,请关闭Excel文件后重试: {e}")
except Exception as e:
raise Exception(f"文件处理错误: {e}")
GUI界面模块 (panel.py):
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
from CaseOutput import generate_test_cases_from_files
class TestCaseGeneratorGUI:
def __init__(self, root):
self.root = root
self.root.title("测试用例生成器")
self.root.geometry("650x350")
# 初始化文件路径
self.template_file = ""
self.info_file = ""
self.output_file = ""
# 设置样式
self.setup_styles()
# 创建界面
self.create_widgets()
def setup_styles(self):
"""设置界面样式"""
style = ttk.Style()
style.theme_use('clam')
# 自定义大按钮样式
style.configure(
'Large.TButton',
font=('Microsoft YaHei', 11, 'bold'),
padding=(10, 8),
anchor='center',
relief='raised',
width=15
)
# 标签样式
style.configure(
'File.TLabel',
font=('Microsoft YaHei', 10),
padding=(5, 2)
)
# 标签框样式
style.configure(
'TLabelframe',
font=('Microsoft YaHei', 11, 'bold'),
padding=10
)
def create_widgets(self):
"""创建界面组件"""
# 主容器
main_container = ttk.Frame(self.root, padding=20)
main_container.pack(fill='both', expand=True)
# 标题
title_label = tk.Label(
main_container,
text="测试用例生成工具",
font=("Microsoft YaHei", 18, "bold"),
fg="#2c3e50",
bg="#ecf0f1",
pady=15
)
title_label.pack(fill='x', pady=(0, 20))
# 创建内容框架
content_frame = ttk.Frame(main_container)
content_frame.pack(fill='both', expand=True)
# 文件选择区域
self.create_file_selection(content_frame)
# 按钮区域
self.create_button_area(content_frame)
def create_file_selection(self, parent):
"""创建文件选择区域"""
# 模板文件选择区域
template_frame = ttk.LabelFrame(parent, text="1. 选择模板文件")
template_frame.pack(fill="x", padx=10, pady=10)
template_inner = ttk.Frame(template_frame)
template_inner.pack(fill='x', padx=5, pady=8)
self.template_label = ttk.Label(
template_inner,
text="未选择文件",
foreground="gray",
style='File.TLabel',
width=50,
anchor='w'
)
self.template_label.pack(side="left", fill='x', expand=True, padx=(10, 5))
template_btn = ttk.Button(
template_inner,
text="选择模板文件",
command=self.select_template_file,
style='Large.TButton'
)
template_btn.pack(side="right", padx=5)
# 信息表文件选择区域
info_frame = ttk.LabelFrame(parent, text="2. 选择信息表")
info_frame.pack(fill="x", padx=10, pady=10)
info_inner = ttk.Frame(info_frame)
info_inner.pack(fill='x', padx=5, pady=8)
self.info_label = ttk.Label(
info_inner,
text="未选择文件",
foreground="gray",
style='File.TLabel',
width=50,
anchor='w'
)
self.info_label.pack(side="left", fill='x', expand=True, padx=(10, 5))
info_btn = ttk.Button(
info_inner,
text="选择信息表",
command=self.select_info_file,
style='Large.TButton'
)
info_btn.pack(side="right", padx=5)
# 输出文件选择区域
output_frame = ttk.LabelFrame(parent, text="3. 选择输出文件位置")
output_frame.pack(fill="x", padx=10, pady=10)
output_inner = ttk.Frame(output_frame)
output_inner.pack(fill='x', padx=5, pady=8)
self.output_label = ttk.Label(
output_inner,
text="未选择位置",
foreground="gray",
style='File.TLabel',
width=50,
anchor='w'
)
self.output_label.pack(side="left", fill='x', expand=True, padx=(10, 5))
output_btn = ttk.Button(
output_inner,
text="选择输出位置",
command=self.select_output_file,
style='Large.TButton'
)
output_btn.pack(side="right", padx=5)
def create_button_area(self, parent):
"""创建按钮区域"""
button_frame = ttk.Frame(parent)
button_frame.pack(pady=30)
# 使用tk.Button获得更多控制
self.generate_btn = tk.Button(
button_frame,
text="生成测试用例",
font=('Microsoft YaHei', 12, 'bold'),
command=self.generate_test_cases,
state="disabled",
bg="#27ae60",
fg="white",
activebackground="#229954",
activeforeground="white",
relief="raised",
bd=2,
padx=30,
pady=12,
cursor="hand2",
width=15
)
self.generate_btn.pack(side="left", padx=20)
self.clear_btn = tk.Button(
button_frame,
text="清空选择",
font=('Microsoft YaHei', 12, 'bold'),
command=self.clear_selection,
bg="#e74c3c",
fg="white",
activebackground="#c0392b",
activeforeground="white",
relief="raised",
bd=2,
padx=30,
pady=12,
cursor="hand2",
width=12
)
self.clear_btn.pack(side="left", padx=20)
def select_template_file(self):
"""选择模板文件"""
file_path = filedialog.askopenfilename(
title="选择模板文件",
filetypes=[("Excel文件", "*.xlsx *.xls"), ("所有文件", "*.*")]
)
if file_path:
self.template_file = file_path
file_name = os.path.basename(file_path)
self.template_label.config(text=file_name, foreground="black")
self.check_generate_button()
def select_info_file(self):
"""选择信息表文件"""
file_path = filedialog.askopenfilename(
title="选择信息表",
filetypes=[("Excel文件", "*.xlsx *.xls"), ("所有文件", "*.*")]
)
if file_path:
self.info_file = file_path
file_name = os.path.basename(file_path)
self.info_label.config(text=file_name, foreground="black")
self.check_generate_button()
def select_output_file(self):
"""选择输出文件位置"""
file_path = filedialog.asksaveasfilename(
title="保存测试用例文件",
defaultextension=".xlsx",
filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")]
)
if file_path:
self.output_file = file_path
file_name = os.path.basename(file_path)
self.output_label.config(text=file_name, foreground="black")
self.check_generate_button()
def check_generate_button(self):
"""检查是否启用生成按钮"""
if self.template_file and self.info_file and self.output_file:
self.generate_btn.config(state="normal", bg="#27ae60")
else:
self.generate_btn.config(state="disabled", bg="#95a5a6")
def clear_selection(self):
"""清空所有选择"""
self.template_file = ""
self.info_file = ""
self.output_file = ""
self.template_label.config(text="未选择文件", foreground="gray")
self.info_label.config(text="未选择文件", foreground="gray")
self.output_label.config(text="未选择位置", foreground="gray")
self.generate_btn.config(state="disabled", bg="#95a5a6")
def generate_test_cases(self):
"""生成测试用例"""
try:
# 检查文件是否存在
if not os.path.exists(self.template_file):
messagebox.showerror("错误", f"模板文件不存在: {self.template_file}")
return
if not os.path.exists(self.info_file):
messagebox.showerror("错误", f"信息表文件不存在: {self.info_file}")
return
# 调用生成函数
result = generate_test_cases_from_files(
self.template_file,
self.info_file,
self.output_file
)
if result:
messagebox.showinfo(
"生成成功",
f"测试用例生成成功!\n\n"
f"保存位置: {self.output_file}\n"
f"共生成 {result} 个测试用例"
)
else:
messagebox.showerror("错误", "生成失败,请检查文件格式")
except Exception as e:
messagebox.showerror("错误", f"生成过程中发生错误:\n{str(e)}")
def main():
root = tk.Tk()
# 设置窗口居中
window_width = 650
window_height = 400
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
root.geometry(f"{window_width}x{window_height}+{x}+{y}")
# 创建应用
app = TestCaseGeneratorGUI(root)
# 运行主循环
root.mainloop()
if __name__ == "__main__":
main()
希望这个详细的解读和完整的项目实践,能帮助你不仅学会使用一个工具,更能掌握用Python解决实际办公自动化问题的思路与方法。自动化不是目的,而是为了让我们有更多时间专注于更有创造性的工作。
---
浙公网安备 33010602011771号