乐于分享
好东西不私藏

Word处理——python-docx图片插入

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(00).text = '左列文字'

# 中间图片
cell = table.cell(01)
p = cell.add_paragraph()
p.add_run().add_picture('image.jpg', width=Inches(3))

# 右列文字
table.cell(02).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=(86))

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': [10201525]
}
inserter.insert_chart(data1, 'bar''销售数据''图1:产品销量分布')

# 折线图
data2 = {
'x': ['1月''2月''3月''4月''5月'],
'y': [100120110130150]
}
inserter.insert_chart(data2, 'line''趋势分析''图2:月度趋势')

# 饼图
data3 = {
'x': ['产品A''产品B''产品C'],
'y': [304525]
}
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(00)
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库可以进一步提高效率。