使用openpyxl为范围内的所有单元格应用边框

Dav*_*arx 5 python excel openpyxl

我有一个脚本,它接受一个pandas数据帧并将其分成几百个块并将每个块保存为单独的excel文件.每个块将具有相同数量的列,但行数会有所不同.我已经想出如何使用openpyxl将所有其他必要的格式应用于这些文件,但我还没有确定应用边框的最快方法.此外,我认为我只是没有正确应用边框,因为下面的代码(我怀疑不应该单独遍历每个单元格)不适用任何边框.

from openpyxl.style import Border

wb = load_workbook(filename = _fname)
ws = wb.worksheets[0]  
for _row in ws.range('A1:L'+str(ws.get_highest_row() ) ):
    for _cell in _row:
            _cell.style.borders.left.border_style = Border.BORDER_THIN
            _cell.style.borders.right.border_style = Border.BORDER_THIN
            _cell.style.borders.top.border_style = Border.BORDER_THIN
            _cell.style.borders.bottom.border_style = Border.BORDER_THIN
wb.save(_fname)
Run Code Online (Sandbox Code Playgroud)

所以这段代码可以工作,但它不会应用我期望的边框(excel中的默认边框),它需要比我更喜欢的步骤.我的期望是我应该能够做到这样的事情:

from openpyxl.style import Border

wb = load_workbook(filename = _fname)
ws = wb.worksheets[0]

_range = ws.some_range_func('A1:L'+str(ws.get_highest_row() ) ):
    _range.style.borders.all_borders = Borders.BORDER_THIN
Run Code Online (Sandbox Code Playgroud)

这个功能是否存在?如果没有,有人可以这么好,至少解释如何应用默认边框样式而不是这个稍厚的边框?Border.BORDER_THICK,Border.BORDER_MEDIUM,Border.BORDER_THIN或Border.BORDER_HAIR似乎都没有.

谢谢!

Shi*_*ani 20

对于 openpyxl==3.0.5,以更 Pythonic 的方式:

from openpyxl.styles import Border, Side

def set_border(ws, cell_range):
    thin = Side(border_style="thin", color="000000")
    for row in ws[cell_range]:
        for cell in row:
            cell.border = Border(top=thin, left=thin, right=thin, bottom=thin)

set_border(worksheet, 'A5:C10') 
Run Code Online (Sandbox Code Playgroud)


Rab*_*eih 6

可能这很方便:

from openpyxl.reader.excel import load_workbook
from openpyxl.style import Border

def set_border(ws, cell_range):
    rows = ws.range(cell_range)
    for row in rows:
        row[0].style.borders.left.border_style = Border.BORDER_THIN
        row[-1].style.borders.right.border_style = Border.BORDER_THIN
    for c in rows[0]:
        c.style.borders.top.border_style = Border.BORDER_THIN
    for c in rows[-1]:
        c.style.borders.bottom.border_style = Border.BORDER_THIN

#usage example:
ws = load_workbook('example.xlsx').get_active_sheet()
set_broder(ws, "C3:H10")
Run Code Online (Sandbox Code Playgroud)

它表现得相当快.

  • `def set_border(ws, cell_range): rows = ws[cell_range] 行中的行:row[0].border = Border(left=Side(style='thin')) row[-1].border = Border( right=Side(style='thin')) for c in rows[0]: c.border = Border(top=Side(style='thin')) for c in rows[-1]: c.border = Border (底部=侧面(风格=“瘦”))` (2认同)
  • 收到错误:`AttributeError:'Worksheet'对象没有属性'range'`具体来说,行:`rows = ws.range(cell_range)` (2认同)

小智 5

适用于 openpyxl 2.3.5 的决定

from openpyxl.styles import Border, Side

def set_border(ws, cell_range):
    border = Border(left=Side(border_style='thin', color='000000'),
                right=Side(border_style='thin', color='000000'),
                top=Side(border_style='thin', color='000000'),
                bottom=Side(border_style='thin', color='000000'))

    rows = ws.iter_rows(cell_range)
    for row in rows:
        for cell in row:
            cell.border = border

set_border(worksheet, 'A5:C10')
Run Code Online (Sandbox Code Playgroud)

  • 我收到的错误:“类型错误:‘str’对象无法解释为整数” (4认同)

Tar*_*hak 5

@Karimov 的回答略有修改
以下是您的代码应该如何

from openpyxl.styles import Border, Side, Font, Alignment
Run Code Online (Sandbox Code Playgroud)
def __format_ws__(self, ws, cell_range):
     border = Border(left=Side(border_style='thin', color='000000'),
                    right=Side(border_style='thin', color='000000'),
                    top=Side(border_style='thin', color='000000'),
                    bottom=Side(border_style='thin', color='000000'))

      rows = ws[cell_range]
      for row in rows:
          for cell in row:
              cell.border = border

Run Code Online (Sandbox Code Playgroud)

使用列表理解的一种更快的方法如下:

 def __format_ws__(self, ws, cell_range):

        #applying border and alignment
        font = Font(size=9)
        align=Alignment(horizontal='left', vertical='center')
        border = Border(left=Side(border_style='thin', color='000000'),
                        right=Side(border_style='thin', color='000000'),
                        top=Side(border_style='thin', color='000000'),
                        bottom=Side(border_style='thin', color='000000'))

        rows = [rows for rows in ws[cell_range]]
        flattened = [item for sublist in rows for item in sublist]
        [(setattr(cell,'border',border), setattr(cell,'font',font), setattr(cell,'alignment',align)) for cell in flattened]
Run Code Online (Sandbox Code Playgroud)

你使用它的方式是:

self.__format_ws__(ws=writer.book.worksheets[0], cell_range='A1:G10')
Run Code Online (Sandbox Code Playgroud)


loc*_*jay 1

如果您需要 pandas excel 数据框的样式(边框...),我的叉子刚刚合并到 master 中 https://github.com/pydata/pandas/pull/2370#issuecomment-10898427

至于你的边界问题。一次设置所有边框在 openpyxl 中不起作用。

In [34]: c.style.borders.all_borders.border_style = openpyxl.style.Border.BORDER_THIN

In [36]: c.style
'Calibri':11:False:False:False:False:'none':False:'FF000000':'none':0:'FFFFFFFF':'FF000000':'none':'FF000000':'none':'FF000000':'none':'FF000000':'none':'FF000000':'none':'FF000000':0:'thin':'FF000000':'none':'FF000000':'none':'FF000000':'none':'FF000000':'none':'FF000000':'general':'bottom':0:False:False:0:'General':0:'inherit':'inherit'
Run Code Online (Sandbox Code Playgroud)

单独设置有效('thin':'FF000000')

In [37]: c.style.borders.top.border_style = openpyxl.style.Border.BORDER_THIN

In [38]: c.style
Out[38]: 'Calibri':11:False:False:False:False:'none':False:'FF000000':'none':0:'FFFFFFFF':'FF000000':'none':'FF000000':'none':'FF000000':'thin':'FF000000':'none':'FF000000':'none':'FF000000':0:'thin':'FF000000':'none':'FF000000':'none':'FF000000':'none':'FF000000':'none':'FF000000':'general':'bottom':0:False:False:0:'General':0:'inherit':'inherit'
Run Code Online (Sandbox Code Playgroud)

也许是 openpyxl 中的一个错误。但没什么大不了的,只需在函数中设置底部,顶部,左侧,右侧即可