Python 自動化辦公室:10 個讓你提早下班的腳本

管管
教學文章 技術分享

每天花 2 小時做重複性工作?讓 Python 幫你做,你去喝咖啡。

這篇文章收集了 10 個實用的 Python 自動化腳本,都是真實辦公室場景會用到的。程式碼可以直接複製使用,也可以根據需求修改。

準備工作

確保你已經安裝 Python 3,然後安裝這些常用套件:

pip install pandas openpyxl python-docx PyPDF2 requests beautifulsoup4 schedule

1. Excel 報表自動合併

每個月要把 30 個分店的 Excel 報表合併成一份?

import pandas as pd
import os
from pathlib import Path

def merge_excel_files(folder_path, output_file):
    """合併資料夾內所有 Excel 檔案"""
    all_data = []
    
    for file in Path(folder_path).glob("*.xlsx"):
        df = pd.read_excel(file)
        df["來源檔案"] = file.name  # 標記資料來源
        all_data.append(df)
    
    merged = pd.concat(all_data, ignore_index=True)
    merged.to_excel(output_file, index=False)
    print(f"已合併 {len(all_data)} 個檔案到 {output_file}")

# 使用方式
merge_excel_files("./月報表/", "合併報表.xlsx")

2. 批次重新命名檔案

幾百個檔案要統一命名格式?

import os
from pathlib import Path
from datetime import datetime

def rename_files(folder, pattern):
    """批次重新命名檔案
    pattern 範例: "報告_{date}_{num:03d}"
    """
    folder = Path(folder)
    files = sorted(folder.glob("*.*"))
    
    today = datetime.now().strftime("%Y%m%d")
    
    for i, file in enumerate(files, 1):
        ext = file.suffix
        new_name = pattern.format(date=today, num=i) + ext
        new_path = folder / new_name
        file.rename(new_path)
        print(f"{file.name} -> {new_name}")

# 使用方式
rename_files("./照片/", "活動照片_{date}_{num:03d}")

3. 自動發送 Email

每天要發固定格式的報告信?

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

def send_email(to_email, subject, body, attachment=None):
    """發送 Email(含附件)"""
    # Gmail 設定(需要應用程式密碼)
    smtp_server = "smtp.gmail.com"
    smtp_port = 587
    sender_email = "your@gmail.com"
    password = "your-app-password"  # 用環境變數更安全
    
    msg = MIMEMultipart()
    msg["From"] = sender_email
    msg["To"] = to_email
    msg["Subject"] = subject
    msg.attach(MIMEText(body, "plain"))
    
    # 加入附件
    if attachment:
        with open(attachment, "rb") as f:
            part = MIMEBase("application", "octet-stream")
            part.set_payload(f.read())
        encoders.encode_base64(part)
        part.add_header("Content-Disposition", f"attachment; filename={attachment}")
        msg.attach(part)
    
    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.starttls()
        server.login(sender_email, password)
        server.sendmail(sender_email, to_email, msg.as_string())
    
    print(f"Email 已發送至 {to_email}")

# 使用方式
send_email(
    "boss@company.com",
    "每日報表 - 2024/01/15",
    "附件為今日銷售報表,請查收。",
    "daily_report.xlsx"
)

4. PDF 合併與拆分

from PyPDF2 import PdfMerger, PdfReader, PdfWriter

def merge_pdfs(pdf_list, output):
    """合併多個 PDF"""
    merger = PdfMerger()
    for pdf in pdf_list:
        merger.append(pdf)
    merger.write(output)
    merger.close()
    print(f"已合併 {len(pdf_list)} 個 PDF 到 {output}")

def split_pdf(input_pdf, output_folder):
    """將 PDF 拆分成單頁"""
    reader = PdfReader(input_pdf)
    for i, page in enumerate(reader.pages):
        writer = PdfWriter()
        writer.add_page(page)
        output_path = f"{output_folder}/page_{i+1}.pdf"
        with open(output_path, "wb") as f:
            writer.write(f)
    print(f"已拆分成 {len(reader.pages)} 個檔案")

# 使用方式
merge_pdfs(["doc1.pdf", "doc2.pdf", "doc3.pdf"], "merged.pdf")
split_pdf("long_document.pdf", "./pages/")

5. 網頁資料爬取

每天要去網站手動複製資料?

import requests
from bs4 import BeautifulSoup
import pandas as pd

def scrape_table(url):
    """爬取網頁上的表格資料"""
    response = requests.get(url)
    soup = BeautifulSoup(response.text, "html.parser")
    
    # 找到所有表格
    tables = soup.find_all("table")
    
    all_data = []
    for table in tables:
        df = pd.read_html(str(table))[0]
        all_data.append(df)
    
    return all_data

def scrape_links(url):
    """爬取網頁上所有連結"""
    response = requests.get(url)
    soup = BeautifulSoup(response.text, "html.parser")
    
    links = []
    for a in soup.find_all("a", href=True):
        links.append({
            "text": a.text.strip(),
            "url": a["href"]
        })
    
    return pd.DataFrame(links)

