Python Excel 配置编辑器
配置工作经常需要同时打开几张 Excel:找字段、对照含义、检查数值,再确认有没有改错列。我希望把这些重复操作收进一个可视化页面,让表格继续承担数据存储,让工具承担输入提示和校验。
这篇先把最小流程做完整:上传一张约定格式的配置表,修改三个字段,下载一份新文件。完整源码、示例表和测试都附在文中;目录扫描、多语言生成、增删行和打包 EXE 仍属于后续设计。
先解决一个具体问题
例如,一个模块需要配置最大玩家数、掉落概率和欢迎语。在 Excel 里,它们都可以放进“值”这一列,但三者的规则不同:玩家数必须是整数,概率只能在 0 到 1 之间,欢迎语应该是文字。
如果只把单元格搬到网页,再允许随意写回,错误仍然会发生。这个工具首先要表达字段含义和约束,再处理读写。
我选择 Python,是因为读写表格、组织业务规则和测试比较方便;Flask 提供本地页面与接口,openpyxl 处理 .xlsx。HTML 表单可以按字段类型提供输入框,后续也容易增加模块。这里并不意味着 VBA 不适合 Excel 自动化,只是这条路线更符合把配置规则拆成独立模块的目标。
下载并运行最小示例
解压后,在 excel-config-demo 目录中操作。需要 Python 3.10 或更新版本;本文实际验证环境为 Python 3.12.14、Flask 3.1.2、openpyxl 3.1.5。依赖版本是本示例的验证基线,不代表最新版本。首次安装依赖需要联网,启动后没有 CDN 或远程接口。
Windows PowerShell:
1 | py -3 -m venv .venv |
macOS / Linux:
1 | python3 -m venv .venv |
使用虚拟环境可以把示例依赖和其他 Python 项目分开;以上直接调用环境内的 Python,不需要激活脚本。Flask 安装说明
启动示例后,打开本机编辑页面,按页面完成四步:
- 点击“先下载示例工作簿”,或使用 ZIP 中的 config-sample.xlsx。
- 选择文件,点击“读取并校验”。
- 修改三个字段,比如把最大玩家数从 100 改为 321。
- 点击“校验并下载副本”,得到 config-edited.xlsx,再用 Excel 检查。
选择新文件后,旧编辑表单会清空,必须重新读取。输入 0 个玩家或 1.2 的概率会被拒绝。服务不会改写原文件;如果浏览器询问保存位置,请为副本选择新文件名。停止示例用终端的 Ctrl+C。端口占用时,先关闭占用程序,或调整 app.py 最后一行的端口。
这是本机开发示例,监听地址限定为 127.0.0.1,关闭调试器和自动重载。Flask 官方不建议把内置开发服务器用于正式部署,即使只有本机单用户也要区分开发演示与生产使用。Flask 部署说明
先约定表格,再写接口
工作簿必须有一张名为“配置”的工作表,A1:C1 依次为“键”“值”“说明”。三个键各出现一次,顺序可以调整;工具按键寻找对应 B 列单元格。
| 键 | 示例值 | 服务端规则 |
|---|---|---|
| max_players | 100 | 1–10000 的整数,不把文字或布尔值当数字 |
| drop_rate | 0.25 | 0–1 的有限数字,0.25 表示 25% |
| welcome_text | 欢迎进入游戏 | 1–80 字非空文字,不接受控制字符或以等号开头的公式 |
接口只接收上传文件和这三个键的新值,不能传服务器路径、工作表名或任意单元格地址。文件名只用于判断 .xlsx 后缀,不用于拼接磁盘路径。读取文件后,服务端检查表头、重复键、字段类型和取值范围;导出时还会重新检查一次,不能只依赖网页的输入控件。
为控制这个示例的处理范围,上传文件限制为 2 MiB,ZIP 解压总量最多 10 MiB、128 个部件;工作簿最多 4 张表,每张表的使用范围最多 1000 行、20 列。代码不把上传文件永久保存到目录,但 Flask 在处理较大上传时可能使用系统临时文件,因此不应把它描述为“全程只在内存”。Flask 文件上传说明
模块之间如何分工
1 | excel-config-demo/ |
workbook_io.py 不认识 HTTP,也不接收磁盘路径,公开三个主要函数:
| 函数 | 输入 | 输出 |
|---|---|---|
| inspect_workbook(data) | 上传文件的字节 | 字段名、类型、原值和说明 |
| edit_workbook(data, changes) | 原文件字节与三个新值 | 新工作簿字节 |
| make_sample() | 无 | 示例工作簿字节 |
前端保留用户选择的 File。预览时上传一次;导出时把同一份原文件和新值一起提交。服务不缓存全局工作簿,两个浏览器页面不会共用一个正在编辑的 Python 对象。未下载的表单修改只存在于当前页面,刷新会丢失。
下面是下载包里的关键片段,用于解释流程;完整运行仍需包内的校验函数、前端和其余路由。
1 | # workbook_io.py:校验成功后,在载入的原单元格上改值 |
这里没有从 JSON 重建整张表。只修改原单元格的 value,更容易保留其已有样式;保存目标也是新的字节流,而不是原文件路径。
1 | # app.py:固定副本名,不使用上传者给出的文件路径 |
send_file 可以发送二进制文件对象,as_attachment 和 download_name 指定下载行为与文件名。这里采用当前参数名,没有沿用旧版的 attachment_filename。Flask API
格式保留的边界
样例验证了填色、字体、百分比格式、列宽和冻结窗格的往返保留,备注表中的公式也保留为公式。这只是这个工作簿与这些属性的验证结果,不能推出任意 Excel 文件都无损。
读入时使用 data_only=False 保留公式表达式,rich_text=True 请求保留已有富文本。openpyxl 官方说明它不能读取 Excel 的全部对象,部分形状可能在重新保存时丢失。因此,示例拒绝已识别的图形、图表、外部工作簿链接、嵌入对象及宏,也不接受配置区的合并或保护单元格;遇到其他高级特性仍需独立检查。openpyxl 读入选项与限制
另外要分开两件事:
- 保存公式不等于计算公式。 openpyxl 不执行公式。本例的备注公式 =配置!B2*2 会保留,但下载后的缓存计算结果可能为空;需要由 Excel 等计算程序重新计算,网页不会把 642 当作已经算出的结果。openpyxl 公式说明
- 修改值不等于正确增删行。 openpyxl 插入或删除行列时,不会自动维护所有公式、表格或图表依赖。本文暂不开放增删行,后续需要为具体模块定义引用更新规则并测试。openpyxl 行列操作说明
宏工作簿也有独立契约:keep_vba=True 只涉及保留 VBA 内容,并不意味着可以编辑或执行 VBA。本例明确只收 .xlsx,没有实现 .xlsm 支持。openpyxl 工作簿选项
如何验证它确实能跑
下载包带有 12 个 unittest 测试。在同一目录运行:
1 | .\.venv\Scripts\python.exe -m unittest -v |
macOS / Linux 将 Python 路径换成 .venv/bin/python。
测试覆盖上传预览、修改后重读、样式和公式保留、原字节不变、错误类型、越界值、重复或缺失键、路径输入、错误格式、宏与复杂部件拒绝、两种大小限制。另有一个测试启动随机空闲端口的本地 WSGI 服务,通过真实 HTTP 下载修改后的 Excel,结束后自动关闭。
2026-09-08 在上述版本环境中,这 12 项测试通过;真实 HTTP 导出也完成。Flask 测试客户端用于大部分接口检查,与真实服务器检查互补。Flask 测试说明
这些结果证明了本文的服务流程和样例文件往返,没有替代桌面 Excel 的显示检查或公式计算。把副本用于实际配置前,仍应打开核对字段、格式和结果。
后续扩展
原先希望做的多表联动、时装属性展开、多语言生成和可配置错误提示,都可以从字段契约继续扩展:先写纯 Python 的规则和测试,再把预览结果放到页面中确认,最后才写回副本。
目录扫描、全文搜索、增删行、撤销历史和打包单文件 EXE,本示例没有实现。下一步应选择一个实际模块补齐规则,而不是先堆叠一组尚无后端实现的接口。最小版本先确保读得明白、改得有约束、输出可核对。