我有一个脚本,它接受一个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)
所以这段代码可以运行,但它不会应用我期望的边框(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
此功能是否存在?如果没有,有人可以这么好,至少解释如何应用默认边框样式而不是这个稍厚的边框? Border.BORDER_THICK,Border.BORDER_MEDIUM,Border.BORDER_THIN或Border.BORDER_HAIR似乎都没有。
谢谢!
答案 0 :(得分:5)
可能这很方便:
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")
它的表现相当快。
答案 1 :(得分:2)
@ user698585你的方法似乎不错,但它不再起作用,因为openpyxl的当前版本改变了实现。所以这应该更新为例如。
ws.cell(row=1, column=1).style.border.top.border_style = borders.BORDER_MEDIUM
但会导致错误,即不允许更改样式。 作为一种解决方法,我只是定义了一个专用样式,但它们只是现有样式和边框定义的重复 - 不是那么好的解决方案,只有当你知道哪个样式有更改的单元格时才有效。
border_style = Style(font=Font(name='Console', size=10, bold=False,
color=Color(openpyxl.styles.colors.BLACK)),
fill=PatternFill(patternType='solid', fgColor=Color(rgb='00C5D9F1')),
border=Border(bottom=Side(border_style='medium', color=Color(rgb='FF000000'))))
答案 2 :(得分:2)
适用于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')
答案 3 :(得分:2)
@Karimov有一个稍作修改的答案
下面是您的代码应如何
def __set_border__(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
答案 4 :(得分:1)
如果您需要为pandas excel数据帧设置样式(边框...),我的fork刚刚合并为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'
单独设置('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'
也许是openpyxl中的一个错误。但是没有什么大不了的,只需在功能中设置底部,顶部,左侧,右侧
答案 5 :(得分:0)
发生了相同的问题,但由于折旧,找不到任何可解决此问题的解决方案(2019年)。我在下面有一些可行的方法..可能更好,但可以满足所有意图和目的。
def set_border(ws, cell_range):
rows = ws[cell_range]
for row in rows:
if row == rows[0][0] or row == rows[0][-1] or row == rows[-1][0] or row == rows[-1][-1]:
pass
else:
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(bottom=Side(style='thin'))
rows[0][0].border = Border(left=Side(style='thin'), top=Side(style='thin'))
rows[0][-1].border = Border(right=Side(style='thin'), top=Side(style='thin'))
rows[-1][0].border = Border(left=Side(style='thin'), bottom=Side(style='thin'))
rows[-1][-1].border = Border(right=Side(style='thin'), bottom=Side(style='thin'))
答案 6 :(得分:0)
对于openpyxl == 3.0.5,以更Python的方式:
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')
答案 7 :(得分:0)
def set_border(ws, cell_range, style='thin'):
rows = ws[cell_range]
for row in rows:
temp_row = copy(row[0].border)
row[0].border = Border(left=Side(style=style), right=temp_row.right, top=temp_row.top, bottom=temp_row.bottom)
temp_row = copy(row[-1].border)
row[-1].border = Border(right=Side(style=style), left=temp_row.left, top=temp_row.top, bottom=temp_row.bottom)
for c in rows[0]:
temp_row = copy(c.border)
c.border = Border(top=Side(style=style), left=temp_row.left, bottom=temp_row.bottom, right=temp_row.right)
for c in rows[-1]:
temp_row = copy(c.border)
c.border = Border(bottom=Side(style=style), left=temp_row.left, top=temp_row.top, right=temp_row.right)
这会保留侧面的现有边框,您还可以设置边框的样式
答案 8 :(得分:-1)
似乎没有内置的任务,我们必须自己做一些步骤,如:
#need make conversion from alphabet to number due to range function
def A2N(s,e):
return range(ord(s), ord(e)+1)
#B1 is the border you defined
#Assume you trying border A1-Q1 ... A3-Q3
X = A2N('A','Q')
#print X
your_desired_sheet_range_rows = range(1,4)
#need two loop to go through cells
for row in your_desired_sheet_rows:
for col in X:
ca = chr(col)
sheet[ca+str(row)].border=B1