吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3133|回复: 20
收起左侧

[Python 原创] python批量插入图片到word--10种插入方式

  [复制链接]
noforgvie 发表于 2025-8-15 16:14
逛论坛发现一个帖子,里面的python代码所实现的功能对我的工作很有帮助。
图片插入word的相关工作。
但还是需要一些其他的功能,于是做了一些扩展。
原贴地址:
python批量插入图片到word文档里并且实现分栏排版 - 吾爱破解 - 52pojie.cn以及11楼hfol85大佬的源码


现在支持如下功能:
图片导入:支持文件夹扫描或手动选择多个图片
排版设置:每页 1~8 张图可选,支持横向/纵向页面
文件名显示:可选择是否显示、是否包含扩展名
样式控制:表格居中、图片居中、行高固定、边距控制
文档保存:自动生成.docx并提示保存位置


支持插入:
纵向页面:每页1张  每页2张  每页4张  每页6张  每页8张
横向页面:每页1张  每页2张  每页4张  每页6张  每页8张


打包的exe地址:https://pan.baidu.com/s/16ZgH7K0N24kdB0cwyvU-lw?pwd=52pj


纵向-显示文件名-带后缀-每页8张.png

横向-显示文件名-不带后缀-每页一张.jpg

程序界面.jpg



源码如下,可根据自己的实际需求微调:
[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import filedialog
from docx import Document
from docx.shared import Inches, Cm
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.shared import OxmlElement, qn
import os

def get_folder_path():
    folder_selected = filedialog.askdirectory()
    folder_path.set(folder_selected)
    selected_files.set("")

def get_output_file_path():
    output_file_selected = filedialog.asksaveasfilename(
        defaultextension=".docx",
        filetypes=[("Word文档", "*.docx"), ("所有文件", "*.*")],
        title="选择输出文件的位置和名称"
    )
    output_filename.set(output_file_selected)

def select_files():
    files_selected = filedialog.askopenfilenames(
        title="选择图片文件",
        filetypes=[("图片文件", "*.jpg *.jpeg *.png *.JPG *.JPEG *.PNG"), ("所有文件", "*.*")]
    )
    if files_selected:
        selected_files.set(";".join(files_selected))
        folder_path.set("")

def set_cell_margins(cell, **kwargs):
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()
    tcMar = OxmlElement('w:tcMar')
    for marge, value in kwargs.items():
        node = OxmlElement("w:{}".format(marge))
        node.set(qn('w:w'), str(value))
        node.set(qn('w:type'), 'dxa')
        tcMar.append(node)
    tcPr.append(tcMar)

def set_row_height(row, height_cm):
    tr = row._tr
    trPr = tr.get_or_add_trPr()
    height_element = OxmlElement('w:trHeight')
    height_element.set(qn('w:val'), str(int(height_cm * 567)))
    height_element.set(qn('w:hRule'), 'exact')
    trPr.append(height_element)

def replace_paragraph_marks(doc):
    paragraphs_to_remove = []
    
    for paragraph in doc.paragraphs:
        if not paragraph.text.strip() and len(paragraph.runs) == 0:
            paragraphs_to_remove.append(paragraph)
    
    for paragraph in reversed(paragraphs_to_remove):
        p = paragraph._element
        p.getparent().remove(p)

def create_document():
    img_folder = folder_path.get()
    files_list = selected_files.get()
    output_file = output_filename.get()
    show_filename = show_filename_var.get()
    include_extension = include_extension_var.get()
    orientation = orientation_var.get()
    images_per_page = images_per_page_var.get()
     
    image_paths = []
    
    if img_folder:
        image_paths = [os.path.join(img_folder, f) for f in os.listdir(img_folder) if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
    elif files_list:
        image_paths = files_list.split(";")
        image_paths = [f for f in image_paths if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
    else:
        status_label.config(text='请先选择图片文件夹或选择图片文件。')
        return
 
    if not output_file:
        status_label.config(text='请先选择输出文件的位置和名称。')
        return
     
    if not image_paths:
        status_label.config(text='没有找到支持的图片格式。')
        return
 
    status_label.config(text='正在创建文档...')
    window.update()
     
    doc = Document()
    
    if orientation == "横向":
        section = doc.sections[0]
        section.orientation = 1
        new_width = section.page_height
        new_height = section.page_width
        section.page_width = new_width
        section.page_height = new_height
    
    vertical_rules = {
        1: {"rows": 1, "cols": 1, "row_height": 22.0, "max_width": Cm(15.0)},
        2: {"rows": 2, "cols": 1, "row_height": 11.0, "max_width": Cm(15.0)},
        4: {"rows": 2, "cols": 2, "row_height": 11.0, "max_width": Cm(7.0)},
        6: {"rows": 3, "cols": 2, "row_height": 7.3, "max_width": Cm(7.0)},
        8: {"rows": 4, "cols": 2, "row_height": 5.3, "max_width": Cm(7.0)}
    }
    
    horizontal_rules = {
        1: {"rows": 1, "cols": 1, "row_height": 16.0, "max_width": Cm(20.0)},
        2: {"rows": 2, "cols": 1, "row_height": 8.0, "max_width": Cm(20.0)},
        4: {"rows": 2, "cols": 2, "row_height": 8.0, "max_width": Cm(10.0)},
        6: {"rows": 3, "cols": 2, "row_height": 5.3, "max_width": Cm(10.0)},
        8: {"rows": 4, "cols": 2, "row_height": 4.0, "max_width": Cm(10.0)}
    }
    
    if orientation == "纵向":
        rules = vertical_rules
    else:
        rules = horizontal_rules
    
    if images_per_page not in rules:
        status_label.config(text='无效的每页图片数量选择。')
        return
        
    current_rule = rules[images_per_page]
    rows_per_page = current_rule["rows"]
    cols_per_page = current_rule["cols"]
    row_height = current_rule["row_height"]
    max_width = current_rule["max_width"]
    
    for page_start in range(0, len(image_paths), images_per_page):
        table = doc.add_table(rows=rows_per_page, cols=cols_per_page)
        table.alignment = WD_TABLE_ALIGNMENT.CENTER
        
        for row in table.rows:
            set_row_height(row, row_height)
            for cell in row.cells:
                cell.vertical_alignment = 1
                set_cell_margins(cell, top=50, bottom=50, left=50, right=50)
                
        page_images = image_paths[page_start:page_start + images_per_page]
        
        for i, img_path in enumerate(page_images):
            row_idx = i // cols_per_page
            col_idx = i % cols_per_page
            
            if row_idx < rows_per_page and col_idx < cols_per_page:
                cell = table.cell(row_idx, col_idx)
                for paragraph in cell.paragraphs:
                    paragraph.clear()
                
                try:
                    img_para = cell.add_paragraph()
                    img_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
                    img_run = img_para.add_run()
                    
                    img_para.paragraph_format.space_before = 0
                    img_para.paragraph_format.space_after = 0
                    img_para.paragraph_format.line_spacing = 1
                    
                    pic = img_run.add_picture(img_path, width=max_width)
                    
                    available_height = row_height - 1.5
                    
                    if pic.height.cm > available_height:
                        scale_ratio = available_height / pic.height.cm
                        new_width = pic.width.cm * scale_ratio
                        pic.width = Cm(new_width)
                        pic.height = Cm(available_height)
                    
                    if show_filename:
                        filename = os.path.basename(img_path)
                        if not include_extension:
                            filename = os.path.splitext(filename)[0]
                        
                        filename_para = cell.add_paragraph()
                        filename_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
                        filename_run = filename_para.add_run(filename)
                        
                        filename_run.font.name = 'Times New Roman'
                        filename_run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
                        from docx.shared import Pt
                        filename_run.font.size = Pt(10.5)
                    
                    status_label.config(text=f'{os.path.basename(img_path)} 已插入到 word 文档中...')
                    window.update()
                except Exception as e:
                    status_label.config(text=f'无法插入 {os.path.basename(img_path)},原因:{e}')
                    window.update()
        
        if page_start + images_per_page < len(image_paths):
            doc.add_page_break()
     
    try:
        replace_paragraph_marks(doc)
        
        doc.save(output_file)
        status_label.config(text=f'所有图片已全部插入,文档保存为 "{os.path.basename(output_file)}"。')
        window.update()
        open_document(output_file)
    except Exception as e:
        status_label.config(text=f'无法保存文档,原因:{e}')

def open_document(file_path):
    try:
        if os.path.isfile(file_path):
            if os.name == 'nt':
                os.startfile(file_path)
            elif os.name == 'posix':
                os.system(f'open "{file_path}"')
            else:
                status_label.config(text='不支持的操作系统,无法自动打开文档。')
    except Exception as e:
        status_label.config(text=f'无法打开文档,原因:{e}')

window = tk.Tk()
window.title('图片插入Word文档工具')

folder_path = tk.StringVar()
output_filename = tk.StringVar()
selected_files = tk.StringVar()
show_filename_var = tk.IntVar(value=1)
include_extension_var = tk.IntVar(value=1)
orientation_var = tk.StringVar(value="纵向")
images_per_page_var = tk.IntVar(value=6)

tk.Label(window, text='图片文件夹路径:').grid(row=0, column=0, sticky='w')
entry_folder_path = tk.Entry(window, textvariable=folder_path, width=40).grid(row=0, column=1)
browse_button_folder = tk.Button(window, text='浏览', command=get_folder_path).grid(row=0, column=2)

tk.Label(window, text='或选择图片文件:').grid(row=1, column=0, sticky='w')
select_files_button = tk.Button(window, text='选择文件', command=select_files).grid(row=1, column=1, sticky='w')
selected_files_label = tk.Label(window, textvariable=selected_files, fg='blue', wraplength=300).grid(row=2, column=1, sticky='w')

tk.Label(window, text='输出文件路径:').grid(row=3, column=0, sticky='w')
entry_output_filename = tk.Entry(window, textvariable=output_filename, width=40).grid(row=3, column=1)
browse_button_output = tk.Button(window, text='浏览', command=get_output_file_path).grid(row=3, column=2)

tk.Label(window, text='页面方向:').grid(row=4, column=0, sticky='w')
tk.Radiobutton(window, text='纵向', variable=orientation_var, value="纵向").grid(row=4, column=1, sticky='w')
tk.Radiobutton(window, text='横向', variable=orientation_var, value="横向").grid(row=4, column=2, sticky='w')

tk.Label(window, text='是否显示文件名:').grid(row=5, column=0, sticky='w')
tk.Radiobutton(window, text='显示文件名', variable=show_filename_var, value=1).grid(row=5, column=1, sticky='w')
tk.Radiobutton(window, text='不显示文件名', variable=show_filename_var, value=0).grid(row=5, column=2, sticky='w')

tk.Label(window, text='是否包含后缀:').grid(row=6, column=0, sticky='w')
tk.Radiobutton(window, text='包含后缀', variable=include_extension_var, value=1).grid(row=6, column=1, sticky='w')
tk.Radiobutton(window, text='不包含后缀', variable=include_extension_var, value=0).grid(row=6, column=2, sticky='w')

tk.Label(window, text='每页图片数量:').grid(row=7, column=0, sticky='w')
tk.Radiobutton(window, text='每页1张', variable=images_per_page_var, value=1).grid(row=7, column=1, sticky='w')
tk.Radiobutton(window, text='每页2张', variable=images_per_page_var, value=2).grid(row=8, column=1, sticky='w')
tk.Radiobutton(window, text='每页4张', variable=images_per_page_var, value=4).grid(row=7, column=2, sticky='w')
tk.Radiobutton(window, text='每页6张', variable=images_per_page_var, value=6).grid(row=8, column=2, sticky='w')
tk.Radiobutton(window, text='每页8张', variable=images_per_page_var, value=8).grid(row=9, column=1, sticky='w')

start_button = tk.Button(window, text='开始', command=create_document, width=20, height=2)
start_button.grid(row=10, column=1, pady=10)

status_label = tk.Label(window, text='', fg='blue')
status_label.grid(row=11, column=1)

window.mainloop()





免费评分

参与人数 8吾爱币 +12 热心值 +7 收起 理由
MQ19781011 + 1 + 1 我很赞同!
wanfon + 1 + 1 热心回复!
helian147 + 1 + 1 热心回复!
qck + 1 + 1 谢谢@Thanks!
yanglinman + 1 谢谢@Thanks!
only2025 + 1 加油
hrh123 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
laserword + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

sai609 发表于 2025-10-14 11:36
这软件有bug,当图片文件名的字数超过该栏一行的,第二行文字会被隐藏,除非人工拉伸图片排版的分割线
so请增加
1、增加word图片下面的三层文件名称栏位(除备注文件名称外,可能还需要另外备注其他信息)
2、同一栏位字数会随着字数添减而自动排版上下左右图片对应的分隔线(不至于第二行文字被分隔线隐藏)
yemind 发表于 2025-8-15 16:54
Alliswell9527 发表于 2025-8-15 17:12
sktao 发表于 2025-8-15 17:23
非常好的程序  很方便
777444 发表于 2025-8-15 19:22
搞一个照片整理
无名 发表于 2025-8-15 19:30
转蓝奏云:
https://wwjn.lanzout.com/iFggz33mc91g
密码:9obw
ly1700 发表于 2025-8-15 20:05
Alliswell9527 发表于 2025-8-15 17:12
可以,挺好的,我现在是AI程序插入

请问如何使用ai插入呀,求教
一场荒唐半生梦 发表于 2025-8-15 20:34
等一个其他盘
sunson1097 发表于 2025-8-15 23:56
我是来学tk怎么写的
DODOZERO 发表于 2025-8-16 00:24

这个小工具可以
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-15 23:00

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表