使用 Zip 处理标记为已启用的小部件

Using Zip to Process Widgets Flagged as Enabled

此代码 returns 电子表格范围内的小部件列表,该范围具有另一个范围,表明它已启用处理。代码有效,但实现不佳,尤其是在正确使用 zip 和布局方面。

我相当确定 zipws.iter_cols 应该是答案的一部分,但不是使用它们的最佳方式。唯一重要的行是 Row/column code 注释下的列表理解。那么,应该怎么做呢?

代码需要在各个范围内 运行,但最初是为了开发而硬编码的。在 openpyxl row/column 中,处理比坐标范围更有效,并且坐标范围功能正在逐渐贬值。 (坐标码仅用于开发,将被删除。)

PEP8 发出 continuation line under-indented for visual indent 警告。

from __future__ import print_function
from openpyxl import Workbook
from openpyxl.utils import get_column_letter
import openpyxl


def do_widgets(ws, col0, col1):
    """ Process each widget. """
    NO_WDGTS = 5
    ENABLE_START_ROW = 6
    ENABLE_END_ROW = ENABLE_START_ROW + NO_WDGTS - 1
    WDGT_START_ROW = 1
    WDGT_END_ROW = WDGT_START_ROW + NO_WDGTS - 1

    # Coordinate code - delete whole block before implementation
    col_letter0 = get_column_letter(col0)
    col_letter1 = get_column_letter(col1)
    wdgos_range = [(col_letter0 + str(ENABLE_START_ROW) + ":" +
                    col_letter0 + str(ENABLE_END_ROW))]
    wdgos_range.append(col_letter1 + str(WDGT_START_ROW) + ":" +
                       col_letter1 + str(WDGT_END_ROW))
    # Delete
    # wdgos = [cell[1][0].value for cell in zip(ws['B6:B10'], ws['C1:C5'])
    #                                          if cell[0][0].value]
    wdgos = [cell[1][0].value for cell in zip(ws[wdgos_range[0]], ws[wdgos_range[1]])
                                             if cell[0][0].value]

    # Row/column code
    wdgts = [cell[1] for cell in zip([cell.value for col
                     in ws.iter_cols(min_row=ENABLE_START_ROW, min_col=col0,
                                     max_row=ENABLE_END_ROW, max_col=col0)
                     for cell in col],
                     [cell.value for col
                     in ws.iter_cols(min_row=WDGT_START_ROW, min_col=col1,
                                     max_row=WDGT_END_ROW, max_col=col1)
                     for cell in col]) if cell[0]]

    # Use list of enabled widgets
    print("Enable range [0], Widget range [1]")
    print(wdgos_range)
    for wdgo in wdgos:
            print(wdgo)
    print()
    print(wdgts, '\n')


wb = Workbook()
ws = wb.active

rows = [
    ['Number', 'Batch 1', 'Batch 2'],
    [2, 40, 30],
    [3, 40, 25],
    [4, 50, 30],
    [5, 30, 10],
    [0, 0, 0],
    [0, 1, 0],
    [1, 1, 0],
    [0, 0, 1],
    [0, 1, 0],
]

for row in rows:
    ws.append(row)
# Worksheet, enable column, widget column
do_widgets(ws, 2, 3)

调试输出:

Enable range [0], Widget range [1]
['B6:B10', 'C1:C5']
30
25
10

[30, 25, 10]

也许你可以简化一下,如下所示:

#define cell "extractor" from given position
def get_cells(row, col):
    for col in ws.iter_cols(min_row = row, min_col = col, max_row = row + NO_WDGTS - 1, max_col = col):
        for cell in col:
            yield cell.value

#use itertools.izip to zip the generators in order to process
#the elements one by one instead of generating them all at once 
wdgts = [cell[1] for cell in itertools.izip(
            get_cells(ENABLE_START_ROW, col0),
            get_cells(WDGT_START_ROW, col1)) if cell[0]]