办公自动化必备:30个高效处理Excel和PDF的Python脚本
在日常办公场景中,处理繁杂的 Excel 表格与海量的 PDF 文档往往占据了知识工作者大量的时间。无论是数十张表结构一致的数据合并、多维度拆分导出,还是数十份合同 PDF 的批量加水印、密码解密与表格提取,人工手动点击不仅容易出错,更难以满足严苛的时效要求。本文直接整理并讲解 30 个面向生产实际的 Python 自动化脚本,分为 Excel 处理篇(15 个)与 PDF 处理篇(15 个),不讲泛泛的理论,聚焦即拷即用、稳定容错的工程化实现。
一、自动化技术栈架构与库选型原则
在动手编写脚本前,首要任务是明确工具库的分工与边界。许多初学者在处理 Excel 时盲目混用 pandas 和 openpyxl,在处理 PDF 时分不清 pypdf 与 pdfplumber 的本质差异,导致脚本运行缓慢或格式损坏。合理的选型应当依据“计算密集”与“排版密集”进行严格划分。
二、Excel 高效自动化实操脚本(01 - 15)
以下15个脚本覆盖了从批量文件操作、数据清洗到报表排版的核心需求。请提前在终端安装依赖:pip install pandas openpyxl xlsxwriter。
脚本 01:批量合并目录下全部同构 Excel 表格
应用场景:每月从各分支机构或部门收集汇总的周报、打卡记录、销售清单,需要统一纵向堆叠到一张总表并标注来源。
import os
import pandas as pd
def batch_merge_excels(input_dir, output_file):
all_dfs = []
for file in os.listdir(input_dir):
if file.endswith(('.xlsx', '.xls')) and not file.startswith('~'):
full_path = os.path.join(input_dir, file)
df = pd.read_excel(full_path)
df['数据来源文件'] = file
all_dfs.append(df)
if all_dfs:
merged_df = pd.concat(all_dfs, ignore_index=True)
merged_df.to_excel(output_file, index=False)
print(f"成功合并 {len(all_dfs)} 个文件,总计 {len(merged_df)} 行。")
batch_merge_excels('./data_folder', './merged_report.xlsx')
脚本 02:按指定字段将总表一键拆分为多个独立文件
应用场景:需要将集团总员工名单或全品类销售流水,按“所属部门”或“销售区域”快速分发给不同对接人。
import pandas as pd
def split_excel_by_column(source_file, split_column, output_dir):
df = pd.read_excel(source_file)
unique_keys = df[split_column].dropna().unique()
for key in unique_keys:
sub_df = df[df[split_column] == key]
clean_key = str(key).replace('/', '_')
save_path = f"{output_dir}/{clean_key}.xlsx"
sub_df.to_excel(save_path, index=False)
print(f"已导出分类 [{key}] -> {len(sub_df)} 行")
split_excel_by_column('./all_staff.xlsx', '部门', './departments')
脚本 03:批量重命名工作簿内的 Sheet 页面
应用场景:系统默认导出的 Sheet1、Sheet2 或带有旧日期格式的名称,需要统一映射为业务规范命名。
from openpyxl import load_workbook
def rename_sheets(wb_path, name_mapping):
wb = load_workbook(wb_path)
for old_name, new_name in name_mapping.items():
if old_name in wb.sheetnames:
wb[old_name].title = new_name
wb.save(wb_path)
print("工作表重命名完成。")
rename_sheets('./project_data.xlsx', {'Sheet1': '汇总核算', 'Sheet2': '原始流水'})
脚本 04:将单一工作簿中所有 Sheet 汇总至统一工作表
应用场景:按月份或业务线存放在不同标签页中的明细账,需要一键汇成平铺表以便进行数据透视或图表分析。
import pandas as pd
def merge_all_sheets_to_one(excel_path, target_sheet_name='总表汇总'):
excel_reader = pd.ExcelFile(excel_path)
sheet_list = [s for s in excel_reader.sheet_names if s != target_sheet_name]
combined = []
for s_name in sheet_list:
sub_df = pd.read_excel(excel_reader, sheet_name=s_name)
sub_df['所属Sheet'] = s_name
combined.append(sub_df)
final_df = pd.concat(combined, ignore_index=True)
with pd.ExcelWriter(excel_path, mode='a', if_sheet_exists='replace', engine='openpyxl') as writer:
final_df.to_excel(writer, sheet_name=target_sheet_name, index=False)
print("全表合并落盘完成。")
merge_all_sheets_to_one('./quarterly_sales.xlsx')
脚本 05:业务数据智能去重与缺失值处理
应用场景:在多渠道抓取或人工填报的名单中,基于特定关键列(如手机号、订单号)去重,并填补指定默认值。
import pandas as pd
def clean_and_deduplicate(file_path, output_path, key_columns):
df = pd.read_excel(file_path)
before_len = len(df)
# 基于主键去重,保留最新录入(最后一条)
df.drop_duplicates(subset=key_columns, keep='last', inplace=True)
# 填充缺失文本与数值
df.fillna({'备注': '无', '数量': 0, '状态': '待审核'}, inplace=True)
df.to_excel(output_path, index=False)
print(f"清洗完成:原始 {before_len} 行,去重后保留 {len(df)} 行。")
clean_and_deduplicate('./leads.xlsx', './leads_cleaned.xlsx', ['客户手机号', '登记日期'])
脚本 06:跨表多条件关联匹配(自动化 VLOOKUP)
应用场景:需要将商品主数据表的“成本价”、“供货商”自动对齐填入日常销售明细表中。
import pandas as pd
def auto_vlookup_merge(sales_file, master_file, output_file):
sales_df = pd.read_excel(sales_file)
master_df = pd.read_excel(master_file)
# 类似 Excel 的左连接 (Left Join)
result = pd.merge(
sales_df,
master_df[['商品编码', '成本价', '供应商分类']],
on='商品编码',
how='left'
)
result['毛利估算'] = result['销售额'] - (result['成本价'] * result['销量'])
result.to_excel(output_file, index=False)
print("跨表关联对齐与核算完成。")
auto_vlookup_merge('./daily_sales.xlsx', './sku_master.xlsx', './sales_with_profit.xlsx')
脚本 07:动态高亮异常数值(openpyxl 条件着色)
应用场景:为毛利率低于特定阈值、或库存超期天数过高的记录自动标红背景,增强报表视觉警示。
from openpyxl import load_workbook
from openpyxl.styles import PatternFill, Font
def highlight_exceptions(file_path, sheet_name, target_col_idx, threshold=100):
wb = load_workbook(file_path)
ws = wb[sheet_name]
red_fill = PatternFill(start_color="FFE2E2", end_color="FFE2E2", fill_type="solid")
red_font = Font(color="9C0006", bold=True)
for row in range(2, ws.max_row + 1):
cell = ws.cell(row=row, column=target_col_idx)
if isinstance(cell.value, (int, float)) and cell.value < threshold:
cell.fill = red_fill
cell.font = red_font
wb.save(file_path)
print("异常指标着色已标记完成。")
highlight_exceptions('./kpi_data.xlsx', '绩效总览', target_col_idx=5, threshold=60)
脚本 08:自适应列宽与文字排版自动化
应用场景:解决导出 Excel 时文字被遮挡、数字变成 ### 的问题,让生成的报表无需人工双击列缝调整宽度。
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
def auto_fit_columns(file_path):
wb = load_workbook(file_path)
for ws in wb.worksheets:
for col in ws.columns:
max_len = 0
col_letter = get_column_letter(col[0].column)
for cell in col:
val = str(cell.value or '')
# 中文字符计 2 字节,英文字符计 1 字节
char_len = sum(2 if ord(c) > 127 else 1 for c in val)
if char_len > max_len:
max_len = char_len
# 设置宽度并预留安全间距
ws.column_dimensions[col_letter].width = max(max_len + 3, 11)
wb.save(file_path)
print("全表自适应列宽调整完毕。")
auto_fit_columns('./formatted_report.xlsx')
脚本 09:批量注入 Excel 动态公式并保护结果联动
应用场景:向生成的月度清单尾行批量注入求和、均值公式,确保他人打开表格调整数值时公式依然联动生效。
from openpyxl import load_workbook
def inject_formulas(file_path, sheet_name):
wb = load_workbook(file_path)
ws = wb[sheet_name]
last_row = ws.max_row
summary_row = last_row + 1
ws.cell(row=summary_row, column=1, value="合计汇总")
# 注入 SUM 动态公式
ws.cell(row=summary_row, column=3, value=f"=SUM(C2:C{last_row})")
# 注入 AVERAGE 均值公式
ws.cell(row=summary_row, column=4, value=f"=AVERAGE(D2:D{last_row})")
wb.save(file_path)
print(f"动态公式已成功注入第 {summary_row} 行。")
inject_formulas('./finance_ledger.xlsx', '明细账')
脚本 10:大数据集快速分块导出为标准 CSV
应用场景:需要将包含数十万行交易明细的重型 Excel 转换为轻量级、逗号分隔的标准 CSV 格式供数仓导入。
import pandas as pd
def excel_to_clean_csv(excel_path, csv_path):
df = pd.read_excel(excel_path, engine='openpyxl')
# 转换日期与时间格式为标准 ISO 字符串,防止乱码
for col in df.select_dtypes(include=['datetime64']):
df[col] = df[col].dt.strftime('%Y-%m-%d %H:%M:%S')
df.to_csv(csv_path, index=False, encoding='utf-8-sig')
print(f"转换完成,输出至 {csv_path}")
excel_to_clean_csv('./huge_log.xlsx', './clean_log.csv')
脚本 11:在 Excel 中自动化插入数据分析柱状图
应用场景:数据写入完成后直接在指定单元格位置附带生成数据柱状图,实现自动化交付看板。
from openpyxl import load_workbook
from openpyxl.chart import BarChart, Reference
def add_bar_chart(file_path, sheet_name):
wb = load_workbook(file_path)
ws = wb[sheet_name]
chart = BarChart()
chart.type = "col"
chart.style = 10
chart.title = "月度销售业绩对比"
chart.y_axis.title = "销售额 (元)"
chart.x_axis.title = "月份"
data = Reference(ws, min_col=2, min_row=1, max_row=ws.max_row)
cats = Reference(ws, min_col=1, min_row=2, max_row=ws.max_row)
chart.add_data(data, titles_from_data=True)
chart.set_categories(cats)
# 定位放置在 F2 单元格
ws.add_chart(chart, "F2")
wb.save(file_path)
print("柱状图绘制并定位成功。")
add_bar_chart('./performance.xlsx', '业绩指标')
脚本 12:批量锁定工作表并设置防篡改密码保护
应用场景:需要向下游或外部客户发放报价表,允许查看但不允许随意修改计算规则或改动表头。
from openpyxl import load_workbook
def protect_workbook_sheets(file_path, password):
wb = load_workbook(file_path)
for ws in wb.worksheets:
ws.protection.sheet = True
ws.protection.password = password
# 允许选择未锁定单元格,禁止修改对象与格式
ws.protection.enable()
wb.save(file_path)
print("所有工作表保护密码已激活。")
protect_workbook_sheets('./quotation.xlsx', 'SafePass2026')
脚本 13:全量双表对比并标红差异单元格
应用场景:对账时比对“系统导出版本”与“财务核对版本”,逐行逐列找出数值变动与文字改动。
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import PatternFill
def diff_two_excels(file_a, file_b, output_diff_file):
df_a = pd.read_excel(file_a)
df_b = pd.read_excel(file_b)
# 结构一致性校验
assert df_a.shape == df_b.shape, "两个表格的行列维度不一致!"
wb = load_workbook(file_a)
ws = wb.active
diff_fill = PatternFill(start_color="FFD1D1", end_color="FFD1D1", fill_type="solid")
diff_count = 0
for r in range(len(df_a)):
for c in range(len(df_a.columns)):
val_a = df_a.iat[r, c]
val_b = df_b.iat[r, c]
if pd.isna(val_a) and pd.isna(val_b):
continue
if val_a != val_b:
diff_count += 1
# 偏移表头与1-indexed
ws.cell(row=r + 2, column=c + 1).fill = diff_fill
wb.save(output_diff_file)
print(f"差异比对完成,共检测到 {diff_count} 处变更并已标红。")
diff_two_excels('./ledger_v1.xlsx', './ledger_v2.xlsx', './ledger_diff.xlsx')
脚本 14:大文件分批读写与极低内存模式流式导出
应用场景:当单表行数超过 50 万甚至达百兆大小时,普通读取会造成内存溢出,需要借助 chunksize 分段流式处理。
import pandas as pd
def process_large_excel_in_chunks(large_csv_source, output_excel, chunk_size=50000):
writer = pd.ExcelWriter(output_excel, engine='openpyxl')
chunk_index = 1
for chunk in pd.read_csv(large_csv_source, chunksize=chunk_size):
# 针对当前批次执行必要的业务清洗
clean_chunk = chunk[chunk['交易状态'] == '成功']
clean_chunk.to_excel(writer, sheet_name=f"Part_{chunk_index}", index=False)
print(f"已流式写入分块 {chunk_index} ({len(clean_chunk)} 行)")
chunk_index += 1
writer.close()
print("流式批处理分卷导出完成。")
process_large_excel_in_chunks('./raw_stream.csv', './partitioned_export.xlsx')
脚本 15:多维度数据透视表自动化生成
应用场景:日常无需手动在 Excel 里拖拉透视字段,直接由 Python 生成“区域-部门”多维统计汇总表。
import pandas as pd
def generate_pivot_report(input_file, output_file):
df = pd.read_excel(input_file)
pivot_table = pd.pivot_table(
df,
values=['销售额', '订单利润'],
index=['华东大区', '城市'],
columns=['销售渠道'],
aggfunc={'销售额': 'sum', '订单利润': 'mean'},
fill_value=0,
margins=True,
margins_name='全国总计'
)
pivot_table.to_excel(output_file)
print("多维交叉透视报表构建完毕。")
generate_pivot_report('./raw_orders.xlsx', './pivot_summary.xlsx')
三、办公自动化脚本的健壮生命周期
批量处理脚本一旦涉及文件写入,如果缺乏防御性设计,很容易因为个别异常文件损坏导致全局崩溃,甚至直接覆盖原始业务凭证。生产环境下的自动化执行,必须严格遵循标准化管道流程。
四、PDF 高效自动化实操脚本(16 - 30)
在处理 PDF 时,推荐使用现代化且活跃维护的 pypdf(注:老旧的 PyPDF2 现已统一回归为 pypdf)配合 pdfplumber。安装命令:pip install pypdf pdfplumber reportlab。
脚本 16:批量无损合并多个 PDF 文档
应用场景:需要将多个单页合同、附件扫描件或按章节排版的说明书合并为一个完整的提交件。
import os
from pypdf import PdfMerger
def merge_pdfs_in_order(pdf_list, output_path):
merger = PdfMerger()
for pdf in pdf_list:
if os.path.exists(pdf):
merger.append(pdf)
print(f"已装载:{pdf}")
merger.write(output_path)
merger.close()
print(f"合并完成,生成目标文件:{output_path}")
file_queue = ['./doc_cover.pdf', './doc_body.pdf', './doc_appendix.pdf']
merge_pdfs_in_order(file_queue, './full_contract.pdf')
脚本 17:按页码范围或步长精准拆分 PDF
应用场景:从厚达数百页的行业研报中提取第 15 到第 30 页核心章节,或单页拆分便于审批分发。
from pypdf import PdfReader, PdfWriter
def extract_pdf_pages(source_pdf, start_page, end_page, output_pdf):
# start_page 与 end_page 为自然数页码(从 1 开始)
reader = PdfReader(source_pdf)
writer = PdfWriter()
total_pages = len(reader.pages)
for p_idx in range(start_page - 1, min(end_page, total_pages)):
writer.add_page(reader.pages[p_idx])
with open(output_pdf, 'wb') as f:
writer.write(f)
print(f"成功截取页码范围 {start_page}-{end_page} 至 {output_pdf}")
extract_pdf_pages('./annual_report.pdf', 15, 25, './financial_section.pdf')
脚本 18:提取 PDF 纯文本并保持自然段落顺序
应用场景:快速提取文字版论文、规章制度或公文内容,保存为纯文本 TXT 进行词频统计或检索归档。
from pypdf import PdfReader
def extract_clean_text(pdf_path, txt_output):
reader = PdfReader(pdf_path)
all_text = []
for i, page in enumerate(reader.pages):
page_text = page.extract_text() or ''
all_text.append(f"--- Page {i + 1} ---\n{page_text}\n")
with open(txt_output, 'w', encoding='utf-8') as f:
f.write("\n".join(all_text))
print(f"文本抓取完成,共提取 {len(reader.pages)} 页。")
extract_clean_text('./policy_document.pdf', './policy_text.txt')
脚本 19:高精度提取 PDF 内嵌表格并转存为 Excel
应用场景:供应商发来的账单、财务报表是 PDF 格式,需要将其中的二维表格完美还原为可计算的 Excel。
import pdfplumber
import pandas as pd
def extract_tables_to_excel(pdf_path, excel_output):
all_tables = []
with pdfplumber.open(pdf_path) as pdf:
for p_idx, page in enumerate(pdf.pages):
tables = page.extract_tables()
for t_idx, table in enumerate(tables):
if table and len(table) > 1:
df = pd.DataFrame(table[1:], columns=table[0])
all_tables.append((f"P{p_idx + 1}_T{t_idx + 1}", df))
if all_tables:
with pd.ExcelWriter(excel_output, engine='openpyxl') as writer:
for sheet_name, df in all_tables:
df.to_excel(writer, sheet_name=sheet_name[:30], index=False)
print(f"成功抽离 {len(all_tables)} 张表格并写入 Excel。")
extract_tables_to_excel('./supplier_invoice.pdf', './extracted_tables.xlsx')
脚本 20:批量为 PDF 文档添加半透明倾斜文字水印
应用场景:需要向下分发机密文件或商业计划书,自动压上带有经办人姓名与防扩散提示的水印层。
import io
from pypdf import PdfReader, PdfWriter
from reportlab.pdfgen import canvas
from reportlab.lib.colors import Color
def create_watermark(text):
packet = io.BytesIO()
can = canvas.Canvas(packet)
can.setFont("Helvetica-Bold", 36)
# 半透明墨灰灰色 (R, G, B, Alpha)
can.setFillColor(Color(0.5, 0.5, 0.5, alpha=0.25))
can.translate(300, 400)
can.rotate(45)
can.drawCentredString(0, 0, text)
can.save()
packet.seek(0)
return PdfReader(packet).pages[0]
def stamp_watermark(input_pdf, output_pdf, watermark_text):
watermark_page = create_watermark(watermark_text)
reader = PdfReader(input_pdf)
writer = PdfWriter()
for page in reader.pages:
# 将水印层合并覆盖在正文上方
page.merge_page(watermark_page)
writer.add_page(page)
with open(output_pdf, 'wb') as f:
writer.write(f)
print("水印批量压印完成。")
stamp_watermark('./business_plan.pdf', './business_plan_watermarked.pdf', 'CONFIDENTIAL - FOR INTERNAL USE')
脚本 21:批量为 PDF 设置密码保护与权限限制
应用场景:对含有薪酬、核心技术的 PDF 文件实施强加密(支持 128/256 位 AES),限制打印与文本复制。
from pypdf import PdfReader, PdfWriter
def encrypt_pdf(source_pdf, target_pdf, user_password, owner_password):
reader = PdfReader(source_pdf)
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
# user_password 用于普通打开查看,owner_password 用于管理与解除限制
writer.encrypt(
user_password=user_password,
owner_password=owner_password,
use_128bit=True
)
with open(target_pdf, 'wb') as f:
writer.write(f)
print(f"已加密导出:{target_pdf}")
encrypt_pdf('./salary_sheet.pdf', './salary_sheet_locked.pdf', 'User123', 'AdminMaster999')
脚本 22:批量解密已知密码的 PDF 文件
应用场景:每月批量下载银行电子回单或发票,已知统一密码(如纳税人识别号后6位),需解密后入库归档。
from pypdf import PdfReader, PdfWriter
def decrypt_pdf(encrypted_pdf, decrypted_output, password):
reader = PdfReader(encrypted_pdf)
if reader.is_encrypted:
success = reader.decrypt(password)
if not success:
raise ValueError("提供的解密密码不正确!")
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
with open(decrypted_output, 'wb') as f:
writer.write(f)
print("文档已成功解密。")
decrypt_pdf('./monthly_statement.pdf', './statement_unlocked.pdf', '987654')
脚本 23:检测并批量修正旋转方向错误的页面
应用场景:扫描仪扫描文档时常出现部分横向发票倒置或 90 度偏转,需要批量归位到正常阅读视角。
from pypdf import PdfReader, PdfWriter
def rotate_pdf_pages(source_pdf, output_pdf, rotation_degrees=90):
reader = PdfReader(source_pdf)
writer = PdfWriter()
for page in reader.pages:
# 旋转必须是 90 的整数倍 (90, 180, 270)
page.rotate(rotation_degrees)
writer.add_page(page)
with open(output_pdf, 'wb') as f:
writer.write(f)
print(f"所有页面已顺时针旋转 {rotation_degrees} 度。")
rotate_pdf_pages('./sideways_scan.pdf', './upright_scan.pdf', 90)
脚本 24:批量抽取 PDF 内嵌的全部原始高分辨率图片
应用场景:从产品手册或图集 PDF 中将插入的全部高清产品照片以独立 JPEG/PNG 形式完整抓取出来。
import os
from pypdf import PdfReader
def extract_images_from_pdf(pdf_path, output_dir):
os.makedirs(output_dir, exist_ok=True)
reader = PdfReader(pdf_path)
count = 0
for p_idx, page in enumerate(reader.pages):
for img_name, img_file in page.images.items():
ext = img_name.split('.')[-1]
save_name = f"page_{p_idx + 1}_{count}.{ext}"
with open(os.path.join(output_dir, save_name), 'wb') as f:
f.write(img_file.data)
count += 1
print(f"成功提取并保存 {count} 张图片到 {output_dir}")
extract_images_from_pdf('./product_catalog.pdf', './extracted_photos')
脚本 25:自动裁剪去除 PDF 页面白边与冗余页边距
应用场景:适配电子墨水屏阅读器或打印裁切,统一将页面周围多余的空白边距去除。
from pypdf import PdfReader, PdfWriter
def crop_pdf_margins(input_pdf, output_pdf, margin_pt=36):
reader = PdfReader(input_pdf)
writer = PdfWriter()
for page in reader.pages:
# 获取当前页的边界框 (MediaBox)
box = page.mediabox
page.cropbox.lower_left = (box.left + margin_pt, box.bottom + margin_pt)
page.cropbox.upper_right = (box.right - margin_pt, box.top - margin_pt)
writer.add_page(page)
with open(output_pdf, 'wb') as f:
writer.write(f)
print("白边裁剪完成。")
crop_pdf_margins('./raw_paper.pdf', './cropped_paper.pdf', margin_pt=30)
脚本 26:读取并导出 PDF 大纲书签为 Markdown 目录
应用场景:需要快速理清长篇技术白皮书、行业标准的章节大纲并生成导航导图。
from pypdf import PdfReader
def dump_outline_to_markdown(pdf_path, md_output):
reader = PdfReader(pdf_path)
lines = []
def parse_outlines(outline_list, depth=0):
for item in outline_list:
if isinstance(item, list):
parse_outlines(item, depth + 1)
else:
indent = " " * depth
page_num = reader.get_destination_page_number(item) + 1
lines.append(f"{indent}- {item.title} (P.{page_num})")
if reader.outline:
parse_outlines(reader.outline)
with open(md_output, 'w', encoding='utf-8') as f:
f.write("\n".join(lines))
print("目录结构导出完成。")
else:
print("该 PDF 未包含内嵌大纲书签。")
dump_outline_to_markdown('./technical_spec.pdf', './toc.md')
脚本 27:为长篇 PDF 自动重构并注入层级书签导航
应用场景:合并生成的长文档没有目录跳转项,通过代码直接向 PDF 中插入可点击的导航书签。
from pypdf import PdfReader, PdfWriter
def inject_bookmarks(source_pdf, target_pdf, bookmark_specs):
reader = PdfReader(source_pdf)
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
for title, p_num in bookmark_specs:
# 注意:add_outline_item 的页码参数为 0-indexed
writer.add_outline_item(title, p_num - 1)
with open(target_pdf, 'wb') as f:
writer.write(f)
print("书签索引注入完成。")
bookmarks = [
("第一章:项目背景与目标", 1),
("第二章:核心业务架构设计", 12),
("第三章:成本与财务分析", 28),
("第四章:风险控制预案", 45)
]
inject_bookmarks('./unindexed_doc.pdf', './indexed_doc.pdf', bookmarks)
脚本 28:PDF 页面重排序与奇偶扫描件交错合并
应用场景:使用无双面扫描功能的进纸器时,通常先扫完全部正面(1, 3, 5...),再翻转扫完全部反面(6, 4, 2...),需要交错还原为正常阅读顺序。
from pypdf import PdfReader, PdfWriter
def interleave_duplex_scans(odd_pdf, even_pdf, output_pdf):
reader_odd = PdfReader(odd_pdf)
reader_even = PdfReader(even_pdf)
writer = PdfWriter()
odd_pages = reader_odd.pages
# 反面扫描件通常是倒序的,先反转恢复
even_pages = list(reversed(reader_even.pages))
max_len = max(len(odd_pages), len(even_pages))
for i in range(max_len):
if i < len(odd_pages):
writer.add_page(odd_pages[i])
if i < len(even_pages):
writer.add_page(even_pages[i])
with open(output_pdf, 'wb') as f:
writer.write(f)
print("双面扫描交错归位还原成功。")
interleave_duplex_scans('./scanned_odd.pdf', './scanned_even.pdf', './final_assembled.pdf')
脚本 29:全量比对两份 PDF 文档的文本内容差异
应用场景:商务合同审校时,快速对比最终盖章版与初始草拟版之间的文字增删与修改。
import difflib
from pypdf import PdfReader
def compare_pdf_text_diff(pdf_v1, pdf_v2, diff_report_txt):
def get_text(pdf):
r = PdfReader(pdf)
return "\n".join([p.extract_text() or '' for p in r.pages]).splitlines()
lines1 = get_text(pdf_v1)
lines2 = get_text(pdf_v2)
diff = difflib.unified_diff(
lines1, lines2,
fromfile='V1_Original',
tofile='V2_Modified',
lineterm=''
)
diff_content = list(diff)
with open(diff_report_txt, 'w', encoding='utf-8') as f:
f.write("\n".join(diff_content))
print(f"差异文本比对完成,发现 {len(diff_content)} 行变动记录。")
compare_pdf_text_diff('./contract_v1.pdf', './contract_v2.pdf', './contract_diff.txt')
脚本 30:将 Excel 报表批量排版并转存为打印级 PDF
应用场景:报表自动计算并美化完毕后,需要一键生成防篡改、格式固定的 PDF 文件直接提交归档。
import win32com.client # 适用于 Windows 环境 Office 驱动
import os
def export_excel_to_pdf_win(excel_abs_path, pdf_abs_path):
excel = win32com.client.DispatchEx("Excel.Application")
excel.Visible = False
excel.DisplayAlerts = False
try:
wb = excel.Workbooks.Open(excel_abs_path)
# 0 代表导出为 PDF 格式
wb.ExportAsFixedFormat(0, pdf_abs_path)
wb.Close(False)
print("Excel 渲染为高保真 PDF 成功。")
finally:
excel.Quit()
# 示例(需绝对路径):export_excel_to_pdf_win(r'C:\data\report.xlsx', r'C:\data\report.pdf')
五、PDF 表格抽取与结构化流转核心机制
在 30 个脚本中,脚本 19(PDF 表格提取)属于复杂度最高、最容易因文档结构变动而失效的环节。理解其背后的底层几何拾取原理,能极大提升定制调试效率。
六、生产环境常见混淆辨析与避坑指南
在推行自动化脚本的过程中,团队常有一些看似合理但实际暗藏隐患的看法。对这些认知进行客观看待与修正,是脚本稳定运行的重要前提。
辨析与修正: 这种说法在“单纯做数据统计与清洗”时是完全成立的,因为 pandas 的矢量速度极快。但一旦进入“业务交付报表”阶段,pandas 的
to_excel 会重置单元格背景色、公式、字体以及冻结窗格。如果需要保留公司现成的美观模板并精准写入数据,必须借助 openpyxl 的对象操作。合理的做法是:数据聚合用 pandas,格式定型与美化用 openpyxl。
辨析与修正: 很多用户在测试扫描件或图片合成的 PDF 时,发现
extract_text() 输出全为空,误以为代码写错了。实际上,pypdf 和 pdfplumber 只能提取由矢量字体渲染的“原生电子版 PDF”。对于扫描纸质合同生成的“图片型 PDF”,本质上每个页面都是一张位图,没有内嵌字符编码,必须先串接 OCR 引擎(如 Tesseract、PaddleOCR)识别文字后,脚本才能处理。
辨析与修正: 针对多个独立的 Excel 文件,多进程(
multiprocessing)确实能有效利用多核 CPU。但如果是往“同一个 Excel 文件的不同 Sheet”并发写入,由于 openpyxl 并不是线程安全的,多线程同时保存同一个文件会导致 ZIP 结构损坏。因此,并发仅用于多文件的各自读写,同一工作簿必须串行合并写入。
七、脚本决策树与自动化工程选型总结
为了让读者在面对具体需求时能够迅速在 30 个脚本中准确定位,下图将全部操作按任务输入与目标形态组织为清晰的选型路径。
总结
掌握 Python 办公自动化的关键不在于记忆库的所有 API,而在于建立针对文件对象、数据流与版面样式的结构化思维。通过本文整理的 30 个生产级脚本,读者可以根据具体业务场景灵活组合与二次扩展,将原本耗时数天的机械劳动转化为数秒内自动完成的稳健管道,真正让技术服务于效率提升。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













