openpyxl使用

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,  # 颜色也可以使用:# FFFFFF
                          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._border = Border(
        #     left=Side(border_style=None, color=colors.BLACK),
        #     right=Side(border_style=None, color=colors.BLACK),
        #     top=Side(border_style=None, color=colors.BLACK),
        #     bottom=Side(border_style=None, color=colors.BLACK),
        #     diagonal=Side(border_style=None, color=colors.BLACK),
        #     diagonal_direction=0,
        #     outline=Side(border_style=None, color=colors.BLACK),
        #     vertical=Side(border_style=None, color=colors.BLACK),
        #     horizontal=Side(border_style=None, 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,  # 颜色也可以使用:# FFFFFF
                  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)]  # 设置每列宽度初始值为0
        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():
            # 创建sheet
            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)


你可能感兴趣的:(python)