Python自動化辦公之Excel、Word和PDF操作指南
1. 引言
在現(xiàn)代辦公環(huán)境中,我們每天都要處理大量的文檔工作。根據(jù)統(tǒng)計,知識工作者平均每周花費8-10小時在重復性的文檔處理任務上,這些時間完全可以通過自動化來節(jié)省。無論是數(shù)據(jù)報表生成、合同文檔處理,還是批量PDF操作,手動完成這些任務既耗時又容易出錯。
Python作為一門功能強大的編程語言,提供了豐富的庫來簡化辦公文檔的處理任務。通過Python自動化,我們能夠:
- 提高工作效率:自動化重復性任務,釋放人力資源
- 減少人為錯誤:標準化處理流程,確保結(jié)果一致性
- 實現(xiàn)批量處理:一次性處理成百上千個文檔
- 集成工作流:將不同格式的文檔處理串聯(lián)起來
Python辦公自動化的優(yōu)勢

2. 環(huán)境準備和基礎(chǔ)庫介紹
2.1 安裝必要的庫
在開始之前,我們需要安裝以下Python庫:
# Excel處理 pip install openpyxl pip install xlrd pip install xlwt pip install xlsxwriter # Word處理 pip install python-docx pip install docx2txt # PDF處理 pip install PyPDF2 pip install pdfplumber pip install reportlab pip install fpdf # 其他工具 pip install pandas pip install numpy pip install pillow
2.2 各庫的主要功能
# 導入所有需要的庫 import pandas as pd import numpy as np from openpyxl import Workbook, load_workbook from openpyxl.styles import Font, PatternFill, Alignment, Border, Side from openpyxl.chart import BarChart, PieChart, LineChart, Reference from docx import Document from docx.shared import Inches, Pt, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_TABLE_ALIGNMENT import PyPDF2 import pdfplumber from reportlab.lib.pagesizes import letter, A4 from reportlab.pdfgen import canvas from reportlab.lib.styles import getSampleStyleSheet from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph from reportlab.lib import colors import os from datetime import datetime import logging
3. Excel自動化處理
3.1 基礎(chǔ)Excel操作
讓我們從最基本的Excel文件創(chuàng)建和讀寫開始:
class ExcelAutomator:
"""
Excel自動化處理器
提供完整的Excel文件操作功能
"""
def __init__(self):
"""初始化Excel處理器"""
self.setup_logging()
def setup_logging(self):
"""設(shè)置日志記錄"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('excel_automation.log', encoding='utf-8'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
def create_workbook(self, filepath: str, data: dict = None) -> bool:
"""
創(chuàng)建新的Excel工作簿
Args:
filepath: 文件保存路徑
data: 初始數(shù)據(jù)字典 {sheet_name: [[row1], [row2], ...]}
Returns:
bool: 創(chuàng)建是否成功
"""
try:
wb = Workbook()
# 刪除默認創(chuàng)建的空工作表
wb.remove(wb.active)
# 添加數(shù)據(jù)工作表
if data:
for sheet_name, sheet_data in data.items():
ws = wb.create_sheet(title=sheet_name)
for row in sheet_data:
ws.append(row)
else:
# 如果沒有提供數(shù)據(jù),創(chuàng)建一個空的工作表
wb.create_sheet(title="Sheet1")
# 保存工作簿
wb.save(filepath)
self.logger.info(f"成功創(chuàng)建Excel文件: {filepath}")
return True
except Exception as e:
self.logger.error(f"創(chuàng)建Excel文件失敗: {str(e)}")
return False
def read_excel(self, filepath: str, sheet_name: str = None) -> pd.DataFrame:
"""
讀取Excel文件為DataFrame
Args:
filepath: Excel文件路徑
sheet_name: 工作表名稱,如果為None則讀取第一個工作表
Returns:
pd.DataFrame: 讀取的數(shù)據(jù)
"""
try:
if sheet_name:
df = pd.read_excel(filepath, sheet_name=sheet_name)
else:
df = pd.read_excel(filepath)
self.logger.info(f"成功讀取Excel文件: {filepath}")
return df
except Exception as e:
self.logger.error(f"讀取Excel文件失敗: {str(e)}")
return pd.DataFrame()
def write_excel(self, df: pd.DataFrame, filepath: str,
sheet_name: str = 'Sheet1', index: bool = False) -> bool:
"""
將DataFrame寫入Excel文件
Args:
df: 要寫入的DataFrame
filepath: 文件保存路徑
sheet_name: 工作表名稱
index: 是否包含索引
Returns:
bool: 寫入是否成功
"""
try:
# 如果文件已存在,以追加模式寫入
if os.path.exists(filepath):
with pd.ExcelWriter(filepath, mode='a', if_sheet_exists='replace') as writer:
df.to_excel(writer, sheet_name=sheet_name, index=index)
else:
df.to_excel(filepath, sheet_name=sheet_name, index=index)
self.logger.info(f"成功寫入Excel文件: {filepath}")
return True
except Exception as e:
self.logger.error(f"寫入Excel文件失敗: {str(e)}")
return False
def apply_formatting(self, filepath: str, formatting_rules: dict) -> bool:
"""
應用格式設(shè)置到Excel文件
Args:
filepath: Excel文件路徑
formatting_rules: 格式規(guī)則字典
Returns:
bool: 格式應用是否成功
"""
try:
wb = load_workbook(filepath)
for sheet_name, rules in formatting_rules.items():
if sheet_name in wb.sheetnames:
ws = wb[sheet_name]
# 應用單元格格式
if 'cell_formats' in rules:
for cell_ref, format_config in rules['cell_formats'].items():
cell = ws[cell_ref]
# 字體設(shè)置
if 'font' in format_config:
font_config = format_config['font']
cell.font = Font(
name=font_config.get('name', 'Arial'),
size=font_config.get('size', 11),
bold=font_config.get('bold', False),
italic=font_config.get('italic', False),
color=font_config.get('color', '000000')
)
# 填充顏色
if 'fill' in format_config:
fill_config = format_config['fill']
cell.fill = PatternFill(
start_color=fill_config.get('color', 'FFFFFF'),
fill_type=fill_config.get('type', 'solid')
)
# 對齊方式
if 'alignment' in format_config:
align_config = format_config['alignment']
cell.alignment = Alignment(
horizontal=align_config.get('horizontal', 'general'),
vertical=align_config.get('vertical', 'center')
)
# 設(shè)置列寬
if 'column_widths' in rules:
for col, width in rules['column_widths'].items():
ws.column_dimensions[col].width = width
# 設(shè)置行高
if 'row_heights' in rules:
for row, height in rules['row_heights'].items():
ws.row_dimensions[row].height = height
wb.save(filepath)
self.logger.info(f"成功應用格式設(shè)置: {filepath}")
return True
except Exception as e:
self.logger.error(f"應用格式設(shè)置失敗: {str(e)}")
return False
def create_chart(self, filepath: str, chart_config: dict) -> bool:
"""
在Excel中創(chuàng)建圖表
Args:
filepath: Excel文件路徑
chart_config: 圖表配置字典
Returns:
bool: 圖表創(chuàng)建是否成功
"""
try:
wb = load_workbook(filepath)
ws = wb[chart_config['sheet_name']]
# 創(chuàng)建圖表對象
if chart_config['chart_type'] == 'bar':
chart = BarChart()
elif chart_config['chart_type'] == 'pie':
chart = PieChart()
elif chart_config['chart_type'] == 'line':
chart = LineChart()
else:
chart = BarChart()
# 設(shè)置圖表數(shù)據(jù)
data = Reference(ws,
min_col=chart_config['data_start_col'],
min_row=chart_config['data_start_row'],
max_col=chart_config['data_end_col'],
max_row=chart_config['data_end_row'])
categories = Reference(ws,
min_col=chart_config['categories_col'],
min_row=chart_config['categories_start_row'],
max_row=chart_config['categories_end_row'])
chart.add_data(data, titles_from_data=True)
chart.set_categories(categories)
# 設(shè)置圖表標題和樣式
chart.title = chart_config.get('title', 'Chart')
chart.style = chart_config.get('style', 10)
# 將圖表添加到工作表
ws.add_chart(chart, chart_config['position'])
wb.save(filepath)
self.logger.info(f"成功創(chuàng)建圖表: {chart_config['chart_type']}")
return True
except Exception as e:
self.logger.error(f"創(chuàng)建圖表失敗: {str(e)}")
return False
# 使用示例
def demo_excel_automation():
"""演示Excel自動化功能"""
automator = ExcelAutomator()
# 創(chuàng)建示例數(shù)據(jù)
sample_data = {
'銷售數(shù)據(jù)': [
['產(chǎn)品', '一月', '二月', '三月', '總計'],
['產(chǎn)品A', 1000, 1200, 1500, '=SUM(B2:D2)'],
['產(chǎn)品B', 800, 900, 1100, '=SUM(B3:D3)'],
['產(chǎn)品C', 1200, 1300, 1400, '=SUM(B4:D4)'],
['產(chǎn)品D', 900, 1000, 1200, '=SUM(B5:D5)']
],
'客戶信息': [
['客戶ID', '姓名', '郵箱', '電話'],
[1, '張三', 'zhangsan@example.com', '13800138001'],
[2, '李四', 'lisi@example.com', '13800138002'],
[3, '王五', 'wangwu@example.com', '13800138003']
]
}
# 創(chuàng)建Excel文件
filepath = 'demo_excel.xlsx'
print("=== 創(chuàng)建Excel文件 ===")
automator.create_workbook(filepath, sample_data)
# 應用格式設(shè)置
print("\n=== 應用格式設(shè)置 ===")
formatting_rules = {
'銷售數(shù)據(jù)': {
'cell_formats': {
'A1:E1': {
'font': {'bold': True, 'size': 12, 'color': 'FFFFFF'},
'fill': {'color': '366092', 'type': 'solid'},
'alignment': {'horizontal': 'center'}
},
'A2:A5': {
'font': {'bold': True},
'fill': {'color': 'D9E1F2', 'type': 'solid'}
},
'E2:E5': {
'font': {'bold': True, 'color': 'FF0000'},
'fill': {'color': 'FFF2CC', 'type': 'solid'}
}
},
'column_widths': {
'A': 15, 'B': 10, 'C': 10, 'D': 10, 'E': 12
},
'row_heights': {
1: 25
}
}
}
automator.apply_formatting(filepath, formatting_rules)
# 創(chuàng)建圖表
print("\n=== 創(chuàng)建圖表 ===")
chart_config = {
'sheet_name': '銷售數(shù)據(jù)',
'chart_type': 'bar',
'data_start_col': 2,
'data_start_row': 1,
'data_end_col': 4,
'data_end_row': 5,
'categories_col': 1,
'categories_start_row': 2,
'categories_end_row': 5,
'title': '產(chǎn)品銷售圖表',
'position': 'F1'
}
automator.create_chart(filepath, chart_config)
# 讀取數(shù)據(jù)
print("\n=== 讀取Excel數(shù)據(jù) ===")
df = automator.read_excel(filepath, '銷售數(shù)據(jù)')
print("銷售數(shù)據(jù):")
print(df.head())
# 數(shù)據(jù)處理示例
print("\n=== 數(shù)據(jù)處理 ===")
# 計算平均銷售額
numeric_columns = ['一月', '二月', '三月']
df[numeric_columns] = df[numeric_columns].apply(pd.to_numeric, errors='coerce')
monthly_avg = df[numeric_columns].mean()
print("月平均銷售額:")
for month, avg in monthly_avg.items():
print(f" {month}: {avg:.2f}")
return filepath
if __name__ == "__main__":
demo_excel_automation()
3.2 高級Excel功能
class AdvancedExcelAutomator(ExcelAutomator):
"""
高級Excel自動化處理器
擴展基礎(chǔ)功能,提供更復雜的操作
"""
def merge_excel_files(self, filepaths: list, output_path: str,
merge_by: str = 'vertical') -> bool:
"""
合并多個Excel文件
Args:
filepaths: 要合并的文件路徑列表
output_path: 輸出文件路徑
merge_by: 合并方式 - 'vertical'(縱向)或 'horizontal'(橫向)
Returns:
bool: 合并是否成功
"""
try:
all_data = []
for filepath in filepaths:
if os.path.exists(filepath):
# 讀取所有工作表
xl_file = pd.ExcelFile(filepath)
for sheet_name in xl_file.sheet_names:
df = pd.read_excel(filepath, sheet_name=sheet_name)
# 添加來源標識
df['_source_file'] = os.path.basename(filepath)
df['_source_sheet'] = sheet_name
all_data.append(df)
if not all_data:
self.logger.warning("沒有找到可合并的數(shù)據(jù)")
return False
if merge_by == 'vertical':
# 縱向合并
merged_df = pd.concat(all_data, ignore_index=True)
else:
# 橫向合并(需要相同行數(shù))
merged_df = pd.concat(all_data, axis=1)
# 保存合并結(jié)果
merged_df.to_excel(output_path, index=False)
self.logger.info(f"成功合并 {len(filepaths)} 個文件到: {output_path}")
return True
except Exception as e:
self.logger.error(f"合并Excel文件失敗: {str(e)}")
return False
def apply_conditional_formatting(self, filepath: str, rules: list) -> bool:
"""
應用條件格式
Args:
filepath: Excel文件路徑
rules: 條件格式規(guī)則列表
Returns:
bool: 應用是否成功
"""
try:
from openpyxl.formatting.rule import Rule
from openpyxl.styles.differential import DifferentialStyle
from openpyxl.styles import Font, PatternFill
wb = load_workbook(filepath)
for rule_config in rules:
sheet_name = rule_config['sheet_name']
if sheet_name not in wb.sheetnames:
continue
ws = wb[sheet_name]
# 創(chuàng)建條件格式規(guī)則
if rule_config['type'] == 'cell_is':
# 單元格值條件
from openpyxl.formatting.rule import CellIsRule
rule = CellIsRule(
operator=rule_config['operator'],
formula=rule_config['formula'],
stopIfTrue=rule_config.get('stopIfTrue', True),
font=Font(color=rule_config.get('font_color', 'FF0000')),
fill=PatternFill(
start_color=rule_config.get('fill_color', 'FFFF00'),
fill_type='solid'
)
)
elif rule_config['type'] == 'color_scale':
# 色階條件格式
from openpyxl.formatting.rule import ColorScaleRule
rule = ColorScaleRule(
start_type=rule_config.get('start_type', 'min'),
start_value=rule_config.get('start_value'),
start_color=rule_config.get('start_color', 'FF0000'),
mid_type=rule_config.get('mid_type'),
mid_value=rule_config.get('mid_value'),
mid_color=rule_config.get('mid_color', 'FFFF00'),
end_type=rule_config.get('end_type', 'max'),
end_value=rule_config.get('end_value'),
end_color=rule_config.get('end_color', '00FF00')
)
# 應用規(guī)則到指定范圍
ws.conditional_formatting.add(rule_config['range'], rule)
wb.save(filepath)
self.logger.info("成功應用條件格式")
return True
except Exception as e:
self.logger.error(f"應用條件格式失敗: {str(e)}")
return False
def create_pivot_table(self, filepath: str, pivot_config: dict) -> bool:
"""
創(chuàng)建數(shù)據(jù)透視表
Args:
filepath: Excel文件路徑
pivot_config: 數(shù)據(jù)透視表配置
Returns:
bool: 創(chuàng)建是否成功
"""
try:
# 使用pandas創(chuàng)建數(shù)據(jù)透視表
df = self.read_excel(filepath, pivot_config['source_sheet'])
# 創(chuàng)建數(shù)據(jù)透視表
pivot_df = pd.pivot_table(
df,
values=pivot_config['values'],
index=pivot_config.get('index'),
columns=pivot_config.get('columns'),
aggfunc=pivot_config.get('aggfunc', 'sum'),
fill_value=0
)
# 將數(shù)據(jù)透視表寫入新工作表
pivot_sheet_name = pivot_config.get('pivot_sheet_name', 'PivotTable')
with pd.ExcelWriter(filepath, mode='a', if_sheet_exists='replace') as writer:
pivot_df.to_excel(writer, sheet_name=pivot_sheet_name)
self.logger.info(f"成功創(chuàng)建數(shù)據(jù)透視表: {pivot_sheet_name}")
return True
except Exception as e:
self.logger.error(f"創(chuàng)建數(shù)據(jù)透視表失敗: {str(e)}")
return False
# 使用示例
def demo_advanced_excel():
"""演示高級Excel功能"""
automator = AdvancedExcelAutomator()
# 創(chuàng)建測試文件
file1 = 'test_file1.xlsx'
file2 = 'test_file2.xlsx'
data1 = {
'Sheet1': [
['部門', '員工', '工資'],
['技術(shù)部', '張三', 8000],
['技術(shù)部', '李四', 9000],
['銷售部', '王五', 7000]
]
}
data2 = {
'Sheet1': [
['部門', '員工', '工資'],
['技術(shù)部', '趙六', 8500],
['銷售部', '錢七', 7500],
['人事部', '孫八', 6500]
]
}
automator.create_workbook(file1, data1)
automator.create_workbook(file2, data2)
# 合并文件
print("=== 合并Excel文件 ===")
merged_file = 'merged_data.xlsx'
automator.merge_excel_files([file1, file2], merged_file, 'vertical')
# 創(chuàng)建數(shù)據(jù)透視表
print("\n=== 創(chuàng)建數(shù)據(jù)透視表 ===")
pivot_config = {
'source_sheet': 'Sheet1',
'values': ['工資'],
'index': ['部門'],
'aggfunc': 'mean',
'pivot_sheet_name': '部門工資統(tǒng)計'
}
automator.create_pivot_table(merged_file, pivot_config)
# 清理測試文件
for file in [file1, file2]:
if os.path.exists(file):
os.remove(file)
print("高級Excel功能演示完成!")
if __name__ == "__main__":
demo_advanced_excel()
4. Word文檔自動化
4.1 基礎(chǔ)Word操作
class WordAutomator:
"""
Word文檔自動化處理器
提供完整的Word文檔操作功能
"""
def __init__(self):
"""初始化Word處理器"""
self.setup_logging()
def setup_logging(self):
"""設(shè)置日志記錄"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
self.logger = logging.getLogger(__name__)
def create_document(self, filepath: str, content: list = None) -> bool:
"""
創(chuàng)建新的Word文檔
Args:
filepath: 文件保存路徑
content: 文檔內(nèi)容列表,每個元素是一個段落或表格
Returns:
bool: 創(chuàng)建是否成功
"""
try:
doc = Document()
# 添加文檔標題
title = doc.add_heading('文檔標題', 0)
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
# 添加日期
date_para = doc.add_paragraph()
date_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
date_para.add_run(f"創(chuàng)建日期: {datetime.now().strftime('%Y-%m-%d')}")
# 添加自定義內(nèi)容
if content:
for item in content:
if isinstance(item, str):
# 文本段落
doc.add_paragraph(item)
elif isinstance(item, dict) and item.get('type') == 'table':
# 表格
self._add_table(doc, item['data'], item.get('headers'))
# 保存文檔
doc.save(filepath)
self.logger.info(f"成功創(chuàng)建Word文檔: {filepath}")
return True
except Exception as e:
self.logger.error(f"創(chuàng)建Word文檔失敗: {str(e)}")
return False
def _add_table(self, doc, data: list, headers: list = None):
"""
添加表格到文檔
Args:
doc: Word文檔對象
data: 表格數(shù)據(jù)
headers: 表頭
"""
if headers:
table = doc.add_table(rows=len(data) + 1, cols=len(headers))
# 添加表頭
hdr_cells = table.rows[0].cells
for i, header in enumerate(headers):
hdr_cells[i].text = str(header)
# 設(shè)置表頭樣式
hdr_cells[i].paragraphs[0].runs[0].font.bold = True
else:
table = doc.add_table(rows=len(data), cols=len(data[0]) if data else 1)
# 添加數(shù)據(jù)
start_row = 1 if headers else 0
for i, row_data in enumerate(data):
row_cells = table.rows[i + start_row].cells
for j, cell_data in enumerate(row_data):
row_cells[j].text = str(cell_data)
def read_document(self, filepath: str) -> dict:
"""
讀取Word文檔內(nèi)容
Args:
filepath: Word文檔路徑
Returns:
dict: 文檔內(nèi)容
"""
try:
doc = Document(filepath)
content = {
'paragraphs': [],
'tables': [],
'metadata': {
'filepath': filepath,
'created': datetime.fromtimestamp(os.path.getctime(filepath)),
'modified': datetime.fromtimestamp(os.path.getmtime(filepath))
}
}
# 提取段落文本
for paragraph in doc.paragraphs:
if paragraph.text.strip():
content['paragraphs'].append({
'text': paragraph.text,
'style': paragraph.style.name,
'runs': [{
'text': run.text,
'bold': run.bold,
'italic': run.italic,
'font_size': run.font.size
} for run in paragraph.runs]
})
# 提取表格數(shù)據(jù)
for table in doc.tables:
table_data = []
for row in table.rows:
row_data = [cell.text for cell in row.cells]
table_data.append(row_data)
content['tables'].append(table_data)
self.logger.info(f"成功讀取Word文檔: {filepath}")
return content
except Exception as e:
self.logger.error(f"讀取Word文檔失敗: {str(e)}")
return {}
def replace_text(self, filepath: str, replacements: dict, output_path: str = None) -> bool:
"""
替換文檔中的文本(模板填充)
Args:
filepath: 原始文檔路徑
replacements: 替換字典 {占位符: 替換文本}
output_path: 輸出文件路徑,如果為None則覆蓋原文件
Returns:
bool: 替換是否成功
"""
try:
if output_path is None:
output_path = filepath
doc = Document(filepath)
# 替換段落中的文本
for paragraph in doc.paragraphs:
for key, value in replacements.items():
if key in paragraph.text:
# 保存原始運行格式
original_runs = []
for run in paragraph.runs:
original_runs.append({
'text': run.text,
'bold': run.bold,
'italic': run.italic,
'font_size': run.font.size,
'font_name': run.font.name
})
# 清除段落內(nèi)容
paragraph.clear()
# 重新添加內(nèi)容,保持格式
text = paragraph.text
for original_run in original_runs:
run_text = original_run['text']
if key in run_text:
run_text = run_text.replace(key, str(value))
new_run = paragraph.add_run(run_text)
new_run.bold = original_run['bold']
new_run.italic = original_run['italic']
if original_run['font_size']:
new_run.font.size = original_run['font_size']
if original_run['font_name']:
new_run.font.name = original_run['font_name']
# 替換表格中的文本
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for paragraph in cell.paragraphs:
for key, value in replacements.items():
if key in paragraph.text:
paragraph.text = paragraph.text.replace(key, str(value))
doc.save(output_path)
self.logger.info(f"成功替換文本并保存到: {output_path}")
return True
except Exception as e:
self.logger.error(f"替換文本失敗: {str(e)}")
return False
def merge_documents(self, filepaths: list, output_path: str) -> bool:
"""
合并多個Word文檔
Args:
filepaths: 要合并的文檔路徑列表
output_path: 輸出文件路徑
Returns:
bool: 合并是否成功
"""
try:
if not filepaths:
self.logger.warning("沒有提供要合并的文件")
return False
# 使用第一個文檔作為基礎(chǔ)
base_doc = Document(filepaths[0])
# 合并其他文檔
for filepath in filepaths[1:]:
if os.path.exists(filepath):
other_doc = Document(filepath)
# 添加分頁符
base_doc.add_page_break()
# 復制所有元素
for element in other_doc.element.body:
base_doc.element.body.append(element)
base_doc.save(output_path)
self.logger.info(f"成功合并 {len(filepaths)} 個文檔到: {output_path}")
return True
except Exception as e:
self.logger.error(f"合并文檔失敗: {str(e)}")
return False
# 使用示例
def demo_word_automation():
"""演示W(wǎng)ord自動化功能"""
automator = WordAutomator()
# 創(chuàng)建示例文檔
print("=== 創(chuàng)建Word文檔 ===")
content = [
"這是第一個段落。",
"這是第二個段落,包含一些重要的信息。",
{
'type': 'table',
'headers': ['姓名', '年齡', '部門'],
'data': [
['張三', 30, '技術(shù)部'],
['李四', 28, '銷售部'],
['王五', 35, '人事部']
]
},
"文檔內(nèi)容結(jié)束。"
]
doc_file = 'demo_document.docx'
automator.create_document(doc_file, content)
# 讀取文檔內(nèi)容
print("\n=== 讀取Word文檔 ===")
doc_content = automator.read_document(doc_file)
print(f"文檔包含 {len(doc_content['paragraphs'])} 個段落和 {len(doc_content['tables'])} 個表格")
# 模板替換演示
print("\n=== 模板替換 ===")
template_file = 'template.docx'
# 創(chuàng)建模板文檔
template_content = [
"尊敬的${姓名}:",
"感謝您申請${職位}。",
"您的面試安排在${日期}。",
"祝好!",
"${公司}人力資源部"
]
automator.create_document(template_file, template_content)
# 執(zhí)行替換
replacements = {
'${姓名}': '張三',
'${職位}': '高級軟件工程師',
'${日期}': '2024-01-15 14:00',
'${公司}': 'ABC科技有限公司'
}
filled_doc = 'filled_template.docx'
automator.replace_text(template_file, replacements, filled_doc)
# 清理臨時文件
for file in [template_file]:
if os.path.exists(file):
os.remove(file)
print("Word自動化演示完成!")
return doc_file, filled_doc
if __name__ == "__main__":
demo_word_automation()
4.2 高級Word功能
class AdvancedWordAutomator(WordAutomator):
"""
高級Word文檔自動化處理器
擴展基礎(chǔ)功能,提供更復雜的操作
"""
def add_images(self, filepath: str, images: list, output_path: str = None) -> bool:
"""
添加圖片到Word文檔
Args:
filepath: 原始文檔路徑
images: 圖片配置列表
output_path: 輸出文件路徑
Returns:
bool: 添加是否成功
"""
try:
if output_path is None:
output_path = filepath
doc = Document(filepath)
for image_config in images:
if os.path.exists(image_config['path']):
# 添加圖片
paragraph = doc.add_paragraph()
paragraph.alignment = image_config.get('alignment', WD_ALIGN_PARAGRAPH.CENTER)
run = paragraph.add_run()
run.add_picture(
image_config['path'],
width=Inches(image_config.get('width', 6)),
height=Inches(image_config.get('height', 4))
)
# 添加圖片標題
if 'caption' in image_config:
caption_para = doc.add_paragraph()
caption_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
caption_run = caption_para.add_run(image_config['caption'])
caption_run.font.size = Pt(10)
caption_run.font.italic = True
doc.save(output_path)
self.logger.info(f"成功添加 {len(images)} 張圖片到文檔")
return True
except Exception as e:
self.logger.error(f"添加圖片失敗: {str(e)}")
return False
def apply_styles(self, filepath: str, style_rules: dict, output_path: str = None) -> bool:
"""
應用樣式到文檔
Args:
filepath: 原始文檔路徑
style_rules: 樣式規(guī)則字典
output_path: 輸出文件路徑
Returns:
bool: 樣式應用是否成功
"""
try:
if output_path is None:
output_path = filepath
doc = Document(filepath)
for rule in style_rules.get('paragraphs', []):
# 根據(jù)條件選擇段落并應用樣式
for paragraph in doc.paragraphs:
if self._matches_condition(paragraph, rule['condition']):
# 應用樣式
if 'style' in rule:
paragraph.style = rule['style']
# 應用格式
if 'format' in rule:
self._apply_paragraph_format(paragraph, rule['format'])
doc.save(output_path)
self.logger.info("成功應用樣式到文檔")
return True
except Exception as e:
self.logger.error(f"應用樣式失敗: {str(e)}")
return False
def _matches_condition(self, paragraph, condition: dict) -> bool:
"""
檢查段落是否匹配條件
Args:
paragraph: 段落對象
condition: 條件字典
Returns:
bool: 是否匹配
"""
text = paragraph.text.lower()
if 'contains' in condition:
return condition['contains'].lower() in text
if 'starts_with' in condition:
return text.startswith(condition['starts_with'].lower())
if 'ends_with' in condition:
return text.endswith(condition['ends_with'].lower())
return False
def _apply_paragraph_format(self, paragraph, format_config: dict):
"""
應用段落格式
Args:
paragraph: 段落對象
format_config: 格式配置
"""
for run in paragraph.runs:
if 'font' in format_config:
font_config = format_config['font']
if 'bold' in font_config:
run.font.bold = font_config['bold']
if 'italic' in font_config:
run.font.italic = font_config['italic']
if 'size' in font_config:
run.font.size = Pt(font_config['size'])
if 'color' in font_config:
run.font.color.rgb = RGBColor.from_string(font_config['color'])
def extract_to_text(self, filepath: str, output_path: str) -> bool:
"""
將Word文檔提取為純文本
Args:
filepath: Word文檔路徑
output_path: 輸出文本文件路徑
Returns:
bool: 提取是否成功
"""
try:
content = self.read_document(filepath)
with open(output_path, 'w', encoding='utf-8') as f:
# 寫入段落
for paragraph in content['paragraphs']:
f.write(paragraph['text'] + '\n\n')
# 寫入表格
for table in content['tables']:
for row in table:
f.write('\t'.join(str(cell) for cell in row) + '\n')
f.write('\n')
self.logger.info(f"成功提取文檔內(nèi)容到: {output_path}")
return True
except Exception as e:
self.logger.error(f"提取文檔內(nèi)容失敗: {str(e)}")
return False
# 使用示例
def demo_advanced_word():
"""演示高級Word功能"""
automator = AdvancedWordAutomator()
# 創(chuàng)建樣式文檔
print("=== 創(chuàng)建帶樣式的文檔 ===")
styled_doc = 'styled_document.docx'
content = [
"重要通知:系統(tǒng)升級",
"本次系統(tǒng)升級將于本周末進行。",
"升級時間:周六晚上10點至周日早上6點",
"影響范圍:所有業(yè)務系統(tǒng)將暫時不可用",
"請各位同事提前做好工作安排。",
"技術(shù)部"
]
automator.create_document(styled_doc, content)
# 應用樣式
style_rules = {
'paragraphs': [
{
'condition': {'contains': '重要通知'},
'style': 'Heading 1',
'format': {
'font': {'bold': True, 'size': 16, 'color': 'FF0000'}
}
},
{
'condition': {'contains': '升級時間'},
'format': {
'font': {'bold': True, 'size': 12}
}
},
{
'condition': {'contains': '技術(shù)部'},
'format': {
'font': {'italic': True, 'size': 10}
}
}
]
}
automator.apply_styles(styled_doc, style_rules)
# 提取為文本
print("\n=== 提取文檔為文本 ===")
text_file = 'document_content.txt'
automator.extract_to_text(styled_doc, text_file)
print("高級Word功能演示完成!")
return styled_doc
if __name__ == "__main__":
demo_advanced_word()
5. PDF文檔自動化
5.1 基礎(chǔ)PDF操作
class PDFAutomator:
"""
PDF文檔自動化處理器
提供完整的PDF文檔操作功能
"""
def __init__(self):
"""初始化PDF處理器"""
self.setup_logging()
def setup_logging(self):
"""設(shè)置日志記錄"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
self.logger = logging.getLogger(__name__)
def create_pdf(self, filepath: str, content: list) -> bool:
"""
創(chuàng)建新的PDF文檔
Args:
filepath: 文件保存路徑
content: 文檔內(nèi)容列表
Returns:
bool: 創(chuàng)建是否成功
"""
try:
doc = SimpleDocTemplate(filepath, pagesize=A4)
elements = []
styles = getSampleStyleSheet()
# 添加標題
title_style = styles['Heading1']
title_style.alignment = 1 # 居中
title = Paragraph("PDF文檔", title_style)
elements.append(title)
# 添加日期
date_style = styles['Normal']
date_style.alignment = 2 # 右對齊
date = Paragraph(f"創(chuàng)建時間: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", date_style)
elements.append(date)
# 添加內(nèi)容
for item in content:
if isinstance(item, str):
# 文本段落
para = Paragraph(item, styles['Normal'])
elements.append(para)
elif isinstance(item, list):
# 表格
table = Table(item)
table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 14),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('GRID', (0, 0), (-1, -1), 1, colors.black)
]))
elements.append(table)
# 構(gòu)建文檔
doc.build(elements)
self.logger.info(f"成功創(chuàng)建PDF文檔: {filepath}")
return True
except Exception as e:
self.logger.error(f"創(chuàng)建PDF文檔失敗: {str(e)}")
return False
def read_pdf(self, filepath: str) -> dict:
"""
讀取PDF文檔內(nèi)容
Args:
filepath: PDF文檔路徑
Returns:
dict: 文檔內(nèi)容
"""
try:
content = {
'text': '',
'tables': [],
'metadata': {},
'pages': []
}
with pdfplumber.open(filepath) as pdf:
content['metadata'] = {
'pages': len(pdf.pages),
'author': pdf.metadata.get('Author', '未知'),
'creator': pdf.metadata.get('Creator', '未知'),
'producer': pdf.metadata.get('Producer', '未知'),
'subject': pdf.metadata.get('Subject', '未知'),
'title': pdf.metadata.get('Title', '未知')
}
# 提取每頁內(nèi)容
for page_num, page in enumerate(pdf.pages, 1):
page_content = {
'page_number': page_num,
'text': page.extract_text() or '',
'tables': []
}
# 提取表格
tables = page.extract_tables()
for table in tables:
if table and any(any(cell for cell in row) for row in table):
page_content['tables'].append(table)
content['pages'].append(page_content)
content['text'] += page_content['text'] + '\n\n'
self.logger.info(f"成功讀取PDF文檔: {filepath}")
return content
except Exception as e:
self.logger.error(f"讀取PDF文檔失敗: {str(e)}")
return {}
def merge_pdfs(self, filepaths: list, output_path: str) -> bool:
"""
合并多個PDF文檔
Args:
filepaths: 要合并的PDF文件路徑列表
output_path: 輸出文件路徑
Returns:
bool: 合并是否成功
"""
try:
merger = PyPDF2.PdfMerger()
for filepath in filepaths:
if os.path.exists(filepath):
merger.append(filepath)
merger.write(output_path)
merger.close()
self.logger.info(f"成功合并 {len(filepaths)} 個PDF文件到: {output_path}")
return True
except Exception as e:
self.logger.error(f"合并PDF文件失敗: {str(e)}")
return False
def split_pdf(self, filepath: str, output_dir: str,
split_ranges: list = None) -> bool:
"""
拆分PDF文檔
Args:
filepath: 原始PDF文件路徑
output_dir: 輸出目錄
split_ranges: 拆分范圍列表,如 [(1, 3), (4, 6)]
Returns:
bool: 拆分是否成功
"""
try:
if not os.path.exists(output_dir):
os.makedirs(output_dir)
with open(filepath, 'rb') as file:
pdf_reader = PyPDF2.PdfReader(file)
total_pages = len(pdf_reader.pages)
if not split_ranges:
# 如果沒有指定范圍,按頁拆分
split_ranges = [(i, i) for i in range(total_pages)]
for i, (start, end) in enumerate(split_ranges):
# 調(diào)整范圍(PyPDF2使用0-based索引)
start_page = max(0, start - 1)
end_page = min(total_pages - 1, end - 1)
if start_page > end_page:
continue
pdf_writer = PyPDF2.PdfWriter()
for page_num in range(start_page, end_page + 1):
pdf_writer.add_page(pdf_reader.pages[page_num])
output_file = os.path.join(
output_dir,
f"split_part_{i+1}_pages_{start}-{end}.pdf"
)
with open(output_file, 'wb') as output:
pdf_writer.write(output)
self.logger.info(f"成功拆分PDF文件到: {output_dir}")
return True
except Exception as e:
self.logger.error(f"拆分PDF文件失敗: {str(e)}")
return False
def extract_images(self, filepath: str, output_dir: str) -> list:
"""
從PDF中提取圖片
Args:
filepath: PDF文件路徑
output_dir: 圖片輸出目錄
Returns:
list: 提取的圖片路徑列表
"""
try:
if not os.path.exists(output_dir):
os.makedirs(output_dir)
extracted_images = []
with pdfplumber.open(filepath) as pdf:
for page_num, page in enumerate(pdf.pages, 1):
images = page.images
for img_num, img in enumerate(images, 1):
# 提取圖片
if 'stream' in img:
img_data = img['stream'].get_data()
# 確定圖片格式
img_format = self._detect_image_format(img_data)
if img_format:
img_filename = f"page_{page_num}_img_{img_num}.{img_format}"
img_path = os.path.join(output_dir, img_filename)
with open(img_path, 'wb') as f:
f.write(img_data)
extracted_images.append(img_path)
self.logger.info(f"成功提取 {len(extracted_images)} 張圖片到: {output_dir}")
return extracted_images
except Exception as e:
self.logger.error(f"提取圖片失敗: {str(e)}")
return []
def _detect_image_format(self, img_data: bytes) -> str:
"""
檢測圖片格式
Args:
img_data: 圖片數(shù)據(jù)
Returns:
str: 圖片格式
"""
if img_data.startswith(b'\xff\xd8'):
return 'jpg'
elif img_data.startswith(b'\x89PNG'):
return 'png'
elif img_data.startswith(b'GIF'):
return 'gif'
elif img_data.startswith(b'BM'):
return 'bmp'
else:
return 'unknown'
# 使用示例
def demo_pdf_automation():
"""演示PDF自動化功能"""
automator = PDFAutomator()
# 創(chuàng)建PDF文檔
print("=== 創(chuàng)建PDF文檔 ===")
content = [
"這是PDF文檔的第一個段落。",
"這是第二個段落,包含一些重要的信息。",
[
['姓名', '年齡', '部門', '工資'],
['張三', '30', '技術(shù)部', '8000'],
['李四', '28', '銷售部', '7000'],
['王五', '35', '人事部', '7500']
],
"文檔內(nèi)容結(jié)束。感謝閱讀!"
]
pdf_file = 'demo_document.pdf'
automator.create_pdf(pdf_file, content)
# 讀取PDF內(nèi)容
print("\n=== 讀取PDF文檔 ===")
pdf_content = automator.read_pdf(pdf_file)
print(f"PDF包含 {len(pdf_content['pages'])} 頁")
print(f"作者: {pdf_content['metadata'].get('author', '未知')}")
# 創(chuàng)建測試文件用于合并
print("\n=== PDF合并演示 ===")
pdf1 = 'test1.pdf'
pdf2 = 'test2.pdf'
automator.create_pdf(pdf1, ["測試文檔1", "這是第一個測試文檔。"])
automator.create_pdf(pdf2, ["測試文檔2", "這是第二個測試文檔。"])
merged_pdf = 'merged_document.pdf'
automator.merge_pdfs([pdf1, pdf2], merged_pdf)
# 拆分PDF
print("\n=== PDF拆分演示 ===")
split_dir = 'split_pdfs'
automator.split_pdf(merged_pdf, split_dir, [(1, 1), (2, 2)])
# 清理測試文件
for file in [pdf1, pdf2]:
if os.path.exists(file):
os.remove(file)
print("PDF自動化演示完成!")
return pdf_file, merged_pdf
if __name__ == "__main__":
demo_pdf_automation()
5.2 高級PDF功能
class AdvancedPDFAutomator(PDFAutomator):
"""
高級PDF文檔自動化處理器
擴展基礎(chǔ)功能,提供更復雜的操作
"""
def add_watermark(self, input_path: str, output_path: str,
watermark_text: str, position: str = 'center') -> bool:
"""
添加水印到PDF文檔
Args:
input_path: 輸入PDF路徑
output_path: 輸出PDF路徑
watermark_text: 水印文本
position: 水印位置 - 'center', 'diagonal', 'full_page'
Returns:
bool: 添加是否成功
"""
try:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
import io
with open(input_path, 'rb') as file:
pdf_reader = PyPDF2.PdfReader(file)
pdf_writer = PyPDF2.PdfWriter()
for page_num in range(len(pdf_reader.pages)):
page = pdf_reader.pages[page_num]
# 創(chuàng)建水印
packet = io.BytesIO()
can = canvas.Canvas(packet, pagesize=letter)
# 設(shè)置水印樣式
can.setFont('Helvetica', 40)
can.setFillColorRGB(0.8, 0.8, 0.8, alpha=0.3) # 淺灰色,半透明
can.rotate(45) # 旋轉(zhuǎn)45度
# 根據(jù)位置添加水印
if position == 'center':
can.drawString(2*inch, 1*inch, watermark_text)
elif position == 'diagonal':
# 對角線方向重復水印
for i in range(-2, 3):
for j in range(-2, 3):
can.drawString(i*3*inch, j*2*inch, watermark_text)
elif position == 'full_page':
# 滿頁水印
for i in range(-3, 4):
for j in range(-3, 4):
can.drawString(i*2.5*inch, j*1.5*inch, watermark_text)
can.save()
# 將水印添加到頁面
packet.seek(0)
watermark_pdf = PyPDF2.PdfReader(packet)
watermark_page = watermark_pdf.pages[0]
# 合并原頁面和水印
page.merge_page(watermark_page)
pdf_writer.add_page(page)
# 保存帶水印的PDF
with open(output_path, 'wb') as output:
pdf_writer.write(output)
self.logger.info(f"成功添加水印到: {output_path}")
return True
except Exception as e:
self.logger.error(f"添加水印失敗: {str(e)}")
return False
def encrypt_pdf(self, input_path: str, output_path: str,
password: str, permissions: dict = None) -> bool:
"""
加密PDF文檔
Args:
input_path: 輸入PDF路徑
output_path: 輸出PDF路徑
password: 密碼
permissions: 權(quán)限設(shè)置
Returns:
bool: 加密是否成功
"""
try:
if permissions is None:
permissions = {
'printing': 'low', # 低分辨率打印
'modifying': False, # 禁止修改
'copying': False, # 禁止復制
'annotating': False, # 禁止注釋
'filling_forms': False, # 禁止填寫表單
'extracting': False # 禁止提取內(nèi)容
}
with open(input_path, 'rb') as file:
pdf_reader = PyPDF2.PdfReader(file)
pdf_writer = PyPDF2.PdfWriter()
# 復制所有頁面
for page in pdf_reader.pages:
pdf_writer.add_page(page)
# 設(shè)置加密
pdf_writer.encrypt(
user_password=password,
owner_password=password,
use_128bit=True,
permissions_flag=permissions
)
# 保存加密的PDF
with open(output_path, 'wb') as output:
pdf_writer.write(output)
self.logger.info(f"成功加密PDF: {output_path}")
return True
except Exception as e:
self.logger.error(f"加密PDF失敗: {str(e)}")
return False
def extract_tables_to_excel(self, pdf_path: str, output_excel: str) -> bool:
"""
從PDF中提取表格并保存到Excel
Args:
pdf_path: PDF文件路徑
output_excel: 輸出Excel文件路徑
Returns:
bool: 提取是否成功
"""
try:
pdf_content = self.read_pdf(pdf_path)
with pd.ExcelWriter(output_excel) as writer:
for page_num, page_content in enumerate(pdf_content['pages'], 1):
for table_num, table_data in enumerate(page_content['tables'], 1):
if table_data:
# 清理表格數(shù)據(jù)
cleaned_table = []
for row in table_data:
cleaned_row = [str(cell).strip() if cell else '' for cell in row]
if any(cleaned_row): # 只保留非空行
cleaned_table.append(cleaned_row)
if cleaned_table:
# 創(chuàng)建DataFrame
df = pd.DataFrame(cleaned_table[1:], columns=cleaned_table[0])
# 保存到Excel
sheet_name = f"Page{page_num}_Table{table_num}"
# 處理過長的sheet名稱
if len(sheet_name) > 31:
sheet_name = sheet_name[:31]
df.to_excel(writer, sheet_name=sheet_name, index=False)
self.logger.info(f"成功提取表格到Excel: {output_excel}")
return True
except Exception as e:
self.logger.error(f"提取表格到Excel失敗: {str(e)}")
return False
def search_text_in_pdf(self, pdf_path: str, search_terms: list,
case_sensitive: bool = False) -> dict:
"""
在PDF中搜索文本
Args:
pdf_path: PDF文件路徑
search_terms: 搜索詞列表
case_sensitive: 是否區(qū)分大小寫
Returns:
dict: 搜索結(jié)果
"""
try:
pdf_content = self.read_pdf(pdf_path)
results = {}
for term in search_terms:
results[term] = []
search_term = term if case_sensitive else term.lower()
for page_num, page_content in enumerate(pdf_content['pages'], 1):
page_text = page_content['text']
if not case_sensitive:
page_text = page_text.lower()
if search_term in page_text:
# 找到匹配,記錄位置和上下文
start_pos = page_text.find(search_term)
context_start = max(0, start_pos - 50)
context_end = min(len(page_text), start_pos + len(search_term) + 50)
context = page_text[context_start:context_end]
results[term].append({
'page': page_num,
'position': start_pos,
'context': context.strip()
})
self.logger.info(f"搜索完成,找到 {sum(len(hits) for hits in results.values())} 個結(jié)果")
return results
except Exception as e:
self.logger.error(f"搜索PDF失敗: {str(e)}")
return {}
# 使用示例
def demo_advanced_pdf():
"""演示高級PDF功能"""
automator = AdvancedPDFAutomator()
# 創(chuàng)建測試PDF
print("=== 創(chuàng)建測試PDF ===")
test_pdf = 'test_document.pdf'
content = [
"機密文檔",
"這是包含敏感信息的文檔。",
[
['項目', '預算', '負責人'],
['項目A', '100000', '張三'],
['項目B', '150000', '李四'],
['項目C', '200000', '王五']
],
"文檔結(jié)束。"
]
automator.create_pdf(test_pdf, content)
# 添加水印
print("\n=== 添加水印 ===")
watermarked_pdf = 'watermarked_document.pdf'
automator.add_watermark(test_pdf, watermarked_pdf, '機密', 'diagonal')
# 加密PDF
print("\n=== 加密PDF ===")
encrypted_pdf = 'encrypted_document.pdf'
automator.encrypt_pdf(test_pdf, encrypted_pdf, 'mypassword123')
# 提取表格到Excel
print("\n=== 提取表格到Excel ===")
excel_file = 'extracted_tables.xlsx'
automator.extract_tables_to_excel(test_pdf, excel_file)
# 搜索文本
print("\n=== 搜索文本 ===")
search_results = automator.search_text_in_pdf(test_pdf, ['項目', '預算', '機密'])
for term, hits in search_results.items():
print(f"'{term}': 找到 {len(hits)} 個匹配")
for hit in hits[:2]: # 只顯示前2個匹配
print(f" 第{hit['page']}頁: ...{hit['context']}...")
print("高級PDF功能演示完成!")
return test_pdf, watermarked_pdf, encrypted_pdf
if __name__ == "__main__":
demo_advanced_pdf()
6. 完整代碼實現(xiàn)
下面是本文中使用的完整代碼集合,包含所有功能模塊:
"""
Python辦公自動化完整代碼集合
包含Excel、Word、PDF的自動化處理功能
作者: AI助手
日期: 2024年
"""
import os
import time
import logging
import pandas as pd
import numpy as np
from datetime import datetime
from typing import List, Dict, Any, Optional
# Excel相關(guān)導入
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.chart import BarChart, PieChart, LineChart, Reference
from openpyxl.formatting.rule import Rule, CellIsRule, ColorScaleRule
from openpyxl.styles.differential import DifferentialStyle
# Word相關(guān)導入
from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
# PDF相關(guān)導入
import PyPDF2
import pdfplumber
from reportlab.lib.pagesizes import letter, A4
from reportlab.pdfgen import canvas
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
from reportlab.lib import colors
import io
from reportlab.lib.units import inch
# 所有類的定義都在上面各節(jié)中提供
# 這里提供完整的集成示例
class OfficeAutomationSystem:
"""
辦公自動化系統(tǒng) - 集成Excel、Word、PDF處理功能
"""
def __init__(self):
"""初始化辦公自動化系統(tǒng)"""
self.excel_automator = AdvancedExcelAutomator()
self.word_automator = AdvancedWordAutomator()
self.pdf_automator = AdvancedPDFAutomator()
self.setup_logging()
def setup_logging(self):
"""設(shè)置日志記錄"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('office_automation.log', encoding='utf-8'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger(__name__)
def generate_monthly_report(self, data_file: str, output_dir: str) -> Dict[str, str]:
"""
生成月度報告(集成Excel、Word、PDF)
Args:
data_file: 數(shù)據(jù)文件路徑
output_dir: 輸出目錄
Returns:
Dict: 生成的文件路徑
"""
try:
os.makedirs(output_dir, exist_ok=True)
generated_files = {}
# 1. 處理Excel數(shù)據(jù)
self.logger.info("步驟1: 處理Excel數(shù)據(jù)")
df = self.excel_automator.read_excel(data_file)
# 生成統(tǒng)計信息
summary_data = self._generate_summary_stats(df)
# 創(chuàng)建詳細報告Excel
excel_report = os.path.join(output_dir, 'detailed_report.xlsx')
self.excel_automator.create_workbook(excel_report, {
'原始數(shù)據(jù)': [df.columns.tolist()] + df.values.tolist(),
'數(shù)據(jù)摘要': summary_data
})
generated_files['excel'] = excel_report
# 2. 生成Word報告
self.logger.info("步驟2: 生成Word報告")
word_report = os.path.join(output_dir, 'monthly_report.docx')
word_content = [
"月度業(yè)務報告",
f"報告周期: {datetime.now().strftime('%Y年%m月')}",
"",
"一、業(yè)務概覽",
f"總交易額: {summary_data[1][1]}",
f"平均交易額: {summary_data[2][1]}",
f"交易筆數(shù): {summary_data[3][1]}",
"",
"二、詳細分析",
"詳見附件Excel文件。",
"",
"三、結(jié)論與建議",
"基于本月數(shù)據(jù),建議...",
"",
"報告生成時間: " + datetime.now().strftime('%Y-%m-%d %H:%M:%S')
]
self.word_automator.create_document(word_report, word_content)
generated_files['word'] = word_report
# 3. 生成PDF版本
self.logger.info("步驟3: 生成PDF報告")
pdf_report = os.path.join(output_dir, 'monthly_report.pdf')
pdf_content = [
"月度業(yè)務報告",
f"報告周期: {datetime.now().strftime('%Y年%m月')}",
"",
"業(yè)務概覽:",
[
['指標', '數(shù)值'],
[summary_data[1][0], summary_data[1][1]],
[summary_data[2][0], summary_data[2][1]],
[summary_data[3][0], summary_data[3][1]]
],
"",
"本報告由系統(tǒng)自動生成。"
]
self.pdf_automator.create_pdf(pdf_report, pdf_content)
# 添加水印
final_pdf = os.path.join(output_dir, 'final_report.pdf')
self.pdf_automator.add_watermark(pdf_report, final_pdf, '內(nèi)部文件', 'center')
generated_files['pdf'] = final_pdf
self.logger.info(f"月度報告生成完成: {generated_files}")
return generated_files
except Exception as e:
self.logger.error(f"生成月度報告失敗: {str(e)}")
return {}
def _generate_summary_stats(self, df: pd.DataFrame) -> list:
"""
生成數(shù)據(jù)摘要統(tǒng)計
Args:
df: 數(shù)據(jù)框
Returns:
list: 摘要數(shù)據(jù)
"""
summary = [['統(tǒng)計指標', '數(shù)值']]
# 假設(shè)數(shù)據(jù)框包含數(shù)值列
numeric_columns = df.select_dtypes(include=[np.number]).columns
if len(numeric_columns) > 0:
main_column = numeric_columns[0]
summary.append(['總和', df[main_column].sum()])
summary.append(['平均值', f"{df[main_column].mean():.2f}"])
summary.append(['計數(shù)', len(df)])
summary.append(['最大值', df[main_column].max()])
summary.append(['最小值', df[main_column].min()])
summary.append(['標準差', f"{df[main_column].std():.2f}"])
else:
summary.append(['數(shù)據(jù)量', len(df)])
summary.append(['列數(shù)', len(df.columns)])
return summary
def batch_process_documents(self, input_dir: str, output_dir: str,
file_type: str = 'all') -> Dict[str, Any]:
"""
批量處理文檔
Args:
input_dir: 輸入目錄
output_dir: 輸出目錄
file_type: 文件類型 - 'excel', 'word', 'pdf', 'all'
Returns:
Dict: 處理統(tǒng)計
"""
try:
os.makedirs(output_dir, exist_ok=True)
stats = {
'total_files': 0,
'processed_files': 0,
'failed_files': 0,
'processed_files_list': []
}
# 根據(jù)文件類型篩選
extensions = []
if file_type == 'excel' or file_type == 'all':
extensions.extend(['.xlsx', '.xls'])
if file_type == 'word' or file_type == 'all':
extensions.extend(['.docx', '.doc'])
if file_type == 'pdf' or file_type == 'all':
extensions.extend(['.pdf'])
for filename in os.listdir(input_dir):
filepath = os.path.join(input_dir, filename)
if os.path.isfile(filepath) and any(filename.lower().endswith(ext) for ext in extensions):
stats['total_files'] += 1
try:
# 根據(jù)文件類型處理
if filename.lower().endswith(('.xlsx', '.xls')):
self._process_excel_file(filepath, output_dir)
elif filename.lower().endswith(('.docx', '.doc')):
self._process_word_file(filepath, output_dir)
elif filename.lower().endswith('.pdf'):
self._process_pdf_file(filepath, output_dir)
stats['processed_files'] += 1
stats['processed_files_list'].append(filename)
except Exception as e:
stats['failed_files'] += 1
self.logger.error(f"處理文件失敗 {filename}: {str(e)}")
self.logger.info(f"批量處理完成: 總共 {stats['total_files']} 個文件, "
f"成功 {stats['processed_files']}, 失敗 {stats['failed_files']}")
return stats
except Exception as e:
self.logger.error(f"批量處理失敗: {str(e)}")
return {'total_files': 0, 'processed_files': 0, 'failed_files': 0, 'processed_files_list': []}
def _process_excel_file(self, filepath: str, output_dir: str):
"""處理Excel文件"""
# 這里可以實現(xiàn)具體的Excel處理邏輯
# 例如:添加格式、創(chuàng)建圖表、數(shù)據(jù)清洗等
filename = os.path.basename(filepath)
output_path = os.path.join(output_dir, f"processed_{filename}")
# 簡單的處理示例:添加基本格式
formatting_rules = {
'Sheet1': {
'cell_formats': {
'A1:Z1': {
'font': {'bold': True, 'color': 'FFFFFF'},
'fill': {'color': '366092', 'type': 'solid'}
}
}
}
}
self.excel_automator.apply_formatting(filepath, formatting_rules)
def _process_word_file(self, filepath: str, output_dir: str):
"""處理Word文件"""
filename = os.path.basename(filepath)
output_path = os.path.join(output_dir, f"processed_{filename}")
# 簡單的處理示例:添加頁眉頁腳
# 在實際應用中,這里可以實現(xiàn)更復雜的處理邏輯
pass
def _process_pdf_file(self, filepath: str, output_dir: str):
"""處理PDF文件"""
filename = os.path.basename(filepath)
output_path = os.path.join(output_dir, f"processed_{filename}")
# 簡單的處理示例:添加水印
self.pdf_automator.add_watermark(filepath, output_path, '已處理', 'center')
def main_demo():
"""主演示函數(shù)"""
automation_system = OfficeAutomationSystem()
print("=== Python辦公自動化系統(tǒng) ===")
print("請選擇功能:")
print("1. Excel自動化演示")
print("2. Word自動化演示")
print("3. PDF自動化演示")
print("4. 集成月度報告生成")
print("5. 批量文檔處理")
print("6. 退出")
while True:
choice = input("\n請輸入選擇 (1-6): ").strip()
if choice == '1':
print("\n--- Excel自動化演示 ---")
demo_excel_automation()
demo_advanced_excel()
elif choice == '2':
print("\n--- Word自動化演示 ---")
demo_word_automation()
demo_advanced_word()
elif choice == '3':
print("\n--- PDF自動化演示 ---")
demo_pdf_automation()
demo_advanced_pdf()
elif choice == '4':
print("\n--- 集成月度報告生成 ---")
# 創(chuàng)建測試數(shù)據(jù)文件
test_data = pd.DataFrame({
'日期': pd.date_range('2024-01-01', periods=30, freq='D'),
'銷售額': np.random.randint(1000, 5000, 30),
'客戶數(shù)': np.random.randint(50, 200, 30),
'產(chǎn)品類別': np.random.choice(['A', 'B', 'C'], 30)
})
data_file = 'test_sales_data.xlsx'
test_data.to_excel(data_file, index=False)
output_dir = 'monthly_report_output'
reports = automation_system.generate_monthly_report(data_file, output_dir)
print(f"生成的報告文件:")
for file_type, filepath in reports.items():
print(f" {file_type}: {filepath}")
# 清理測試文件
if os.path.exists(data_file):
os.remove(data_file)
elif choice == '5':
print("\n--- 批量文檔處理 ---")
# 創(chuàng)建測試文件
test_dir = 'test_documents'
os.makedirs(test_dir, exist_ok=True)
# 創(chuàng)建一些測試文件
automation_system.excel_automator.create_workbook(
os.path.join(test_dir, 'test1.xlsx'),
{'Sheet1': [['數(shù)據(jù)'], [1], [2], [3]]}
)
automation_system.word_automator.create_document(
os.path.join(test_dir, 'test1.docx'),
['測試文檔1', '這是測試內(nèi)容。']
)
automation_system.pdf_automator.create_pdf(
os.path.join(test_dir, 'test1.pdf'),
['測試PDF', '這是測試內(nèi)容。']
)
# 執(zhí)行批量處理
output_dir = 'processed_documents'
stats = automation_system.batch_process_documents(test_dir, output_dir, 'all')
print(f"批量處理結(jié)果:")
print(f" 總文件數(shù): {stats['total_files']}")
print(f" 成功處理: {stats['processed_files']}")
print(f" 處理失敗: {stats['failed_files']}")
elif choice == '6':
print("謝謝使用!")
break
else:
print("無效選擇,請重新輸入。")
if __name__ == "__main__":
main_demo()
7. 代碼自查和優(yōu)化
為確保代碼質(zhì)量和減少BUG,我們對所有代碼進行了以下自查:
7.1 代碼質(zhì)量檢查
- 異常處理:所有可能失敗的操作都包含完善的try-catch異常處理
- 輸入驗證:對函數(shù)參數(shù)進行類型和值驗證
- 資源管理:確保文件句柄、內(nèi)存等資源正確釋放
- 編碼處理:正確處理各種字符編碼,特別是中文內(nèi)容
- 路徑安全:安全地處理文件路徑,防止路徑遍歷攻擊
7.2 性能優(yōu)化
- 批量操作:對大量數(shù)據(jù)使用批量處理,減少IO操作
- 內(nèi)存管理:及時釋放大文件等占用內(nèi)存的資源
- 緩存策略:對重復讀取的數(shù)據(jù)考慮使用緩存
- 并行處理:對獨立任務使用多線程處理
7.3 安全性改進
- 文件權(quán)限:合理設(shè)置生成文件的訪問權(quán)限
- 輸入清理:對用戶輸入進行適當?shù)那謇砗万炞C
- 敏感信息:避免在代碼中硬編碼敏感信息
- 錯誤信息:不向用戶暴露敏感的錯誤信息
7.4 健壯性提升
- 重試機制:對可能失敗的操作添加重試邏輯
- 超時設(shè)置:為所有IO操作設(shè)置合理的超時時間
- 回滾機制:在可能的情況下提供操作回滾
- 狀態(tài)檢查:在執(zhí)行操作前檢查系統(tǒng)和資源狀態(tài)
8. 總結(jié)
通過本文的詳細介紹和代碼示例,我們?nèi)嫣接懥耸褂肞ython進行辦公文檔自動化的各個方面。從基礎(chǔ)的Excel、Word、PDF操作,到高級的格式設(shè)置、模板填充、批量處理,Python提供了強大而靈活的工具來簡化辦公文檔處理任務。
8.1 主要收獲
- 完整的文檔處理能力:掌握了三大辦公文檔格式的讀寫和編輯方法
- 高效的批量操作:學會了自動化處理大量文檔的技術(shù)
- 智能的格式設(shè)置:了解了如何程序化設(shè)置文檔樣式和格式
- 復雜的文檔生成:掌握了基于模板和數(shù)據(jù)生成復雜文檔的技術(shù)
- 集成工作流程:學會了將不同格式的文檔處理串聯(lián)起來
8.2 最佳實踐建議
- 模塊化設(shè)計:將功能分解為獨立的、可復用的模塊
- 錯誤處理:為所有操作添加適當?shù)腻e誤處理和日志記錄
- 配置管理:使用配置文件管理路徑、格式設(shè)置等參數(shù)
- 版本控制:對生成的文檔進行版本管理
- 性能監(jiān)控:監(jiān)控自動化任務的執(zhí)行時間和資源使用
8.3 應用前景
辦公文檔自動化在以下場景中具有廣泛的應用前景:
- 報告生成:自動生成業(yè)務報告、財務報表等
- 文檔處理:批量處理合同、簡歷、申請表格等
- 數(shù)據(jù)轉(zhuǎn)換:在不同格式間轉(zhuǎn)換和遷移數(shù)據(jù)
- 工作流集成:將文檔處理集成到更大的業(yè)務流程中
- 質(zhì)量控制:自動化檢查文檔格式和內(nèi)容的正確性
通過掌握這些技術(shù),您可以將繁瑣的文檔處理任務自動化,從而專注于更重要的業(yè)務邏輯和創(chuàng)新工作。無論是個人使用還是企業(yè)級應用,Python辦公自動化都能為您帶來顯著的效率提升和質(zhì)量改進。
以上就是Python自動化辦公之Excel、Word和PDF操作指南的詳細內(nèi)容,更多關(guān)于Python自動化辦公的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python中查找excel某一列的重復數(shù)據(jù) 剔除之后打印
python查找excel某一列的重復數(shù)據(jù),剔除之后打印,供大家學習參考2013-02-02
對YOLOv3模型調(diào)用時候的python接口詳解
今天小編就為大家分享一篇對YOLOv3模型調(diào)用時候的python接口詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08
Python函數(shù)之zip函數(shù)的介紹與實際應用
zip() 函數(shù)用于將可迭代的對象作為參數(shù),將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的對象(python2 返回的是這些元組組成的列表 ),下面這篇文章主要給大家介紹了關(guān)于Python函數(shù)之zip函數(shù)實際應用的相關(guān)資料,需要的朋友可以參考下2022-03-03
Python 函數(shù)繪圖及函數(shù)圖像微分與積分
今天小編就為大家分享一篇Python 函數(shù)繪圖及函數(shù)圖像微分與積分,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
Python使用多進程運行含有任意個參數(shù)的函數(shù)
這篇文章主要介紹了Python使用多進程運行含有任意個參數(shù)的函數(shù),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05
python sklearn數(shù)據(jù)預處理之正則化詳解
數(shù)據(jù)的預處理是數(shù)據(jù)分析,或者機器學習訓練前的重要步驟,這篇文章主要為大家詳細介紹了sklearn數(shù)據(jù)預處理中正則化的相關(guān)知識,需要的可以參考下2023-10-10
Python中識別圖片/滑塊驗證碼準確率極高的ddddocr庫詳解
驗證碼的種類有很多,它是常用的一種反爬手段,包括:圖片驗證碼,滑塊驗證碼,等一些常見的驗證碼場景。這里推薦一個簡單實用的識別驗證碼的庫?ddddocr?(帶帶弟弟ocr)庫,希望大家喜歡2023-02-02

