文章目录

  • 前言
  • 一、Python Excel 自动化之 OpenPyXL
    • 2.0 包的安装
    • 2.1 Excel读取
      • 2.1.1 读取Excel中的工作表
      • 2.1.2 读取工作表中的单元格
      • 2.1.3 读取多个单元格的值
      • 2.1.4 练习题
    • 2.2 Excel写入
      • 2.2.1 写入数据并保存
      • 2.2.2 将公式写入单元格保存
      • 2.2.3 插入空列/行
      • 2.2.4 删除
      • 2.2.5 移动
    • 2.3 Excel 样式
      • 2.3.1设置字体样式
      • 2.3.2 设置边框样式
      • 2.3.3 设置单元格其他样式¶
      • 2.3.3 合并、取消合并单元格
    • 2.4 综合练习
      • 2.4.1 将 业务联系表.xlsx 拆分成以下两个 excel:
      • 2.4.2 将 客户信息表.xlsx 和 客户关系表.xlsx 合并成一个excel
  • 二、Python Excel 自动化之 XLWings
    • 2.0 模块基本介绍与使用
    • 2.1 xlwings模块实战
      • 2.1.1 基础语法一览
      • 2.1.2 单元格样式设置
      • 2.1.3 Excel中生成统计图或者插入图片
    • 2.2 实战练习
      • 2.2.1 将消费数据可视化生成带平均线的趋势图,存入excel
      • 2.2.2 将股票数据以指定的格式存储到excel并生成股票走势图
  • 总结

前言

本篇文章主要讲解了python与excel的自动化办公,主要介绍了两个模块:OpenPyXL、XLWings,从安装到实战,清晰可见,非常实用。

一、Python Excel 自动化之 OpenPyXL

2.0 包的安装

打开 CMD/Terminal 进入到自己环境后,执行下面语句安装openpyxl模块。

pip3 install openpyxl

注:openpyxl可以读/写 .xlsx /.xlsm /.xltx /.xltm 的格式文件,但是不支持去读 /.xls 格式;读取 xls 格式,可以安装 xlrd 模块,pip3 install xlrd,本章节以 /.xlsx 格式为主。

2.1 Excel读取

Excel 全称为 Microsoft Office Excel,2003年版本的是 xls 格式,2007和2007年之后的版本是 xlsx 格式。
xlsx 格式通过 openpyxl 模块打开; xls 格式通过 xlwt 模块写,xlrd 模块读取。
本文以 xlsx 模式为例。

2.1.1 读取Excel中的工作表

# 获取当前工作目录
import os
os.getcwd()import warnings
warnings.filterwarnings('ignore')
root_path = './OpenPyXL_test/'

1. 读取Excel文件 用户行为偏好.xlsx ,查看返回值属性

# 导入模块,查看属性
import openpyxlwb = openpyxl.load_workbook(root_path+'用户行为偏好.xlsx')
type(wb)
openpyxl.workbook.workbook.Workbook

这里我们使用 openpyxl 中的 load_workbook 函数来加载指定的 xlsx 文件。

openpyxl.load_workbook( filename, read_only=False, keep_vba=False, data_only=False, keep_links=True, )
load_workbook 函数有五个参数,除 filename 外,其他参数都有默认值,各参数含义如下:

filename: str 类型,表示要打开的文件的相对/绝对路径;

read_only: bool 类型,是否以只读模式打开文件,默认值为 False,可读写;

keep_vba: bool 类型,是否保留文件中的 vba 内容(即使保留了也不一定在代码中能使用),默认值为 False,不保留;

data_only: bool 类型,如果单元格中是 excel 公式,是以公式计算后的值的形式显示还是以公式内容形式显示,默认值为 False,以公式内容形式展示;

keep_links: bool 类型,是否保留单元格中的外链,默认值为 True,保留外链;

返回值类型: openpyxl.workbook.Workbook

如无特殊要求,我们只需要指定filename参数即可

import 和from…import…的区别 :
import导入一个模块,相当于导入的是一个文件夹,相对路径。
from…import…导入了一个模块中的一个函数,相当于文件夹中的文件,绝对路径。

2. 查看对应工作簿包含的 sheet(工作表) 的名称,读取活动表

# 导入模块中的函数,查询对应表的名称
print(wb.sheetnames)
['订单时长分布', 'Sheet3']

这里我们使用 openpyxl.workbook.Workbook 类对象的 sheetnames 属性来获取读取的工作簿中包含的 sheet(工作表) 的名称。

通过上述代码输出内容,我们可以知道 用户行为偏好.xlsx 中包含两个 sheet(工作表),分别是:订单时长分布、 Sheet3。

# 读取工作簿的活动表
# 活动表是工作簿在 Excel 中打开时出现的工作表,在取得 Worksheet 对象后,可通过 title 属性取得它的名称。
active_sheet = wb.active
print(f'active_sheet对象: {active_sheet}')
print(f'active_sheet 名称: {active_sheet.title}')
active_sheet对象: <Worksheet "订单时长分布">
active_sheet 名称: 订单时长分布

活动表是可以修改的,在我们正常打开excel,完成修改后,保存excel,在关闭 excel 前显示的 sheet 就是活动表。
3. 查看指定sheet信息

# 通过传递表名字符串读取表、类型和名称、内容占据的大小
sheet = wb.get_sheet_by_name('Sheet3')
print(f'sheet: {sheet}')
print(f'type(sheet): {type(sheet)}')
print(f'sheet.title: {sheet.title}')
print(f'sheet.dimensions: {sheet.dimensions}')
sheet: <Worksheet "Sheet3">
type(sheet): <class 'openpyxl.worksheet.worksheet.Worksheet'>
sheet.title: Sheet3
sheet.dimensions: A1:I17

这里我们使用 openpyxl.workbook.Workbook 类对象的 get_sheet_by_name 方法,通过指定 sheetname 的方式来获取读取的工作簿中指定的 sheet(工作表) 对象。

并使用 openpyxl.worksheet.worksheet.Worksheet 类对象的一些属性来获取 sheet 的基本信息,比如 Worksheet.title获取 sheet 名称,Worksheet.dimensions 获取 sheet 中值的范围。

