#!/usr/bin/env python # -*- encoding: utf-8 -*- ''' @Date:2022/08/27 11:05:06 ''' import sys sys.path.append('.') import string import os import datetime from openpyxl.workbook import Workbook from openpyxl.styles import Alignment, Side, Border, Font, PatternFill class ReportData: def __init__(self): # 新建一个workbook self.wb = Workbook() # 定义设置样式 self.a = 0 def set_style(self, title='sheet1'): # 如果是第一次调用则删除默认创建的sheet表 if self.a == 0: self.wb.remove(self.wb['Sheet']) self.a += 1 # 创建第几个sheet self.ws = self.wb.create_sheet() # 设置sheet的标题 self.ws.title = title # 设置1 2 3 行固定的高度 self.ws.row_dimensions[1].height = 35 self.ws.row_dimensions[2].height = 25 self.ws.row_dimensions[3].height = 28 # 水平对齐, 居中对齐 self.alignment_style = Alignment( horizontal='center', vertical='center') # 定义Border边框样式 left, right, top, bottom = [Side(style='thin', color='000000')] * 4 self.border_style = Border( left=left, right=right, top=top, bottom=bottom) # 设置列宽 # 生成前14个大写字母 ascii_uppercase生成所有大写字母 self.upper_string = string.ascii_uppercase[:15] # 定义字体 self.font_size = Font(size=9) for col in self.upper_string: self.ws.column_dimensions[col].width = 20 # 创建第一行 def create_row1(self, value, length): # 合并第1行1-14列单元格 self.ws.merge_cells(start_row=1, end_row=1, start_column=1, end_column=length) # 写入值 self.ws.cell(row=1, column=1).value = value self.ws['A1'].alignment = self.alignment_style self.ws['A1'].font = Font(size=16, bold=True) self.create_row2(length) def create_row2(self, length): # 第2行写入值 now_time = datetime.datetime.now().strftime('%Y%m%d %H%M') # 格式化时间为中文年月日 now_time = now_time[:4] + '年' + now_time[4:6] + '月' + \ now_time[6:8] + '日' + now_time[8:11] + '时' + now_time[11:13] + '分' self.ws.cell(row=2, column=1).value = '报表导出时间:{}'.format(now_time) self.ws.cell(row=2, column=3).value = '终端系统版本:3.1' self.ws.cell(row=2, column=5).value = '' self.ws.cell(row=2, column=7).value = '报表导出位置:终端' # 合并单元格 x = 1 while x < 6: self.ws.merge_cells(start_row=2, end_row=2, start_column=x, end_column=x + 1) x += 2 self.ws.merge_cells(start_row=2, end_row=2, start_column=7, end_column=length) # 遍历取1, 3, 5, 7为第二行添加样式 for x in range(1, 8, 2): self.ws.cell(row=2, column=x).font = Font(size=9) # 水平对齐 垂直对齐 self.ws.cell(row=2, column=x).alignment = self.alignment_style if x < 7: # 边框样式 self.ws.cell(row=2, column=x).border = self.border_style self.ws.cell(row=2, column=x + 1).border = self.border_style else: # 因为第2行第7-14列是合并的单元格 所以需要循环添加边框样式 while x < length + 1: self.ws.cell(row=2, column=x).border = self.border_style x += 1 # 创建第三行, 需要传入一个列表用来写入单元格的值 def create_row3(self, data_list): for data in range(1, len(data_list) + 1): # 第三行写入值 self.ws.cell(row=3, column=data).value = data_list[data - 1] # 设置文本水平居中, 垂直居中 self.ws.cell(row=3, column=data).alignment = self.alignment_style # 设置字体加粗 self.ws.cell(row=3, column=data).font = Font(bold=True, size=9) # 背景颜色 self.ws.cell(row=3, column=data).fill = PatternFill( fill_type='solid', fgColor='EE9A49') # 边框样式 self.ws.cell(row=3, column=data).border = self.border_style # 创建多行固定样式 start_row从第几行开始有规律 传入一个数据库获取的列表对象的值, 传入一个数据对象keys列表 def create_multiple_rows(self, start_row, data_list, keys_list): # 从第4行创建 for row_number in range(start_row, len(data_list) + start_row): # 设置每一行的行高 self.ws.row_dimensions[row_number].height = 18 # 遍历每一个对象的长度 col_ = 1 for key_ in keys_list: # 写入值 try: # 判断是否时datetime 类型, if isinstance(dict(data_list[row_number - start_row]).get(key_), datetime.datetime): value = dict(data_list[row_number - start_row]).get(key_).replace(tzinfo=None) # 判断是否时state elif key_=='state': value = dict(data_list[row_number - start_row]).get(key_).value else: value = dict(data_list[row_number - start_row]).get(key_) except : value = "/" self.ws.cell(row=row_number, column=col_).value = value # 设置文本水平居中, 垂直居中 self.ws.cell(row=row_number, column=col_).alignment = self.alignment_style # 设置边框样式 self.ws.cell(row=row_number, column=col_).border = self.border_style # 设置字体大小 self.ws.cell(row=row_number, column=col_).font = Font(size=9) col_ += 1 # 保存文件 def save(self, file_path): self.wb.save('{}.xlsx'.format(file_path)) self.close() # 关闭文件 def close(self): self.wb.close() # 替换空白 def replace_space(self, length): self.max_lines = self.ws.max_row upper_letter_str = string.ascii_uppercase[:length] for upper_letter in upper_letter_str: print(upper_letter) for row_ in range(1, self.max_lines + 1): b = self.ws[upper_letter + str(row_)].value # print(b) if not b: self.ws[upper_letter + str(row_)].value = 'null' # 编辑excel表格中列药剂状态1 2 3 替换为在库 出库 def editor_status(self, col_): self.max_lines = self.ws.max_row for row_ in range(4, self.max_lines + 1): b = self.ws[col_ + str(row_)].value if b == 1: self.ws[col_ + str(row_)].value = '在库' elif b == 0: self.ws[col_ + str(row_)].value = '待入库' elif b == 2: self.ws[col_ + str(row_)].value = '出库' elif b == 3: self.ws[col_ + str(row_)].value = '空瓶' elif b == 4: self.ws[col_ + str(row_)].value = '销毁' # 编辑 温度报警类型 0,1 替换为正常和异常 def eidtor_temperature_type(self,col_): self.max_lines = self.ws.max_row for row_ in range(4,self.max_lines +1): b = self.ws[col_ + str(row_)].value if b==0: self.ws[col_ + str(row_)].value = "正常" elif b ==1 : self.ws[col_ + str(row_)].value = "异常" # 编辑药剂重点监管列为1 0 替换为是 否 def editor_isSupervise(self, col_): self.max_lines = self.ws.max_row for row_ in range(4, self.max_lines + 1): b = self.ws[col_ + str(row_)].value if b == 1: self.ws[col_ + str(row_)].value = '是' elif b == 0: self.ws[col_ + str(row_)].value = '否' # 编辑操作类型 1 2 3 入库 领用 归还 def editor_RecordType(self, col_): self.max_lines = self.ws.max_row for row_ in range(4, self.max_lines + 1): b = self.ws[col_ + str(row_)].value if b == 1: self.ws[col_ + str(row_)].value = '入库' elif b == 2: self.ws[col_ + str(row_)].value = '领用' elif b == 3: self.ws[col_ + str(row_)].value = '归还' # 替换sqlAlchemy时间格式 def editor_time(self, keys_list, params): self.max_lines = self.ws.max_row for row_ in range(4, self.max_lines + 1): col_ = string.ascii_uppercase[keys_list.index(params)] b = self.ws[col_ + str(row_)].value # print('sssssssssssssssssssssssssssssssssssssssssassssssssssssssss:::', b,type(b)) try: if len(b) == 19: self.ws[col_ + str(row_)].value = b.replace('T', ' ') except Exception as e : pass # print(e) # 编辑用户管理列为1 0 替换为正常 禁用 def editor_user_status(self, col_): self.max_lines = self.ws.max_row for row_ in range(4, self.max_lines + 1): b = self.ws[col_ + str(row_)].value if b == 1: self.ws[col_ + str(row_)].value = '正常' elif b == 0: self.ws[col_ + str(row_)].value = '禁用' # 构建文件内容 def build_file(self,**kwargs): data_list = kwargs.pop("data_list") key_list = kwargs.pop("key_list") finds_name = kwargs.pop("finds_name") self.set_style(title="Sheet") file_name = kwargs.pop("file_name") self.create_row1(file_name, len(finds_name)) self.create_row3(finds_name) self.create_multiple_rows(4, data_list, key_list) for i in key_list: if "date" in i: self.editor_time(key_list, i) if "state" in i: self.editor_status(string.ascii_uppercase[key_list.index(i)]) if "temperature_type" in i: self.eidtor_temperature_type(string.ascii_uppercase[key_list.index(i)]) if "is_supervise" in i: self.editor_isSupervise(string.ascii_uppercase[key_list.index(i)]) if "record_type" == i: self.editor_RecordType( string.ascii_uppercase[key_list.index(i)]) return self # 下载文件 @staticmethod def download_excel(filename, chunk_size=512): try: f = open(filename, 'rb') except: return while True: c = f.read(chunk_size) if c: yield c else: f.close() os.remove(filename) break # # 导出用户数据报表接口 # @dataReport.route('/downloadUserReport', methods=["GET", "POST"]) # def downloadUserReport(): # try: # uPath = Utils.getUDiskPath() # if (uPath == ''): # return jsonify(Utils.resultData(1, '未检测到U盘!')) # else: # data_user_list = BllUser().findList().all() # data_user_list = json.loads( # Utils.resultAlchemyData(data_user_list)) # # 创建一个报表类实例 # a = ReportData() # a.set_style(title='Sheet') # data_list = ['工号', '角色', '姓名', '性别', 'QQ', '手机', '邮箱', # '条码', '状态', '最后一次登录时间', ] # a.create_row1('用户角色数据统计表', len(data_list)) # a.create_row3(data_list) # keys_list = ['UserCode', 'RoleName', 'RealName', 'Sex', 'QQ', 'Mobile', 'Email', # 'BarCode', 'IsEnabled', 'LastVisitDate', ] # a.create_multiple_rows(4, data_user_list, keys_list) # a.replace_space(len(data_list)) # a.editor_time(keys_list, 'LastVisitDate') # # 判断用户角色 # for row_ in range(4, a.max_lines + 1): # col_ = string.ascii_uppercase[keys_list.index('UserCode')] # b = a.ws[col_ + str(row_)].value # if b == 'admin': # for col_value in range(1, len(keys_list) + 1): # a.ws.cell(row=row_, column=col_value).fill = PatternFill( # fill_type='solid', fgColor='FF0000') # elif b == 'yanyi': # for col_value in range(1, len(keys_list) + 1): # a.ws.cell(row=row_, column=col_value).fill = PatternFill( # fill_type='solid', fgColor='FFFF00') # # 优化用户性别 # for row_ in range(4, a.max_lines + 1): # col_ = string.ascii_uppercase[keys_list.index('Sex')] # b = a.ws[col_ + str(row_)].value # if b == 0: # a.ws[col_ + str(row_)].value = '女' # else: # a.ws[col_ + str(row_)].value = '男' # a.editor_user_status('I') # file_name = '用户角色数据统计表{}'.format(Utils.UUID()) # a.save(uPath + '/' + file_name) # returnData = Utils.resultData(0, '导出成功') # return jsonify(returnData) # except Exception as e: # return jsonify(Utils.resultData(2, str(e)))