首页 / 资讯中心 / 文章详情

用Python一键汇总Excel水果销售数据,告别手动统计

用Python一键汇总Excel水果销售数据,告别手动统计 ★ FEATURED ARTICLE
每个月月底对着那几十份水果销售表格的时候我是真想掀桌子。重复的复制粘贴、眼花缭乱的SUM公式、一不留神漏掉的某一行都会让一天的统计白干。后来我用Python把它变成了一个自动化的活儿一键汇总Excel里的水果数量双击运行脚本汇总表、明细表、甚至柱状图都自动生成。今天就把这套完整方案拆开讲清楚哪怕你连pandas是什么都没听说过只要照着操作也能跑通。这套东西解决的痛点很具体多份销售表、多个Sheet、好几种水果名称写法需要按水果把数量加到一起。它适合谁适合每个月都要做销售统计的店主、超市运营、财务文员以及所有被Excel表格反复折磨的办公族。核心原理不复杂无非是让pandas把Excel读进来、按水果名称分组求和、再写回一个新的Excel。但真要做得顺手、不出错里面的细节和坑也不少。1. 项目思路与需求拆解1.1 手动统计到底差在哪我先说一个真实场景。你手上有5月1日到5月31日的31张销售记录表每张表几十行记录着当天卖了哪些水果、各卖了多少斤。要得到“本月苹果总销量”“香蕉总销量”常规做法是新建一张汇总表然后一张一张打开原始表选中“苹果”对应的行手动抄数量再用SUM加到一起。31张表下来少说也要二十到三十分钟。这个过程中最坑的不是慢而是容易出错。漏一行、看错行、复制的时候多选了一个单元格数字就错了。更麻烦的是月底查账时根本说不清这个数字怎么来的——没有过程记录只有结果一旦被追问就只能重新查一遍。手动统计的另一个隐性成本是每次统计都要重复做一遍月月如此年中大促、节假日加场次时统计量直接翻倍。所以这个项目的第一需求就是把“重复手工劳动”变成“一次写好、永久复用”的自动化脚本。第二需求是数据可追溯脚本能把每一条原始记录保留在明细表里汇总结果从头到尾可核对。第三需求是易用不是每个人都熟悉编程脚本最好能做到“双击运行、自动出结果”最好连命令行都不用碰。1.2 为什么选Python而不只用Excel透视表很多人会问Excel本身有数据透视表按水果名称汇总不是几分钟就能搞定吗为什么非要写Python这个问题的答案取决于你的真实使用频率。如果只是偶尔一次、表格只有一两张数据透视表完全够用我不反对。但如果你面对的是“每天一张表、每月汇总一次、格式还可能经常变”的情况透视表就不太行了。每次都要手动选择数据区域、刷新字段一换文件就得重来如果某个同事发来的表里多了一列或者改了个表头之前的操作又得调整。Python脚本的好处在于数据格式只要按约定放好无论来多少张表脚本都是一样跑结果一致、过程可控。脚本还能顺手把汇总结果导出成新的Excel、同时保留原始明细、自动生成图表、甚至把结果发到钉钉群或者邮箱。这些是透视表做起来很别扭、脚本却很顺手的事。我还想强调一个思维方式先规范数据格式再谈工具。用Python汇总Excel前提是原始表格的格式大致规整——表头的位置固定、水果名称在同一列、数量是数字。如果数据乱到连列名都不统一那不管用Python还是透视表都会很痛苦。所以在动手写代码前我会先教你把表整理成统一结构这一步做好了后面的脚本就是体力活。2. 环境准备与核心工具选型2.1 装好Python运行环境新手最容易卡在这Python环境的安装是整个项目里门槛最低、但新手最容易卡住的一步。多数人不是不会装而是装上之后没有把路径配好导致在命令行里敲python没反应。这里给第一次装的朋友一条最稳的路去Python官网下载Windows安装包勾选底部的Add Python to PATH然后一路Next。勾选Add to PATH这一步特别关键。如果漏了安装完成后在命令行输入python会提示“不是内部或外部命令”那基本就是没配环境变量。另一个常见问题是不知道自己装没装成功Windows下打开命令行输入python --version如果能输出类似Python 3.12.2的版本号就说明成功了。编辑器方面新手用VS Code或者PyCharm都可以社区版免费够用。如果只是跑今天这个脚本其实Windows自带记事本都能写只是没有高亮和提示容易打错单词。我个人建议用VS Code装一个Python插件写代码的时候有语法提示能省不少低级错误。Linux和macOS用户一般自带Python 3不过版本可能偏老建议用python3命令区分必要时用系统包管理器装新版。2.2 认识两个得力库pandas和openpyxl写代码之前先装两个库。打开命令行执行pip install pandas openpyxlpandas是一个数据处理库几乎所有Excel汇总操作的核心逻辑都由它完成。openpyxl是Excel文件读写引擎专门负责处理.xlsx格式。pandas读取Excel时底层需要调用openpyxl来解析文件所以这两个库要一起装。如果下载速度慢可以加-i https://pypi.tuna.tsinghua.edu.cn/simple指定国内镜像源。有一点值得提醒不要用xlrd这个库来读.xlsx文件。xlrd老版本确实能读Excel但新版只支持旧版.xls格式很多人装了之后莫名其妙报错就是因为库选错了。pandas在读取不同格式时会自动选择引擎一般不需要手动指定但如果你明确知道文件是.xlsx也可以写成pd.read_excel(文件.xlsx, engineopenpyxl)这样最稳。装好之后可以顺手测试一下在命令行输入python进入交互模式执行import pandas和import openpyxl不报错就说明环境没问题。这一步花一分钟能帮你排除掉后面一半的疑难杂症。3. 核心代码实现与逐行解读3.1 表格先整理成规整的“一维数据表”代码实现之前先定一个数据规范。假设你的原始销售记录长这样销售日期水果名称数量销售金额2025-05-01苹果12362025-05-01香蕉8162025-05-01苹果5152025-05-02橘子2030............这就是典型的“一维数据表”结构每一行是一条独立的销售记录列代表不同的字段。Python汇总数据的核心逻辑就是在这种结构上按“水果名称”分组把“数量”加起来。如果你的原始表里“水果名称”这一列混着空格比如“苹果”和“苹果 ”看似不同实则相同汇总结果就会出现两条苹果的记录。这是一个新手非常容易踩的坑后面会专门讲。现在你只需要保证表头固定、列名保持一致剩下的都可以交给代码处理。3.2 一行代码完成分组求和导出汇总结果最基础的需求是一个Excel文件里面是所有销售记录现在要按水果名称汇总数量。完整代码如下import pandas as pd # 读取原始数据 df pd.read_excel(水果销售记录.xlsx) # 按水果名称分组对数量和金额求和 result df.groupby(水果名称, as_indexFalse)[[数量, 销售金额]].sum() # 按数量从高到低排列 result result.sort_values(数量, ascendingFalse) # 导出到新文件 result.to_excel(水果数量汇总.xlsx, indexFalse) print(汇总完成共统计水果种类, len(result))代码只有四五行但每一行的作用都值得说清楚。pd.read_excel负责把Excel里的数据读成一个DataFrame可以把它理解为“内存里的一张表格”。groupby是pandas里最核心的分组聚合方法它把相同水果名称的行归到一组然后对指定的列求和。as_indexFalse的意思是不要用水果名称当行索引保持为一个普通列这样导出表格时第一列就是水果名称而不是一串数字索引。sort_values(数量, ascendingFalse)把结果按数量从高到低排序这样一眼就能看到卖得最好的水果排在最前面。最后的to_excel把结果写到新文件里indexFalse特别关键如果不加导出结果里会多出一列“索引”看起来像一行行序号很多新手觉得难看又不知道怎么去掉其实就是少了这个参数。如果你希望汇总结果里加一行“总计”可以这样total_row result[[数量, 销售金额]].sum() result.loc[总计] total_row这种方式会多出一行总计方便月底对账时和原始数据核对。3.3 把几十个日销售表合并成一个总表再统计单表汇总只是入门真正解决“告别手动统计”的是多文件合并。假设5月有31张表文件名分别是5月1日.xlsx、5月2日.xlsx……都放在一个叫“销售记录”的文件夹里。用Python可以一次性把所有文件读进来合并成一个大表再进行汇总。import glob import pandas as pd # 匹配文件夹下所有 xlsx 文件 files glob.glob(销售记录/*.xlsx) frames [] for file in files: df pd.read_excel(file) df[来源文件] file # 加一列记录数据来自哪个文件 frames.append(df) # 把多张表纵向拼接 all_data pd.concat(frames, ignore_indexTrue) # 此时 all_data 就是所有记录的合并表后续汇总逻辑和前面完全一样 result all_data.groupby(水果名称, as_indexFalse)[[数量, 销售金额]].sum() # 保存一个文件里放汇总表和明细表两个Sheet with pd.ExcelWriter(水果数量汇总.xlsx, engineopenpyxl) as writer: result.to_excel(writer, sheet_name汇总, indexFalse) all_data.to_excel(writer, sheet_name全部明细, indexFalse) print(共处理文件数, len(files)) print(合并后总行数, len(all_data))这里有几个点要注意。glob.glob(销售记录/*.xlsx)返回文件夹下所有.xlsx文件的路径列表如果你的文件后缀大小写不统一匹配会漏掉可以再加一个*.XLSX的匹配项。pd.concat是把多个DataFrame按行拼起来ignore_indexTrue让合并后的表从0开始重新编号避免行号混乱。在合并每个文件时我加了一列来源文件记录这条数据来自哪个文件。这样做的好处是将来哪种水果销量异常时可以立刻定位到是哪一天的记录出了问题查账溯源非常方便。导出一个工作簿同时放“汇总”和“全部明细”两个Sheet也是方便日后核对总表看结果明细表看过程两不误。3.4 加一点容错让脚本更“抗造”一个能长期用的脚本不能只在“一切顺利”时跑通。现实里总会出现文件找不到、表头改了一个字、某个单元格是空值的情况。所以我会给脚本加一层保护让它在出错时先提示问题而不是直接报一屏看不懂的红色错误。import glob import os import pandas as pd folder 销售记录 files glob.glob(os.path.join(folder, *.xlsx)) glob.glob(os.path.join(folder, *.XLSX)) if not files: raise FileNotFoundError(f在 {folder} 文件夹下没有找到任何 Excel 文件) frames [] for file in files: try: df pd.read_excel(file) # 清理列名两端的空格防止表头不一致 df.columns df.columns.str.strip() # 清理水果名称两端的空格防止“苹果 ”和“苹果”分家 df[水果名称] df[水果名称].str.strip() # 把数量列强制转成数字出现无法转换时填入空值 df[数量] pd.to_numeric(df[数量], errorscoerce) # 去掉数量为空的行避免求和时混入脏数据 df df.dropna(subset[数量]) df[来源文件] file frames.append(df) except Exception as e: print(f文件 {file} 处理失败{e}) if not frames: print(没有任何文件被成功读取请检查原始表格格式) exit() all_data pd.concat(frames, ignore_indexTrue) result all_data.groupby(水果名称, as_indexFalse)[[数量, 销售金额]].sum() result result.sort_values(数量, ascendingFalse) with pd.ExcelWriter(水果数量汇总.xlsx, engineopenpyxl) as writer: result.to_excel(writer, sheet_name汇总, indexFalse) all_data.to_excel(writer, sheet_name全部明细, indexFalse) print(汇总完成共处理文件数, len(files)) print(汇总水果种类数, len(result))这几行保护在项目初期看起来多余但实际用起来能救你无数次。df.columns.str.strip()把列名里的空格去掉防止同一个列被pandas当成两个不同列。pd.to_numeric(errorscoerce)把文本型数字转成真正的数字转不了的基本都是写错了的数据errorscoerce会让它变成NaN空值最后用dropna把这些脏行清理掉。这一套下来统计算法已经能应付绝大多数不规范的原始表。4. 常见问题与排查技巧实录4.1 文件路径报错FileNotFoundError总是在第一步等你最常见的报错是FileNotFoundError: [Errno 2] No such file or directory。原因一般是脚本文件和分析用的Excel没放在同一个文件夹或者文件夹名写错了。我的习惯是把脚本文件直接放在“销售记录”文件夹的上一级让脚本里的相对路径销售记录/*.xlsx始终能找得到目标文件夹。如果你不确定当前Python的工作目录在哪里可以在脚本开头打印一下import os print(os.getcwd())它会显示脚本运行时的当前目录。如果你发现目录和预期不一致最省事的办法是用绝对路径文件夹 rD:\我的文档\销售数据注意路径前加r表示原生字符串Windows路径里的反斜杠就不会被转义。还有一个隐藏较深的坑文件名里有全角空格或者在代码里多打了一个空格。建议直接把文件复制到项目文件夹用英文或数字重命名比如sales_05.xlsx可以避开很多编码和路径问题。4.2 明明有数据汇总出来全是0或None如果脚本跑完没报错但汇总表里水果名称是空、数量全是0先检查两件事一是列名是否完全匹配。比如原始表里叫“品名”而不叫“水果名称”那df[水果名称]就会报KeyError如果表头是“水果名称 ”带了一个空格pandas会因为列名不完全一致而把它当成不同的列。解决办法是先用print(df.columns.tolist())打印出实际的列名肉眼确认一遍。二是检查原始表有没有合并单元格。如果A列有合并单元格pandas默认只会把合并区域左上角的值填上其余位置是NaN空值。这种情况下水果名称列里会有大量空白分组求和就什么都加不起来。处理方式有两个一是取消原始表的合并单元格并填充值二是用df[水果名称] df[水果名称].fillna(methodffill)把前一行有值的名称向下填充。这个方法在Excel里面叫“向下填充”pandas里用ffill实现遇到合并单元格的表特别管用。4.3 数量列带黄色三角文本型数字转数值的问题Excel里单元格左上角出现绿色或者黄色小三角说明它是以文本形式存储的数字。这种数字pandas读进来后是字符串而不是数值直接求和会报错或者把数字拼在一起。解决办法就是我前面代码里用到的pd.to_numeric(df[数量], errorscoerce)。一个常见的自查方法是汇总结果如果每个水果名称对应一行但数字诡异比如“12”和“5”加起来不是17而是字符串拼接的“125”那几乎肯定是文本型数字的问题。转成数值之后排序和求和就都正常了。顺手说一句这种单元格在Excel里可以批量选中后点击“转换为数字”但如果每天都有新表格进来每次手动转换反而更费事不如在脚本里统一处理。4.4 导出乱码、Sheet名错误等杂项问题如果你用to_csv导出CSV文件然后用Excel打开出现乱码是因为Excel默认按ANSI编码解析文件而pandas写出的UTF-8编码它会认错。解决办法是给to_csv加一个参数df.to_csv(汇总.csv, indexFalse, encodingutf-8-sig)utf-8-sig带BOM头Excel就能正确识别。另一个常见问题是报错ValueError: Sheet name 总-汇 is invalid...。Excel对Sheet名有限制不能为空、不能超过31个字符、不能含有反斜杠等特殊字符。所以保存Sheet时名字尽量用中文或英文短名不要加/ \ ? * [ ]这些符号。我把这些高频问题整理成一个速查表方便你排查时直接对照问题现象可能原因处理办法FileNotFoundError报错路径不对或文件夹不存在用print(os.getcwd())查看目录改用绝对路径汇总结果水果名称为空列名不一致或有合并单元格打印列名核对用ffill向下填充数量被拼成“125”文本型数字未转换pd.to_numeric(errorscoerce)强制转数值导出的CSV打开乱码编码不是Excel默认encodingutf-8-sig提示Sheet名无效含特殊字符或超长换用简短纯文字Sheet名排查的顺序也很有讲究先看文件路径再看列名再查数据类型最后看导出格式。按这个顺序走绝大多数问题十分钟内能定位。5. 进阶玩法从“一键汇总”走向“自动日报”5.1 同时处理多个Sheet一个工作簿也不怕有些同事习惯把一个月的数据全部放在同一个Excel文件里一天一个Sheet名字叫5月1日、5月2日……这时候可以换个读法all_sheets pd.read_excel(5月销售记录.xlsx, sheet_nameNone)sheet_nameNone会让pandas返回一个字典键是Sheet名值是对应的DataFrame。然后用循环把每个Sheet都取出来拼接frames [] for sheet_name, df in all_sheets.items(): df[来源Sheet] sheet_name frames.append(df) all_data pd.concat(frames, ignore_indexTrue)这里有个实用细节文件名可能没什么信息量但Sheet名往往是日期把它作为一列保留下来后面按时间筛选会非常方便。甚至可以直接从Sheet名里解析日期pd.to_datetime(sheet_name)如果格式规整就能自动转成日期类型。5.2 把汇总结果直接画成柱状图汇总表出来之后如果还想更直观地看哪种水果卖得好可以用matplotlib生成柱状图并且直接把图片保存下来放进Word周报或者PPT里都没问题。安装matplotlibpip install matplotlib绘图代码import matplotlib.pyplot as plt # 设置中文字体防止图里出现方块 plt.rcParams[font.sans-serif] [SimHei] plt.figure(figsize(8, 5)) plt.bar(result[水果名称], result[数量], colorsteelblue) plt.title(水果销售数量汇总) plt.xlabel(水果名称) plt.ylabel(数量) plt.savefig(水果销量图.png, dpi200) plt.show()中文字体这块是Windows下的老问题不设置字体的话图里中文全变成“口口口”。如果SimHei在你的系统上无效可以改成Microsoft YaHei或KaiTi。保存图片时注意dpi参数200以上放到PPT里才清晰。5.3 脚本定时跑Windows任务计划程序最后一步是把脚本变成“没人管也能自己跑”的定时任务。Windows自带任务计划程序可以做到每周五17:00、每月最后一天23:00自动运行Python脚本。设置方法是打开任务计划程序新建任务触发器选择按周或按月操作选择“启动程序”“程序或脚本”里填python参数里填脚本的完整路径。要注意的是任务计划程序里“起始于”这个字段经常被人忽略它决定了程序的工作目录。如果脚本用了相对路径必须在起始于里填上脚本所在的实际文件夹否则定时跑的时候会找不到Excel文件。这是定时任务失败率最高的原因没有之一。如果还想更自动一点可以在脚本末尾加一个发送结果到群里的动作。网上通常的做法是用钉钉机器人或者企业微信机器人的Webhook地址把汇总结果拼成文本POST过去。这一步不涉及复杂逻辑核心就是用requests.post把JSON格式的消息体发出去。我的几点实操体会做完这套脚本之后我最大的感受是写代码本身并不难真正决定它能不能长期用的是原始表格的规范程度。所以我特别建议在团队内部定一个最小标准至少要有“水果名称”和“数量”两列列名固定不要用合并单元格日期用日期格式而不是文本。标准定了脚本基本一劳永逸。另外一个小技巧值得分享每次跑完脚本我习惯把生成的“水果数量汇总.xlsx”文件名加上日期后缀比如水果数量汇总_20250531.xlsx用time.strftime(%Y%m%d)自动生成就好。这样月底做对比报表时可以直接依据日期命名找到每次的统计快照。如果你之前只会手动复制粘贴第一次用脚本跑出汇总表的时候可能还会有点不放心这很正常。我的建议是第一次用的时候花十分钟用Excel透视表手算一遍两边数字对上了你就敢放心把这条流程完全交给Python了。之后你会越来越发现真正省下来的不是几分钟而是每个月反复劳动积累下来的那几十次深呼吸。
阅读完成 · 觉得有帮助?
咨询建站