from openpyxl.styles import NamedStyle, Font, Border, Side, PatternFill, Alignment, colors, Protection
from openpyxl.worksheet.datavalidation import DataValidation
class MakeExcel(object):
def __init__(self, wb, data, excel_name_path):
"""
初始化参数
:param wb: 创建的Workbook对象
:param data: 每个sheet中所有数据字典,例如
{"sheet1名": [[第一行数据], [第二行数据]...], "sheet2名": [[第一行数据], [第二行数据]...], ....}
:param excel_name_path: excel表路径
"""
self._wb = wb
self._data = data
self._excel_name_path = excel_name_path
self._font = Font(name="微软雅黑",
color=colors.BLACK,
italic=True,
size=14,
bold=False,
vertAlign=None,
underline="none",
strike=False
)
self._fill = PatternFill(
fill_type=None,
start_color=colors.BLACK,
end_color=colors.BLACK
)
self._alignment = Alignment(
horizontal="general",
vertical="bottom",
text_rotation=0,
wrap_text=False,
shrink_to_fit=False,
indent=0
)
self._number_format = "General"
self._protection = Protection(
locked=True,
hidden=False
)
self._title = NamedStyle(name="title")
self._border = Side(style="thin", color="000000")
self._title.border = Border(
left=self._border,
right=self._border,
top=self._border,
bottom=self._border
)
def set_freeze(self, ws, row_col):
"""
冻结,传入单元格位置,这个单元格之上的所有行和左边的所有列都会被冻结,例如:A2,只会冻结首行
:param ws: sheet对象
:param row_col: 单元格位置,例如:A2
:return:
"""
ws.freeze_panes = row_col
def set_table_col_width(self, ws, col_name_len_dict):
"""
批量设置列宽, 最大设置80
:param ws: sheet对象
:param col_name_len_dict: 列名长度字典,例如:{"A": 10, "B":15}
:return: None
"""
for col_name, length in col_name_len_dict.items():
ws.column_dimensions[col_name].width = length if length <= 80 else 80
def set_hyperlink(self, ws, row, column, font, link, value):
"""
设置超链接
:param ws: sheet对象
:param row: 行号
:param column: 列号
:param font: 字体样式
:param link: 超链接地址
:param value: 单元格值
:return:
"""
self.set_title_style(ws.cell(row=row, column=column),
value='=HYPERLINK("{}","{}")'.format(link, value),
font=font)
def record_max_col(self, col_num_list, text, index):
"""
记录每一列的最大宽度值
:param col_num_list: 每一列的最大宽度值列表
:param text: 单元格的值
:param index: 单元格列位置
:return:
"""
col = len(str(text).encode("gb18030"))
if col > col_num_list[index]:
col_num_list[index] = col
def get_col_num_dict(self):
"""
获取位置和列字母的对应关系
:return: 返回结果 {0: "A", 1: "B", ... 25: "Z"}
"""
A_Z = [chr(a) for a in range(ord("A"), ord("Z"))]
col_num_dict = {
k: v for k, v in enumerate(A_Z)}
return col_num_dict
def set_upslide(self, ws, cell_alignment, upslide_list, allow_blank=True):
"""
设置单元格下拉菜单
:param ws: sheet对象
:param cell_alignment: 单元格范围,例如:"G2:G10"
:param upslide_list: 下拉选项列表
:param allow_blank: 是否可以为空,默认为空
:return:
"""
dv = DataValidation(
type="list",
formula1=upslide_list,
allow_blank=allow_blank
)
dv.error = "Your entry is not in the list"
dv.errorTitle = "Invalid Entry"
dv.prompt = "Please select from the list"
dv.promptTitle = "List Selection"
dv.add(cell_alignment)
ws.add_data_validation(dv)
def set_title_style(self, cell, value="", font=None, alignment=None):
"""
设置单元格数据及样式
:param cell: 单元格位置
:param value: 单元格数据
:param font: 样式
:param alignment: 位置
:return:
"""
cell.value = value
cell.style = self._title
cell.font = font if font else self._font
cell.alignment = alignment if alignment else self._alignment
def set_table_data(self, ws, data_list):
"""
给sheet中添加数据
:param ws: sheet对象
:param data_list: sheet中的数据列表
:return: 每列的最大长度列表
"""
font = Font(
name="微软雅黑",
color=colors.BLACK,
italic=True,
size=14,
bold=True,
vertAlign=None,
underline="none",
strike=False
)
column_num = len(data_list[0])
col_num_list = [0 for _ in range(column_num)]
for row_num, row_list in enumerate(data_list):
for col_num, value in row_list:
self.set_title_style(
ws.cell(row=row_num + 1, column_num=col_num + 1),
value=value,
font=font if row_num == 0 else self._font,
)
self.record_max_col(col_num_list, value, col_num)
return col_num_list
def run(self):
index = 0
for sheet_name, data_list in self._data.items():
ws = self._wb.create_sheet(sheet_name, index)
col_num_list = self.set_table_data(ws, data_list)
col_num_dict = self.get_col_num_dict()
col_name_len_dict = {
col_num_dict[i]: value for i, value in enumerate(col_num_list)}
self.set_table_col_width(ws, col_name_len_dict)
index += 1
self._wb.save(self._excel_name_path)