Python办公自动化之Excel(中)


Posted in Python onMay 24, 2021

准备

首先,我们需要安装依赖包

# 安装依赖包
pip3 install openpyxl

读取数据

使用 openpyxl 中的 load_workbook(filepath) 加载本地一个 Excel 文件,返回结果是一个工作簿对象

import openpyxl

# 加载本地的Excel文件
wb = openpyxl.load_workbook(file_path)

利用工作簿对象,可以获取所有的 Sheet 名称及 Sheet 列表

def get_all_sheet_names(wb):
    """
    获取所有sheet的名称
    :param wb:
    :return:
    """
    # sheet名称列表
    sheet_names = wb.sheetnames
    return sheet_names


def get_all_sheet(wb):
    """
    获取所有的sheet
    :param wb:
    :return:
    """
    # sheet名称列表
    sheet_names = get_all_sheet_names(wb)

    # 所有sheet
    sheets = []
    for sheet_name in sheet_names:
        sheet = wb[sheet_name]
        sheets.append(sheet)

    return sheets

工作簿对象提供了 active 属性,用于快速获取当前选择的 Sheet

def get_current_sheet(wb):
    """
    获取当前选择的sheet,默认是最后一个sheet
    :param wb:
    :return:
    """
    # 当前选中的sheet
    current_sheet = wb.active

    return current_sheet

另外,也可以通过 Sheet 名称去获取某一个特定的 Sheet 对象

def get_sheet_by_name(wb, sheet_name):
    """
    通过sheetname去查找某一个sheet
    :param wb:
​    :param sheet_name:
    :return:
    """
    sheet_names = get_all_sheet_names(wb)
    if sheet_name in sheet_names:
        result = wb[sheet_name]
    else:
        result = None
    return result

使用 sheet.max_row 和 sheet.max_column 可以获取当前 Sheet 中的数据行数和列数

def get_row_and_column_num(sheet):
    """
    获取sheet的行数和列数
    :param sheet:
    :return:
    """
    # 行数
    row_count = sheet.max_row
    # 列数
    column_count = sheet.max_column

    return row_count, column_count

# 行数和列数
row_count, column_count = get_row_and_column_num(sheet)
print('行数和列数分别为:', row_count, column_count)

openpyxl 提供 2 种方式来定位一个单元格,分别是:

  • 数字索引,从 1 开始

数字索引:行数字索引、列数字索引

比如:row_index=1,column_index=1

  • 行和列组成的字符串索引

字符串索引:列由字母组成 + 行索引

比如:A1 对应第一行、第一列的单元格

并且,openpyxl.utils 提供了方法,便于 列索引 在两者之间进行转换

from openpyxl.utils import get_column_letter, column_index_from_string

def column_num_to_str(num):
    """
    Excel索引列从数字转为字母
    :param num:
    :return:
    """
    return get_column_letter(num)


def column_str_to_num(str):
    """
    Excel索引列,从字母转为数字
    :param str:
    :return:
    """
    return column_index_from_string(str)

单元格的获取,同样可以通过上面 2 种索引方式来获取

def get_cell(sheet, row_index, column_index):
    """
    获取单元格
    :param sheet:
    :param row_index:
    :param column_index:
    :return:
    """
    # openpyxl索引都是从1开始计数,这与xlrd有所不同
    # 获取某一个单元格(二选一)
    # 比如:获取A1单元格的数据,即第一个行、第一列的数据
    # cell_one = sheet['A1']
    cell_one = sheet.cell(row=row_index, column=column_index)
    return cell_one

在日常处理 Excel 数据过程中,可能需要判断单元格数据类型,而 openpyxl 并没有提供现成的方法

这里,我们可以通过单元格对象的 value 属性拿到值,接着使用 isinstance 方法判断数据类型

def get_cell_value_and_type(cell):
    """
    获取某一个cell的内容及数据类型
    :param cell:
    :return:
    """
    # 单元格的值
    cell_value = cell.value
    # 单元格的类型
    cell_type = get_cell_value_type(cell_value)

    return cell_value, cell_type

def get_cell_value_type(cell_value):
    """
    获取数据类型
    :param cell_value:
    :return:
    """
    # 其中
    # 0:空
    # 1:数字
    # 2:字符串
    # 3:日期
    # 4:其他
    if not cell_value:
        cell_type = 0
    elif isinstance(cell_value, int) or isinstance(cell_value, float):
        cell_type = 1
    elif isinstance(cell_value, str):
        cell_type = 2
    elif isinstance(cell_value, datetime.datetime):
        cell_type = 3
    else:
        cell_type = 4
    return cell_type

单独获取某一行[列]的数据,可以使用下面的方式:

