如何批量获取excel的图片并准确命名?自动化办公 | 快速从Excel中提取图片并匹配命名

需求:当有一张如下图所示的excel表,一列是图片,另一列是图片对应的名称(如型号)。如何把里面的图片批量下载下来并按对应列的单元格命名呢?

这个过程,在Python里可以这么做:

import os
import zipfile
# 判断是否是文件和判断文件是否存在
def isfile_exist(file_path):
    if not os.path.isfile(file_path):
        print("It's not a file or no such file exist ! %s" % file_path)
        return False
    else:
        return True
          
        
# 修改指定目录下的文件类型名,将excel后缀名修改为.zip
def change_file_name(file_path, new_type='.zip'):
    if not isfile_exist(file_path):
        return ''

    extend = os.path.splitext(file_path)[1]  # 获取文件拓展名
    if extend != '.xlsx' and extend != '.xls':
        print("It's not a excel file! %s" % file_path)
        return False

    file_name = os.path.basename(file_path)  # 获取文件名
    new_name = str(file_name.split('.')[0]) + new_type  # 新的文件名,命名为:xxx.zip

    dir_path = os.path.dirname(file_path)  # 获取文件所在目录
    new_path = os.path.join(dir_path, new_name)  # 新的文件路径
    if os.path.exists(new_path):
        os.remove(new_path)

    os.rename(file_path, new_path)  # 保存新文件,旧文件会替换掉

    return new_path  # 返回新的文件路径,压缩包


# 解压文件
def unzip_file(zipfile_path):
    if not isfile_exist(zipfile_path):
        return False

    if os.path.splitext(zipfile_path)[1] != '.zip':
        print("It's not a zip file! %s" % zipfile_path)
        return False

    file_zip = zipfile.ZipFile(zipfile_path, 'r')
    file_name = os.path.basename(zipfile_path)  # 获取文件名
    zipdir = os.path.join(os.path.dirname(zipfile_path), str(file_name.split('.')[0]))  # 获取文件所在目录
    for files in file_zip.namelist():
        file_zip.extract(files, os.path.join(zipfile_path, zipdir))  # 解压到指定文件目录

    file_zip.close()
    return True


# 读取解压后的文件夹,打印图片路径
def read_img(zipfile_path):
    if not isfile_exist(zipfile_path):
        return False

    dir_path = os.path.dirname(zipfile_path)  # 获取文件所在目录
    file_name = os.path.basename(zipfile_path)  # 获取文件名
    pic_dir = 'xl' + os.sep + 'media'  # excel变成压缩包后,再解压,图片在media目录
    pic_path = os.path.join(dir_path, str(file_name.split('.')[0]), pic_dir)

    file_list = os.listdir(pic_path)
    for file in file_list:
        filepath = os.path.join(pic_path, file)
        print(filepath)


# 组合各个函数
def compenent(excel_file_path):
    zip_file_path = change_file_name(excel_file_path)
    if zip_file_path != '':
        if unzip_file(zip_file_path):
            read_img(zip_file_path)


# main
if __name__ == '__main__':
    compenent('C:/Users/dell/Desktop/XXX.xlsx')

压缩再解压虽然一次性得到了图片,但是该图片命名方式(“image”+序号)并不是我们所想要的。更麻烦的是,图片的序号跟excel表里图片的顺序并不一致,而且是乱序的,导致不能使用批量重命名的手法修改该图片名称。

如何批量获取excel的图片并准确命名?自动化办公 | 快速从Excel中提取图片并匹配命名

换言之,这种烂大街的方法只解决了我们问题的一半,而且剩下那半还很不容顺下去解决。有效的解决方案请看下文!

解决方案

Python法:

既然上述压缩再解压的方法不行,Python要换个思路。引用openpyxl库。核心代码如下:

import openpyxl
from openpyxl_image_loader import SheetImageLoader
import tkinter as tk
from tkinter import filedialog

# 制作获取文件的弹窗
root = tk.Tk()
root.wm_attributes('-topmost',1) # 弹窗置顶
root.withdraw()
file_path = filedialog.askopenfilename()  # 获取 excel 路径
# 加载excel表和图片
pxl_doc = openpyxl.load_workbook(file_path) 
sheet = pxl_doc[Sheet]  # excel的Sheet名
image_loader = SheetImageLoader(sheet)

# 用pd获取图片所在列的起止行号list——ls, 此处省略代码
# 用pd获取图片名称所在列list——image_name,此处省略代码

for i in range(len(ls)):
    #get the image (put the cell you need instead of 'A1')
    image = image_loader.get("C"+str(ls[i]))  # 假设图片在C列
    image.save('/文件夹/'+image_name[i]+'.jpg')

