办公自动化必备:30个高效处理Excel和PDF的Python脚本

慢慢来
慢慢来
发布时间:2026-10-24| 5人浏览过
原创

在日常办公场景中,处理繁杂的 Excel 表格与海量的 PDF 文档往往占据了知识工作者大量的时间。无论是数十张表结构一致的数据合并、多维度拆分导出,还是数十份合同 PDF 的批量加水印、密码解密与表格提取,人工手动点击不仅容易出错,更难以满足严苛的时效要求。本文直接整理并讲解 30 个面向生产实际的 Python 自动化脚本,分为 Excel 处理篇(15 个)与 PDF 处理篇(15 个),不讲泛泛的理论,聚焦即拷即用、稳定容错的工程化实现。

一、自动化技术栈架构与库选型原则

在动手编写脚本前,首要任务是明确工具库的分工与边界。许多初学者在处理 Excel 时盲目混用 pandas 和 openpyxl,在处理 PDF 时分不清 pypdf 与 pdfplumber 的本质差异,导致脚本运行缓慢或格式损坏。合理的选型应当依据“计算密集”与“排版密集”进行严格划分。

办公自动化必备:30个高效处理Excel和PDF的Python脚本
图1:Python 办公自动化核心生态技术分工与能力匹配模型

二、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')

三、办公自动化脚本的健壮生命周期

批量处理脚本一旦涉及文件写入,如果缺乏防御性设计,很容易因为个别异常文件损坏导致全局崩溃,甚至直接覆盖原始业务凭证。生产环境下的自动化执行,必须严格遵循标准化管道流程。

办公自动化必备:30个高效处理Excel和PDF的Python脚本
图2:稳健型办公脚本处理生命周期标准流程图

四、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 表格提取)属于复杂度最高、最容易因文档结构变动而失效的环节。理解其背后的底层几何拾取原理,能极大提升定制调试效率。

办公自动化必备:30个高效处理Excel和PDF的Python脚本
图3:PDF 二维表格视觉拓扑重组与特征提取原理

六、生产环境常见混淆辨析与避坑指南

在推行自动化脚本的过程中,团队常有一些看似合理但实际暗藏隐患的看法。对这些认知进行客观看待与修正,是脚本稳定运行的重要前提。

常见误区一:“处理 Excel 只要用 pandas 就够了,不需要学 openpyxl”
辨析与修正: 这种说法在“单纯做数据统计与清洗”时是完全成立的,因为 pandas 的矢量速度极快。但一旦进入“业务交付报表”阶段,pandas 的 to_excel 会重置单元格背景色、公式、字体以及冻结窗格。如果需要保留公司现成的美观模板并精准写入数据,必须借助 openpyxl 的对象操作。合理的做法是:数据聚合用 pandas,格式定型与美化用 openpyxl。
常见误区二:“只要是 PDF,脚本就能直接提取出清晰的文字”
辨析与修正: 很多用户在测试扫描件或图片合成的 PDF 时,发现 extract_text() 输出全为空,误以为代码写错了。实际上,pypdf 和 pdfplumber 只能提取由矢量字体渲染的“原生电子版 PDF”。对于扫描纸质合同生成的“图片型 PDF”,本质上每个页面都是一张位图,没有内嵌字符编码,必须先串接 OCR 引擎(如 Tesseract、PaddleOCR)识别文字后,脚本才能处理。
常见误区三:“多线程并行处理能成倍提升 Excel 脚本速度”
辨析与修正: 针对多个独立的 Excel 文件,多进程(multiprocessing)确实能有效利用多核 CPU。但如果是往“同一个 Excel 文件的不同 Sheet”并发写入,由于 openpyxl 并不是线程安全的,多线程同时保存同一个文件会导致 ZIP 结构损坏。因此,并发仅用于多文件的各自读写,同一工作簿必须串行合并写入。

七、脚本决策树与自动化工程选型总结

为了让读者在面对具体需求时能够迅速在 30 个脚本中准确定位,下图将全部操作按任务输入与目标形态组织为清晰的选型路径。

办公自动化必备:30个高效处理Excel和PDF的Python脚本
图4:30个高效办公自动化脚本技术选型综合决策模型

总结

掌握 Python 办公自动化的关键不在于记忆库的所有 API,而在于建立针对文件对象、数据流与版面样式的结构化思维。通过本文整理的 30 个生产级脚本,读者可以根据具体业务场景灵活组合与二次扩展,将原本耗时数天的机械劳动转化为数秒内自动完成的稳健管道,真正让技术服务于效率提升。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。