使用 openpyxl 将数据验证应用于不同工作表中的特定列

Applying data validation to specific columns in different sheets using openpyxl

提问人:bobbobbbobbob 提问时间:11/17/2023 更新时间:11/17/2023 访问量:25

问:

我正在尝试使用 openpyxl 对不同选项卡中的不同列应用不同的数据验证。

当我只指定一个工作表时,我的代码可以工作,但是当我同时定义三个工作表时,它就会变得混乱。 ChatGPT 和 Google Bard 给了我错误的答案,只是发明了无法编译的代码,非常令人沮丧。有人可以帮忙吗?

from openpyxl import Workbook
from openpyxl.worksheet.datavalidation import DataValidation
from openpyxl.utils import get_column_letter

# Anonymized state lists
state_list_1 = ["State1", "State2", "State3"]  # Anonymized list of financial institutions
state_list_2 = ["Yes", "No"]  # Anonymized list of yes/no options
state_list_3 = ["USD", "EUR", "CAD"]  # Anonymized list of currency codes

# Create a workbook
workbook = Workbook()
workbook.create_sheet('Tab 1')
workbook.create_sheet('Tab 2')
workbook.create_sheet('Tab 3')
workbook.create_sheet('List')
sheet_one = workbook['Tab 1']
sheet_two = workbook['Tab 2']
sheet_three = workbook['Tab 3']
sheet_four = workbook['List']

# Populate sheets with anonymized state lists
state_lists = [state_list_1, state_list_2, state_list_3]
for i, state_list in enumerate(state_lists, start=1):
    for idx, state in enumerate(state_list, start=1):
        sheet_four.cell(row=idx, column=i, value=state)

# Create data validations
data_1 = DataValidation(type="list", formula1='=List!$A:$A')
data_2 = DataValidation(type="list", formula1='=List!$B:$B')
data_3 = DataValidation(type="list", formula1='=List!$C:$C')

# Define columns to apply DataValidations
columns_to_validate = {
    'Tab 1': {5: data_2},
    'Tab 2': {8: data_2, 9: data_2, 14: data_3, 15: data_1, 23: data_2},
    'Tab 3': {6: data_3, 7: data_3, 8: data_1}
}

# Apply DataValidations to specified columns in respective sheets
for sheet_name, columns in columns_to_validate.items():
    sheet = workbook[sheet_name]
    for col_num, data in columns.items():
        column_letter = get_column_letter(col_num)
        sheet.add_data_validation(data)
        for row in range(3, sheet.max_row + 1):
            cell = f"{column_letter}{row}"
            data.add(sheet[cell])

# Saving the workbook
workbook.save('mwe.xlsx')

Excel OpenPyXL

评论

0赞 kb2136 11/18/2023
你必须更具体——“混淆”并不能说明什么......描述出了什么问题。
0赞 moken 11/18/2023
代码示例创建具有四个附加工作表的新工作簿,除了名为“列表”的最后一个工作表外,没有在工作表中输入任何数据。因此,工作表“Tab1”、“Tab2”和“Tab3”是空工作表。(评论在下一条评论中继续)。
0赞 moken 11/18/2023
(评论接上一篇)添加数据验证 # Apply DataValidations to specified... 时,循环使用字典 'columns_to_validate',它只包含空工作表 'Tab(1 - 3)。在行中,鉴于工作表没有数据,因此没有使用任何行,这意味着循环将永远不会执行,实际上是并且因此永远不会被执行,从而导致工作簿损坏。这些工作表“Tab(1 - 3)”是否应该填充在某个地方,或者为什么要从第 3 行开始?for row in range(3, sheet.max_row + 1):range(3, 2)data.add(sheet[cell])
0赞 bobbobbbobbob 11/21/2023
@kb2136混淆我的意思是,我希望工作表 1-2-3 中的特定列具有特定的数据验证列表 A-B-C。取而代之的是,我得到了所有选项卡,其中包含为工作表 1-2-3 指定的所有列以及所有数据验证列表。
0赞 bobbobbbobbob 11/21/2023
@moken对不起,我在构建我的 MBE 时有点懒惰,你是对的,我的实际文件充满了选项卡 1-2-3 的数据

答:

0赞 bobbobbbobbob 11/21/2023 #1

感谢您的评论。最后,我通过为每个工作表定义不同的 DataValidation 对象来解决了我的问题(使用双循环函数可以缩短代码,但它有效)。

`data_1_sheet_one = DataValidation(type="list", formula1='=List!$A:$A')
data_2_sheet_one = DataValidation(type="list", formula1='=List!$B:$B')
data_3_sheet_one = DataValidation(type="list", formula1='=List!$C:$C')
data_1_sheet_two = DataValidation(type="list", formula1='=List!$A:$A')
data_2_sheet_two = DataValidation(type="list", formula1='=List!$B:$B')
data_3_sheet_two = DataValidation(type="list", formula1='=List!$C:$C')
data_1_sheet_three = DataValidation(type="list", formula1='=List!$A:$A')
data_2_sheet_three = DataValidation(type="list", formula1='=List!$B:$B')
data_3_sheet_three = DataValidation(type="list", formula1='=List!$C:$C')

# Apply data validation to entire columns in different sheets
for row in range(1, 100): 
    cell = f"E{row}"
    data_2_sheet_one.add(sheet_one[cell])

sheet_one.add_data_validation(data_2_sheet_one)

for row in range(1, 100): 
    cell = f"O{row}"
    data_1_sheet_two.add(sheet_two[cell])

for row in range(1, 100): 
    cell = f"H{row}"
    data_2_sheet_two.add(sheet_two[cell])

for row in range(1, 100): 
    cell = f"I{row}"
    data_2_sheet_two.add(sheet_two[cell])

for row in range(1, 100): 
    cell = f"H{row}"
    data_2_sheet_two.add(sheet_two[cell])

for row in range(1, 100): 
    cell = f"N{row}"
    data_3_sheet_two.add(sheet_two[cell])

for row in range(1, 100): 
    cell = f"W{row}"
    data_2_sheet_two.add(sheet_two[cell])

sheet_two.add_data_validation(data_1_sheet_two)
sheet_two.add_data_validation(data_2_sheet_two)
sheet_two.add_data_validation(data_3_sheet_two)

for row in range(1, 100): 
    cell = f"F{row}"
    data_3_sheet_three.add(sheet_three[cell])

for row in range(1, 100): 
    cell = f"G{row}"
    data_3_sheet_three.add(sheet_three[cell])

for row in range(1, 100): 
    cell = f"H{row}"
    data_1_sheet_three.add(sheet_three[cell])

sheet_three.add_data_validation(data_1_sheet_three)
sheet_three.add_data_validation(data_2_sheet_three)
sheet_three.add_data_validation(data_3_sheet_three)`