Word处理——python-docx图片插入
一、图片插入基础
1.1 基本图片插入
from docx import Document
from docx.shared import Inches
doc = Document()
# 插入图片(使用英寸单位)
doc.add_picture('image.jpg', width=Inches(4))
# 插入图片(使用厘米单位)
from docx.shared import Cm
doc.add_picture('image.jpg', width=Cm(10))
doc.save('basic_image.docx')
1.2 图片尺寸控制
from docx import Document
from docx.shared import Inches, Cm, Mm, Pt
doc = Document()
# 指定宽度(高度自动按比例缩放)
doc.add_picture('image.jpg', width=Inches(5))
# 指定高度(宽度自动按比例缩放)
doc.add_picture('image.jpg', height=Inches(3))
# 同时指定宽度和高度(可能变形)
doc.add_picture('image.jpg', width=Inches(4), height=Inches(3))
# 使用不同单位
doc.add_picture('image.jpg', width=Cm(12))
doc.add_picture('image.jpg', width=Mm(100))
doc.save('image_size.docx')
二、图片位置控制
2.1 内联图片
from docx import Document
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
doc = Document()
# 居中放置
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture('image.jpg', width=Inches(4))
# 右对齐
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
p.add_run().add_picture('image.jpg', width=Inches(3))
# 左对齐(默认)
p = doc.add_paragraph()
p.add_run().add_picture('image.jpg', width=Inches(3))
doc.save('image_position.docx')
2.2 浮动图片(使用表格)
from docx import Document
from docx.shared import Inches
from docx.enum.table import WD_TABLE_ALIGNMENT
doc = Document()
# 使用表格控制图片位置
table = doc.add_table(rows=1, cols=3)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# 左列文字
table.cell(0, 0).text = '左列文字'
# 中间图片
cell = table.cell(0, 1)
p = cell.add_paragraph()
p.add_run().add_picture('image.jpg', width=Inches(3))
# 右列文字
table.cell(0, 2).text = '右列文字'
doc.save('floating_image.docx')
三、图片与文字混合
3.1 图文混排
from docx import Document
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
doc = Document()
# 文字说明
doc.add_heading('图1 示例图片', level=2)
# 图片
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture('image.jpg', width=Inches(5))
# 图注
p = doc.add_paragraph('图1:示例图片说明')
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.runs[0].font.italic = True
doc.save('image_caption.docx')
3.2 行内图片
from docx import Document
from docx.shared import Inches
doc = Document()
p = doc.add_paragraph()
# 插入文本和图片混合
p.add_run('这是文本,然后插入图片:')
run = p.add_run()
run.add_picture('icon.jpg', width=Inches(0.5))
p.add_run(' 后面继续文字。')
# 多张图片同行
p = doc.add_paragraph()
p.add_run('图片:')
for i inrange(3):
run = p.add_run()
run.add_picture('icon.jpg', width=Inches(0.5))
p.add_run(' ')
doc.save('inline_images.docx')
四、图片样式
4.1 图片边框
from docx import Document
from docx.shared import Inches
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
doc = Document()
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run()
run.add_picture('image.jpg', width=Inches(4))
# 添加边框
defadd_picture_border(paragraph, border_color='000000', border_size=2):
"""为图片添加边框"""
# 获取图片的drawing元素
drawing = paragraph._element.xpath('.//w:drawing')[0]
# 创建边框属性
ln = OxmlElement('a:ln')
ln.set(qn('w'), str(border_size * 12700)) # 边框宽度
# 设置边框颜色
solidFill = OxmlElement('a:solidFill')
srgbClr = OxmlElement('a:srgbClr')
srgbClr.set(qn('val'), border_color)
solidFill.append(srgbClr)
ln.append(solidFill)
# 应用到图片
pic = drawing.xpath('.//pic:pic')[0]
pic.append(ln)
# 应用边框
add_picture_border(p, border_color='FF0000', border_size=3)
doc.save('border_image.docx')
4.2 图片阴影效果
from docx import Document
from docx.shared import Inches
doc = Document()
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run()
run.add_picture('image.jpg', width=Inches(4))
# 添加阴影(通过底层XML)
defadd_shadow(doc, paragraph):
"""为图片添加阴影效果"""
# 获取图片元素
drawing = paragraph._element.xpath('.//w:drawing')[0]
# 创建阴影
effect = OxmlElement('a:effectLst')
shadow = OxmlElement('a:outerShdw')
shadow.set(qn('dist'), '30000') # 阴影距离
# 阴影颜色
srgbClr = OxmlElement('a:srgbClr')
srgbClr.set(qn('val'), '808080')
shadow.append(srgbClr)
effect.append(shadow)
# 应用到图片
pic = drawing.xpath('.//pic:pic')[0]
pic.append(effect)
add_shadow(doc, p)
doc.save('shadow_image.docx')
五、实战案例
5.1 报告图片插入
from docx import Document
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
import os
classImageReporter:
"""图片报告生成器"""
def__init__(self):
self.doc = Document()
defadd_image_section(self, title, image_path, caption=None, width=Inches(5)):
"""添加图片章节"""
# 标题
self.doc.add_heading(title, level=2)
# 图片
if os.path.exists(image_path):
p = self.doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture(image_path, width=width)
# 图注
if caption:
p = self.doc.add_paragraph(caption)
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.runs[0].font.italic = True
else:
self.doc.add_paragraph(f'图片不存在: {image_path}')
defadd_gallery(self, images, cols=2, width=Inches(2.5)):
"""添加图片画廊"""
# 创建表格
rows = (len(images) + cols - 1) // cols
table = self.doc.add_table(rows=rows, cols=cols)
table.style = 'Table Grid'
for i, image_info inenumerate(images):
row = i // cols
col = i % cols
cell = table.cell(row, col)
# 添加图片
if os.path.exists(image_info['path']):
p = cell.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture(image_info['path'], width=width)
# 添加图注
if image_info.get('caption'):
p = cell.add_paragraph(image_info['caption'])
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.runs[0].font.size = Pt(9)
defsave(self, filename):
"""保存文档"""
self.doc.save(filename)
# 使用
reporter = ImageReporter()
# 添加单张图片
reporter.add_image_section(
'系统架构图',
'architecture.png',
'图1:系统整体架构'
)
# 添加图片画廊
images = [
{'path': 'image1.png', 'caption': '图2a'},
{'path': 'image2.png', 'caption': '图2b'},
{'path': 'image3.png', 'caption': '图2c'},
{'path': 'image4.png', 'caption': '图2d'}
]
reporter.add_gallery(images, cols=2)
reporter.save('image_report.docx')
5.2 图片批量插入
from docx import Document
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
import os
from pathlib import Path
classImageBatchInserter:
"""图片批量插入器"""
def__init__(self):
self.doc = Document()
definsert_images_from_folder(self, folder_path, pattern='*.jpg'):
"""从文件夹批量插入图片"""
images = sorted(Path(folder_path).glob(pattern))
ifnot images:
print(f'未找到匹配的图片: {folder_path}/{pattern}')
return
for image_path in images:
self.insert_image_with_caption(
str(image_path),
title=image_path.stem,
width=Inches(4.5)
)
definsert_image_with_caption(self, image_path, title=None, caption=None, width=Inches(4.5)):
"""插入带标题的图片"""
# 标题
if title:
self.doc.add_heading(title, level=3)
# 图片
if os.path.exists(image_path):
p = self.doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture(image_path, width=width)
# 图注
if caption or title:
p = self.doc.add_paragraph(caption or title)
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.runs[0].font.italic = True
p.runs[0].font.size = Pt(10)
else:
self.doc.add_paragraph(f'图片不存在: {image_path}')
definsert_image_grid(self, image_paths, cols=2, width=Inches(2.5)):
"""插入图片网格"""
rows = (len(image_paths) + cols - 1) // cols
table = self.doc.add_table(rows=rows, cols=cols)
table.style = 'Table Grid'
for i, image_path inenumerate(image_paths):
row = i // cols
col = i % cols
cell = table.cell(row, col)
if os.path.exists(image_path):
p = cell.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture(image_path, width=width)
defsave(self, filename):
"""保存文档"""
self.doc.save(filename)
# 使用
inserter = ImageBatchInserter()
# 批量插入文件夹中的图片
# inserter.insert_images_from_folder('./images', '*.jpg')
# 插入图片网格
image_paths = [
'image1.jpg', 'image2.jpg', 'image3.jpg', 'image4.jpg'
]
inserter.insert_image_grid(image_paths, cols=2, width=Inches(2.5))
# 插入带标题的图片
inserter.insert_image_with_caption(
'cover.jpg',
title='封面图片',
caption='图1:项目封面',
width=Inches(5)
)
inserter.save('batch_images.docx')
5.3 动态图表插入
from docx import Document
from docx.shared import Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
import matplotlib.pyplot as plt
import io
import os
classChartInserter:
"""图表插入器"""
def__init__(self):
self.doc = Document()
self.chart_counter = 0
defcreate_chart(self, data, chart_type='bar', title='图表'):
"""创建图表并返回图片路径"""
plt.figure(figsize=(8, 6))
if chart_type == 'bar':
plt.bar(data['x'], data['y'])
elif chart_type == 'line':
plt.plot(data['x'], data['y'], marker='o')
elif chart_type == 'pie':
plt.pie(data['y'], labels=data['x'])
elif chart_type == 'scatter':
plt.scatter(data['x'], data['y'])
plt.title(title)
plt.grid(True, alpha=0.3)
# 保存为临时文件
self.chart_counter += 1
filename = f'chart_{self.chart_counter}.png'
plt.savefig(filename, dpi=150, bbox_inches='tight')
plt.close()
return filename
definsert_chart(self, data, chart_type='bar', title='图表', caption=None):
"""插入图表"""
# 创建图表
chart_path = self.create_chart(data, chart_type, title)
# 插入标题
self.doc.add_heading(title, level=2)
# 插入图片
p = self.doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture(chart_path, width=Inches(5))
# 添加图注
if caption:
p = self.doc.add_paragraph(caption)
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.runs[0].font.italic = True
# 删除临时文件
if os.path.exists(chart_path):
os.remove(chart_path)
defsave(self, filename):
"""保存文档"""
self.doc.save(filename)
# 使用
inserter = ChartInserter()
# 柱状图
data1 = {
'x': ['A', 'B', 'C', 'D'],
'y': [10, 20, 15, 25]
}
inserter.insert_chart(data1, 'bar', '销售数据', '图1:产品销量分布')
# 折线图
data2 = {
'x': ['1月', '2月', '3月', '4月', '5月'],
'y': [100, 120, 110, 130, 150]
}
inserter.insert_chart(data2, 'line', '趋势分析', '图2:月度趋势')
# 饼图
data3 = {
'x': ['产品A', '产品B', '产品C'],
'y': [30, 45, 25]
}
inserter.insert_chart(data3, 'pie', '市场份额', '图3:市场占比')
inserter.save('chart_document.docx')
六、总结
# 快速参考
# 1. 插入图片
doc.add_picture('image.jpg', width=Inches(4))
# 2. 设置图片位置
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run().add_picture('image.jpg', width=Inches(4))
# 3. 图片尺寸单位
Inches(4) # 英寸
Cm(10) # 厘米
Mm(100) # 毫米
Pt(72) # 磅
# 4. 图片与文字混合
p = doc.add_paragraph()
p.add_run('文本')
run = p.add_run()
run.add_picture('icon.jpg', width=Inches(0.5))
p.add_run('文本')
# 5. 图片网格
table = doc.add_table(rows=2, cols=2)
cell = table.cell(0, 0)
p = cell.add_paragraph()
p.add_run().add_picture('image.jpg', width=Inches(2))
# 6. 图注
p = doc.add_paragraph('图1:图片说明')
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.runs[0].font.italic = True
python-docx提供了完整的图片插入功能,支持多种尺寸单位和位置控制。通过结合表格和段落,可以实现灵活的图文混排。掌握图片操作可以生成包含丰富视觉元素的Word文档,适用于报告、手册、宣传材料等场景。对于批量插入和动态图表生成,结合其他Python库可以进一步提高效率。
夜雨聆风