2015-12-29 3 views
4

Я использую python 2.7.10 и openpyxl 2.3.2, и я новичок Python.Применить границу к диапазону ячеек с помощью Openpyxl

Я пытаюсь применить границу к указанному диапазону ячеек на листе Excel (например, C3:H10). Ниже приведена моя попытка ниже:

AttributeError: 'Cell' object has no attribute 'styles'.

Как присоединить границу к ячейке? Любые идеи были бы с благодарностью получены.

Мой текущий код:

import openpyxl 
from openpyxl.styles import Border, Side 

def set_border(ws, cell_range): 
    rows = ws.iter_rows(cell_range) 
    for row in rows: 
     row[0].styles.borders = Border(left=Side(border_style='thin', color="FF000000")) 
     row[-1].styles.borders = Border(right=Side(border_style='thin', color="FF000000")) 
    for c in rows[0]: 
     c.styles.borders = Border(top=Side(border_style='thin', color="FF000000")) 
    for c in rows[-1]: 
     c.styles.borders = Border(bottom=Side(border_style='thin', color="FF000000")) 


# Example call to set_border 
wb = openpyxl.load_workbook('example.xlsx') 
ws = wb.get_sheet_by_name('Sheet1') 

set_border(ws, "B3:H10") 
+0

Откуда у вас возникла идея попробовать работать со стилями? –

ответ

7

Прежде всего свойства называются style (не styles) и border (не borders). Также для изменения границы вы должны установить cell.border напрямую.

Кроме того, у вас есть некоторые проблемы с логикой границ, сложнее заставить его работать правильно, из-за итераторов и углов. Вот примерный вариант (это так просто, как я мог бы получить, но не память эффективной):

def set_border(ws, cell_range): 
    rows = ws[cell_range] 
    side = Side(border_style='thin', color="FF000000") 

    rows = list(rows) # we convert iterator to list for simplicity, but it's not memory efficient solution 
    max_y = len(rows) - 1 # index of the last row 
    for pos_y, cells in enumerate(rows): 
     max_x = len(cells) - 1 # index of the last cell 
     for pos_x, cell in enumerate(cells): 
      border = Border(
       left=cell.border.left, 
       right=cell.border.right, 
       top=cell.border.top, 
       bottom=cell.border.bottom 
      ) 
      if pos_x == 0: 
       border.left = side 
      if pos_x == max_x: 
       border.right = side 
      if pos_y == 0: 
       border.top = side 
      if pos_y == max_y: 
       border.bottom = side 

      # set new border only if it's one of the edge cells 
      if pos_x == 0 or pos_x == max_x or pos_y == 0 or pos_y == max_y: 
       cell.border = border 
+0

Во-первых, спасибо за ответ. Как только моя репутация превысит 15, моя обратная связь покажет, что ваш ответ был полезен. Во-вторых, игнорируя возможные логические проблемы на данный момент, изменяя имя свойства на границу (из границ) и напрямую устанавливая cell.border (путем удаления .styles), получаем TypeError: объект 'generator' не имеет атрибута '__getitem__' в строке 9 (для c в строках [0] :). Не могли бы вы предложить какую-либо помощь в этом смысле? –

+0

@PeteB 'ws.iter_rows (cell_range)' возвращает [generator] (http://stackoverflow.com/q/1756096/1377864). Вы не можете использовать синтаксис 'row [N]' для получения элемента 'N'th из генератора (вот почему я конвертирую его в список в моем примере). –

+0

Ответ принят. Спасибо. –

0
border = Border(
      left=cell.border.left, 
      right=cell.border.right, 
      top=cell.border.top, 
      bottom=cell.border.bottom) 

можно заменить:

border = cell.border.copy() 

PS: Ваш ответ помогли мне ...

+0

Это приводит к тысячам строк предупреждений об устаревании для меня в последней версии openpyxl. –

Смежные вопросы