【问题标题】:Openpyxl - Transfer range of rows from a worksheet to anotherOpenpyxl - 将行范围从工作表转移到另一个
【发布时间】:2020-05-19 10:02:54
【问题描述】:

我想从一张表中取出某部分数据并将其复制到另一张表中。

到目前为止,我有一个字典,其中键作为开始行,值作为结束行。

使用这个,我想做以下事情:

-从 sheet0 中获取第一个范围并将其附加到 sheet1

-从 sheet0 中获取第二个范围并将其附加到 sheet2

-从 sheet0 中获取第三个范围并将其附加到 sheet3

我尝试了以下方法:

#First range starts at 1 and ends at 34, second range from 34-52 and third from 52-75
myDict = {1: 34, 34: 52, 52: 75}

#store all the sheets, ignoring main sheet
sheet = wb.worksheets[1:] 


for item in myDict:
    for col in ws.iter_cols(min_row=item, max_row=myDict[item], min_col=1 , max_col=ws.max_column):
        for cell in col:
            for z in sheet:
                z.append(col)

另一种方法是使用函数和列表:

startRow=[1,34,52]
endRow=[34,52,75]

def addRange(first, second):
    for col in ws.iter_cols(min_row=first, max_row=second, min_col=1 , max_col=ws.max_column):
        for cell in col:
            for z in sheet:
                z.append(col)    

#Call function    
for start, end in zip(startRow, endRow):
    addRange(start, end)  

但在这两种情况下,我都会收到以下错误“ValueError:无法从其他工作表复制单元格”

有人知道我在这里缺少什么吗?

提前致谢!

【问题讨论】:

  • 我注意到几件事:你的代码中没有 ws 声明。您不能将 col 附加到工作表。你要附加值。因此,您必须迭代到单元格级别,然后将单元格值添加到您的工作表中。找到一种方法来压缩带有范围的工作表名称,这应该会让你的迭代更容易
  • 感谢萨米的提问。我没有添加不必要的介绍代码。 ws 是这样制作的:#wb = xl.Workbook() #ws = wb.active
  • @sammywemmy 我添加了“for cell in col”来遍历单元格。
  • 分享一个示例文件,我会用它来看看问题出在哪里,或者建议其他方法
  • @sammywemmy 我在这里使用 WeTransfer 添加了 Excel 文件和 Info 记事本文件:wetransfer.com/downloads/…

标签: python excel pandas openpyxl


【解决方案1】:
from openpyxl import load_workbook
from itertools import product

filename = 'wetransfer-a483c9/testFile.xlsx'
wb = load_workbook(filename)

sheets = wb.sheetnames[1:]

sheets['Table 1', 'Table 2', 'Table 3']

# access the main worksheet
ws = wb['Main']

首先,获取每个表的边界(起点/终点)

span = []
for row in ws:
    for cell in row:
        if (cell.value
                and (cell.column == 2)  # restrict search to column2, which is where the Table entries are
                # this also avoids the int error, since integers are not iterable
                and ("Table" in cell.value)):
            span.append(cell.row)

# add sheet's length -> allows us to effectively capture the data boundaries
span.append(ws.max_row + 1)

结果span[1, 29, 42, 58]

其次,得到边界的配对。 +1 确保在捕获表格并将它们转换为 string 格式时包含结尾 由于 openpyxl 以字符串形式引用边界,并且有一个 1 的索引表示法,所以你必须去掉一个,而不是加 1。

boundaries = [":".join(map(str,(start, end-1)))  for start, end in zip(span,span[1:])]

结果boundaries['1:28', '29:41', '42:57']

第三,创建主工作表、边界和其他工作表的笛卡尔坐标。请注意,边界和床单是带拉链的——本质上它们是一对。因此,我们将每个表与边界配对:

#table 1 is bound to 1:28,
#table 2 is bound to 29:41, ...

接下来,我们将主表与配对组合,因此主表与(table 1, 1:28) 配对。同一张主表与(table 2, 29:41) ...配对

第四,获取范围内的数据。由于我们已经成功地将主工作表与每一对表格和边界配对,我们可以安全地获取该特定区域的数据并将其转移到特定表格。

所以主表中的table 1 指的是1:28,因为它绑定到这个特定的表。当使用table 1 完成时,它返回循环并从“表2”开始,只选择“29:41”,因为这是本节的限制,依此类推。

for main,(ref, table) in product([ws],zip(boundaries, sheets)):

    sheet_content = main[ref]
    # append row to the specified table

    for row in sheet_content:
        #here we iterate through the main sheet
        #get one row of data
        #append it to the table
        #move to the next row, append to the table beneath the previous one
        #and repeat the process till the boundary has been exhausted
        wb[table].append([cell.value for cell in row])
    

最后,保存您的文件。

wb.save(filename)

【讨论】:

  • 是不是太多了,请您澄清一下从“#create a cartesian of main sheet,边界和其他表格”开始的代码。我不太明白这是如何工作的。
  • 在代码中做了一些cmets。让我知道您是否需要更多详细信息
  • 对代码进行了更改。消除了不必要的臃肿。现在应该好多了。我还在代码中的相关点制作了 cmets。告诉我进展如何
  • 你先生,真是个天才!它现在起作用了。我唯一关心的是时间效率。完成6张桌子花了3分钟。将进一步研究如何提高效率。非常感谢@sammywemmy!
  • 很高兴它对你有用。让我知道效率改进。这对我来说也是有用的学习。欢呼
猜你喜欢
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 1970-01-01
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多