# 使用方式
tables = scrape_table("https://example.com/data")
tables[0].to_excel("scraped_data.xlsx")

6. 自動備份檔案

import shutil
from datetime import datetime
from pathlib import Path

def backup_folder(source, backup_root):
    """備份整個資料夾(含時間戳記)"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    source_name = Path(source).name
    backup_path = Path(backup_root) / f"{source_name}_backup_{timestamp}"
    
    shutil.copytree(source, backup_path)
    print(f"已備份到 {backup_path}")
    return backup_path

def cleanup_old_backups(backup_root, keep_count=5):
    """只保留最新的 N 個備份"""
    backups = sorted(Path(backup_root).glob("*_backup_*"), reverse=True)
    
    for old_backup in backups[keep_count:]:
        shutil.rmtree(old_backup)
        print(f"已刪除舊備份 {old_backup}")

# 使用方式
backup_folder("./重要專案/", "./備份/")
cleanup_old_backups("./備份/", keep_count=5)

7. Excel 資料清理

import pandas as pd

def clean_excel(input_file, output_file):
    """清理 Excel 資料"""
    df = pd.read_excel(input_file)
    
    # 移除空白列
    df = df.dropna(how="all")
    
    # 移除重複
    df = df.drop_duplicates()
    
    # 去除文字前後空白
    for col in df.select_dtypes(include=["object"]).columns:
        df[col] = df[col].str.strip()
    
    # 統一日期格式
    for col in df.columns:
        if "日期" in col or "date" in col.lower():
            df[col] = pd.to_datetime(df[col]).dt.strftime("%Y-%m-%d")
    
    # 填補空值
    df = df.fillna("")
    
    df.to_excel(output_file, index=False)
    print(f"清理完成: {len(df)} 筆資料")
    return df

# 使用方式
clean_excel("messy_data.xlsx", "clean_data.xlsx")

8. 定時執行任務

import schedule
import time

def job():
    print("執行定時任務...")
    # 在這裡放你要定時執行的程式

# 設定排程
schedule.every().day.at("09:00").do(job)  # 每天 9:00
schedule.every().monday.at("10:00").do(job)  # 每週一 10:00
schedule.every(30).minutes.do(job)  # 每 30 分鐘

# 持續執行
while True:
    schedule.run_pending()
    time.sleep(60)

9. Word 文件批次處理

from docx import Document
from pathlib import Path

def replace_in_word(template, replacements, output):
    """Word 文件批次取代"""
    doc = Document(template)
    
    for para in doc.paragraphs:
        for old, new in replacements.items():
            if old in para.text:
                para.text = para.text.replace(old, new)
    
    # 也處理表格內的文字
    for table in doc.tables:
        for row in table.rows:
            for cell in row.cells:
                for old, new in replacements.items():
                    if old in cell.text:
                        cell.text = cell.text.replace(old, new)
    
    doc.save(output)
    print(f"已生成 {output}")

# 使用方式:批次生成合約
clients = [
    {"{{姓名}}": "王小明", "{{公司}}": "ABC 公司", "{{日期}}": "2024/01/15"},
    {"{{姓名}}": "李小華", "{{公司}}": "XYZ 公司", "{{日期}}": "2024/01/15"},
]

for i, client in enumerate(clients):
    replace_in_word("合約模板.docx", client, f"合約_{i+1}.docx")

10. 監控資料夾變化

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import time

class FileHandler(FileSystemEventHandler):
    def on_created(self, event):
        if not event.is_directory:
            print(f"新檔案: {event.src_path}")
            # 在這裡處理新檔案
            # 例如:自動移動、重新命名、發送通知
    
    def on_modified(self, event):
        if not event.is_directory:
            print(f"檔案修改: {event.src_path}")

def watch_folder(path):
    """監控資料夾變化"""
    observer = Observer()
    observer.schedule(FileHandler(), path, recursive=True)
    observer.start()
    
    print(f"開始監控 {path}")
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

# 使用方式
watch_folder("./incoming/")

進階技巧

1. 用 .env 管理敏感資訊

# .env 檔案
EMAIL_PASSWORD=your-password

# Python
from dotenv import load_dotenv
import os

load_dotenv()
password = os.getenv("EMAIL_PASSWORD")

2. 加上錯誤處理

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def safe_task():
    try:
        # 你的程式碼
        pass
    except Exception as e:
        logger.error(f"執行失敗: {e}")

3. 打包成執行檔

pip install pyinstaller
pyinstaller --onefile your_script.py

這樣不用 Python 環境也能執行。

結語

自動化的精髓是:做一次,用一輩子

每次你發現自己在做重複性的工作,就問自己:「這能不能寫成腳本?」答案通常是可以的。

從今天開始,把這些腳本加到你的工具箱裡,讓 Python 幫你做那些無聊的事。