python批量插入图片到word--10种插入方式

查看 62|回复 9
作者:noforgvie   
逛论坛发现一个帖子,里面的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 (247.61 KB, 下载次数: 1)
下载附件
2025-8-15 15:52 上传



横向-显示文件名-不带后缀-每页一张.jpg (128.25 KB, 下载次数: 1)
下载附件
2025-8-15 15:52 上传



程序界面.jpg (45.02 KB, 下载次数: 3)
下载附件
2025-8-15 15:52 上传


源码如下,可根据自己的实际需求微调:
[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  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

每页, 图片

yemind   

好东西 赞一个
Alliswell9527   

可以,挺好的,我现在是AI程序插入
sktao   

非常好的程序  很方便
777444   

搞一个照片整理
无名   

转蓝奏云:
https://wwjn.lanzout.com/iFggz33mc91g
密码:9obw
ly1700   


Alliswell9527 发表于 2025-8-15 17:12
可以,挺好的,我现在是AI程序插入

请问如何使用ai插入呀,求教
一场荒唐半生梦   

等一个其他盘
wu1357924680   

这个小工具可以
sunson1097   

我是来学tk怎么写的
您需要登录后才可以回帖 登录 | 立即注册