干数据分析这些年,Python和Excel是我每天打交道最多的两样东西。经常有同行问我:Python处理Excel到底该学哪个库?这种问题我回答过很多次,但每次都会因人而异给不同答案。处理Excel这件事看着简单,实际上需求跨度极大——从读几百行销售数据做汇总,到批量生成几十个格式统一的报表,再到直接操纵Excel界面做自动化操作,完全不是一个工具能覆盖的。今天就把我实战中真正用过的5种常用方式一次性讲清楚,每种方式的适用场景、核心代码、踩过的坑都放出来。
1. 工具选型:不同场景下选哪种方式的判断逻辑
1.1 五种方式各自的能力边界
网上搜“Python处理Excel”,跳出来的教程基本都在推pandas,好像会一个pandas就能打天下。但真正做过项目就知道,pandas解决的是“表格数据加工”这个环节,而Excel处理还包含格式保留、样式控制、工作簿合并、调用Excel自身功能等一堆需求。
我常用的这5种方式,各有各的主场:
- pandas:最主流的表格数据读取、清洗、聚合、分析方案,适合把Excel当成数据源来处理。
- openpyxl:能直接读写xlsx文件并控制单元格样式、列宽、合并区域,适合生成格式精致的交付报表。
- xlrd / xlwt / xlutils:老牌三件套,读xls、写xls、改xls,适合和老旧系统对接。
- csv标准库:当数据量大、格式要求低时,先转成CSV再处理是最快路径,也用不着装任何第三方库。
- pywin32 / xlwings:调用本机Excel程序的COM接口,能操作Excel的界面能力,比如执行VBA宏、刷新透视表、弹窗交互。
这5种不是互相替代的关系,而是一条链路里不同环节的工具。比如一套数据从旧系统导出,可能是xls格式,我需要用xlrd读出来、用pandas清洗、再通过openpyxl输出成带格式的xlsx报表,最后用xlwings打开检查一下视觉效果。每个工具解决一个环节的问题。
1.2 选型判断矩阵与我的推荐组合
新手最容易犯的错是“只学一个工具,然后硬套所有场景”。用openpyxl去跑几万行的数据聚合,速度慢到怀疑人生;用pandas去改单元格背景色,费半天劲还不如直接操作Excel。与其背API,不如先建立一张选型判断表:
| 需求类型 | 推荐方案 | 理由 |
|---|---|---|
| 大量数据读取、筛选、分组统计 | pandas | 底层是向量化运算,性能强、语法简洁 |
| 生成带样式、图表的Excel报表 | openpyxl | 对单元格样式、列宽、合并区域控制最细 |
| 读写老式xls文件(2003版) | xlrd / xlwt / xlutils | 专为xls设计,兼容老系统 |
| 数据量大、不需要格式、只做中转 | csv标准库 | 无第三方依赖,读写速度最快 |
| 调用Excel程序自身能力 | xlwings / pywin32 | 可以执行宏、操作Excel窗口、使用插件功能 |
我本人目前的固定组合是:pandas加上openpyxl打底,遇到老格式文件补一个xlrd/xlwt,数据大到内存吃紧就切csv中转,只有必须用Excel原生功能时才上xlwings。这套组合跑过财务对账、运营报表、库存分析等几十个真实任务,基本覆盖了日常能遇到的绝大多数情况,后面每个部分我都会给出可直接落地的代码。
2. 方式一:pandas——最全能的通用数据加工方案
2.1 读写Excel的基础操作
pandas做Excel处理的入口非常简单,最常用的就是read_excel和to_excel。但这里有几个参数值得认真掌握,用好了能省掉大量代码。
import pandas as pd # 读取单个sheet df = pd.read_excel("销售明细.xlsx", sheet_name="上海区") # 一次读取多个sheet,返回一个字典 sheets = pd.read_excel("销售明细.xlsx", sheet_name=["上海区", "北京区"]) # 读取全部sheet all_sheets = pd.read_excel("销售明细.xlsx", sheet_name=None)实际工作中,Excel表第一行经常不是表头,可能是大标题、备注甚至空行。比如我接过一份门店POS导出的数据,前3行是门店信息和导出时间,第4行才是真正的列名,第5行开始是数据。这时候就用skiprows跳过去。
df = pd.read_excel("门店销售.xlsx", sheet_name="Sheet1", skiprows=3)如果文件里只有那几列需要,可以用usecols减少加载量,尤其是列特别多、每列数据量还很大的时候,这个参数能明显缩短读取时间。
df = pd.read_excel("销售明细.xlsx", usecols=["订单号", "客户名", "销售额"])写入方向也一样简洁。一个DataFrame要落成Excel,核心就是一个to_excel。
df.to_excel("结果.xlsx", sheet_name="汇总", index=False)注意我刻意写了index=False。如果不写这个参数,pandas默认会把行号也写进Excel第一列,这通常是别人不需要的脏数据。带多个DataFrame输出到一个文件时,需要借助ExcelWriter:
with pd.ExcelWriter("多表结果.xlsx") as writer: df_sales.to_excel(writer, sheet_name="销售", index=False) df_cost.to_excel(writer, sheet_name="成本", index=False)2.2 数据清洗与字段处理实战
Excel文件读进来之后,数据处理才是大头。这块我用一个真实场景举例:一张从ERP导出的订单表,里面有重复行、空值、日期列乱成三种格式、销售金额还是文本带横杠。
先造一份类似的示例数据:
import pandas as pd # 模拟一份ERP导出的脏数据 df = pd.DataFrame({ "订单号": ["A001", "A002", "A002", "A003", None], "下单日期": ["2024/1/5", "2024-01-08", "2024/1/12", "20240115", "2024-02-03"], "客户": ["张三", "李四", "李四", "王五", "赵六"], "金额": ["1,200", "3,400", "3,400", "0", "-"] })处理脏数据的常规动作是:先看整体结构,再逐列处理。
# 看数据概况 print(df.info()) print(df.describe())日期列是最乱的部分。不同系统导出的日期格式五花八门,"2024/1/5"、"2024-01-08"、"20240115"这种实际是三种写法。我的经验是先把所有内容统一转成字符串,再用pd.to_datetime的format参数挨个清洗。
# 统一处理日期列 df["下单日期"] = df["下单日期"].astype(str) # 识别三种常见格式 df["下单日期"] = df["下单日期"].str.replace("/", "-", regex=False) # 处理“20240115”这种紧凑格式 df["下单日期"] = df["下单日期"].apply( lambda x: f"{x[:4]}-{x[4:6]}-{x[6:]}" if x.isdigit() else x ) df["下单日期"] = pd.to_datetime(df["下单日期"])金额列也麻烦。ERP导出的金额常常带千分位逗号,缺失值则可能显示成横杠。处理逻辑是:先把横杠替换成NaN,再去掉逗号,最后转成数值类型。
df["金额"] = df["金额"].replace("-", pd.NA) df["金额"] = df["金额"].str.replace(",", "", regex=False) df["金额"] = pd.to_numeric(df["金额"], errors="coerce")订单号列有重复和空值,需要去重和填充。
df = df.drop_duplicates(subset=["订单号"]) df["订单号"] = df["订单号"].fillna("未知")这几段代码汇总到一起,就是一份能直接套用的清洗模板。我在很多项目里都是这个套路:先info看类型,再逐列处理格式问题,最后去重去空。Excel里人工做这些操作可能要半个小时,脚本跑下来不到一秒。
2.3 pandas实操要点与常见坑
用pandas处理Excel,有几个坑我反复踩过,写出来提醒一下。
第一个是公式值的问题。pd.read_excel读到的单元格内容,如果那个格子是Excel公式,比如=SUM(C2:C10),pandas读取时拿到的不是计算结果,而是公式字符串。这其实是openpyxl引擎的读取方式导致的。解决办法是先用Excel打开文件计算并保存一遍,或者干脆使用openpyxl的data_only=True去读缓存结果,再把数据交给pandas。
第二个是数据类型被自动推断的问题。比如订单号明明是001,Excel文件里也显示001,但pandas读进来可能变成数字1,导致关联时对不上。处理办法是在read_excel时指定dtype参数,把订单号强制按字符串读取。
df = pd.read_excel("订单.xlsx", dtype={"订单号": str})第三个是内存问题。一个几十MB的Excel,pandas读进来可能占到几百MB内存,因为Excel本身就是压缩格式,解析成DataFrame后会膨胀。遇到大文件,我的建议是能转CSV就转CSV,或者分sheet读取,尽量避免一次性装载全部数据。
3. 方式二:openpyxl——需要保留样式的精细写入方案
3.1 读已有工作簿的关键细节
openpyxl和pandas最大的不同,在于它操作的是Excel文件本身,精确到单元格、样式、合并区域这些颗粒度。先看一个最常见的读取需求:从已有xlsx里读取数据,同时还要保留原文件的样式。
这里有一个关键参数要特别记住:data_only。
from openpyxl import load_workbook # 不写data_only时,拿到的是公式文本 wb = load_workbook("统计.xlsx") ws = wb["Sheet1"] print(ws["B2"].value) # 可能是 =SUM(B3:B10) # 写data_only=True,拿到的是Excel保存时的计算结果 wb2 = load_workbook("统计.xlsx", data_only=True) ws2 = wb2["Sheet1"] print(ws2["B2"].value) # 可能是 45600这个坑非常隐蔽。我接过一个同事的需求,他想读取一个模板文件里的汇总数字,结果脚本明明没报错,数字却读不到,最终发现单元格里是公式,而data_only=False时openpyxl返回的就是公式文本。
另外,data_only=True读到的计算值,本质是Excel打开文件后缓存的结果。如果文件生成后从未被Excel或WPS打开过,某些缓存值可能是None。最稳妥的办法是,读文件前先确保它被一个能计算公式的程序保存过。
3.2 批量写入与样式控制的完整示例
openpyxl真正强的地方是写报表。我需要生成月度销售报表时,经常要同时设置标题合并、表头底色、数据列宽、数字格式、冻结窗格。一个完整示例长这样:
from openpyxl import Workbook from openpyxl.styles import Font, PatternFill, Alignment, Border, Side from openpyxl.utils import get_column_letter wb = Workbook() ws = wb.active ws.title = "月度销售" # 写入标题并合并单元格 ws.merge_cells("A1:D1") ws["A1"] = "2025年1月销售汇总" ws["A1"].font = Font(name="微软雅黑", size=14, bold=True) ws["A1"].alignment = Alignment(horizontal="center", vertical="center") # 表头样式 headers = ["区域", "销售额", "目标额", "完成率"] ws.append(headers) header_font = Font(name="微软雅黑", bold=True, size=11) header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") thin_border = Border( left=Side(style="thin"), right=Side(style="thin"), top=Side(style="thin"), bottom=Side(style="thin"), ) for cell in ws[2]: cell.font = header_font cell.fill = header_fill cell.alignment = Alignment(horizontal="center", vertical="center") cell.border = thin_border # 写入数据 data = [ ["华东", 520000, 500000, "104%"], ["华北", 430000, 450000, "96%"], ["华南", 610000, 580000, "105%"], ] for row in data: ws.append(row) # 所有数据行加边框 for row in ws.iter_rows(min_row=2, max_row=ws.max_row, min_col=1, max_col=4): for cell in row: cell.border = thin_border # 设置列宽 widths = [12, 14, 14, 12] for i, w in enumerate(widths, start=1): ws.column_dimensions[get_column_letter(i)].width = w # 设置行高与冻结窗格 ws.row_dimensions[1].height = 30 ws.freeze_panes = "A3" wb.save("月度销售_报表.xlsx")这段代码生成的文件,打开之后视觉效果和手工做的报表基本没差。字体、底色、边框、对齐这些属性都是Font、PatternFill、Border、Alignment这几个类控制的,使用前先创建样式对象,再赋值给单元格即可。
3.3 适合哪些场景,不适合哪些场景
openpyxl适合的场景非常清晰:生成交付给领导、客户看的正式报表,批量套模板填数,需要精确控制每行每列样式的任务。我接过一个需求,要把几十个销售人员的月度KPI填进统一的模板,每个人员一个sheet,样式完全一致。用openpyxl循环创建sheet、赋值、设置样式,几分钟就搞定,手工复制粘贴得做半天。
但不适合的场景也要说清楚。openpyxl虽然能读数据,但数据量一大性能就明显下降。我测过读一个2万行、10列的xlsx,load_workbook需要好几秒,而pandas读取差不多是零点几秒的级别。所以做数据分析聚合时,别用它替代pandas。
还有一个容易忽略的限制:openpyxl只能读写xlsx格式,不能处理xls。碰到老式的xls文件,我通常先用工具转成xlsx,或者直接用下一部分讲的xlrd/xlwt三件套。
4. 方式三:xlrd / xlwt / xlutils——老牌方案里的取舍
4.1 三件套各自承担的职责
在很多老公司的内部系统里,导出的数据仍然是xls格式。这类文件用openpyxl是读不了的,pandas底层在读取xls时也会依赖xlrd。所以xlrd/xlwt/xlutils这套老方案虽然看起来不够时髦,我依然认为有必要掌握。
三个库的分工是:
xlrd:读取xls文件,能拿到单元格的值、日期、格式信息。xlwt:创建xls文件并向单元格写入数据。xlutils:在已有xls文件基础上做修改,因为xlwt只能新建文件,不能直接改已有内容。
一个典型的读取示例:
import xlrd workbook = xlrd.open_workbook("老数据.xls") sheet = workbook.sheet_by_index(0) print(sheet.nrows, sheet.ncols) # 总行数、总列数 for row in range(sheet.nrows): print(sheet.row_values(row))写入新xls的示例:
import xlwt wb = xlwt.Workbook() ws = wb.add_sheet("Sheet1") ws.write(0, 0, "省份") ws.write(0, 1, "销量") ws.write(1, 0, "浙江") ws.write(1, 1, 1200) # 设置列宽 ws.col(0).width = 256 * 20 wb.save("输出.xls")这里col(0).width的单位是1/256个字符宽度,所以256 * 20表示20个字符宽。这个细节当年困扰了我一会儿,写法很隐蔽,但设置列宽又经常要用。
4.2 典型批量报表改造案例
真正能发挥xlutils价值的是“改旧文件”的场景。举个例子:分公司发来一个固定的费用明细表,表头、格式、已有公式都不能动,我只想在每个月的汇总行旁边填入新的金额。
实现方案是:先用xlrd以formatting_info=True打开原文件,再交给xlutils.copy复制一份新的工作簿,最后在新工作簿上修改单元格。
import xlrd from xlutils.copy import copy rb = xlrd.open_workbook("费用表.xls", formatting_info=True) wb = copy(rb) ws = wb.get_sheet(0) # 假设第5行第3列是当月费用 ws.write(5, 2, 35999.0) wb.save("费用表_更新.xls")注意xlrd.open_workbook里的formatting_info=True必须开启,否则复制出来的工作簿会丢失原有格式。这个参数在读取xlsx时并不支持,所以这个方案仅针对xls文件。
代码本身不复杂,但它的价值在于:不用重新生成整个文件,原有样式、宏、公式都保留,只是改动指定格子。这在处理由第三方系统生成、不允许大幅改动的模板文件时非常好用。
4.3 使用中的注意事项
这套三件套的问题也很明显,我提几点实际经验:
第一,xlwt只能写xls,写xlsx会直接报错。如果你面对的交付物必须是xlsx,建议绕道openpyxl。
第二,xlwt有行数上限,最多65536行,列数上限是256列。听起来数字不小,但我处理过一份上百万行的明细数据时,这个限制就成了硬伤。这时候只能拆分成多个sheet,或者改用CSV。
第三,xlrd的新版本有个坑:从2.0版本开始,xlrd只支持xls,不再支持xlsx。这意味着如果你用pip install xlrd装的是最新版,想让它直接读xlsx,会报"xlsx file format not supported"。解决方法是装旧版本,或者读xlsx时老老实实用openpyxl。
我现在的习惯是:只有处理老系统输出的xls才用xlrd,其他地方尽量统一用pandas和openpyxl,减少依赖冲突。
5. 方式四:csv标准库——轻量场景下的最高效搬运
5.1 为什么有些Excel处理直接用csv更省事
你可能会问:已经有pandas了,为什么还提csv?原因很简单:很多Excel处理场景里,真正的瓶颈不是计算,而是文件IO和格式兼容。
Excel文件本质是压缩包,读取时要解压、解析XML,天然比纯文本的csv慢。一个10MB的csv,读取速度可能是同样数据量xlsx的10倍以上。如果只是做简单的数据筛选、转存、对接,完全没必要动用Excel格式。
另一个场景是上下游系统对接。很多数据平台导出功能,Excel直接导出到几万行就开始卡,但CSV可以轻松导出几十万行。所以我的习惯是:在大数据量场景下,先让数据以CSV格式落地,再用pandas等工具处理,最后需要给业务方看时才转成带格式的Excel。
import csv with open("大文件.csv", "r", encoding="utf-8") as f: reader = csv.reader(f) header = next(reader) for row in reader: # 逐行处理 pass5.2 编码问题的正确处理方式
用csv最头疼的永远是编码。同一个CSV文件,在Windows上用Excel打开正常,用Python默认方式读就可能乱码;在Mac上正常,拷到Windows又变乱码。
原因在于Excel在不同语言环境下默认编码不一样。国内Windows环境的Excel打开csv时,优先按ANSI编码解析,而ANSI在国内环境就是GBK。如果Python用UTF-8写入csv,Excel直接双击打开就会看到一堆乱码。
解决办法是写文件时用带BOM的UTF-8编码,也就是utf-8-sig:
import csv data = [ ["地区", "销量"], ["华东", 1200], ["华北", 900], ] with open("销售_out.csv", "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) writer.writerows(data)utf-8-sig会在文件开头加一个BOM头,Excel识别到BOM就知道这是UTF-8编码,不会按GBK去解析。这个细节我记了很多年,每次写CSV都默认带utf-8-sig,再也没有乱码反馈。
读取时也要注意编码判断。我常用的方式是先试UTF-8,失败再回退GBK:
def read_csv_flexible(path): for encoding in ["utf-8", "gbk", "gb18030"]: try: return pd.read_csv(path, encoding=encoding) except UnicodeDecodeError: continue raise ValueError("无法识别的编码")5.3 从Excel导出csv再加工的完整脚本
把一个多sheet的xlsx转成多个csv,再逐个读取处理,是我在大数据量场景下经常用的操作模板。
import pandas as pd from pathlib import Path # 第一步:把xlsx的每个sheet导出为csv src_path = Path("超大报表.xlsx") out_dir = Path("csv_output") out_dir.mkdir(exist_ok=True) sheets = pd.read_excel(src_path, sheet_name=None) for sheet_name, df in sheets.items(): safe_name = sheet_name.replace(" ", "_").replace("/", "_") df.to_csv(out_dir / f"{safe_name}.csv", index=False, encoding="utf-8-sig") # 第二步:按需读取单个csv并处理 df_part = pd.read_csv(out_dir / "销售明细.csv", encoding="utf-8-sig")这套流程的最大优势是中间产物可见。xlsx转csv之后,可以先用文本编辑器确认编码和字段,再跑后续逻辑。出问题时排查路径也比直接内存操作清晰。
6. 方式五:pywin32/xlwings——调用Excel自身能力的自动化路径
6.1 为什么需要调用Excel COM接口
前面几种方式都是在“文件”层面操作Excel,但有些场景绕不开Excel程序本身。比如:工作簿里有透视表需要刷新、有VBA宏需要执行、有外部数据连接需要更新,甚至有些插件只提供Excel界面操作入口。这时候就只能把Excel程序启动起来,像人一样通过界面去操作它。
pywin32和xlwings就是干这个的。它们在Windows上通过COM接口控制Excel应用程序,能做到和手工操作几乎一致的效果。
我举一个具体例子:某公司的月报模板里有一个透视表,数据源是另一个关闭的xlsx。每次拿到新数据,都得手动打开Excel、点击“刷新全部”,再另存为新文件。用pywin32就能自动完成这整套动作。
import win32com.client as win32 excel = win32.Dispatch("Excel.Application") excel.Visible = False # 不显示Excel窗口 excel.DisplayAlerts = False # 不弹出保存提示 wb = excel.Workbooks.Open(r"C:\工作目录\月报模板.xlsx") wb.RefreshAll() # 刷新所有数据连接和透视表 wb.SaveAs(r"C:\工作目录\月报_已更新.xlsx") wb.Close() excel.Quit()这段代码里的Visible = False很关键,适用于服务器或后台执行。如果调试时想观察操作过程,可以把它改成True,Excel窗口就会显示出来。
6.2 一个批量格式调整的实战案例
pywin32做批量格式化也非常顺手。我之前有个需求:把工作簿里所有sheet的A1单元格都加上黄色底纹,列宽调成18,同时在第一行前面插入两行说明。手工做要重复几十次,用脚本一次搞定。
import win32com.client as win32 excel = win32.Dispatch("Excel.Application") excel.Visible = False excel.DisplayAlerts = False wb = excel.Workbooks.Open(r"C:\工作目录\多表统计.xlsx") for ws in wb.Worksheets: # 插入两行 ws.Rows(1).Insert() ws.Rows(1).Insert() # 写说明 ws.Cells(1, 1).Value = "本表由系统自动生成" ws.Cells(2, 1).Value = "生成日期:" + str(excel.WorksheetFunction.Text(excel.Now(), "yyyy-mm-dd")) # 设置列宽 ws.Columns(1).ColumnWidth = 18 # 给A1加黄色底纹 ws.Cells(1, 1).Interior.Color = 65535 # 黄色 wb.Save() wb.Close() excel.Quit()注意Interior.Color给的是BGR格式的整数值,65535是黄色,255是红色,65280是绿色。想用RGB颜色的话,可以自己写个换算函数:red + green * 256 + blue * 65536这种方式。
6.3 xlwings与pywin32的选择建议
pywin32是最底层的COM封装,功能最强,但写起来比较啰嗦。如果你不太想记那么多COM对象的属性名,可以用xlwings。
xlwings的语法更接近人的阅读习惯。同样一个“打开工作簿、改A1、保存”的操作,pywin32要写好几行,xlwings可以这样:
import xlwings as xw app = xw.App(visible=False) wb = app.books.open(r"C:\工作目录\测试.xlsx") ws = wb.sheets["Sheet1"] ws.range("A1").value = "你好" wb.save() wb.close() app.quit()xlwings还有一个杀手级功能:可以从Excel中调用Python函数作为自定义公式(UDF),不过这个功能在公司内部分发时配置比较麻烦,我目前用得不多。
我的选型建议是:脚本自己用、追求可控,选pywin32;要交付给别人维护,或者你刚开始接触COM对象,选xlwings更省心。
还有一个重要提醒:这两种方式都要求本机装有完整的Excel应用,Linux服务器上用不了。生产环境如果跑在Linux上,需要操作Excel文件的场景还是老老实实走前面的pandas/openpyxl方案。
7. 新手必看:环境安装与常见问题排查
7.1 Python环境与依赖库的快速安装
很多人卡在第一步的Python安装上。国内用户建议直接从官网下载安装包,安装在Windows上时一定要勾选“Add Python to PATH”,这一步不勾后面在命令行执行python会提示找不到命令。如果已经安装过,检查PATH的方法是打开命令行输入python --version,能输出版本号就说明环境正常。
依赖库的安装就一条命令:
pip install pandas openpyxl xlrd xlwt xlutils xlwings其中xlwings在macOS和Windows都能用,但pywin32只在Windows上有意义。如果只需要最基本的Excel读写,装pandas和openpyxl两个库就够了。
我自己写代码时用的编辑器是VS Code,配置Python环境时注意右下角要选中正确的解释器,不然pip install装完的包在另一个解释器里根本导入不了。这个问题非常多见,尤其在电脑上装过多个Python版本的时候。
7.2 常见报错与解决方法
我在实战中遇到的报错,几乎都集中在下面这几个点。整理成表格方便你排查:
| 报错或现象 | 原因 | 解决办法 |
|---|---|---|
ModuleNotFoundError: No module named 'pandas' | 没装库,或解释器选错 | 执行pip install pandas,检查VS Code解释器 |
Excel file format can't be determined | 文件不是真正的xlsx,可能是xls或伪后缀文件 | 用file命令看真实格式,或改用xlrd读取 |
xlrd.biffh.XLRDError: Excel xlsx file not supported | xlrd 2.0以上不支持xlsx | 读xlsx改用openpyxl,读xls保留xlrd |
KeyError: 'Sheet1' | 文件中没有叫Sheet1的工作表 | 先打印wb.sheetnames确认sheet名 |
PermissionError: [Errno 13] Permission denied | 目标Excel文件正被WPS/Excel打开占用 | 关闭打开的文件,或换文件名保存 |
读取单元格拿到=SUM(...) | openpyxl默认拿公式文本 | load_workbook(..., data_only=True) |
| Excel打开CSV乱码 | 编码不对,缺少BOM | 写入时用encoding="utf-8-sig" |
| 双击Excel出现“此操作只对当前安装的产品有效” | 某类COM组件或插件注册异常 | 修复Office安装,或重装对应Excel插件 |
这些坑我一个一个都踩过,最频繁的是文件占用和sheet名写错。我的习惯是:脚本里读取前先打印一下可用的sheet名,再做后续操作,能省掉很多调试时间。
7.3 我个人的工作流建议
最后分享一套我常用的工作流,新项目接到手基本按这个顺序走:
先判断数据量级。小文件(几千行)直接pd.read_excel硬读,大文件先转csv或分sheet处理。再判断输出要求。如果只要数据结果,写csv或者用to_excel就够了;要交付正式报表,用openpyxl把样式一并生成。最后检查有没有必须调用Excel功能的步骤。有透视表刷新或宏执行,再用xlwings补上。整个过程可以用一个Python脚本串起来,也可以拆成多个脚本按需运行。
我的建议是不要追求一步到位,先让每个环节跑通,再串成完整流程。这个方式适合处理从几万行到几十万行的数据,覆盖面广、坑踩得少,也是我向团队新人推荐的学习路径。