简体   繁体   English

仅垂直或水平 Openpyxl 取消合并和分配值

[英]Unmerge and Assign Values Only Vertically or Horizontally Openpyxl

Using the answer provided by aka863 here: How to split merged Excel cells with Python?在此处使用 aka863 提供的答案: How to split merged Excel cells with Python?

I can unmerge, fill values and copy the styling.我可以取消合并、填充值和复制样式。 My questions is how to make the value assigning/filling process configurable.我的问题是如何使值分配/填充过程可配置。

I want the user to be able to choose whether the values will be filled vertically/horizontally.我希望用户能够选择是否垂直/水平填充值。

I have tried changing the last loop where we assign the top_left_cell_values to unmerged cells.我尝试更改最后一个循环,我们将 top_left_cell_values 分配给未合并的单元格。 However I couldn't find a way to make it horizontal/vertical configurable.但是我找不到使它水平/垂直可配置的方法。 (I'm planning to use radio buttons and tkinter for this) (我打算为此使用单选按钮和 tkinter)

Its certainly possible to have the code de-merge cells and fill cells in whichever direction, vertically or horizontally regardless of which way the merge was originally.它当然可以让代码取消合并单元格并在垂直或水平方向的任何方向填充单元格,而不管最初合并的方式如何。 Or not fill at all, so only the top left cell retains the 'value' of the previously merged cells, which is default on unmerge.或者根本不填充,因此只有左上角的单元格保留先前合并单元格的“值”,这是取消合并时的默认值。
Changing the direction of the fill requires some change and re-calculation on the max row and column values in the iter_rows loop, but is simple enough.更改填充方向需要对 iter_rows 循环中的最大行和列值进行一些更改和重新计算,但这很简单。

However it seems in your last comment you just want to give the user the option to fill or not fill on horizontal merges.但是,在您的最后一条评论中,您似乎只想让用户选择填充或不填充水平合并。 In that case you just need to ask the question, and then run the iter_rows loop only if the response is yes.在那种情况下,您只需要提出问题,然后仅当响应为是时才运行 iter_rows 循环。

The code sample below is based on the answer referenced question.下面的代码示例基于答案引用的问题。
I'm assuming only horizontal merges since you dont mention what if anything should be done with vertical merges in the comment.我假设只有水平合并,因为你没有在评论中提到垂直合并应该做什么。
The code does initially check and indicate the merge direction either vertically or horizontally so it can be included take some action if a merge is vertical.该代码最初会检查并指示垂直或水平的合并方向,因此如果合并是垂直的,则可以包含它并采取一些措施。
On code run after displaying the range and direction of the merge, the question is asked to fill, yes or no.在显示合并的范围和方向后运行的代码中,要求填写问题,是或否。 If yes the cells are de-merged and all cells filled with the top left cell value using the iter_rows loop.如果是,则取消合并单元格,并使用 iter_rows 循环使用左上角的单元格值填充所有单元格。 If answer no then the cells are just de-merged.如果回答否,则单元格将被取消合并。

from openpyxl import load_workbook
from openpyxl.utils.cell import range_boundaries

wb = load_workbook(filename='foo.xlsx')

st = wb['Sheet1']
mcr_coord_list = [mcr.coord for mcr in st.merged_cells.ranges]
direction_dict = {'v': 'vertical', 'h': 'horizontal'}

for mcr in mcr_coord_list:
    print('---------------------------------------------------\n')
    merge_direction = ''
    min_col, min_row, max_col, max_row = range_boundaries(mcr)
    top_left_cell_value = st.cell(row=min_row, column=min_col).value
    if min_col == max_col:
        merge_direction = 'v'
    elif min_row == max_row:
        merge_direction = 'h'

    print(f"The cell range {mcr} is merged {direction_dict[merge_direction]}ly with the data '{top_left_cell_value}'")

    while True:
        demerge_fill = input('Do you want the de-merge to fill all cells(y|n)? ')
        if demerge_fill.lower() in ["y", "n"]:
            break
        else:
            print('Invalid response')

    st.unmerge_cells(mcr)

    if demerge_fill == 'y':
        for row in st.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
    else:
        print(f"Only the top left cell {mcr.split(':')[0]} will contain the data!")

wb.save('merged_tmp.xlsx')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM