excel Python代码只使用openpyxl从第二个工作簿复制数据-第一个工作簿有问题吗?

l2osamch  于 2023-03-20  发布在  Python
关注(0)|答案(2)|浏览(195)

为什么我的Python代码只能使用openpyxl从第二个工作簿复制数据,而不能从第一个工作簿复制数据,即使代码看起来编写正确?
代码分为三个部分:

块1:导入库和设置路径

该块导入必需的库,如openpyxl、os和re。输入和输出目录的路径也使用input_path和output_path变量设置。

import openpyxl
import os
import re

input_path = r'C:\\Users\\input'
output_path = r'C:\\Users\\output'
res = []

块2:定义函数该块定义以下函数:
**subs(file_name)**该函数以file_name为输入,用下划线替换文件名中的年份值,返回修改后的文件名。
**获取数据(file_path)**此函数将file_path作为输入,并检查文件名中的年份值是2021还是2022。如果是2021,则加载工作簿和名为“DRE”的工作表,并将数据复制到新创建的工作簿中名为“_2021”的工作表中。如果是2022,加载工作簿和名为“DRE”的工作表,并将数据复制到新建工作簿的名为“_2022”的工作表中,最后将复制了数据的新建工作簿保存到输出目录中,如果年份值有效,则返回file_path,否则,则返回None。
块3:与输入目录交互这个块使用for循环遍历输入目录中的所有文件,对于每个文件,它检查对象是否是文件,如果是,它将文件名添加到res列表中。

# interact with the directory
for p in os.listdir(input_path):
    # checar se o obejto atual é um arquivo
    if os.path.isfile(os.path.join(input_path, p)):
        res.append(p)

第四区:主逻辑这个代码块使用一个for循环来遍历res列表中的所有文件名。它使用openpyxl库创建一个包含两个工作表“_2021”和“_2022”的新工作簿,然后加载新创建的工作簿并将工作表分别赋给ws21和ws22变量。()函数将数据从原始Excel文件复制到新创建的Excel文件中。

for r in res:
    nw = openpyxl.Workbook()
    file = str(r)
    file = subs(file)
    nw.create_sheet('_2021')
    nw.create_sheet('_2022')
    nw.save(output_path + '\\' + file)

    wbn = openpyxl.load_workbook(output_path + '\\' + file, data_only=True)
    ws21 = wbn['_2021']
    ws22 = wbn['_2022']

    get_data(input_path + '\\' + r)

总而言之,该代码从目录中读取Excel文件,创建新的Excel文件,并将数据从原始文件复制到新创建的文件中。

完整代码

import openpyxl
import os
import re

input_path = r''
output_path = r''
res = []

def subs(file_name):
    if re.search(r' 2021 ', file_name):
        file_name = file_name.replace(' 2021 ', '_')
    elif re.search(r' 2022 ', file_name):
        file_name = file_name.replace(' 2022 ', '_')
    return file_name

def get_data(file_path):
    if re.search(r' 2021 ', file_path):
        data = file_path
        wb = openpyxl.load_workbook(data, data_only=True)
        ws = wb['DRE']

        for row in ws:
            for cell in row:
                ws21[cell.coordinate].value = cell.value

        wbn.save(output_path + '\\' + file)
    
    elif re.search('2022', file_path):
        data = file_path
        wb = openpyxl.load_workbook(data, data_only=True)
        ws = wb['DRE']

        for row in ws:
            for cell in row:
                ws22[cell.coordinate].value = cell.value

        wbn.save(output_path + '\\' + file)

    else:
        data = None
    return data

# interagir com o diretório apresentado
for p in os.listdir(input_path):
    # checar se o obejto atual é um arquivo
    if os.path.isfile(os.path.join(input_path, p)):
        res.append(p)

for r in res:

    nw = openpyxl.Workbook()
    file = str(r)
    file = subs(file)
    nw.create_sheet('_2021')
    nw.create_sheet('_2022')
    nw.save(output_path + '\\' + file)
    # nw.close()

    # Planilha compilada com as abas de 2021 e 2022
    wbn = openpyxl.load_workbook(output_path + '\\' + file, data_only=True)
    ws21 = wbn['_2021']
    ws22 = wbn['_2022']

    get_data(input_path + '\\' + r)
mftmpeh8

mftmpeh81#

与前面的注解沿着,此示例代码显示了如何使其更有效。
我不知道你的原始xlsx文件的名称,除了他们似乎包括一个年份日期,如'_2021_''_2022_',或有多少表每个。这段代码应该管理这一点,只是复制名称为'DRE'的表到新的工作簿,命名它从第一个文件名与日期删除,并保存。
代码操作;
1.subs*函数和带有注解*interagir com o diretório apresentado的部分似乎没有必要。
新工作簿只有一个名称,因此可以用类似的方法从第一个文件中获取。要创建此文件名,如果此文件包含“*2021 ”,'2022'或甚至'2023',则可以更改regex模式以查找以20开头的日期,然后查找要删除的2个数字(带下划线)。文件名在处理第一个文件时生成。
更新后的代码中不再使用
res
列表,因此不再需要此部分,本示例中也不再使用此部分。
1.为了复制工作表,我们循环查找xlsx文件名。因为我不知道
input_path
中可能存在哪些文件名,所以我从input_path中包含数字'20'且扩展名为. xlsx的文件创建了文件列表。这可能不足以过滤到您想要的特定文件,因此如果需要,可以扩展此过滤。
现在我们假设列表中只包含要从中复制的文件。
1.考虑到新工作簿是来自现有工作簿的工作表的副本,而不是创建新工作表并依次从每个工作簿复制每个工作表,新工作簿可以作为第一个文件减去任何不需要的工作表的副本开始。因此,在files循环的第一次迭代(其由file_count确定)上,new_wb对象是通过打开first xlsx file创建的工作簿。如果在第一个文件中存在“DRE”以外的工作表(我认为您不希望这样),循环删除所有工作表,除了重命名为
*'dre_{file date}'**的'DRE'工作表。

