
简介这是基于Python开发的Excel数据分析系统面向计算机相关专业毕业生及Python实战学习者覆盖从项目源码、可执行程序到程序配置说明书、使用说明书的完整交付物适合用于毕业设计或企业日常表格数据处理。系统基于Python 3.6与PyCharm环境构建借助PyQt5完成界面、pandas与numpy处理数据、matplotlib绘制图表整体功能包括Excel导入、数据提取、定向筛选、多表合并与统计排行、图表生成、贡献度分析等模块划分清晰便于二次开发。压缩包共688个文件、约100.28MB其中以py源码为主体535个配合exe可执行程序、pyd动态库及dll依赖开箱即可运行另有xls示例数据、png界面示意与txt说明文档方便对照学习。当前已有587人学习下载对于需要快速搭建数据可视化分析工具或完成毕设项目的学习者来说是一份可直接落地参考的完整资料。1. 一个 Excel 数据分析系统为什么交付清单里会有两份说明书这个标题的交付物看起来是“代码 exe 文档”的常见组合真正决定用户会不会骂人的是最后两样程序配置说明书和程序使用说明书。一个基于 Python 的 Excel 数据分析系统面向的用户通常不会打开 IDE也不会看 pandas 报错他们只会双击 exe把 Excel 文件放进某个目录再打开输出的 xlsx 看结果。所以开发者的核心工作不是写出漂亮的分析模型而是把读取、清洗、汇总、输出的链路做成一个“放进去文件拿出来结果配置项改坏了也能快速定位”的闭环。源码用于维护和二次开发可执行程序用于交给业务方配置说明书回答“改哪里”使用说明书回答“怎么用”。下面按这个顺序把一个可交付的系统拆成五个层面用 pandas 和 openpyxl 接住 Excel 文件把分析规则参数化再用 PyInstaller 打成 exe最后把两类说明书写成真正能排障的工具。适合读下去的人有两类一是要给内部团队交付 Excel 数据处理工具的工程师二是已经写好脚本、卡在“打包后不能运行”或“配置文件找不到”阶段的人。确认这两个场景后面每章的代码和参数可以直接抄。2. 用 pandas openpyxl 先接住 Excel读取与清洗的边界在 Excel 数据分析系统里最不稳定的数据源就是 Excel 本身。同一个“金额”列本周是文本、下周是数字同一个 Sheet上个月有合并单元格、这个月多了两行空表头。所以第一层要做的是“把 Excel 变成干净的 DataFrame”而不是急着算数。2.1 先按文本读入再按业务规则做类型转换很多教程推荐pd.read_excel默认读取让 pandas 自己推类型。但这个智能推断在身份证号、订单号这类长数字列上会翻车18 位数字被读成 float后几位变成 0。更稳妥的做法是先固定dtypestr读入保住原始内容再在清洗步骤里针对需要计算的列做转换。import pandas as pd from pathlib import Path def load_excel(path: Path, sheet_name: str, header_row: int 0) - pd.DataFrame: df pd.read_excel( path, sheet_namesheet_name, headerheader_row, dtypestr, # 先全部按文本读避免长数字失真 keep_default_naTrue, na_values[, #N/A, NULL], ) df.columns [str(c).strip() for c in df.columns] # 去掉列名首尾空格 df df.dropna(howall) # 删除整行都是空值的行 return df这里的header_row让你能应对“表头不在第 1 行”的 Excelna_values能把业务中常见的空字符串、#N/A、NULL统一识别为缺失值。去掉列名空格这段容易被忽略一旦某个 Excel 的列名是金额 后面执行df[金额]就会抛 KeyError而且报错信息完全不提空格问题。类型转换不要在read_excel里做而是放到独立的清洗函数中。比如金额列先去逗号和人民币符号再pd.to_numeric(..., errorscoerce)日期列用pd.to_datetime(..., format%Y-%m-%d)。errorscoerce会把非法值变成NaN或NaT这样可以在报表里单独输出“无法解析的行”而不是让整个程序崩溃。2.2 表头和多级表头怎么探测实际交付的 Excel 经常不是规整的一行表头。常见做法是先用 openpyxl 快速查看前几行结构而不是直接猜。from openpyxl import load_workbook def inspect_sheet(path: Path, sheet_name: str): wb load_workbook(path, read_onlyTrue, data_onlyTrue) ws wb[sheet_name] for i, row in enumerate(ws.iter_rows(min_row1, max_row6, values_onlyTrue)): print(i 1, row)这段脚本用来确认真正的表头在第几行、有没有合并单元格留下的None。根据输出再确定header_row和skiprows。如果 Excel 表头只有一层直接写header0如果第 1 行是标题、第 2 行才是列名就用header1。系统里应该把“表头行号”写进配置文件而不是写死在代码中。如果 Excel 只有数据没有列名可以用df.columns [日期, 金额, 类型]手动指定。多级表头会生成 MultiIndex 列写入 Excel 时会产生两层表头下游做数据透视会很痛苦。我的原则是读取阶段把列名压平比如销售额_2024宁可失去视觉分组也不能让列名变成 tuple。2.3 脏数据要分流不要默默丢弃数据分析系统最怕安静的数据丢失。用户把一千行数据放进去出来只剩九百行如果程序不提示这个系统就失去了可信度。合理的模型是拆成三路可用的业务数据、可修复的脏数据、必须抛给用户的异常数据。def clean_amount(s: pd.Series) - pd.Series: s s.astype(str).str.replace(,, , regexFalse) s s.str.replace(元, , regexFalse) return pd.to_numeric(s, errorscoerce)调用这个函数时先记录原行数转换后通过isna()拿到失败索引把对应行写到“异常数据”Sheet。注意replace的参数在新旧版本 pandas 中有差异建议显式写regexFalse避免把逗号当成正则语义。下面这张表是读取阶段最常调优的参数也是配置说明书中要写清楚的部分参数作用建议值sheet_name指定读取哪个 SheetSheet 名不要用序号header表头所在行按实际探测结果配置dtype列类型覆盖默认str需要计算时再转换usecols只读需要的列用A:C,F或列表降低内存skiprows跳过表头前的说明行只在header不适用时使用na_values自定义缺失标识包含,#N/A,NULL这些参数不会影响算法精度但会影响系统在真实 Excel 文件上的存活率。我见过不少项目在测试文件上全对换到业务方文件后金额被读成浮点数小数位全乱。从那以后这类系统的读取层统一走“先文本、后规则转换”的路线。提示xlrd新版本只支持.xls不支持.xlsx。读.xlsx直接用 openpyxl 或 pandas 底层依赖的 engine。3. 分析逻辑放到 DataFrame回写 Excel 再交给 openpyxl读取清洗完成后分析功能要能被配置驱动。如果业务方说“我要按地区汇总不要按部门”你不能改代码重新打包。把分组键、聚合指标、输出文件名都做成配置系统才算真正的数据分析系统。3.1 用 groupby 和 agg 实现可配置的汇总规则pandas 做分组汇总的常规写法是df.groupby(地区)[金额].sum()但业务需求通常不止一个指标。更好的做法是构造一个聚合规则字典把多个列的多个聚合函数一次性传给agg。agg_rules { 金额: [sum, mean, count], 订单数: sum, } summary clean_df.groupby([地区, 渠道]).agg(agg_rules) summary.columns [_.join(col).strip(_) for col in summary.columns]groupby的键可以来自配置文件比如group_cols [地区, 渠道]agg_rules的 value 可以是字符串也可以是字符串列表。这样用户不用动代码只需要在配置里声明按哪几列分组、对哪几列求和。拼列名这段经常被忽略因为agg之后列名会变成带层级结构的 MultiIndex直接写进 Excel 会给下游解析增加很大的成本。3.2 透视表与明细 Sheet 同时输出分组汇总之外透视表是 Excel 用户最熟悉的形态。pd.pivot_table的参数和 Excel 透视表一一对应index是行字段、columns是列字段、values是汇总值。为了避免生成一个又多又杂的巨型 Sheet我一般把输出拆成三张表汇总表、透视表、明细表。with pd.ExcelWriter(out_path, engineopenpyxl) as writer: summary.to_excel(writer, sheet_name汇总, indexTrue) pivot.to_excel(writer, sheet_name透视, indexTrue) valid_df.to_excel(writer, sheet_name明细, indexFalse)如果同一份输出文件需要重复写入用pd.ExcelWriter(path, engineopenpyxl, modea, if_sheet_existsreplace)。这个参数在 pandas 1.2 之后才可靠旧版本往往会因为覆盖失败抛Sheet already exists。所以打包前确认 pandas 和 openpyxl 的版本别用太老的。3.3 用 openpyxl 给输出报表做最后一公里美化很多人写完to_excel就结束了但业务方打开报表看到的是默认列宽和没有筛选键体验会差一截。在数据量不大、几千行以内时用 openpyxl 对生成的文件做后处理是性价比最高的方案。from openpyxl import load_workbook from openpyxl.styles import Font, PatternFill, Alignment wb load_workbook(out_path) for ws in wb.worksheets: for cell in ws[1]: cell.font Font(boldTrue) cell.fill PatternFill(solid, fgColorDDEBF7) cell.alignment Alignment(horizontalcenter) ws.auto_filter.ref ws.dimensions ws.freeze_panes A2 wb.save(out_path)这段代码为每个 Sheet 的第一行加粗、加底色打开自动筛选并冻结首行。freeze_panes A2表示首行固定用户滚动时表头始终可见。注意auto_filter.ref使用ws.dimensions得到的有数据范围如果 Sheet 里存在合并单元格部分区域会失效建议只对“汇总”和“明细”这类规整的 Sheet 做美化。3.4 纯配置驱动的分析参数分析层的配置项可以集中成一张表方便写进配置说明书配置名可选值说明group_cols逗号分隔的列名汇总分组字段agg_rulesJSON 字符串列名与聚合函数映射pivot_index列名透视表行字段pivot_values列名透视表数值字段output_modenew/append覆盖或追加写入这些值最好放在配置文件中而不是命令行参数。因为业务方会忘记管道符和引号而配置文件可以写注释他们能照着改。我见过一个项目把分组键放在命令行参数里结果业务方在快捷方式里写错了逗号整个 batch 文件失效。配置文件至少能保证“改错容易发现”。4. 源码如何变成可执行程序配置、打包和路径陷阱标题里的“可执行程序”是交付物中最容易出问题的环节。很多源码在 IDE 里跑得好好的一打包就找不到配置文件、读不到 Excel、甚至直接闪退。问题根源是 Python 脚本里的文件路径在打包后不再代表源码目录而是指向 PyInstaller 生成的临时目录。4.1 用 configparser 管理业务配置一个交付给非技术用户的程序配置项应该集中在同一份.ini文件里。configparser是标准库用户改起来比 Python 脚本安全得多。[excel] input_dir ./input output_dir ./output sheet_name 明细表 header_row 0 [clean] dtype_mode str na_values ,#N/A,NULL [report] group_cols 地区,渠道 agg_rules {金额: [sum, mean], 订单数: sum}读取配置的代码import configparser from pathlib import Path def load_config(path: Path): config configparser.ConfigParser() if not path.exists(): raise FileNotFoundError(f缺少配置文件: {path}) config.read(path, encodingutf-8) return config注意ConfigParser.read如果文件不存在不会抛错这会让程序用空配置继续跑后面才报 KeyError。所以这里要提前检查文件是否存在。配置文件里的agg_rules是 JSON 字符串读取后用json.loads解析不要用eval避免把配置项变成代码执行入口。4.2 PyInstaller 打包命令和隐式依赖用 PyInstaller 打包 pandas openpyxl 项目命令一般是pyinstaller -F -c --name excel_analysis ^ --hidden-import openpyxl ^ --collect-data pandas ^ main.pyWindows 上^是换行符Linux/macOS 用\。-F生成单一 exe-c保留控制台窗口方便看日志。如果你不希望用户看到黑色窗口可以用-w但排障会变难。我建议交付 beta 版时用-c稳定后再换成-w。--hidden-import openpyxl是因为 PyInstaller 的静态分析有时抓不到 pandas 运行期动态导入的组件。--collect-data pandas会把 pandas 自带的样式和日期数据文件一起打包避免执行时出现“找不到 pandas data 文件”的诡异报错。打包后一定要在命令行里执行一次生成好的 exe观察有没有 ImportError。4.3 可执行程序旁边的配置文件路径怎么取最让新手踩坑的是打包后__file__不是 exe 所在路径而是_MEIPASS临时目录。给 exe 用的外部配置文件必须按 exe 所在目录定位。下面这段代码是常见且兼容开发、打包两种环境的写法import sys def app_base_dir() - Path: if getattr(sys, frozen, False): return Path(sys.executable).resolve().parent return Path(__file__).resolve().parent config_path app_base_dir() / config.inisys.frozen只在 PyInstaller 打包后的程序里存在。开发环境用__file__打包环境用sys.executable这样程序无论从哪里双击启动都能找到旁边的config.ini。如果配置文件要随临时目录一起打包才用sys._MEIPASS但配置文件需要被用户修改所以它属于“外置资源”不应该打包进 exe。下表总结了三种路径在打包前后的差异路径写法开发环境PyInstaller onefile建议Path(__file__).parent源码目录_MEIPASS临时目录只用于只读资源Path(sys.executable).parent解释器目录exe 所在目录外置配置和输入输出Path(sys.argv[0]).parent脚本目录exe 所在目录受快捷方式影响不推荐sys.argv[0]在通过快捷方式启动时可能指向.lnk所在位置所以别用它定位配置。另一个建议是 exe 名称和程序内写入的文件路径尽量不要用中文。虽然大多数情况能跑但某些 Windows 代码页会让中文路径在日志里变成乱码。交付前把input、output、config.ini、excel_analysis.exe全部放在同一个文件夹目录结构越扁平越好。4.4 打包后常见的三个运行期错误如果打包后程序启动就闪退先回到命令行手动执行 exe看输出。常见三类问题No module named openpyxl命令里漏了--hidden-import。双击无反应检查杀毒软件是否隔离了 exe或者用-c模式确认是否在导入阶段崩溃。读不到 Excel 文件程序默认工作目录不是 exe 所在目录而是“当前启动目录”。所以程序内部要用app_base_dir()拼输入路径不要依赖cd。在这个阶段config.ini要和 exe 放在同一个文件夹。配置说明书中出现的示例路径都应该只显示这一层的相对路径不要给出任何写死的绝对路径。5. 交付前的说明书和验证清单让可执行程序真正可验收标题里专门列出了“程序配置说明书”和“程序使用说明书”说明文档不只是附带品而是系统的一部分。配置说明书写给“改参数的人”使用说明书写给“每天运行的人”两者混在一起会导致用户改错段落甚至把配置项填进输入目录。5.1 配置说明书最少要包含的参数表配置说明书的核心是解释config.ini里的每一项而不是复述代码。我一般按表格组织参数名、含义、可选值、默认值、示例、改错后会怎样。比如sheet_name改错了程序不应该报 Python 的 KeyError而是要在日志中提示“Sheet [工资表] 不存在请检查配置中的 sheet_name”。如果代码里能输出这类带配置字段名的错误说明书就不需要把每个报错都列出来。对于聚合字段agg_rules说明书要给出一个可运行的 JSON 示例并注明“列名必须与 Excel 表头完全一致包括空格”。这一条能避开很多“为什么金额列是空”的提问。5.2 使用说明书按操作顺序写使用说明书不要从架构讲起直接写“把 Excel 文件放入input目录双击excel_analysis.exe等待output里出现结果文件”。然后列输入规范文件名要求、Sheet 名要求、表头行数、编码。程序本身最好提供一个--check参数让用户不用跑完整流程就能先验证环境。import argparse parser argparse.ArgumentParser() parser.add_argument(--check, actionstore_true, help检查配置文件与输入目录) args parser.parse_args() if args.check: ...使用说明书里可以写“先运行excel_analysis.exe --check看到‘配置 OK’再正式运行”。这个参数对电话排障特别有用因为你可以让用户把输出结果告诉你而不是让他在 Excel 里手动找问题。5.3 打包后的验证清单打包后的验证不是跑一次成功就算完。至少要有这张检查清单检查项操作通过标准干净环境运行在没有 Python 的机器上运行 exe正常生成结果中文路径把输入文件放到带中文的目录不报编码错误配置文件缺失删掉 config.ini提示明确错误不闪退配置内容非法把 sheet_name 改为不存在的名字日志定位到配置项结果可打开用 Excel 打开输出文件无文件损坏提示最后一条比较隐蔽如果输出文件正被 Excel 打开写入时会抛PermissionError。程序应该在保存前捕获这个异常并提示“请先关闭 output 目录中的 Excel 文件”。把这些检查项写进一个简单的 PowerShell 脚本交付前自动跑一遍比手动点十次可靠。还可以做一个实用的小技巧在 exe 同级放一个check.bat内容只有一行excel_analysis.exe --check让用户先执行这个文件。很多非技术用户不敢碰命令行但“双击 check.bat”和“双击 excel”没有区别。本文还有配套的精品资源点击获取