def get_row_cells_by_index(sheet, row_index):
    """
    通过行索引,获取某一行的单元格
    :param row_index:
    :return:
    """
    # 注意:第一列从1开始
    row_cells = sheet[row_index]
    return row_cells


def get_column_cells_by_index(sheet, column_index):
    """
    通过列索引,获取某一列的单元格
    """
    # 数字转为字母
    column_index_str = column_num_to_str(column_index)
    # 获取某一列的数据
    column_cells = sheet[column_index_str]
    return column_cells

需要注意的是,获取某一行的数据需要传入数字索引;而对于列数据的获取,必须传入字符串索引

和 Python 列表范围取值类似,openpyxl 同样支持使用 : 符号拿到某个范围内的数据行[列]

def get_rows_by_range(sheet, row_index_start, row_index_end):
    """
    通过范围去选择行范围
    比如:选择第2行到第4行的所有数据,返回值为元组
    :param sheet:
    :param row_index_start:
    :param row_index_end:
    :return:
    """
    rows_range = sheet[row_index_start:row_index_end]
    return rows_range


def get_columns_by_range(sheet, column_index_start, column_index_end):
    """
    通过范围去选择列范围
    比如:选择第2列到第4列的所有数据,返回值为元组
    :param sheet:
    :param column_index_start:
    :param column_index_end:
    :return:
    """
    columns_range = sheet[column_num_to_str(column_index_start):column_num_to_str(column_index_end)]
    return columns_range

写入数据

要写入数据到 Excel 表格

首先,使用 openpyxl.Workbook() 创建一个 Excel 工作簿对象

接着,使用工作簿对象的 create_sheet() 新建一个 Sheet

# 创建一个Excel工作簿
# 注意:每次新建一个Excel文件,都会默认生成一个名称为【Sheet】的工作表Sheet
wb = openpyxl.Workbook()

# 创建一个新的sheet,默认被插到尾部
# new_sheet = wb.create_sheet('新的Sheet')
# 也可以通过第二个参数:index来指定插入的位置
# 比如:插入到开头
new_sheet = wb.create_sheet('新的Sheet', 0)

默认创建的 Sheet 被插入到最后一个位置,第 2 个参数可以指定 Sheet 插入的位置

Sheet 标签的背景色同样支持修改,使用 sheet_properties.tabColor 指定 RGB 颜色值

比如,要设置某一个 Sheet 的背景色为红色,只需要先查询到对应的 Sheet,然后指定颜色值为 FF0000 即可

def set_sheet_bg_color(sheet, rgb_value):
    """
    设置Sheet标签的颜色
    :param rgb_value:
    :return:
    """
    # 设置Sheet底部按钮的颜色(RRGGBB)
    sheet.sheet_properties.tabColor = rgb_value

 # 设置Sheet的背景色(红色)
set_sheet_bg_color(new_sheet, 'FF0000')

openpyxl 支持行列数字索引、字符串索引以这 2 种方式写入数据到单元格中

def write_value_to_cell_with_num(sheet, row_index, column_index, value):
    """
    按行索引、列索引写入数据
    :param shell:
    :param row_index: 行索引
    :param column_index: 列索引
    :param value:
    :return:
    """
    # 二选一
    sheet.cell(row=row_index, column=column_index, value=value)
    # shell.cell(row=row_index, column=column_index).value = value


def write_value_to_cell_with_index_str(sheet, index_str, value):
    """
    按字母位置,写入数据到对应单元格
    :param shell:
    :param index_str: 字母对应的单元格位置
    :param value:
    :return:
    """
    sheet[index_str] = value

在单元格中插入图片也很简单,openpyxl 提供的 add_image() 方法

参数有 2 个,分别是:图片对象、单元格字符串索引

为了便于使用,我们可以将列索引进行转换,然后封装成两个插入图片的方法

from openpyxl.drawing.image import Image

def insert_img_to_cell_with_num(sheet, image_path, row_index, column_index):
    """
    往单元格中插入图片
    :param sheet:
    :param image_path:
    :param row_index:
    :param column_index:
    :return:
    """
    # 通过行索引、列索引,获取到字母索引
    index_str = column_num_to_str(column_index) + str(row_index)
    insert_img_to_cell_with_str(sheet, image_path, index_str)

def insert_img_to_cell_with_str(sheet, image_path, index_str):
    """
    往单元格中插入图片
    :param sheet:
    :param image_path:
    :param index_str:
    :return:
    """
    sheet.add_image((image_path), index_str)

最后,调用工作簿对象的 save() 方法,将数据真实写入到 Excel 文件中

