Python自动化办公常用库:怎么操作Excel、PDF与发送邮件
在日常办公中,许多岗位经常需要重复处理类似的流水线任务:从业务系统导出多份Excel表格进行核算汇总,提取数十份PDF发票或验收单中的关键金额,最后将生成的统计报表打包作为附件,通过邮件分发给不同部门的负责人。若完全依赖人工点击与复制粘贴,不仅耗时耗力,而且容易遗漏。借助Python生态中成熟的几个专用库——用于表格读写的openpyxl、用于文档解析与合并的pypdf,以及用于邮件协议交互的内置库smtplib,即可将整套繁琐流程编排为全自动脚本。
本文将围绕这三大高频办公需求展开,逐一拆解对应库的安装方式、核心工作机制、标准操作范例以及避坑要点,帮助读者建立清晰的自动化脚本编写路径。
一、操作Excel:使用 openpyxl 读写表格与设置样式
在Python处理Excel的生态中,最常被提及的两个库是openpyxl和pandas。它们各自适用的场景非常明确:
- pandas:专长在于数据分析、多表关联运算与大数据集清洗。如果任务是做百兆级别的离线统计计算,pandas是首选;但若将其导出为Excel,往往会丢失原有表格中的单元格样式、公式和多级表头。
- openpyxl:专长在于对
.xlsx格式进行高精度的对象化控制。它能够精确读取指定单元格、修改公式、插入行、设置边框字体与背景颜色,非常适合用于基于“现成模板”生成汇报表格。
1. 依赖安装与基本读写
通过 pip 命令安装 openpyxl:
pip install openpyxl
下面的示例展示了如何使用 openpyxl 新建工作簿、向指定单元格写入内容,并对已存在的表格进行数据读取与总计统计:
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
# 1. 创建工作簿并写入基础业务数据
wb = Workbook()
ws = wb.active
ws.title = "月度销售核算"
# 写入表头
headers = ["员工编号", "姓名", "负责区域", "销售额(元)", "达标状态"]
ws.append(headers)
# 写入数据行
rows = [
["E101", "张伟", "华北", 85000, "达标"],
["E102", "李娜", "华东", 120000, "超额"],
["E103", "王强", "华南", 62000, "未达标"],
["E104", "赵敏", "西南", 98000, "达标"],
]
for row in rows:
ws.append(row)
# 2. 写入汇总公式与单元格样式设置
total_row_idx = len(rows) + 2
ws.cell(row=total_row_idx, column=3, value="总计销售额")
ws.cell(row=total_row_idx, column=4, value=f"=SUM(D2:D{total_row_idx - 1})")
# 设定标题行与汇总行样式
header_fill = PatternFill(start_color="142537", end_color="142537", fill_type="solid")
header_font = Font(name="Microsoft YaHei", size=11, bold=True, color="FFFFFF")
thin_border = Border(
left=Side(style="thin", color="CBD5E1"),
right=Side(style="thin", color="CBD5E1"),
top=Side(style="thin", color="CBD5E1"),
bottom=Side(style="thin", color="CBD5E1"),
)
for col in range(1, len(headers) + 1):
cell = ws.cell(row=1, column=col)
cell.fill = header_fill
cell.font = header_font
cell.alignment = Alignment(horizontal="center", vertical="center")
cell.border = thin_border
# 保存工作簿
wb.save("月度销售核算表.xlsx")
2. 读取与修改已有表格的注意事项
避坑提示:openpyxl 本身不包含任何公式计算引擎。当在代码中写入 =SUM(...) 时,写入的仅仅是公式表达式字符串。如果随后立即以 data_only=True 重新读取该文件,获取到的值将是 None,因为只有通过微软 Office 或 WPS 打开并保存过一次后,计算出的数值缓存才会被填入文件。
二、操作PDF:使用 pypdf 提取文本与合并页面
在企业办公流中,PDF 通常作为电子凭证、合同或归档报告的文件载体。与结构化清晰的 Excel 不同,PDF 本质上是一种面向排版和打印的“绘制描述语言”。理解 PDF 的基本处理边界至关重要:
- 文本型 PDF:由 Word、Markdown 或代码直接导出,页面内包含真实的文字矢量流,可直接使用 Python 快速提取纯文本和关键字。
- 扫描件 / 纯图片 PDF:本质是包含在一页画布中的位图图像,页面内没有任何文字字符信息。对于此类文档,任何轻量 PDF 库提取出的文字都为空,必须前置引入 OCR(光学字符识别)组件进行预处理。
1. 依赖安装
现代 Python 项目推荐使用 pypdf(即 PyPDF2 的官方最新演化版本):
pip install pypdf
2. 核心操作:多份报表合并与页面提取
在月底对账时,常需要把多个部门各自上交的单页 PDF 验收单合并为一份完整的年度总报告;或者在扫描的大文件中拆分出指定页。利用 PdfMerger 和 PdfReader 可以轻松实现:
from pypdf import PdfReader, PdfWriter, PdfMerger
import os
# 1. 批量合并多个 PDF 文件
def merge_pdf_files(file_list, output_path):
merger = PdfMerger()
for file in file_list:
if os.path.exists(file):
print(f"正在载入单据: {file}")
merger.append(file)
merger.write(output_path)
merger.close()
print(f"合并完成,已生成总文档: {output_path}")
# 2. 遍历页面提取文本并检索关键指标
def extract_invoice_summary(pdf_path):
reader = PdfReader(pdf_path)
total_pages = len(reader.pages)
extracted_records = []
for page_num in range(total_pages):
page = reader.pages[page_num]
text = page.extract_text()
# 简单关键字检索示例
if "发票金额" in text or "合计" in text:
extracted_records.append({
"page": page_num + 1,
"preview": text.strip().split("\n")[:3] # 记录前3行摘要
})
return extracted_records
# 执行示例
sample_files = ["华北销售明细.pdf", "华东销售明细.pdf", "华南销售明细.pdf"]
# merge_pdf_files(sample_files, "全国销售汇总总报告.pdf")
三、发送邮件:使用 smtplib 与 EmailMessage 安全批量分发
在 Python 脚本完成报表生成与文档整理后,最后的交付动作通常是“发送通知邮件”。Python 标准库自带了 smtplib 与 email 模块,这意味着完全不需要通过 pip 安装第三方包,即可搭建出专业且安全的邮件分发流水线。
1. 邮件协议与关键认证概念
- SMTP 协议:简单邮件传输协议(Simple Mail Transfer Protocol),负责与网易企业邮、腾讯企业邮、QQ邮箱或 Gmail 等发信服务器建立通信通道。
- SSL/TLS 加密端口:通常推荐使用 465(SMTPS / SSL 直连)或 587(STARTTLS 握手),避免明文暴露通信内容。
- 应用授权码(Authorization Code):现代主流邮箱服务商出于安全考虑,均禁止在第三方代码中直接填入登录密码。开发者必须在邮箱的“设置 -> 账户 -> POP3/IMAP/SMTP 服务”中生成一串专用的独立授权码。
2. 构建与发送包含附件的现代邮件
在 Python 3 中,推荐使用高阶面向对象的 EmailMessage 替代老旧繁琐的 MIMEMultipart。下面的完整示例展示了如何组装 HTML 正文、挂载生成的 Excel/PDF 附件并安全发送:
import smtplib
from email.message import EmailMessage
import mimetypes
import os
def send_automation_report(receiver_email, subject, body_html, attachment_paths=None):
# 发件人配置(按需替换为企业邮箱服务器与授权码)
smtp_server = "smtp.qiye.aliyun.com"
smtp_port = 465
sender_email = "report_robot@yourcompany.com"
auth_code = "YOUR_AUTHORIZATION_CODE_HERE"
# 1. 实例化现代 EmailMessage 对象
msg = EmailMessage()
msg["Subject"] = subject
msg["From"] = f"财务自动化助手 <{sender_email}>"
msg["To"] = receiver_email
# 2. 设置邮件正文(支持 HTML 格式,便于排版整洁表格)
msg.set_content("这是自动导出的销售与对账核算报表,请在支持 HTML 的客户端查看。")
msg.add_alternative(body_html, subtype="html")
# 3. 自动探测类型并挂载附件
if attachment_paths:
for file_path in attachment_paths:
if not os.path.exists(file_path):
print(f"附件未找到,已跳过: {file_path}")
continue
# 猜测 MIME 类型,如 application/pdf 或 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
mime_type, _ = mimetypes.guess_type(file_path)
if mime_type is None:
mime_type = "application/octet-stream"
main_type, sub_type = mime_type.split("/", 1)
# 读取二进制内容并附加
with open(file_path, "rb") as f:
file_data = f.read()
filename = os.path.basename(file_path)
msg.add_attachment(
file_data,
maintype=main_type,
subtype=sub_type,
filename=filename
)
print(f"已成功添加附件: {filename}")
# 4. 建立 SSL 安全通信并投递
try:
with smtplib.SMTP_SSL(smtp_server, smtp_port, timeout=15) as server:
server.login(sender_email, auth_code)
server.send_message(msg)
print(f"邮件已成功投递至: {receiver_email}")
return True
except smtplib.SMTPAuthenticationError:
print("错误: SMTP 认证失败,请检查发信账号与授权码是否正确。")
except smtplib.SMTPConnectError:
print("错误: 无法连接至发信服务器,请检查域名、端口或本地网络代理设置。")
except Exception as e:
print(f"发送过程中出现未预期异常: {e}")
return False
# 测试调用
html_content = """
<div style="font-family: Arial, sans-serif; padding: 16px; border: 1px solid #e2e8f0; border-radius: 6px;">
<h3 style="color: #0f172a;">2026年第3季度销售汇总与凭证归档</h3>
<p style="color: #475569;">各部门主管您好:</p>
<p style="color: #475569;">系统已完成全量数据的核算与对账,相关明细表与扫描发票合集已打包随邮件附上,请查收审阅。</p>
</div>
"""
# send_automation_report("manager@company.com", "【自动化报表】Q3全国销售汇总", html_content, ["月度销售核算表.xlsx"])
附件文件名包含中文时的处理:使用旧版 email.mime 模块时,中文附件名常在某些邮箱客户端出现类似 utf-8''xxxx.xlsx 的乱码或无后缀问题。而在 Python 3.6+ 引入的 EmailMessage 中,add_attachment() 已经原生遵循 RFC 2231 标准,直接传入包含中文的 filename 字符串即可正确自适应编码。
四、常用库能力总结与技术选型指南
在编写自动化脚本时,盲目引入复杂的重型框架不仅会增加部署难度,还可能因为环境依赖问题导致脚本无法长期稳定运行。下表归纳了本文涉及的几大核心库及协同选型原则:
| 功能模块 | 推荐使用库 | 是否标准库 | 核心长处 | 局限与注意事项 |
|---|---|---|---|---|
| Excel 表格 | openpyxl |
否 (第三方) | 精确保留样式、模板、公式,支持只读流式模式 | 不支持老旧的 .xls 格式;不自带公式重新计算引擎 |
| Excel 运算 | pandas |
否 (第三方) | 极速的数据清洗、列聚合、透视表分析与批量过滤 | 覆盖导出时通常不保留已有 Excel 的单元格精细装饰样式 |
| PDF 页面 | pypdf |
否 (第三方) | 轻量、纯 Python 编写,合并、拆分、旋转及提取快速 | 扫描件需要额外接入 OCR;复杂表格排版提取容易错行 |
| 邮件分发 | smtplib + email |
是 (内置) | 零外部依赖,支持 SSL/TLS,对附件与中文编码支持完善 | 高频批量发送需注意被服务商限频,应控制发送间隔时间 |
五、总结与脚本编排建议
掌握 Excel 读写、PDF 文档处理与邮件自动发送,就涵盖了企业办公自动化中最核心的数据输入、文档规整与结果交付环节。在将这些片段整合为一个长期运转的独立工程时,建议遵守以下三个工程原则:
- 敏感凭据解耦:严禁将邮箱的发信密码或授权码直接以明文硬编码在
.py脚本中。应统一通过操作系统环境变量(如os.getenv("SMTP_AUTH_CODE"))或本地加密的.env文件读取,防止随代码提交造成泄露。 - 操作幂等性与中间产物归档:处理 Excel 和 PDF 时,尽量避免直接覆盖原始文件,应保持“输入目录 -> 处理流水线 -> 输出/归档目录”的单向流程。若单次执行中断,可直接重新运行而不破坏源数据。
- 完善的分步日志与重试机制:邮件发送受限于网络抖动与邮件服务商频率限制。在循环批量分发时,应加入适量的时间延迟(如每封间隔 1~2 秒),并在捕捉到发送超时等瞬时异常时进行有限次重试,确保每位收件人都能准确收到报表。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