如果xlsx文件只有图纸“DRE”,则可以跳过图纸删除,只重命名图纸。

这是从完成的第一个xlsx文件复制的第一个“DRE”图纸。
1.在文件的第二个循环中,对于下一个'DRE'工作表,我们需要将单元格值复制到新工作簿中的新工作表中。source sheet也是已知的,因此我们可以直接选择它,并且可以从file name date创建和命名target sheet。然后,我们将工作表值逐个单元格复制到这个新工作表中。
1.复制完值后,循环将转到下一个文件(如果存在),然后再次完成步骤4。如果不存在其他文件,则保存新工作簿,并结束代码运行。
所以你可以看到这是非常简化和快速和工作表复制单元格的数量减少了1。
复制单元格后不需要关闭源工作簿,事实上,除非文件以read-onlywrite-only打开,否则wb.close什么也不做。
新工作簿创建/打开一次,并在复制数据后保存在末尾。

import openpyxl
import os
import re

def file_date(f):
    return re.findall('20[\d]{2}', f)[0]

input_path = r'F:\PycharmProjects\Stack7\Stack1\ExcelFiles'
output_path = r'F:\PycharmProjects\Stack7\Stack1\OutExcelFiles'

new_filename = ''
sheet_name = 'DRE'
### Get files list where the file name includes '20' and extension is .xlsx
files = [f for f in os.listdir(input_path) if '20' in f and f.endswith('.xlsx')]

for file_count, file in enumerate(files):
    data = []

    ### First workbook can become the new workbook
    if file_count == 0:
        ### New workbook has one name only, we can get this from the first wb
        new_filename = re.sub(r'_20[\d]{2}_', '_', file)
        ### New workbook is the first opened workbook
        new_wb = openpyxl.load_workbook(os.path.join(input_path, file), data_only=True)
        ### If there are other Sheets in the original workbook these can be removed
        ### The 'DRE' Sheet to keep is be renamed to 'dre_20{file date}
        for sheet in new_wb.sheetnames:
            if sheet != sheet_name:
                del new_wb[sheet]
            else:
                new_wb[sheet_name].title = f'{sheet_name.lower()}_{file_date(file)}'

    ### Second and subsequent files need to copy sheet to sheet
    else:
        ### Open next workbook 
        wb = openpyxl.load_workbook(os.path.join(input_path, file), data_only=True)

        ### Only want to copy sheet 'DRE' so just need to select that sheet as source
        source_sheet = wb[sheet_name]
        ### Sheet to copy to is new. Rename to 'dre_{file date}
        target_sheet = new_wb.create_sheet(f'{sheet_name.lower()}_{file_date(file)}')

        ### Copy cell data from source to target cell by cell
        for (row, col), source_cell in source_sheet._cells.items():
            target_cell = target_sheet.cell(column=col, row=row)
            target_cell.value = source_cell.value

### Save the new file one time
new_wb.save(f'{output_path}\\{new_filename}')
uxh89sit

uxh89sit2#

@moken,非常感谢你的建议,我需要重新构造代码的方式,它对应于你提出的点,我的代码执行完美。

import openpyxl
import glob
import os
import re

output_path = r'C:\\Users\\output'
input_path = r'C:\\Users\\input'
res = []

def subs(name):
    if re.search(r'_2021_', name):
        name = name.replace('_2021_', '_')
    elif re.search(r'_2022_', name):
        name = name.replace('_2022_', '_')
    return name

### This code is not used and not needed
## interagir com o diretório apresentado
#for p in os.listdir(input_path):
#    # checar se o obejto atual é um arquivo
#    if os.path.isfile(os.path.join(input_path, p)):
#        res.append(p)

files = os.listdir(input_path)

for file in files:
    name = str(file)
    name = subs(name)

    if file.endswith('.xlsx') and '2021' in file:
        wb = openpyxl.load_workbook(os.path.join(input_path, file), data_only=True)
        data = []

        for sheetname in wb.sheetnames:
            sheet = wb[sheetname]
            sheet_data = []

            for row in sheet.iter_rows():
                row_data = []

                for cell in row:
                    row_data.append(cell.value)
                sheet_data.append(row_data)
            data.append((sheetname, sheet_data))
        
        wb.close()

        new_wb = openpyxl.Workbook()

        for sheetname, sheet_data in data:
            new_sheet = new_wb.create_sheet('dre_2021')

            for row_data in sheet_data:
                new_sheet.append(row_data)

        new_filename = f'{name}'
        new_wb.save(output_path + '\\' + new_filename)
        new_wb.close()

    if file.endswith('.xlsx') and '2022' in file:
        wb = openpyxl.load_workbook(os.path.join(input_path, file), data_only=True)
        data = []

        for sheetname in wb.sheetnames:
            sheet = wb[sheetname]
            sheet_data = []

            for row in sheet.iter_rows():
                row_data = []

                for cell in row:
                    row_data.append(cell.value)
                sheet_data.append(row_data)
            data.append((sheetname, sheet_data))
        
        wb.close()

        new_filename = f'{name}'
        new_wb = openpyxl.load_workbook((output_path + '\\' + new_filename))

        for sheetname, sheet_data in data:
            new_sheet = new_wb.create_sheet('dre_2022')

            for row_data in sheet_data:
                new_sheet.append(row_data)

        new_wb.save((output_path + '\\' + new_filename))
        new_wb.close()

相关问题