# 注意:必须要写入,才能真实的保存到文件中
wb.template = False
wb.save('new.xlsx')

修改数据

修改数据包含:单元格数据的修改、单元格样式的修改

对于单元格数据的修改,只需要先读取工作簿对象,查询到要操作的 Sheet 对象,然后调用上面的方法修改单元格数据,最后调用 save() 函数保存覆盖即可

def modify_excel(self, file_path):
    """
    修改本地Excel文件中数据
    :param file_path:
    :return:
    """
    # 读取本地Excel文件
    wb = openpyxl.load_workbook(file_path)

    # 读取某一个sheet
    sheet = wb['第一个Sheet']
    print(sheet)

    # 直接修改某一个单元格的数据
    write_value_to_cell_with_num(sheet, 1, 1, '姓名1')

    # 保存并覆盖
    wb.save(file_path)

单元格样式包含:字体样式、单元格背景样式、边框样式、对齐方式等

以常见的字体样式、对齐方式为例

首先,使用 openpyxl 中的 Font 类创建一个对象,指定字体名称、字体大小、是否加粗、是否斜体、颜色、下划线等

from openpyxl.styles import Font

# 字体格式
# 指定字体类型、大小、是否加粗、颜色等
font0 = Font(name='Calibri',
             size=20,
             bold=False,
             italic=False,
             vertAlign=None,  
             underline='none', 
             strike=False,
             color='FF00FF00')

接着,构建一个 Alignment 对象,指定单元格的对齐方式

from openpyxl.styles import Font,Alignment

# 单元格对齐方式
alignment0 = Alignment(horizontal='center',
                       vertical='bottom',
                       text_rotation=0,
                       wrap_text=False,
                       shrink_to_fit=False,
                       indent=0)

最后,使用单元格对象的 font/alignment 属性,将字体样式和对齐方式设置进去即可

# 设置属性样式(字体、对齐方式)
sheet['A1'].font = font0
sheet['A1'].alignment = alignment0

进阶用法

接下来,聊聊几个常用的进阶用法

1、获取可见及隐藏的 Sheet

通过判断 Sheet 对象的 sheet_state 属性值,可以判断当前 Sheet 是显示还是隐藏

当值为 visible 时,代表 Sheet 是显示的

当值是 hidden 时,代表这个 Sheet 被隐藏了

def get_all_visiable_sheets(wb):
    """
    获取工作簿中所有可见的sheet
    :param wb:
    :return:
    """
    return [sheet for sheet in get_all_sheet(wb) if sheet.sheet_state == 'visible']


def get_all_hidden_sheets(wb):
    """
    获取工作簿中所有隐藏的sheet
    :param wb:
    :return:
    """
    return [sheet for sheet in get_all_sheet(wb) if sheet.sheet_state == 'hidden']

2、获取隐藏/显示的行索引列表、列索引列表

受限于篇幅,这里以获取所有显示/隐藏的行索引列表为例

遍历 Sheet 对象的 row_dimensions 属性值,通过判断行属性的 hidden 值,判断当前行是否隐藏或显示

def get_all_rows_index(sheet, hidden_or_visiable):
    """
    获取所有隐藏/显示的行
    :param hidden_or_visiable:  True:隐藏;False:显示
    :param sheet:
    :return:
    """
    # 遍历行
    # 隐藏的索引
    hidden_indexs = []

    # 所有隐藏的行索引
    for row_index, rowDimension in sheet.row_dimensions.items():
        if rowDimension.hidden:
            hidden_indexs.append(row_index)

    # 所有显示的行索引
    visiable_indexs = [index + 1 for index in range(get_row_and_column_num(sheet)[0]) if index + 1 not in hidden_indexs]

    # 隐藏或者显示的行索引列表
    return hidden_indexs if hidden_or_visiable else visiable_indexs

3、获取单元格字体颜色及单元格背景颜色

单元格对象的 font.color.rgb、fill.fgColor.rgb 属性值分别代表字体颜色值、单元格背景颜色

def get_cell_font_color(sheet, row_index, column_index):
    """
    获取单元格字体的颜色
    :param sheet:
    :param row_index:行索引
    :param column_index:列索引
    :return:
    """
    cell_color = sheet.cell(row_index, column_index).font.color
    if cell_color:
        return sheet.cell(row_index, column_index).font.color.rgb
    else:
        # 颜色不存在,可能单元格没有数据
        return None


def get_cell_bg_color(sheet, row_index, column_index):
    """
    获取单元格背景的颜色
    :param sheet:
    :param row_index:行索引
    :param column_index:列索引
    :return:
    """
    return sheet.cell(row_index, column_index).fill.fgColor.rgb

最后