Workbook.get_sheet_by_name(name) 函数只有一个参数,就是:sheetname(工作表名称),功能是:通过 sheetname 获取到 Worksheet 对象,除了通过函数的方式获取到 Worksheet 对象,你还可以提过索引的方式,如:

wb['Sheet3']

2.1.2 读取工作表中的单元格


Cell(Excel单元格)
Cell 对象有一个 value 属性,包含这个单元格中保存的值。
Cell 对象也有 row 、column 和 coordinate 属性,提供该单元格的位置信息。
Excel 用字母指定列,在Z列之后,列开始使用两个字母:AA、AB等,所以在调用的 cell() 方法时,可传入整数作为 row 和 column 关键字参数,也可以得到一个单元格。
注:第一行或第一列的整数取1,而不是0.

# 从表中取得单元格 在 2.1.1 中我们已经读取过工作簿了 返回结果存储变量为 wb
## 获取表格名称
print(f'sheetnames: {wb.sheetnames}')
sheetnames: ['订单时长分布', 'Sheet3']
# 获取指定sheet
sheet = wb.get_sheet_by_name('订单时长分布')# 通过单元格位置获取单元格对象,如:B1
a = sheet['B1']
print(f"sheet[B1']: {a}")# 获取并打印 B1 单元格的文本内容
print(f"sheet[B1'].value: {a.value}")# 获取并打印 B1 单元格所在行、列和数值
print(f'Row: {a.row}, Column: {a.column}')# 获取并打印 B1 单元格坐标 和 值
print(f'Cell {a.coordinate} is {a.value}')
sheet[B1']: <Cell '订单时长分布'.B1>
sheet[B1'].value: 日期
Row: 1, Column: B
Cell B1 is 日期
# 获取并打印出 B列 前8行的奇数行单元格的值
for i in range(1,8,2):print(i, sheet.cell(row=i,column=2).value)
# 获取并打印出 B列 前8行的奇数行单元格的值
for i in range(1,8,2):print(i, sheet.cell(row=i,column=2).value)
# 获取并打印出 B列 前8行的奇数行单元格的值
for i in range(1,8,2):print(i, sheet.cell(row=i,column=2).value)
1 日期
3 2020-07-24 00:00:00
5 2020-07-24 00:00:00
7 2020-07-24 00:00:00
# 确定表格的最大行数和最大列数,即表的大小
print(f'sheet.max_row: {sheet.max_row}')
print(f'sheet.max_column: {sheet.max_column}')
sheet.max_row: 14
sheet.max_column: 4

2.1.3 读取多个单元格的值



2.1.4 练习题

找出用户行为偏好.xlsx中 Sheet3 表中空着的格子,并输出这些格子的坐标。

from openpyxl import load_workbookexl = load_workbook(root_path+'用户行为偏好.xlsx')
sheet3 = exl.get_sheet_by_name('Sheet3')
sheet3.dimensions
'A1:I17'
# 直接通过sheet索引,sheet3.dimensions获取sheet数据区域
cells = sheet3[sheet3.dimensions]# 遍历元组 判断每一个cell值是否为空
for rows in cells:for cell in rows:if not cell.value:print(f'{cell.coordinate} is None \n')
D3 is None D8 is None G10 is None 

2.2 Excel写入

2.2.1 写入数据并保存

1. 原有工作簿中修改数据并保存

# 1) 导入 openpyxl 中的 load_workbook 函数
from openpyxl import load_workbook# 2) 获取指定 excel文件对象 Workbook
exl = load_workbook(filename=root_path+'用户行为偏好.xlsx')
# 3) 通过指定 sheetname 从 Workbook 中获取 sheet 对象 Worksheet
sheet = exl.get_sheet_by_name('Sheet3')
# 4) 通过索引方式获取指定 cell 值,并重新赋值
print(f"修改前 sheet['A1']: {sheet['A1'].value}")
sheet['A1'].value = 'hello world'
print(f"修改后 sheet['A1']: {sheet['A1'].value}")
# 5) 保存修改后的内容
# 如果 filename 和原文件同名,则是直接在原文件中修改;
# 否则会新建一个 excel 文件,并保存内容
exl.save(filename=root_path+'用户行为偏好_1.xlsx')  # 保存到一个新文件中 新文件名称为:用户行为偏好_1.xlsx
修改前 sheet['A1']: 1
修改后 sheet['A1']: hello world
# 验证保存修改内容是否成功
exl_1 = load_workbook(filename=root_path+'用户行为偏好_1.xlsx')
# 我们将原表中 Sheet3 中的 A1 值改为了 'hello world'
# 所以读取保存文件,查看对应值是否为 'hello world' 即可
a1 = exl_1['Sheet3']['A1'].value
if a1 == 'hello world':print(f"修改保存成功啦~,exl_1['Sheet3']['A1'].value = {a1}")
else:print(f"修改保存有问题,现在exl_1['Sheet3']['A1'].value = {a1}")
修改保存成功啦~,exl_1['Sheet3']['A1'].value = hello world

我们只需要获取到 sheet 中的 cell 对象后,就可以通过改变 cell.value 的值来改变对应单元格中的值,然后使用 Workbook 对象的 save 函数可以将修改后的工作簿内容保存起来。
2. 创建新的表格写入数据并保存

2.2.2 将公式写入单元格保存

# 1) 导入 openpyxl 中的 load_workbook 函数
from openpyxl import load_workbook# 2) 获取指定 excel文件对象 Workbook
exl_1 = load_workbook(filename=root_path+'用户行为偏好_1.xlsx')
# 3) 通过指定 sheetname 从 Workbook 中获取 sheet 对象 Worksheet
sheet = exl_1['订单时长分布']print(f'订单时长分布 值范围: {sheet.dimensions}')      #先查看原有表格的单元格范围,防止替代原有数据
订单时长分布 值范围: A1:D14
# 单元格 A15 中写入 合计
sheet['A15'].value = '合计'
# 单元格 D15 中写入求和公式:SUM(D2:D14)
sheet['D15'] = '=SUM(D2:D14)'
exl_1.save(filename='用户行为偏好_1.xlsx')
# 使用 xlwings 打开 excel 文件然后保存 使写入的 公式生效
import xlwings as xw
# 打开工作簿
app = xw.App(visible=False, add_book=False)
wb = app.books.open('用户行为偏好_1.xlsx')
wb.save()
# 关闭工作簿
wb.close()
app.quit()
# 验证写入是否成功
# 1) 获取指定 excel文件对象 Workbook,
#    并设置 data_only=True,表示读取的时候如果单元格内是公式的话,以公式计算后的值的形式显示
exl_2 = load_workbook(filename = '用户行为偏好_1.xlsx', data_only=True)
# 2) 打印相关信息
sheet = exl_2['订单时长分布']
print(f"sheet['A15']={sheet['A15'].value},sheet['D15']={sheet['D15'].value}")
print(f"{sheet['D1'].value} 求和值为SUM(D2:D14)={sheet['D15'].value}")
sheet['A15']=合计,sheet['D15']=4004.72615615615
次数 求和值为SUM(D2:D14)=4004.72615615615

【注意】

即使设置了 data_only=True,也不能立即获取到刚刚添加的公式计算后的结果,需要自己 手动/添加代码 打开下 对应excel表格,然后 ctrl s保存下,再运行上面代码才能获取到对应公式计算后的值。

你可以使用下面代码自动打开指定 excel 文件然后保存使写入的公式生效,使用前你需要安装 xlwings,输入pip3 install xlwings即可,后面我们也会学习这个模块。

# 使用 xlwings 打开 excel 文件然后保存 使写入的 公式生效
import xlwings as xw
# 打开工作簿
app = xw.App(visible=False, add_book=False)
wb = app.books.open('用户行为偏好_1.xlsx')
wb.save()
# 关闭工作簿
wb.close()
app.quit()

2.2.3 插入空列/行

# 获取指定 sheet
sheet = exl_1['Sheet3']# 插入列数据 insert_cols(idx,amount=1)
# idx是插入位置,amount是插入列数,默认是1
# idx=2第2列,第2列前插入一列
sheet.insert_cols(idx=2)
# 第2列前插入5
# sheet.insert_cols(idx=2, amount=5)# 插入行数据 insert_rows(idx,amount=1)
# idx是插入位置,amount是插入行数,默认是1
# 在第二行前插入一行
sheet.insert_rows(idx=2)
# 第2行前插入5行
# sheet.insert_rows(idx=2, amount=5)exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2.2.4 删除

# 删除多列
sheet.delete_cols(idx=5, amount=2)
# 删除多行
sheet.delete_rows(idx=2, amount=5)exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2.2.5 移动

当数字为正即向下或向右,为负即为向上或向左。

# 移动
# 当数字为正即向下或向右,为负即为向上或向左
sheet.move_range('B3:E16',rows=1,cols=-1)
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2.3 Excel 样式

2.3.1设置字体样式

1. 设置单个 cell(单元格) 字体样式
Font(name字体名称,size大小,bold粗体,italic斜体,color颜色)

# 1) 导入 openpyxl 中的 load_workbook 函数
#    导入 openpyxl 中的  styles 模块中的 Font 类
from openpyxl import load_workbook
from openpyxl.styles import Font# 2) 获取指定 excel文件对象 Workbook
exl_1 = load_workbook(filename=root_path+'用户行为偏好_1.xlsx')
# 3) 通过指定 sheetname 从 Workbook 中获取 sheet 对象 Worksheet
sheet = exl_1['订单时长分布']
# 4) 获取到指定 cell 后,查看cell字体属性
cell = sheet['A1']
cell.font
<openpyxl.styles.fonts.Font object>
Parameters:
name='宋体', charset=134, family=None, b=True, i=False, strike=None, outline=None, shadow=None, condense=None, color=<openpyxl.styles.colors.Color object>
Parameters:
rgb=None, indexed=None, auto=None, theme=1, tint=0.0, type='theme', extend=None, sz=11.0, u=None, vertAlign=None, scheme='minor'
# 5) 实例化一个 Font 对象,设置字体样式
#    字体改为:黑体  大小改为:20  设置为:加粗 斜体 红色
font = Font(name='黑体', size=20, bold=True, italic=True, color='FF0000')
cell.font = font
# 6) 保存修改
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2. 设置多个 cell 的字体样式

# 上面我们已经获取到了 '用户行为偏好_1.xlsx' 中的 订单时长分布 工作表
# 我们处理了 单元格 A1 的字体样式,我们也可以通过遍历的形式,批量设置单元格字体样式# 1) 获取要处理的单元格
#    通过 sheet 索引获取第二行 cell
#    获取列可以用 字母索引,如 sheet['A'] 获取第一列 cell
cells = sheet[2]
# 2) 实例化一个 Font 对象,设置字体样式
#    字体改为:黑体  大小改为:10  设置为:加粗 斜体 红色
font = Font(name='黑体', size=10, bold=True, italic=True, color='FF0000')
# 3) 遍历给每一个 cell 都设置上对应字体样式
for cell in cells:cell.font = font
# 4) 保存修改
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2.3.2 设置边框样式

1. 设置单元格边框样式
Side:边线样式设置类,边线颜色等

Side(style=None, color=None, border_style=None)

style:边线的样式,有以下值可选:double, mediumDashDotDot, slantDashDot, dashDotDot, dotted, hair, mediumDashed, dashed, dashDot, thin, mediumDashDot, medium, thick
color:边线颜色
border_style:style 的别名,必须设置,一般直接设置 border_style 就行,不用设置 style
Border:边框定位类,左右上下边线

Border常用参数解释:

top bottom left right diagonal:上下左右和对角线的边线样式,为 Side 对象
diagonalDown:对角线从左上角向右下角方向,默认为 False
diagonalUp:对角线从右上角向左下角方向,默认为 False

# 上面我们已经获取到了 '用户行为偏好_1.xlsx' 中的 订单时长分布 工作表 sheet
# 1) 导入 openpyxl 中的  styles 模块中的 Side, Border 类
from openpyxl.styles import Side, Border
# 2) 首先初始化一个边线对象(也可以设置多个)
side = Side(border_style='double', color='FF000000')
# 3) 通过 Border 去设置 整个单元格边框样式
border = Border(left=side, right=side, top=side, bottom=side, diagonal=side, diagonalDown=True, diagonalUp=True)
# 4) 查看目前单元格边框样式
# 获取第一行 cells
cells = sheet[1]
# 取出一个 cell 看边框样式
cells[0].border
<openpyxl.styles.borders.Border object>
Parameters:
outline=True, diagonalUp=False, diagonalDown=False, start=None, end=None, left=<openpyxl.styles.borders.Side object>
Parameters:
style=None, color=None, right=<openpyxl.styles.borders.Side object>
Parameters:
style=None, color=None, top=<openpyxl.styles.borders.Side object>
Parameters:
style=None, color=None, bottom=<openpyxl.styles.borders.Side object>
Parameters:
style=None, color=None, diagonal=<openpyxl.styles.borders.Side object>
Parameters:
style=None, color=None, vertical=None, horizontal=None
# 5) 修改边框样式,并保存修改
for cell in cells:cell.border = border
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2.3.3 设置单元格其他样式¶

1. 设置单元格背景色

2.设置水平居中
openpyxl.styles 中的 Alignment 类常用参数介绍:

horizontal:水平对齐,常见值 distributed, justify, center, left, fill, centerContinuous, right, general
vertical:垂直对齐,常见值 bottom, distributed, justify, center, top
textRotation:文字旋转角度,数值:0-180
wrapText:是否自动换行,bool值,默认 False

# 上面我们已经获取到了 '用户行为偏好_1.xlsx' 中的 订单时长分布 工作表 sheet
# 1) 从 openpyxl.styles 中导入 对齐方式设置类 Alignment
from openpyxl.styles import Alignment# 2) 实例化一个 Alignment 对象,设置水平、垂直居中
alignment = Alignment(horizontal='center', vertical='center')# 3) 获取指定 cells 遍历填充
# 对第五行数据设置上面的对齐方式
cells = sheet[5]
for cell in cells:cell.alignment = alignment
# 4) 保存修改
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

3. 设置行高与列宽

# 1) 设置行高,通过 row_dimensions 和 column_dimensions 来获取行和列对象
# 2) 设置第1行行高为 30
sheet.row_dimensions[1].height = 30
# 3) 设置第3列列款为 24
sheet.column_dimensions['C'].width = 24
# 4) 保存修改
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2.3.3 合并、取消合并单元格

# 注意:合并后的单元格只会显示合并区域中最右上角的单元格的值,会导致其他单元格内容丢失
# 上面我们已经获取到了 '用户行为偏好_1.xlsx' 对象 exl_1,我们可以通过 exl_1 来索引获取自己想要的 sheet
# 1) 获取 Sheet3 这个工作表
sheet = exl_1['Sheet3']# 合并指定区域单元格
sheet.merge_cells('A1:B2')# sheet.merge_cells(start_row=1, start_column=3,
#                  end_row=2, end_column=4)# 保存修改
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')
# 解除合并
sheet.unmerge_cells('A1:B2')# sheet.unmerge_cells(start_row=1, start_column=3,
#                     end_row=2, end_column=4)# 保存修改
exl_1.save(filename=root_path+'用户行为偏好_1.xlsx')

2.3.5 练习题
打开 test.xlsx 文件,找出文件中购买数量 buy_mount 超过5的单元格,并对其标红、加粗、加上红色边框。

# 1) 导入 openpyxl 相关函数和类
from openpyxl import load_workbook
from openpyxl.styles import Font, Side, Border# 2) 读取 test.xlsx 文件,并筛选出 buy_mount 这一列
workbook = load_workbook(root_path+'test.xlsx')
sheet = workbook.active
buy_mount = sheet['B']
# 3) 设置边框 文字样式
side = Side(style='thin', color='FF0000')
border = Border(left=side, right=side, top=side, bottom=side)
font = Font(bold=True, color='FF0000')
# 4) 遍历判断 cell 值是否满足筛选条件
for cell in buy_mount:if isinstance(cell.value, float) and cell.value > 5:cell.font = fontcell.border = border
# 5) 修改内容另存为 new_test.xlsx
workbook.save(root_path+'new_test.xlsx')

2.4 综合练习

2.4.1 将 业务联系表.xlsx 拆分成以下两个 excel:

客户信息表:客户名称 客户地址 客户方负责人 性别 联系电话 对接业务经理编号
业务经理信息表:业务经理编号 所在分区 所在区域 业务经理姓名

# 1) 导入 openpyxl 相关函数和类
from openpyxl import load_workbook, Workbook# 2) 读取原表数据
wb = load_workbook(root_path+'业务联系表.xlsx')
# 3) 获取工作表
sheet = wb.active
# 草稿纸
# 我们知道我们表格的实际列名在第二行
# 获取每列第二行的坐标和值
for i in sheet[2]:print(i.coordinate, i.value)
A2 业务经理编号
B2 分区
C2 区域
D2 业务经理
E2 客户名称
F2 客户地址
G2 客户方负责人
H2 性别
I2 联系电话
J2 备注
sheet.max_column, sheet.max_row
(10, 57)
# 4) 筛选出需要的列
# 4.1) 客户信息表:客户名称 客户地址 客户方负责人 性别 联系电话 备注 对接业务经理编号
cust_info = {'业务经理编号': 'A', '客户名称': 'B', '客户地址': 'C', '客户方负责人': 'D', '性别': 'E', '联系电话': 'F', '备注': 'G'}# 4.2) 新建一个工作簿,并将默认sheet名称改成 客户信息
cust_info_excel = Workbook()
cust_info_sh = cust_info_excel.active
cust_info_sh.title = '客户信息'
# 4.3) 遍历筛选,如果是需要的表头,就将该列的值复制到新的工作簿中的 客户信息 工作表中
for i in sheet[2]:if i.value in cust_info:# 遍历将这一列中除了第一个cell外的所有cell值复制到新表for cell in sheet[i.coordinate[0]]:if cell.row == 1:continuecust_info_sh[f'{cust_info[i.value]}{cell.row-1}'].value = cell.value
# 5) 筛选出需要的列
# 5.1) 业务经理信息表:业务经理编号 所在分区 所在区域 业务经理姓名
manager_info = {'业务经理编号': 'A', '分区': 'B', '区域': 'C', '业务经理': 'D'}# 5.2) 新建一个工作簿,并将默认sheet名称改成 客户信息
manager_info_excel = Workbook()
manager_info_sh = manager_info_excel.active
manager_info_sh.title = '业务经理信息'
# 5.3) 遍历筛选,如果是需要的表头,就将该列的值复制到新的工作簿中的 业务经理信息 工作表中
for i in sheet[2]:if i.value in manager_info:# 遍历将这一列中除了第一个cell外的所有cell值复制到新表for cell in sheet[i.coordinate[0]]:if cell.row == 1:continuemanager_info_sh[f'{manager_info[i.value]}{cell.row-1}'].value = cell.value
# 6.1 ) 保存 客户信息表 工作簿内容
cust_info_excel.save(root_path+'客户信息表_xl.xlsx')
# 6.2) 保存 业务经理信息表 工作簿内容
manager_info_excel.save(root_path+'业务经理信息表_xl.xlsx')

以上,虽然完成了数据拆分,但是对于进一步数据处理,继续使用 openpyxl 并不是很便捷,比如数据去重,筛选等,接下来我将给大家介绍如何使用 pandas 更便捷的处理 excel 数据。

import pandas as pd# 1) 读取数据
data = pd.read_excel(root_path+'业务联系表.xlsx', header=1)
# 2) 数据筛选处理
# 2.1) 客户信息表
# 筛选出 客户信息表 需要的列
cust_info_pd = data[['业务经理编号', '客户名称', '客户地址', '客户方负责人', '性别', '联系电话', '备注']]
# 去除重复行
cust_info_pd.drop_duplicates(inplace=True)
# 打印出前三行
cust_info_pd.head(3)

# 2.2) 业务经理信息表
# 筛选出 业务经理信息表 需要的列,并打印出前三行
manager_info_pd = data[['业务经理编号', '分区', '区域', '业务经理']]
# 去除重复行
manager_info_pd.drop_duplicates(inplace=True)
# 打印出前三行
manager_info_pd.head(3)

# 3) 数据保存
cust_info_pd.to_excel(root_path+'客户信息表_pd.xlsx', index=None)
manager_info_pd.to_excel(root_path+'业务经理信息表_pd.xlsx', index=None)

2.4.2 将 客户信息表.xlsx 和 客户关系表.xlsx 合并成一个excel

# 接上面的,将 客户信息表.xlsx 和 客户关系表.xlsx 合并成一个excel
# 这里我们依然用 pandas 来处理
business_contact = pd.merge(manager_info_pd, cust_info_pd, on='业务经理编号')
# 查看合并后数据基本信息
business_contact.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 55 entries, 0 to 54
Data columns (total 10 columns):
业务经理编号    55 non-null int64
分区        55 non-null object
区域        55 non-null object
业务经理      55 non-null object
客户名称      55 non-null object
客户地址      55 non-null object
客户方负责人    55 non-null object
性别        55 non-null object
联系电话      55 non-null object
备注        0 non-null float64
dtypes: float64(1), int64(1), object(8)
memory usage: 4.7+ KB
# 查看前10条数据
business_contact.head(10)

# 数据保存
manager_info_pd.to_excel(root_path+'业务联系表_pd.xlsx', index=None)

二、Python Excel 自动化之 XLWings

2.0 模块基本介绍与使用

xlwings
基本介绍:用于Python与Excel之间的交互,可以轻松地从 Excel 调用 Python,也可以利用Python自动化操作Excel,调用VBA,非常方便。

项目地址:https://github.com/xlwings/xlwings

基本使用方法:新建一个excel文件,取名为xlwings_wb.xlsx,并新建一个sheet,取名为first_sht,在其A1单元格内插入字符串Datawhale。

打开 CMD/Terminal 进入到自己环境后,执行下面语句安装 xlwings 模块。

pip3 install xlwings
# 导入xlwings,并起一个别名 xw,方便操作
import xlwings as xw# 1、创建一个app应用,打开Excel程序
# visible=True 表示打开操作Excel过程可见 初次接触可以设置为True,了解其过程
# add_book=False 表示启动app后不用新建个工作簿
app = xw.App(visible=True, add_book=False)# 2、新建一个工作簿
wb = app.books.add()# 3、新建一个sheet,并操作
# 3.1 新建sheet 起名为first_sht
sht = wb.sheets.add('first_sht')
# 3.2 在新建的sheet表中A1位置插入一个值:Datawhale
sht.range('A1').value = 'Datawhale'
# 3.3 保存新建的工作簿,并起一个名字
wb.save(root_path+'xlwings_wb.xlsx')# 4、关闭工作簿
wb.close()# 5、程序运行结束,退出Excel程序
app.quit()

2.1 xlwings模块实战

2.1.1 基础语法一览

导包

# 基础导入包
import xlwings as xw  # 程序第一步

打开关闭Excel程序(理解成excel软件打开、关闭)

# visible=True 表示打开操作Excel过程可见 初次接触可以设置为True,了解其过程
# add_book=False 表示启动app后不用新建个工作簿
app = xw.App(visible=True, add_book=False)  # 程序第二步# 关闭excel程序
# app.quit()  # 程序最后一步

工作簿相关操作(理解成excel文件)

# 1、新建一个工作簿
# wb = app.books.add()  # 程序第三步# 2、保存新建的工作簿,并起一个名字
# 程序倒数第三步,非常关键,保存操作数据结果
# wb.save(root_path+'xlwings_wb.xlsx')  # 3、打开一个已经存在的工作簿
wb = app.books.open(root_path+'xlwings_wb.xlsx')  # 程序第三步# 4、关闭工作簿
# wb.close()  # 程序倒数第二步

sheet相关操作(理解成工作表)

# 在工作簿中新建一个sheet,起名为 second_sht
sht1 = wb.sheets.add('second_sht')
print('sht1:', sht1)# 选中已经存在的sheet
sht2 = wb.sheets('first_sht')
print('sht2:', sht2)# 也可以通过索引选择已存在的sheet
sht3 = wb.sheets[0]  # 选中工作簿中的第一个sheet
print('sht3:', sht3)# 获取工作簿中工作表的个数
sht_nums = wb.sheets.count
print('工作簿中的sheet个数为:%d'% sht_nums)# 当前工作表名字
print('sht1.name:', sht1.name)# 获取指定sheet中数据的行数
print('sht1.used_range.last_cell.row:', sht1.used_range.last_cell.row)# 获取指定sheet中数据的列数
print('sht1.used_range.last_cell.column:', sht1.used_range.last_cell.column)# 删除指定的sheet 比如删除:first_sht
wb.sheets('first_sht').delete()
sht1: <Sheet [xlwings_wb.xlsx]second_sht>
sht2: <Sheet [xlwings_wb.xlsx]first_sht>
sht3: <Sheet [xlwings_wb.xlsx]second_sht>
工作簿中的sheet个数为:3
sht1.name: second_sht

单元格相关操作(就是excel单元格子)

'''
写入
'''
# 在工作表中指定位置插入数据
sht1.range('B1').value = 'Datawhale'# 在工作表指定位置插入多个数据 默认是横向插入
sht1.range('B2').value = ['DATAWHALE', 'FOR', 'THE', 'LEARNER']# 在工作表指定位置竖向插入多个数据
# 设置 options(transpose=True),transpose=True 表示转置的意思
sht1.range('B3').options(transpose=True).value = [1, 2, 3, 4]# 在工作表指定位置开始插入多行数据
sht1.range('B7').value = [['a', 'b'], ['c', 'd']]# 在工作表指定位置开始插入多列数据
sht1.range('B9').options(transpose=True).value = [['a', 'b'], ['c', 'd']]# 向单元格写入公式
sht1.range('F2').formula = '=sum(B2:E2)'

'''
读取
'''
# 在工作表中读取指定位置数据
print('单元格B1=', sht1.range('B1').value)# 在工作表中读取指定区域数据 一行
print('单元格B2:F2=', sht1.range('B2:F2').value)# 在工作表中读取指定区域数据 一列
print('单元格B3:B6=', sht1.range('B3:B6').value)# 在工作表中读取指定区域数据 一个区域
# 设置options(transpose=True)就可以按列读 不设置就是按行读
print('单元格B7:C10=', sht1.range('B7:C10').options(transpose=True).value)
单元格B1= Datawhale
单元格B2:F2= ['DATAWHALE', 'FOR', 'THE', 'LEARNER', 0.0]
单元格B3:B6= [1.0, 2.0, 3.0, 4.0]
单元格B7:C10= [['a', 'c', 'a', 'b'], ['b', 'd', 'c', 'd']]
'''
删除
'''
# 删除指定单元格中的数据
sht1.range('B10').clear()# 删除指定范围内单元格数据
sht1.range('B7:B9').clear()

2.1.2 单元格样式设置

'''
格式修改
'''
# 选中已经存在的sheet
sht1 = wb.sheets('second_sht')
# 返回单元格绝对路径
sht1.range('B3').get_address()
# sht1.range('B3').address# 合并单元格B3 C3
sht1.range('B3:C3').api.merge()# 解除合并单元格B3 C3
# sht1.range('B3:C3').api.unmerge()# 向指定单元格添加带超链接文本
# address- 超连接地址
# text_to_display- 超链接文本内容
# screen_tip- 鼠标放到超链接上后显示提示内容
sht1.range('C2').add_hyperlink(address='https://datawhale.club',text_to_display='DATAWHALE 官网',screen_tip='点击查看 DATAWHALE 官网 ')# 获取指定单元格的超链接地址
sht1.range('C2').hyperlink# 自动调试指定单元格高度和宽度
sht1.range('B1').autofit()# 设置指定单元格背景颜色
sht1.range('B1').color = (93,199,221)# 返回指定范围内的中第一列的编号 数字,如:A-1 B-2
sht1.range('A2:B2').column# 获取或者设置行高/列宽
# row_height/column_width会返回行高/列宽 ,范围内行高/列宽不一致会返回None
# 也可以设置一个新的行高/列宽
sht1.range('A2').row_height = 25
sht1.range('B2').column_width = 20


在windows上可以使用以下方法设置单元格文字颜色等格式,如下:
windows系统下字体设置在 sheet.range().api.Font下
颜色
sht1.range(‘A1’).api.Font.Color = (255,0,124)

字体名字
sht1.range(‘A1’).api.Font.Name = ‘宋体’

字体大小
sht1.range(‘A1’).api.Font.Size = 28

是否加粗
sht1.range(‘A1’).api.Font.Bold = True

数字格式
sht1.range(‘A1’).api.NumberFormat = ‘0.0’
-4108 水平居中
-4131 靠左
-4152 靠右

sht1.range(‘A1’).api.HorizontalAlignment = -4108
-4108 垂直居中(默认)
-4160 靠上
-4107 靠下
-4130 自动换行对齐。

sht1.range(‘A1’).api.VerticalAlignment = -4130

设置上边框线风格和粗细
sht1.range(‘A1’).api.Borders(8).LineStyle = 5
sht1.range(‘A1’).api.Borders(8).Weight = 3

在mac下可以通过以下方法设置字体格式
设置单元格的字体颜色
rgb_tuple = (0, 10, 200)
sht1.range(‘B1’).api.font_object.color.set(rgb_tuple)

获取指定单元格字体颜色
sht1.range(‘B1’).api.font_object.color.get()

获取指定单元格字体名字 可以使用set方法修改字体 set(‘宋体’)
sht1.range(‘B1’).api.font_object.name.get()

设置指定单元格字体格式 可以用get方法查看单元格字体格式
sht1.range(‘B3’).api.font_object.font_style.set(‘加粗’)

设置指定单元格字体大小
sht1.range(‘B3’).api.font_object.font_size.set(20)

设置边框线粗细
sht1.range(‘B2’).api.get_border(which_border=9).weight.set(4)

设置边框线风格
sht1.range(‘B2’).api.get_border(which_border=9).line_style.set(8)
样式值含义基本说明:


再次提醒,进行完所有操作后一定要记得执行以下三句:

# 保存新建的工作簿,并起一个名字(如果已存在有名字的excel文件,就直接save即可)
wb.save()
# 关闭工作簿(关闭Excel文件)
wb.close()
# 程序运行结束,退出Excel程序
app.quit()

2.1.3 Excel中生成统计图或者插入图片

自动生成统计图

import xlwings as xw# 新建一个sheet
app = xw.App(visible=True, add_book=False)
wb = app.books.open(root_path+'xlwings_wb.xlsx')
sht3 = wb.sheets.add('third_sht')import pandas as pd
import numpy as np# 生成模拟数据
df = pd.DataFrame({'money':np.random.randint(45, 50, size = [1, 20])[0],
},index=pd.date_range('2021-02-01', '2021-02-20'),  # 行索引和时间相关
)
df.index.name = '消费日期'  # 设置索引名字sht3.range('A1').value = df# 生成图表
chart1 = sht3.charts.add()  # 创建一个图表对象
chart1.set_source_data(sht3.range('A1').expand())  # 加载数据
chart1.chart_type = 'line'  # 设置图标类型
chart1.top = sht3.range('D2').top
chart1.left = sht3.range('D2').left  # 设置图标开始位置


除了绘制折线图,我们还可以绘制其他类型的图,修改chart_type值即可。

查看其他chart_types值
xw.constants.chart_types
返回结果很长,这里选几个常见的图形列出来:

 '3d_line',  # 3D折线图'3d_pie', # 3D饼图'area',  # 面积图'bar_clustered',  # 柱状图相关'bubble',  # 气泡图'column_clustered',  # 条形图相关'line',  # 折线图'stock_hlc',  # 有意思 股票K线图

将本地图片或者matplotlib图片保存到excel

'''
matplotlib 生成的图片存入excel
'''
import matplotlib.pyplot as plt
# 随便绘制一个饼图
fig1 = plt.figure()  # 先创建一个图像对象
plt.pie([0.5, 0.3, 0.2],  # 值labels=['a', 'b', 'c'],  # 标签explode=(0, 0.2, 0),  # (爆裂)距离autopct='%1.1f%%',   # 显示百分数格式shadow=True)  # 是否显示阴影
plt.show() # 将饼图添加到excel指定位置 J17为图片开始位置
sht3.pictures.add(fig1, name='matplotlib', left=sht3.range('J17').left, top=sht3.range('J17').top, update=True)

'''
本地图片存入excel
'''
# 将本地图片添加到excel指定位置 J1为图片开始位置
pic_path = 'F:\\桌面\\office-automation-main-20220709160400\\office-automation-main\\Task02-Python与Excel\\imgs\\logo.png'
sht3.pictures.add(pic_path, name='local', left=sht3.range('J1').left, top=sht3.range('J1').top, update=True)

2.2 实战练习

2.2.1 将消费数据可视化生成带平均线的趋势图,存入excel

'''
实战练习一:将消费数据可视化生成带平均线的趋势图,存入excel
数据就是之前生成的模拟数据
'''
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
fig, ax = plt.subplots()  # 创建一个画板
# 生成一条新线- 平均消费数据
money_m = [df['money'].mean(axis=0) for i in range(len(df['money']))]
# 建一条线:消费趋势折线图
ax.plot(df.index, df['money'], color='#f16a0b', label='每日消费')
# 再建一条线:平均消费直线图
ax.plot(df.index, money_m, linestyle='--', color='#301502', label='平均消费')
# 设置横纵坐标基础说明
ax.set_xlabel(u'日期')
ax.set_ylabel(u'消费金额/元')
ax.set_title(u'消费折线图')
# 设置x轴值显示方向
plt.setp(ax.get_xticklabels(), rotation=70, horizontalalignment='right')
# 添加图例(label说明到图片上) loc设置显示位置
ax.legend(loc=2)
plt.show()
sht3.pictures.add(fig, name='消费情况', left=sht3.range('D17').left, top=sht3.range('D17').top, update=True)

# 保存新建的工作簿,并起一个名字(如果已存在有名字的excel文件,就直接save即可)
wb.save()
# 关闭工作簿(关闭Excel文件)
wb.close()
# 程序运行结束,退出Excel程序
app.quit()

2.2.2 将股票数据以指定的格式存储到excel并生成股票走势图

新建一个sheet,然后获取数据

'''
实战练习二:将股票数据以指定的格式存储到excel并生成股票走势图
利用akshare爬取上证指数数据 代号:sh000001
'''
# 需要提前 pip install akshare 安装 akshare
import akshare as ak
import xlwings as xw
import datetime # 新建一个sheet
app = xw.App(visible=True, add_book=False)
wb = app.books.open(root_path+'xlwings_wb.xlsx')
sz_sht = wb.sheets.add('sz_sht')  # 第一次新建
# sz_sht = wb.sheets['sz_sht']  # 已经存在,直接打开# 获取数据 open high low close volume index-date
# volume 是成交量 多少股
# 0、获取数据
sz_index = ak.stock_zh_index_daily(symbol="sh000001")
sz_index

处理并存储数据到excel

# 1、处理下数据
sz_index.set_index('date', inplace=True)
sz_data = sz_index[datetime.date(2022,1,1):datetime.date(2022,6,14)].iloc[:,0:4]  # 只取今年数据 ohlc
sz_data.index = sz_data.index.to_series().apply(lambda x : x.strftime('%m-%d')) # 将索引日期格式改为 月-日# 2、存储数据
sz_sht.range('A1').value = sz_data

处理表格中数据格式

# 3、处理数据格式
# - 表头字体 格式加粗 背景颜色
sz_sht.range('A1:E1').api.font_object.name.set('Calibri')
sz_sht.range('A1:E1').api.font_object.font_style.set('加粗')
sz_sht.range('A1:E1').api.font_object.color.set((255, 255, 255))
# 背景颜色
sz_sht.range('A1:E1').color = (16, 156, 245)
# mac上居中未实现,有了解的小伙伴可以留言指出下,感谢
# sz_sht.range('B1').api.font_object.horizontalalignment = xw.constants.Constants.xlCenter# - 添加边框
# 1 左+内部竖线
sz_sht.range('A1:E177').api.get_border(which_border=1).weight.set(2)
# 10 最右侧竖线
sz_sht.range('A1:E177').api.get_border(which_border=10).weight.set(2)
# 3 上+内部横线
sz_sht.range('A1:E177').api.get_border(which_border=3).weight.set(2)
# 9 最下面横线
sz_sht.range('A1:E177').api.get_border(which_border=9).weight.set(2)

生成ohlc k线图并存储到excel指定位置

# 4、生成图表
chart_ohlc = sz_sht.charts.add()  # 创建一个图表对象
chart_ohlc.set_source_data(sz_sht.range('A1').expand())  # 加载数据
chart_ohlc.chart_type = 'stock_ohlc'  # 设置图标类型
chart_ohlc.top = sz_sht.range('G2').top
chart_ohlc.left = sz_sht.range('G2').left  # 设置图标开始位置

# 保存新建的工作簿,并起一个名字(如果已存在有名字的excel文件,就直接save即可)
wb.save()
# 关闭工作簿(关闭Excel文件)
wb.close()
# 程序运行结束,退出Excel程序
app.quit()

总结

本篇文章主要讲解了python与excel的自动化办公,主要介绍了两个模块:OpenPyXL、XLWings,从模块的安装到实战运用再到最后的练习,层层递进,收获颇多!

Task02 python与excel相关推荐

  1. python拆分excel的sheet为单文件_python拆分Excel表格并发送邮件

    工作中经常会出现需要将数据按一定的条件拆分并分发给不同的收件人的情况,今天就来给大家分享一下如何使用python拆分Excel表格并分发邮件. 以下表(2019年下半年销量数据表)数据为例: 首先我们 ...

  2. python 读取excel文件 效率 时间 格式_python读取Excel文件中的时间数据

    在使用python读取Excel文件中的时间格式,碰到的时间格式转换问题: 读取这样的表格: 输出这样的数据结果: 然而这样的结果却不是我们想要的,我们需要的是这样的结果: 1.安装python官方库 ...

  3. python连接excel存放数据_有了这篇python操作Excel学习笔记,以后储存数据 办公很轻松!...

    最近在做一些数据处理和计算的工作,因为数据是以.csv格式保存的,因此刚开始直接用Excel来处理.但是做着做着发现重复的劳动其实并没有多大的意义,于是就想着写个小工具帮着处理.以前正好在一本书上看到 ...

  4. 太赞!Python和Excel终于可以互通了

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 今天为大家分享一篇使用python将大量数据导出到Excel中的技巧心得,可以让Pyt ...

  5. python 表格格式输出_利用python对excel中一列的时间数据更改格式操作

    问题场景:需要将下列的交期一列的数据格式更改成2019/05/10 存货编码 尺寸 数量 交期 0 K10Y0190000X B140 200 2019-05-10 00:00:00 1 K10Y01 ...

  6. python excel增加一列_(用Python修改excel中一列数据)python新增一列

    python怎么从excel中读取数据? ⒈ #import παέτο import xlrd #Ρύθμι διαδρής path='C:\\Users\\jyjh\\Desktop\\data ...

  7. 使用PYTHON操作Excel的工具

    作者:卓晴博士,清华大学自动化系 更新时间:2020-07-25 Saturday Python和Excel都是分析处理数据的很强大的工具.如果将它们结合在一起则更加的强大.由于自己经常处理一些Exc ...

  8. Python 与 Excel结合

    很多开发者说自从有了 Python/Pandas,Excel 都不怎么用了,用它来处理与可视化表格非常快速.但是这样还是有一大缺陷,操作不是可视化的表格,因此对技能要求更高一点.近日,开发者构建了名为 ...

  9. excel python 形状_何使用Python操作Excel绘制柱形图

    开发工具,环境 PyCharm Python3 Office Excel 我们已经创建好了一张Excel表. 现在我们要根据已有的数据,往里面添加柱形图. 柱形图 BarChart 我们主要使用Bar ...

最新文章

  1. float gpu 加速_tensorflow - GPU 加速
  2. C# 反射与dynamic最佳组合
  3. poj 1699 Best Sequence (搜索技巧 剪枝 dfs)
  4. iOS之深入解析内存管理NSTimer的强引用问题
  5. virt-manager 的桥接网络配置问题
  6. tplink-wr841n无线路由接入到局域网三层交换机方法
  7. mac下常用数据库及nginx笔记
  8. 每天一点正则表达式积累(五)
  9. Vim快捷键(三):剪切复制粘贴
  10. urllib爬虫封装(可设置代理,记录日志)方法
  11. 使用nodejs发送电子邮件
  12. mysql 告警日志_错误日志监控报警脚本
  13. 以图搜图-自动生成图模式匹配Cypher
  14. 一筐梨子amp;一筐水果——协变性(covariant)
  15. 计算机内存条如何区分频率,Win7怎么看内存条频率,教您查看方法
  16. 点击获取验证码并登录的实现和验证原理
  17. NetBIOS、WINS、DNS的联系和区别
  18. 《神经科学:探索脑》学习笔记(第19章 脑的节律)
  19. android 下载管理器简介
  20. 什么是(抽象方法,普通方法,抽象类、接口),区别又是什么?

热门文章

  1. mysql中各种类型的锁
  2. 华为桌面云虚拟机白屏无法启动的修复方法
  3. Homework 1 : Knowledge items of C++ Answer (part 1)
  4. 关于JS下offsetLeft,style.left,以及jquery中的offset().left,css(left)的区别。
  5. 敏捷回顾会:经验教训的总结
  6. 微信开放平台之公众号第三方平台开发及全网发布验证
  7. php在html中无法解析json数据,json字符串无法解析的问题
  8. 如何简单的修改文件名及文件扩展名重命名
  9. 文件重命名,文件名快速修改重命名
  10. 【算法 | 实验18】在字符矩阵中查找给定字符串的所有匹配项