【问题标题】:Python - read excel file into a list and rename files in a folderPython - 将excel文件读入列表并重命名文件夹中的文件
【发布时间】:2019-02-13 03:56:16
【问题描述】:

我们有一个 2094 行 3 列的 excel 文件,结构如下:

员工旧 ID |员工姓名 |员工新身份证

007219 |约翰·多伊 | 001234

最终结果是:John Doe 001234.jpg

我们有一个文件夹,其中包含员工旧 ID 的照片标签,我们想要读取 excel 文件,然后使用新 ID 复制和重命名照片。

代码问题 - 它在复制并重命名第一张照片后停止。我想我需要调整最后一个 for 循环,但我对如何让它进行迭代持空白。

注意:我试图通过包含一个文件对话框 folderSource 来使代码更灵活。另外,我是 Python 的新手,所以如果您想尽办法清理代码,请告诉我,我在代码的 cmets 中添加了一些问题:

import openpyxl
import os
import shutil
from tkinter import *
from tkinter import filedialog

root = Tk()
root.withdraw()

# File with file name data
# Add the file name
file_names = openpyxl.load_workbook(filedialog.askopenfilename())
# Add the sheet name - can you make this more flexible? 
file_names_sheet = file_names['piclist2']  

# Select the source folder with files in it
folderSource = filedialog.askdirectory()

# New Folder Name - is there a filedialog way to flexibly create this?
folderDestination = 'SSL Photos Renamed'

# Takes: start cell, end cell, and sheet you want to copy from.
def copyRange(startCol, startRow, endCol, endRow, sheet):
    rangeSelected = []
    # Loops through selected Rows
    for i in range(startRow, endRow + 1, 1):
    # Appends the row to a RowSelected list
        rowSelected = []
        for j in range(startCol, endCol + 1, 1):
            rowSelected.append(sheet.cell(row=i, column=j).value)
    # Adds the RowSelected List and nests inside the rangeSelected
    rangeSelected.append(rowSelected)

return rangeSelected


def renameFiles():
    print('Processing...')

    # Make a folder for the files
    current_directory = os.getcwd()
    folder_n_path = os.path.join(current_directory, folderDestination)
    print("Files saved to: " + folder_n_path)
    try:
    newFolder = os.makedirs(folder_n_path)

except:
    print("Folder already exists")
    return

# Get the Data to make the file names
selectedRange = copyRange(1, 1, 2, 2, file_names_sheet)
print(selectedRange)

for i, filename in zip(selectedRange, os.listdir(folderSource)):
    print(filename)
    file_name = str(i[0]) + " " + i[1] + ".jpg"
    filename = os.path.join(folderSource, filename)
    file_name = os.path.join(folderDestination, file_name)
    shutil.copy(filename, file_name)
    print("Done")

go = renameFiles()

我认为问题出在最后一段代码中,但我不知道如何进行循环。想法?

【问题讨论】:

  • 在循环中的每个变量赋值后运行打印,看看值是否如您所愿,这将帮助您快速解决问题所在。例如:for filename in os.listdir(folderSource): print(filename), filename = os.path.join(folderSource, filename) print(filename) file_name = os.path.join(folderDestination, file_name) print(file_name) ... 每个打印命令都应该在自己的行上运行。
  • 所以它循环遍历文件夹源目录中的文件名,它没有做的是从 selectedRange 移动到列表中的下一个文件名:第一次循环: C:/Users/jx00/Documents/PythonTest/Photos - Copy\000232.jpg. Photos Renamed\000197 MC.jpg. 第二次循环抓取下一张照片,但仍在使用之前的重命名文件名: C:/Users/jx00/Documents/PythonTest/Photos - Copy\000292.jpg. Photos Renamed\Photos Renamed\000197 MC.jpg Thoughts?
  • The line ` for i in range(startRow, endRow, 1): # 将行追加到 RowSelected 列表 rowSelected = []` 没有做任何事情。您没有在此列表中添加任何内容。另一方面,for j in range(startCol, endCol+1, 1): 是否应该嵌套?
  • 我看到了编辑,明白了。对于最后一个循环for filename in os.listdir(folderSource):,它将遍历 folderSource 中的每个文件,并将其添加到选定范围内的第一个 i 中(我假设这不是您想要的。然后它将添加 folderSource 中的每个文件名到在 selectedRange 中 i 的第二次迭代,这显然不是你想要的。

标签: python excel rename openpyxl shutil


【解决方案1】:

在您的最后一个循环中尝试此方法,然后告诉我结果如何,可能需要进行一些修改,因为我看不到您的数据。看来你想在列表上一起运行 for 循环,所以试试这个:

for i, filename in zip(selectedRange, os.listdir(folderSource)):
    file_name = str(i[1]) + " " + i[2] + ".jpg"
    filename = os.path.join(folderSource, filename)
    file_name = os.path.join(folderDestination, file_name)
    shutil.copy(filename, file_name)
print(done)
go = renameFiles()

对于嵌套的 for 循环结构,请考虑以下事项:

loop1 = ['a','b','c','d','e']
loop2 = ['f','g','h','i','j']
for i in loop1: # iterates through a,b,c,d,e
    print(i) #prints a,b,c,d,e
    for j in loop2: # compares all j objects of loop2 to i in loop 1:
        ij = i + j
        print(ij) # this will add all j's to each i

sn-p 输出会在 i 的每次迭代中添加所有 j,然后再移动到 i 的下一次迭代:

'af','ag','ah','ai','aj','bf','bg','bh','bi',bj'... etc

将 2 个列表压缩在一起,(这是我在答案中所做的)将 loop1 中的每个元素与两个列表中相同索引处的 loop2 进行比较:

for i,j in zip(loop1,loop2):
    ij = i + j
    print(ij)

输出:

'af','bg','ch','di','ej'

当您对 2 个列表使用 zip 函数时,唯一需要考虑的是迭代只会发生到最短列表的末尾。因此,如果 loop1 和 loop2 的长度不相等,那么 i+j 将在较短的列表完成后停止。我希望这能澄清我所做的一些事情。

【讨论】:

  • 不得不更改范围,但效果很好。是的,这就是我想要做的。因此,对于我的学习(我来自一点 VBA)- 似乎我被困在较低的 for loop 中并且没有循环回到 selectedRange loop。那是对的吗?如果是这样,将来当我想嵌套 for loops 时,我是否需要像你一样构造它们?第一个for 代码行中的所有变量,然后在下面引用它们?非常感谢!
  • 我将编辑我的答案,向您展示嵌套 for 循环的工作原理。
  • @JasonDL 查看编辑以回答以了解 2 个不同的列表遍历是如何工作的。
  • 我添加了一个if 语句,以便代码查找文件,然后根据您帮助我完成的循环复制并重命名它。上面的代码已编辑 - filesToFindRange 列表正在正确加载,但它一直说找不到文件。想法?
  • 是的,你不需要 if 语句中的 for 循环,你的 if 语句中的 for 循环应该是顶层 for 循环。然后你可以包含你的 if 语句,if filename in filesToFind: 在下面做所有事情。您不需要在 if 语句下包含 for 循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 1970-01-01
  • 1970-01-01
  • 2016-12-18
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多