excel 处理
只能处理.xlsx格式的excel
依赖包安装
pip install openpyxl==3.0.10
封装常用方法
点击查看代码
import functools
from typing import Mapping, List
import openpyxl
from openpyxl.drawing.image import Image
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment
from openpyxl.utils import get_column_letter
def load_wrap(func):
@functools.wraps(func)
def inner(self, *args, **kwargs):
self._load(*args, **kwargs)
func(self, *args, **kwargs)
param = list(args)
if args:
param += kwargs.values()
save_as = param[-1] if param[-1].endswith('.xlsx') else None
self._load_save(save_as)
return inner
class MyExcel:
def __init__(self, file, sheet_name=None):
self.file = file
self.sheet_name = sheet_name
self._workbook = openpyxl.Workbook()
self._sheet = self._workbook.active
def create(self):
"""
创建excel
:return:
"""
if self.sheet_name:
self._sheet.title = self.sheet_name
self._save()
def _save(self):
self._workbook.save(self.file)
def _load(self, *args, **kwargs):
"""加载数据"""
self._load_workbook = openpyxl.load_workbook(self.file)
self._load_sheet = self._load_workbook[self.sheet_name] if self.sheet_name else self._load_workbook.active
def _load_save(self, save_as=None):
"""
加载数据存储
:param save_as: 另存为文件名
:return:
"""
if save_as:
self._load_workbook.save(save_as)
else:
self._load_workbook.save(self.file)
def get_cell_text(self, area: str) -> list:
"""
获取单元格文本
:param area: 单元格区域.例 'A1:B3'
:return: 单元格内的文本
"""
self._load()
cell = self._load_sheet[area]
text = []
if isinstance(cell, tuple):
for item in cell:
row_text = [i.value for i in item]
text.append(row_text)
else:
text.append(cell.value)
return text
def modify_cell_text(self, data: Mapping[str, str or int], save_as=None) -> None:
"""
修改单元格文本值
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param data: 数据体。{'单元格': 值}
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load()
for k, v in data.items():
self._load_sheet[k] = v
self._load_save(save_as)
def add(self, data: List[list], save_as=None) -> None:
"""
按行增加写入数据
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param data: 数据体。
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load()
for row in data:
self._load_sheet.append(row)
self._load_save(save_as)
@load_wrap
def insert_empty(self, axis: str, ids: int, amount: int, save_as=None) -> None:
"""
插入空行或空列
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param axis: 轴向。可选值为row,col
:param ids: 数据编号。
axis为row时:是在ids的下方插入
axis为col时:是在ids的左侧插入
:param amount: 插入数量
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
if axis == 'row':
self._load_sheet.insert_rows(ids, amount)
elif axis == 'col':
self._load_sheet.insert_cols(ids, amount)
else:
pass
@load_wrap
def insert_image(self, cell: str, img_path: str, save_as=None) -> None:
"""
插入图片
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param cell: 要插入图片的单元格
:param img_path: 图片路径
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
img = Image(img_path)
self._load_sheet.add_image(img, cell)
@load_wrap
def delete(self, axis: str, ids: int, amount: int, save_as=None) -> None:
"""
删除行或列
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param axis: 轴向。可选值为row,col
:param ids: 数据编号。
axis为row时:是在ids及其下方删除
axis为col时:是在ids及其右侧删除
:param amount: 插入数量
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
if axis == 'row':
self._load_sheet.delete_rows(ids, amount)
elif axis == 'col':
self._load_sheet.delete_cols(ids, amount)
else:
pass
@load_wrap
def move_cell(self, area: str, rows: int, cols: int, save_as=None) -> None:
"""
移动单元格
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param area: 目标区域 例: 'A1:B3' 表示A1,B3组成的区域
:param rows: 行方向移动单元格, 正数向下,负数向上
:param cols: 列方向移动单元格, 正数向右,负数向左
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load_sheet.move_range(area, rows, cols)
def font_style(self, cell: str) -> dict:
"""
查看字体样式
:param cell: 单元格 例: 'A1'
:return: 样式信息
"""
self._load()
font = self._load_sheet[cell].font
return {
'name': font.name,
'size': font.size,
'bold': font.bold,
'italic': font.italic,
'color': font.color
}
@load_wrap
def modify_font_style(self, cell: str, name: str, size: int, bold: bool,
italic: bool, color: str, save_as=None) -> None:
"""
修改字体样式
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param cell: 单元格. 例:
- 'A1': 修改单元格A1的样式
- 'A1:A3': 修改单元格A1到A3的样式
- 'A1:B3': 修改单元格A1,B3组成的矩形区域
- 'A': 修改A列
:param name: 字体名称
:param size: 字体大小
:param bold: 是否加粗
:param italic: 斜体
:param color: 字体颜色
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
_cell = self._load_sheet[cell]
for item in _cell:
if isinstance(item, tuple):
for i in item:
i.font = Font(name=name, size=size, bold=bold, italic=italic, color=color)
else:
item.font = Font(name=name, size=size, bold=bold, italic=italic, color=color)
@load_wrap
def modify_alignment(self, cell: str, horizontal: str, vertical: str,
text_rotation: int, text_wrap: bool, save_as=None) -> None:
"""
修改对齐方式
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param cell: 单元格. 例:
- 'A1': 修改单元格A1的样式
- 'A1:A3': 修改单元格A1到A3的样式
- 'A1:B3': 修改单元格A1,B3组成的矩形区域
- 'A': 修改A列
:param horizontal: 水平对齐模式.
可选值: ‘distributed’,‘justify’,‘center’,‘left’, ‘centerContinuous’,'right,‘general’
:param vertical: 垂直对齐模式
可选值: ‘bottom’,‘distributed’,‘justify’,‘center’,‘top’
:param text_rotation: 字体旋转角度
:param text_wrap: 是否自动换行
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
_cell = self._load_sheet[cell]
_alignment = Alignment(horizontal=horizontal, vertical=vertical,
text_rotation=text_rotation, wrap_text=text_wrap)
for item in _cell:
if isinstance(item, tuple):
for i in item:
i.alignment = _alignment
else:
item.alignment = _alignment
@load_wrap
def modify_cell_style(self, ids: int, amount: int, height: int, width: int, bg_color='', save_as=None) -> None:
"""
修改单元格宽,高以及背景色
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param ids: 数据编号.从1开始
:param amount: 要修改的数量
:param height: 行高
:param width: 行宽
:param bg_color: 背景色
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
cols = []
for i in range(ids, amount + 1):
col = get_column_letter(i)
cols.append(col)
self._load_sheet.row_dimensions[i].height = height
self._load_sheet.column_dimensions[col].width = width
if bg_color:
for _col in cols:
for i in range(ids, amount + 1):
_cell = f'{_col}{i}'
self._load_sheet[_cell].fill = PatternFill(start_color=bg_color, fill_type='solid')
self._load_sheet[_cell].border = Border(left=Side(style='thin'),
top=Side(style='thin'),
right=Side(style='thin'),
bottom=Side(style='thin'))
@load_wrap
def merge_cell(self, area: str, save_as=None):
"""
合并单元格,合并后居中对齐
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param area: 要合并的单元格区域.例'A1:A3'
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load_sheet.merge_cells(area)
_alignment = Alignment(horizontal='center', vertical='center', text_rotation=0, wrap_text=True)
self._load_sheet[area.split(':')[0]].alignment = _alignment
@load_wrap
def unmerge_cell(self, area: str, save_as=None):
"""
拆分单元格
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param area: 要拆分的单元格区域.例'A1:A3'
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load_sheet.unmerge_cells(area)
@load_wrap
def create_sheet(self, name: str, save_as=None) -> None:
"""
创建新的sheet页
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param name: sheet名称
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load_workbook.create_sheet(name)
@load_wrap
def remove_sheet(self, name: str, save_as=None) -> None:
"""
删除sheet页
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param name: 要删除的sheet页名称
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load_workbook.remove(self._load_workbook[name])
@load_wrap
def rename_sheet(self, name: str, save_as=None) -> None:
"""
修改sheet页名称
如果要另存为save_as必须以.xlsx结尾,否则另存为无效。
:param name: 新sheet名称名称
:param save_as: 另存为文件名,必须以.xlsx结尾,否则另存为无效。 None 表示不另存,直接在源文件修改。
:return:
"""
self._load_sheet.title = name
if __name__ == '__main__':
my_excel = MyExcel('test111.xlsx')
# 创建excel
my_excel.create()
# 修改单元格
my_excel.modify_cell_text({'A1': '名字', 'B1': '年龄'})
# # 按行插入
# my_excel.add([['python', 'nan', 12], ['c', 'nan', 29, '222;']], save_as='tmp.xlsx')
# # 插入空列
# my_excel.insert_empty('col', 2, 3, 'tmp.xlsx')
# 插入图片
# my_excel.insert_image('A5', 'C:/Users/yalong/Pictures/Camera Roll/1.jpg', 'tmp.xlsx')
# # 删除行
# my_excel.delete('row', 2, 2, 'tmp.xlsx')
# # 移动单元格
# my_excel.move_cell('A1:B2', 6, 6, 'tmp.xlsx')
# 查看样式
# print(my_excel.font_style('A2'))
# 修改字体样式
# my_excel.modify_font_style('A1:B3', '微软雅黑', 20, True, True, 'FF0000', 'tmp.xlsx')
# 修改对齐方式
# my_excel.modify_alignment('A1:B2', 'center', 'center', 45, False, 'tmp.xlsx')
# 修改单元格样式
# my_excel.modify_cell_style(1, 5, 20, 20, '0000FFFF', 'tmp.xlsx')
# 合并单元格
# my_excel.merge_cell('A3:A4', 'tmp.xlsx')
# 拆分单元格
# my_excel.unmerge_cell('A3:A4', 'tmp.xlsx')
# 创建新sheet页
# my_excel.create_sheet('新的sheet')
# 修改sheet页名称
# my_excel.rename_sheet('修改名称', 'tmp.xlsx')
# 删除sheet页
# my_excel.remove_sheet('测试sheet', 'tmp.xlsx')
# 获取单元格文本
# print(my_excel.get_cell_text('A:C'))
openpyxl官网地址:https://openpyxl.readthedocs.io/en/stable/index.html
参考链接:
https://blog.csdn.net/weixin_44288604/article/details/120731317?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166555665216782417057294%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166555665216782417057294&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-3-120731317-null-null.142v53control,201v3add_ask&utm_term=python%20excel&spm=1018.2226.3001.4187