循环工作表、复制范围、粘贴到不同的工作簿

问题描述 投票:0回答:2

我有两个带有许多选项卡的 Excel 工作簿,但是两个 Excel 文件之间的它们是相同的,并且顺序相同。 这是针对财务报告的,我每月获取更新(实际数据),然后用它来更新预测。 我不能简单地合并或连接数据框,我需要复制相同的范围(例如本月的更新)并覆盖预计的每月数据。

我有下面的代码,可以让我从源复制一个范围并将其粘贴到目标中。我想要一些更干净的东西,但这已经过测试并且有效。 这里的问题是我已经明确命名了一个工作表以使代码能够工作。 如何让 python 循环执行从工作表 1(源 Excel 文件)复制范围并粘贴到目标文件的工作表 1,然后移动到所有后续工作表的过程?

import openpyxl
#File to be copied
wb = openpyxl.load_workbook(r'C:\Users\source.xlsx') 
sheet = wb["Combined Total by Month"]

#File to be pasted into
template = openpyxl.load_workbook(r'C:\Users\destination.xlsx')
temp_sheet = template["Combined Total by Month"] 

#Copy range of cells as a nested list
#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

#Paste range
#Paste data from copyRange into template sheet
def pasteRange(startCol, startRow, endCol, endRow, sheetReceiving,copiedData):
    countRow = 0
    for i in range(startRow,endRow+1,1):
        countCol = 0
        for j in range(startCol,endCol+1,1):
            sheetReceiving.cell(row = i, column = j).value = copiedData[countRow][countCol]
            countCol += 1
        countRow += 1
def createData():
    selectedRange = copyRange(17,11,19,29,sheet) 
    pastingRange = pasteRange(16,11,18,29,temp_sheet,selectedRange) 
template.save("output.xlsx")
python excel tabs openpyxl worksheet
2个回答
1
投票

对于您的具体问题,我认为您只是要求在工作簿(wb)中循环工作表,以便您可以使用工作簿中的每个工作表调用复制和粘贴功能。
有两个主要选项可以做到这一点;

  1. wb.工作表
  2. wb.sheetnames

第一个是工作簿中实际工作表对象的列表,而第二个是工作表名称的列表。
工作表对象显然是特定于列表列表所在工作簿的。
我建议在这里使用名称作为

  1. 然后源工作簿或目标工作簿可以使用它们来获取正确的工作表对象
  2. 如果您有不想复制的表格,可以根据名称删除它们。
  3. 您绝对确定在两个工作簿中使用同一张工作表 但是,循环工作表然后获取当前工作表的标题以用于引用其他工作簿中的工作表仍然是有效的,例如
for worksheet in wb.worksheets:
    # worksheet is the worksheet object of the source workbook
    print(worksheet['A1'].value)
    # Create the destination worksheet from the source worksheet name
    template_ws = template[worksheet.title]
    print(template_ws['A1'].value)

正如另一个答案中提到的,如果它们与您指定的顺序相同,您可以使用任一列表中的工作表索引(在 Excel 中不一定保证,但应该如此)。 如果需要,您可以使用sheet_name检查它是否符合标准,例如包括“总计”或“月份”或“合并总计”等词


...
def createData():
    for sheet_name in wb.sheetnames:
        if <sheet_name fits criteria>:
            selectedRange = copyRange(17,11,19,29,sheet_name)
            pastingRange = pasteRange(16,11,18,29,sheet_name,selectedRange)

然后,如果两者使用不同的工作簿,则在函数中使用适当的工作簿对象创建工作表对象。 例如

def copyRange(startCol, startRow, endCol, endRow, sheetn):
    sheet = wb[sheetn]
    rangeSelected = []
    ...

def pasteRange(startCol, startRow, endCol, endRow, sheetn, copiedData):
    sheetReceiving = template[sheetn]
    countRow = 0
    ...

但是您的代码似乎不必要地复杂,您应该能够仅在一个操作中复制和粘贴。
读取范围内的单元格,然后复制到另一个工作簿工作表中偏移一列的同一单元格。

import openpyxl
#File to be copied
wb = openpyxl.load_workbook('source.xlsx')

#File to be pasted into
template = openpyxl.load_workbook('destination.xlsx')


def copy_paste(startCol,startRow,endCol,endRow):
    for sheet_name in wb.sheetnames:

        for row in wb[sheet_name].iter_rows(min_row=startRow,min_col=startCol,max_row=endRow,max_col=endCol):
            for cell in row:
                cell_coord = cell.coordinate
                ### Copy Source workbook cell value to the same cell (offset by one column) in the destination workbook
                ### So value in 'Q11' is copied to 'P11' etc
                template[sheet_name].cell(row=cell.row, column=cell.column-1).value = cell.value


copy_paste(17,11,19,29)
template.save("output.xlsx")

0
投票

您可以通过索引获取它们:

ws = wb.worksheets[0] 
ts = template.worksheets[0]

其中 0 是第一张工作表,1 是第二张工作表,依此类推,如果两个工作簿上工作表的顺序相互关联,或者您知道哪些工作表相互对应。

© www.soinside.com 2019 - 2024. All rights reserved.