可以发现,openpyxl 相比 xlrd/xlwt,提供了大量实用的 API,功能更强大,并且完美支持 xlsx!

受限于篇幅,文中只展示了部分功能和代码,更加复杂的功能,比如:单元格合并、单元格完整样式操作,我已经封装成方法上传到后台

代码地址:https://github.com/xingag/test_auto/tree/master/office_auto/Excel

以上就是Python办公自动化之Excel(中)的详细内容,更多关于Python Excel自动化的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
利用python打印出菱形、三角形以及矩形的方法实例
Aug 08 Python
利用Python如何批量更新服务器文件
Jul 29 Python
PyQt5实现五子棋游戏(人机对弈)
Mar 24 Python
python 动态迁移solr数据过程解析
Sep 04 Python
Django学习之文件上传与下载
Oct 06 Python
基于python实现语音录入识别代码实例
Jan 17 Python
opencv python图像梯度实例详解
Feb 04 Python
基于梯度爆炸的解决方法:clip gradient
Feb 04 Python
Python 实现黑客帝国中的字符雨的示例代码
Feb 20 Python
Python将字典转换为XML的方法
Aug 01 Python
Python生成并下载文件后端代码实例
Aug 31 Python
Python特殊属性property原理及使用方法解析
Oct 09 Python
PyTorch梯度裁剪避免训练loss nan的操作
May 24 #Python
python3读取文件指定行的三种方法
May 24 #Python
pytorch中Schedule与warmup_steps的用法说明
May 24 #Python
Python Pycharm虚拟下百度飞浆PaddleX安装报错问题及处理方法(亲测100%有效)
May 24 #Python
pytorch交叉熵损失函数的weight参数的使用
May 24 #Python
pytorch 实现变分自动编码器的操作
May 24 #Python
Pytorch数据读取之Dataset和DataLoader知识总结
May 23 #Python
You might like
什么是短波收听SWL
2021/03/01 无线电
PHP获取ip对应地区和使用网络类型的方法
2015/03/11 PHP
jQuery checkbox全选/取消全选实现代码
2009/11/14 Javascript
解决js数据包含加号+通过ajax传到后台时出现连接错误
2013/08/01 Javascript
js调用后台、后台调用前台等方法总结
2014/04/17 Javascript
探寻Javascript执行效率问题
2014/11/12 Javascript
javascript 面向对象封装与继承
2014/11/27 Javascript
jQuery中has()方法用法实例
2015/01/06 Javascript
jQuery结合HTML5制作的爱心树表白动画
2015/02/01 Javascript
javascript获得当前的信息的一些常用命令
2015/02/25 Javascript
JavaScript获取并更改input标签name属性的方法
2015/07/02 Javascript
JQuery validate插件验证用户注册信息
2016/05/11 Javascript
通过Ajax使用FormData对象无刷新上传文件方法
2016/12/08 Javascript
基于jQuery插件jqzoom实现的图片放大镜效果示例
2017/01/23 Javascript
Extjs gridpanel 中的checkbox(复选框)根据某行的条件不能选中的解决方法
2017/02/17 Javascript
JSON与js对象序列化实例详解
2017/03/16 Javascript
浅谈ES6新增的数组方法和对象
2017/08/08 Javascript
Node.JS使用Sequelize操作MySQL的示例代码
2017/10/09 Javascript
详细分析JS函数去抖和节流
2017/12/05 Javascript
浅谈React深度编程之受控组件与非受控组件
2017/12/26 Javascript
JavaScript的数据类型转换原则(干货)
2018/03/15 Javascript
angularjs通过过滤器返回超链接的方法
2018/10/26 Javascript
Vue 禁用浏览器的前进后退操作
2020/09/04 Javascript
使用Python3中的gettext模块翻译Python源码以支持多语言
2015/03/31 Python
python 编程之twisted详解及简单实例
2017/01/28 Python
python计算列表内各元素的个数实例
2018/06/29 Python
TensorFlow keras卷积神经网络 添加L2正则化方式
2020/05/22 Python
如何使用Python进行PDF图片识别OCR
2021/01/22 Python
利用CSS3实现文字折纸效果实例代码
2018/07/10 HTML / CSS
HTML5对手机页面长按会粘贴复制禁用的解决方法
2016/07/19 HTML / CSS
医药专业推荐信
2013/11/15 职场文书
圣诞节红领巾广播稿
2014/02/03 职场文书
党员教师工作决心书
2014/03/13 职场文书
2014年“世界无车日”活动方案
2014/09/21 职场文书
会计专业自荐信范文
2019/05/22 职场文书
导游词之湖北武当山
2019/09/23 职场文书