fix:实现基础功能
This commit is contained in:
111
utils/pptx_utils.py
Normal file
111
utils/pptx_utils.py
Normal file
@@ -0,0 +1,111 @@
|
||||
# ==========================================
|
||||
# 3. PPT 通用工具 (PPT Utilities)
|
||||
# ==========================================
|
||||
import os
|
||||
|
||||
from utils.font_utils import is_font_available
|
||||
|
||||
|
||||
def replace_text_in_slide(prs, slide_index, placeholder, text):
|
||||
"""在指定幻灯片中替换指定占位符的文本,并保持原有格式"""
|
||||
slide = prs.slides[slide_index]
|
||||
for shape in slide.shapes:
|
||||
if shape.name == placeholder:
|
||||
if not shape.has_text_frame:
|
||||
continue
|
||||
|
||||
# 1. 保存原有格式
|
||||
original_paragraph_formats = []
|
||||
for paragraph in shape.text_frame.paragraphs:
|
||||
paragraph_format = {
|
||||
'alignment': paragraph.alignment,
|
||||
'space_before': getattr(paragraph, 'space_before', None),
|
||||
'space_after': getattr(paragraph, 'space_after', None),
|
||||
'line_spacing': getattr(paragraph, 'line_spacing', None),
|
||||
'left_indent': getattr(paragraph, 'left_indent', None),
|
||||
'right_indent': getattr(paragraph, 'right_indent', None),
|
||||
'first_line_indent': getattr(paragraph, 'first_line_indent', None),
|
||||
'font_info': []
|
||||
}
|
||||
for run in paragraph.runs:
|
||||
run_format = {
|
||||
'font_name': run.font.name,
|
||||
'font_size': run.font.size,
|
||||
'bold': run.font.bold,
|
||||
'italic': run.font.italic,
|
||||
'underline': run.font.underline,
|
||||
'color': run.font.color,
|
||||
'character_space': getattr(run.font, 'space', None),
|
||||
'all_caps': getattr(run.font, 'all_caps', None),
|
||||
'small_caps': getattr(run.font, 'small_caps', None)
|
||||
}
|
||||
paragraph_format['font_info'].append(run_format)
|
||||
original_paragraph_formats.append(paragraph_format)
|
||||
|
||||
# 2. 设置新文本
|
||||
shape.text = str(text) # 确保是字符串
|
||||
|
||||
# 3. 恢复格式
|
||||
for i, paragraph in enumerate(shape.text_frame.paragraphs):
|
||||
orig_idx = i if i < len(original_paragraph_formats) else -1
|
||||
if not original_paragraph_formats: break
|
||||
|
||||
original_para = original_paragraph_formats[orig_idx]
|
||||
|
||||
# 恢复段落属性
|
||||
for attr in ['alignment', 'space_before', 'space_after', 'line_spacing',
|
||||
'left_indent', 'right_indent', 'first_line_indent']:
|
||||
if original_para[attr] is not None:
|
||||
setattr(paragraph, attr, original_para[attr])
|
||||
|
||||
# 恢复字体属性
|
||||
for j, run in enumerate(paragraph.runs):
|
||||
font_idx = j if j < len(original_para['font_info']) else 0
|
||||
if not original_para['font_info']: break
|
||||
|
||||
original_font = original_para['font_info'][font_idx]
|
||||
|
||||
# 字体名称检查与回退
|
||||
if original_font['font_name']:
|
||||
if is_font_available(original_font['font_name']):
|
||||
run.font.name = original_font['font_name']
|
||||
else:
|
||||
run.font.name = "微软雅黑"
|
||||
|
||||
# 恢复其他字体属性
|
||||
if original_font['font_size']: run.font.size = original_font['font_size']
|
||||
if original_font['bold']: run.font.bold = original_font['bold']
|
||||
if original_font['italic']: run.font.italic = original_font['italic']
|
||||
if original_font['underline']: run.font.underline = original_font['underline']
|
||||
if original_font['all_caps']: run.font.all_caps = original_font['all_caps']
|
||||
|
||||
if original_font['character_space']:
|
||||
try:
|
||||
run.font.space = original_font['character_space']
|
||||
except:
|
||||
pass
|
||||
|
||||
if original_font['color']:
|
||||
try:
|
||||
if hasattr(original_font['color'], 'rgb'):
|
||||
run.font.color.rgb = original_font['color'].rgb
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def replace_picture(prs, slide_index, placeholder, img_path):
|
||||
"""在指定幻灯片中替换指定占位符的图片"""
|
||||
if not os.path.exists(img_path):
|
||||
print(f"警告: 图片路径不存在 {img_path}")
|
||||
return
|
||||
|
||||
slide = prs.slides[slide_index]
|
||||
sp_tree = slide.shapes._spTree
|
||||
|
||||
for i, shape in enumerate(slide.shapes):
|
||||
if shape.name == placeholder:
|
||||
left, top, width, height = shape.left, shape.top, shape.width, shape.height
|
||||
sp_tree.remove(shape._element)
|
||||
new_shape = slide.shapes.add_picture(img_path, left, top, width, height)
|
||||
sp_tree.insert(i, new_shape._element)
|
||||
break
|
||||
Reference in New Issue
Block a user