VBA方法: 首先,把excel另存为xlsm格式,然后同时按alt和F11调出VBA编辑器,接着输入以下代码。该代码比较详细地考虑了图片输出的各种场景,详解代码里的中文注释。最后点击编辑器上方的运行就会实现我们的需求。
如何批量获取excel的图片并准确命名?自动化办公 | 快速从Excel中提取图片并匹配命名

Sub 输出图片并重命名()
    '做一个文件搜索框,让用户选择输出文件夹
    OpenFile = Application.GetOpenFilename("请选择任一文件后按确定(*.*),*.*", , "选择任一文件确定图片输出文件夹,或取消获得当前文件所在文件夹。")

    If OpenFile = False Then
        myDir = ThisWorkbook.Path & "\"
    Else
        myDir = Left(OpenFile, InStrRev(OpenFile, "\"))
    End If
   
   '判断图片名称列是在图片列的左边还是右边
    k = InputBox("1=列左,2=列右,3=上一行,4=下一行,取消=图片所在单元格或无名称", "选择图片名称位置:", 2)
    If k = 1 Then
        r = 0: c = -1
    ElseIf k = 2 Then
        r = 0: c = 1
    ElseIf k = 3 Then
        r = -1: c = 0
    ElseIf k = 4 Then
        r = 1: c = 0
    End If
    
    '设置导出图片的尺寸
    k = MsgBox("Yes=按原尺寸,No=按新设定,Cancel=按现在显示", vbYesNoCancel, "输出图片尺寸大小选择")
    For Each p In ActiveSheet.Shapes
        ph = p.Height
        pw = p.Width
        On Error Resume Next
        pn = p.TopLeftCell.Offset(r, c).Value
        If Err.Number <> 0 Then Err.Clear
        If pn = "" Then n = n + 1: pn = Left(ThisWorkbook.Name, InStrRev(ThisWorkbook.Name, ".") - 1) & Format(n, "000")
     
     '图片重命名   
GetPicName:
        On Error Resume Next
        p.Name = pn & ".jpg"
        If Err.Number <> 0 Then
            Err.Clear
            pn = InputBox("图片名称重复,请重新命名", "图片名称重复", pn)
            GoTo GetPicName
        End If
        
        p.Select
        If k = vbYes Then
            Selection.Copy
            ActiveSheet.PasteSpecial Format:="图片 (JPEG)" '英文版为"Picture (JPEG)"
            Selection.Name = "myPic"
        ElseIf k = vbNo Then
            Selection.ShapeRange.LockAspectRatio = msoFalse
            f = InputBox("放大缩小比率", "图片尺寸设定", 2)
            If IsNumeric(f) And f > 0 Then
                Selection.ShapeRange.Height = ph * f
                Selection.ShapeRange.Width = pw * f
            Else
                Selection.ShapeRange.Height = InputBox("重新设定图片高度", "图片高尺寸设定", ph)
                Selection.ShapeRange.Width = InputBox("重新设定图片宽度", "图片宽尺寸设定", pw)
            End If
        End If
       
       '图片导出       
        Selection.CopyPicture
        With ActiveSheet.ChartObjects.Add(0, 0, Selection.Width + 5, Selection.Height + 5).Chart
            .Paste
            .Export myDir & p.Name, "JPG"
            .Parent.Delete
        End With
        
        If k = vbYes Then
            ActiveSheet.Shapes("myPic").Delete
        ElseIf k = vbNo Then
            p.Height = ph
            p.Width = pw
        End If
        p.TopLeftCell.Offset(r, c).Select
    Next
   
End Sub

VBA代码,有需要的同学自己学习研究一下

Sub 导出图片()
    On Error Resume Next
    MkDir ThisWorkbook.Path & "\图片"
    For Each pic In ActiveSheet.Shapes
        If pic.Type = 13 Then
            RN = pic.TopLeftCell.Offset(0, -1).Value
            pic.Copy
            With ActiveSheet.ChartObjects.Add(0, 0, pic.Width, pic.Height).Chart    '创建图片
                .Parent.Select
                .Paste
                .Export ThisWorkbook.Path & "\图片\" & RN & ".jpg"
                .Parent.Delete
            End With
        End If
    Next
End Sub
© 版权声明 本站提供的所有软件、素材和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络收集搬砖整理,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。如果您喜欢该程序和内容,请支持正版,购买注册,得到更好的正版服务。我们非常重视版权问题,如若本站内容侵犯了原著者的合法权益,携带权利证明请发送邮箱到 liukaien@foxmail.com 指出,我们将及时做出处理。声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

给TA打赏
共{{data.count}}人
人已打赏
技术教程精品软件

凯玄数字生活指南软件集合-办公必备

2024-7-21 22:56:38

技术教程精品软件

无人驾驶航空器飞行管理暂行条例

2024-7-25 15:49:42

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