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

posted @ 2022-10-13 15:33  一枚码农  阅读(72)  评论(0编辑  收藏  举报