zoukankan      html  css  js  c++  java
  • excel写入类——实现合并单元格,pandas,xlwt

    import xlwt
    import pandas as pd
    
    class Excel_style:
        """excel表格样式类"""
        def __init__(self, font_heigh):
            self.font_heigh = font_heigh  # 字体大小:磅
    
        @property
        def cell_style(self):
            """表格内容样式"""
            style = xlwt.XFStyle()  # 创建一个样式对象,初始化样式
            al = xlwt.Alignment()
            al.horz = 0x02  # 设置水平居中
            al.vert = 0x01  # 设置垂直居中
            style.alignment = al
            font=xlwt.Font()
            font.height = 20*self.font_heigh
            style.font=font
            return style
    
        @property
        def title_style(self):
            """表格标题样式"""
            style = xlwt.XFStyle()  # 创建一个样式对象,初始化样式
            al = xlwt.Alignment()
            al.horz = 0x02  # 设置水平居中
            al.vert = 0x01  # 设置垂直居中
            style.alignment = al
            font=xlwt.Font()
            font.height = 20*self.font_heigh
            font.bold = True
            style.font=font
            return style
    
        def fit_width(self,max_width,value):
            """调整自适应列宽"""
            width = len(str(value).encode('utf-8'))*256
            if width < 2960:
                max_width = 2960
            if width > max_
                max_width = width
            return int(max_width + max_width * 1/10)
    
        @property
        def fit_heigh(self):
            """调整自适应行高"""
            heigh_style = xlwt.easyxf('font:height %s;'%(20 * (self.font_heigh+4)))
            return heigh_style
    
    class Excel_writer:
        """excel表格写入类"""
        def __init__(self, excel_path, df):
            self.excel_path = excel_path
            self.df = (df.drop(columns='index') if 'index' in df.columns else df)
            self.cols = list(self.df.columns.values)  # 行索引值列表
            self.index_len = self.df.index.size  # 索引长度
            self.column_number = {col: idx for idx, col in enumerate(self.cols)}  # 得到 行索引值:索引
            self.excel = xlwt.Workbook(excel_path)
            self.worksheet = self.excel.add_sheet('sheet1')
            self.style_obj = Excel_style(10)
        
        def write_to_exel(self):
            """pandas 写入 excel 表格"""
            self.df.to_excel(self.excel_path, index=False)
    
        def _get_group_idx(self, key_col):
            """合并单元格的索引数据"""
            """
            return [[1,2],[3,4]]
            """
            groups = self.df.groupby(key_col)
            idxs = [[groups.get_group(i).index.min() + 1, groups.get_group(i).index.max() + 1] for i in groups.size().index]
            return idxs, len(idxs)        
        
        def _fit_value(self,value):
            """调整 pandas 值,适应 excel 表格"""
            if isinstance(value,str):
                return str(value)
            if isinstance(value,pd._libs.tslibs.timestamps.Timestamp):
                value = str(value)
                if '.' in value:
                    value = value.split('.')[0]
                return value
            return int(value)
            
        
        def write_merged_by_col_to_excel(self, key_col, merged_cols):
            """根据 key列,合并设定的单元格,写入 excel 表格,有样式"""
            if key_col not in self.cols:  # 校验key_cols中各元素 是否都包含与对象的列
                return
            if not all([v in self.cols for i, v in enumerate(merged_cols)]):  # 校验merge_cols中各元素 是否都包含与对象的列
                return
            self.write_head()
            self.write_merge_body(key_col,merged_cols)
            self.save()
    
        def write_style_to_excel(self):
            """写入excel,有样式"""
            self.write_head()
            self.write_body()
            self.save()
    
        def write_head(self):
            """写入标题,有样式"""
            for col_value, i in self.column_number.items():  # 写表头
                heigh_style = self.style_obj.fit_heigh
                self.worksheet.row(0).set_style(heigh_style)
                self.worksheet.write(0, i, col_value, self.style_obj.title_style)
    
        def write_body(self):
            """写入内容,有样式"""
            for col_value, idx in self.column_number.items():
                max_width = 2960
                for i in range(self.index_len):
                    value = self.df.at[i, col_value]
                    if pd.isna(value):
                        value = ''
                    max_width = self.style_obj.fit_width(max_width,value)
                    self.worksheet.col(idx).width = max_width
                    heigh_style = self.style_obj.fit_heigh
                    self.worksheet.row(i + 1).set_style(heigh_style)
                    self.worksheet.write(i + 1, int(idx), self._fit_value(value),self.style_obj.cell_style)
        
        def write_merge_body(self, key_col, merged_cols):
            """"写入内容,合并单元格,有样式"""
             for col_value, idx in self.column_number.items():
                max_width = 2960
                if col_value not in merged_cols:
                    for i in range(self.index_len):
                        value = self.df.at[i, col_value]
                        if pd.isna(value):
                            value = ''
                        max_width = self.style_obj.fit_width(max_width,value)
                        self.worksheet.col(idx).width = max_width
                        heigh_style = self.style_obj.fit_heigh
                        self.worksheet.row(i + 1).set_style(heigh_style)
                        self.worksheet.write(i + 1, int(idx), self._fit_value(value),self.style_obj.cell_style)
                else:
                    idxs, _ = self._get_group_idx(key_col)
                    for j in idxs:
                        value = self.df.at[j[0] - 1, col_value]
                        if pd.isna(value):
                            value = ''
                        max_width = self.style_obj.fit_width(max_width,value)
                        self.worksheet.col(idx).width = max_width
                        heigh_style = self.style_obj.fit_heigh
                        self.worksheet.row(int(j[0])).set_style(heigh_style)
                        self.worksheet.write_merge(int(j[0]), int(j[1]), int(idx), int(idx), self._fit_value(value),self.style_obj.cell_style)
        
        def save(self):
            """保存 excel 表格"""
            self.excel.save(self.excel_path)
    
    
    if __name__ == '__main__':
        te = {'A': ['aaa', 'aaa', 'aaa', 'aaa', 'CCC', 'CCC'], 'B': ['bbbb', 'aaa', 'aaa', 'aaa', 'aaa', 'aaa'], 'C': ['aaa', 'aaa', 'aaa', 'aaa', 'aaa', 'aaa']}
        t_f = pd.DataFrame(te)
        DF = Excel_writer(r'D:EL_giteeel_appsrcapp_vi00_1.xls', t_f)
        # DF.merged_by_col_to_excel('A',['A', 'B', 'C'])
        DF.write_style_to_excel()
    

    参考:https://blog.csdn.net/cakecc2008/article/details/59203980

  • 相关阅读:
    PHP 方法整合类 -- 1.根据概率产生随机数 --2.判断手机号归属地及运营商 --3.过滤emoji表情
    PHP 多图下载并打包压缩方法
    PHP 导出excel 精简版
    PHP获取首字母相关方法
    no input file specified 解决办法
    百度地图相关
    经纬度相关方法
    阿里云SSL证书部署至宝塔
    微信入口、生成菜单,公众号授权获取用户信息(unionid)
    超级好用超级简单的支付类库
  • 原文地址:https://www.cnblogs.com/pythonwl/p/15103020.html
Copyright © 2011-2022 走看看