openPyXL - 在取消合并期间为单元格范围指定值

时间:2017-09-26 12:31:33

标签: python excel openpyxl

所以我有excel文件,每个文件都有几张,我正在编写脚本,如果它们存在于文件中,它将从选定的工作表中收集数据并将其合并到一个大页面中。通常它正在工作,迭代文件,如果需要,它会找到包含数据的单元格范围并将其附加到数据框。我现在需要做的是将标题行(列名称)添加到Dataframe,但在表单中是多行标题。

为了使它在数据帧中看起来相同,我需要将顶部标题行中的单元格取消合并,并将值从第一个单元格复制到其余部分,并在之前合并的范围内。“

我正在使用OpenPyXL访问Excel工作表。我的函数接收工作表作为唯一参数。它看起来像这样:

def checkForMergedCells(sheet):
    merged = ws.merged_cell_ranges
    for mergedCell in merged:
        mc_start, mc_stop = str(mergedCell).split(':')
        cp_value = sheet[mc_start]
        sheet.unmerge_cells(mergedCell)
        cell_range = sheet[mergedCell]
        for cell in cell_range:
            cell.value = cp_value

问题是cell_range返回一个元组,最终会收到错误信息:

  

AttributeError:'tuple'对象没有属性'value'   下面你可以看到调试期间的screencap,它显示了每个变量中传递的值。

Debugger running

4 个答案:

答案 0 :(得分:3)

通过索引访问通常会返回一个元组元组,除非您尝试获取单个单元格或行。要进行程序化访问,您应该使用iter_cols()utils

您可能希望花一些时间查看from openpyxl.utils import range_boundaries for group in ws.merged_cell_ranges: min_col, min_row, max_col, max_row = range_boundaries(group) top_left_cell_value = ws.cell(row=min_row, column=min_col).value for row in ws.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row): for cell in row: cell.value = top_left_cell_value 模块。

$source_path = "/var/www/ci/htdocs/assets/images/";
echo str_replace(FCPATH, base_url(), $source_path);

答案 1 :(得分:1)

http://thequickblog.com/merge-unmerge-cells-openpyxl-in-python/中的以下代码对我有用。

import openpyxl 
from openpyxl.utils import range_boundaries
wbook=openpyxl.load_workbook("openpyxl_merge_unmerge.xlsx")
sheet=wbook["unmerge_sample"]
for cell_group in sheet.merged_cells.ranges:
    min_col, min_row, max_col, max_row = range_boundaries(str(cell_group))
    top_left_cell_value = sheet.cell(row=min_row, column=min_col).value
    sheet.unmerge_cells(str(cell_group))
    for row in sheet.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row):
        for cell in row:
            cell.value = top_left_cell_value
wbook.save("openpyxl_merge_unmerge.xlsx")
exit()

答案 2 :(得分:0)

在执行此操作之前,我遇到了错误和弃用警告:

from openpyxl.utils import range_boundaries

for group in sheet.merged_cells.ranges: # merged_cell_ranges deprecated
    display(range_boundaries(group._get_range_string())) # expects a string instead of an object
    min_col, min_row, max_col, max_row = range_boundaries(group._get_range_string())
    top_left_cell_value = sheet.cell(row=min_row, column=min_col).value
    for row in sheet.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row):
        for cell in row:
            cell.value = top_left_cell_value

答案 3 :(得分:0)

以上答案均无效。 所以我详细说明了这一点,对其进行了测试,它对我有用。

from openpyxl.utils import range_boundaries
wb = load_workbook('Example.xlsx')

sheets = wb.sheetnames  ##['Sheet1', 'Sheet2']
for i,sheet in enumerate(sheets):
    ws = wb[sheets[i]]

    # you need a separate list to iterate on (see explanation #2 below)
    mergedcells =[]  
    for group in ws.merged_cells.ranges:
        mergedcells.append(group)

    for group in mergedcells:
        min_col, min_row, max_col, max_row = group.bounds 
        top_left_cell_value = ws.cell(row=min_row, column=min_col).value
        ws.unmerge_cells(str(group))   # you need to unmerge before writing (see explanation #1 below)
        for irow in range(min_row, max_row+1):
            for jcol in range(min_col, max_col+1): 
                ws.cell(row = irow, column = jcol, value = top_left_cell_value)



@ДмитроОлександрович几乎是正确的,但是我不得不更改一些内容以修正他的答案:

  1. 您将遇到一个AttributeError: 'MergedCell' object attribute 'value' is read-only错误,因为在更改其值之前需要取消合并的单元格。 (请参见此处:https://bitbucket.org/openpyxl/openpyxl/issues/1228/unmerged-cells-are-still-considered-merged

  2. 您无法直接在ws.merged_cells.ranges上进行迭代,因为在python中的“范围”列表对象中进行迭代并对其进行更改(例如,使用unmerge_cells函数或pop函数)将只更改一半的对象(请参见此处:https://bitbucket.org/openpyxl/openpyxl/issues/1085/unmerge-of-wsmerged_cell_ranges-works-but)。您需要创建一个不同的列表并对其进行迭代。