kinit/kinit-api/utils/excel/excel_manage.py
ktianc 7fbdcb3b0f 版本升级
1. 新增:微信小程序端新增微信手机号登录功能(必须为企业认证小程序)
2. 新增:加入动态更新常见问题
3. 新增:新增小程序分享功能
4. 新增:小程序新增第一次登录需要修改密码
5. 新增:新增接口权限控制
6. 新增:用户新增is_staff用来判断是否为工作人员
7. 新增:软删除新增is_delete字段来判断,delete_datetime当前主要来记录时间
8. 更新:部分接口删除功能已更新,需要试用软删除的才会试用软删除
9. 更新:更新系统配置缓存功能
10. 更新:接口认证依赖项更新
11. 更新:获取系统基础配置信息与用户协议与隐私协议更新
12. 优化:优化接口与数据库操作
2023-02-27 17:28:27 +08:00

202 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Creaet Time : 2022/5/6 17:25
# @File : excel_manage.py
# @IDE : PyCharm
# @desc : EXCEL 文件操作
import datetime
import os
import re
from openpyxl.utils import get_column_letter
from openpyxl import load_workbook, Workbook
from application.settings import TEMP_DIR, TEMP_URL
import hashlib
import random
from openpyxl.styles import Alignment
class ExcelManage:
"""
excel 文件序列化
"""
# 列名A-Z
EXCEL_COLUMNS = [chr(a) for a in range(ord('A'), ord('Z') + 1)]
def __init__(self):
self.sheet = None
self.wb = None
def open_workbook(self, file: str, read_only: bool = False, data_only: bool = False) -> None:
"""
初始化 excel 文件
:param file: 文件名称或者对象
:param read_only: 是否只读,优化读取速度
:param data_only: 是否加载文件对象
"""
# 加载excel文件获取表单
self.wb = load_workbook(file, read_only=read_only, data_only=data_only)
def open_sheet(self, sheet_name: str = None, **kwargs) -> None:
"""
初始化 excel 文件
:param sheet_name: 表单名称,为空则默认第一个
"""
# 加载excel文件获取表单
if not self.wb:
self.open_workbook(kwargs.get("file"), kwargs.get("read_only", False), kwargs.get("data_only", False))
if sheet_name:
self.sheet = self.wb[sheet_name]
else:
self.sheet = self.wb.active
def get_sheets(self) -> list:
"""
读取所有工作区名称
:return: 一维数组
"""
return self.wb.sheetnames
def create_excel(self, sheet_name: str = None) -> None:
"""
创建 excel 文件
:param sheet_name: 表单名称,为空则默认第一个
"""
# 加载excel文件获取表单
self.wb = Workbook()
self.sheet = self.wb.active
if sheet_name:
self.sheet.title = sheet_name
def readlines(self, min_row: int = 1, min_col: int = 1, max_row: int = None, max_col: int = None) -> list:
"""
读取指定表单所有数据
:return: 二维数组
"""
rows = self.sheet.iter_rows(min_row=min_row, min_col=min_col, max_row=max_row, max_col=max_col)
result = []
for row in rows:
_row = []
for cell in row:
_row.append(cell.value)
if any(_row):
result.append(_row)
return result
def get_header(self, row: int = 1, col: int = None, asterisk: bool = False) -> list:
"""
读取指定表单的表头(第一行数据)
:param row: 指定行
:param col: 最大列
:param asterisk: 是否去除 * 号
:return: 一维数组
"""
rows = self.sheet.iter_rows(min_row=row, max_col=col)
result = []
for row in rows:
for cell in row:
value = cell.value.replace("*", "").strip() if asterisk else cell.value.strip()
result.append(value)
break
return result
def write_list(self, rows: list, header: list = None) -> None:
"""
写入 excel文件
:param rows: 行数据集
:param header: 表头
"""
if header:
self.sheet.append(header)
for index, data in enumerate(rows):
format_columns = {
"date_columns": []
}
for i in range(0, len(data)):
if isinstance(data[i], datetime.datetime):
data[i] = data[i].strftime("%Y/%m/%d %H:%M:%S")
format_columns["date_columns"].append(i+1)
self.sheet.append(data)
self.__set_row_style(index+2, len(data)-1)
self.__set_row_format(index+2, format_columns)
self.__auto_width()
def save_excel(self, filename: str = None):
"""
保存 excel 文件到本地
默认保存到临时目录中
"""
date = datetime.datetime.strftime(datetime.datetime.now(), "%Y%m%d")
file_dir = os.path.join(TEMP_DIR, date)
if not os.path.exists(file_dir):
os.mkdir(file_dir)
if not filename:
name = hashlib.md5(str(random.random()).encode()).hexdigest() + ".xlsx"
filename = os.path.join(file_dir, name)
else:
name = filename
filename = os.path.join(file_dir, filename)
self.wb.save(filename)
# 返回访问路由
return f"{TEMP_URL}/{date}/{name}"
def __set_row_style(self, row: int, max_column: int):
"""
设置行样式
:param row: 行
:param max_column: 最大列
"""
for index in range(0, max_column):
# 设置单元格对齐方式
# Alignment(horizontal=水平对齐模式,vertical=垂直对齐模式,text_rotation=旋转角度,wrap_text=是否自动换行)
alignment = Alignment(horizontal='center', vertical='center', text_rotation=0, wrap_text=False)
self.sheet.cell(row=row, column=index+1).alignment = alignment
def __set_row_format(self, row: int, columns: dict):
"""
设置行样式
:param row: 行
:param columns: 列数据
"""
for index in columns.get("date_columns", []):
self.sheet.cell(row=row, column=index).number_format = "yyyy/mm/dd h:mm:ss"
def __auto_width(self):
"""
设置自适应列宽
"""
# 设置一个字典用于保存列宽数据
dims = {}
# 遍历表格数据,获取自适应列宽数据
for row in self.sheet.rows:
for cell in row:
if cell.value:
# 遍历整个表格,把该列所有的单元格文本进行长度对比,找出最长的单元格
# 在对比单元格文本时需要将中文字符识别为1.7个长度英文字符识别为1个这里只需要将文本长度直接加上中文字符数量即可
# re.findall('([\u4e00-\u9fa5])', cell.value)能够识别大部分中文字符
cell_len = 0.7 * len(re.findall('([\u4e00-\u9fa5])', str(cell.value))) + len(str(cell.value))
dims[cell.column] = max((dims.get(cell.column, 0), cell_len))
for col, value in dims.items():
# 设置列宽get_column_letter用于获取数字列号对应的字母列号最后值+2是用来调整最终效果的
self.sheet.column_dimensions[get_column_letter(col)].width = value + 10
def close(self):
"""
关闭文件
"""
self.wb.close()
if __name__ == '__main__':
print([chr(a) for a in range(ord('A'), ord('Z') + 1)])