代码之家  ›  专栏  ›  技术社区  ›  flywire

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

  •  0
  • flywire  · 技术社区  · 6 年前

    此代码返回电子表格范围中的小部件列表,该电子表格范围具有另一个范围,指示它已启用处理。代码可以工作,但它的实现很差,特别是在正确使用zip和布局方面。

    我很确定 zip ws.iter_cols 应该是答案的一部分,但不是最好的使用方法。唯一重要的一行是 Row/column code 注释。那么,应该怎么做呢?

    代码需要在不同的范围内运行,但最初是为开发而硬编码的。在OpenPYXL中,行/列处理比坐标范围更有效,坐标范围功能正在逐步降低。(坐标代码仅用于开发,将被删除。)

    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]
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   ewcz    6 年前

    也许您可以将其简化如下:

    #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]]