最近在尝试用Python操作Excel,接触到了xlwings这个库,在我查阅关于这个库的介绍文章时,发现绝大多数的教程都写得很含糊,要么“点到为止”,只介绍了几种常用的操作,要么就是将一堆代码罗列出来,没有进行解释说明,还有一些文章里的解释压根就是错误的。总之,我还没有发现一篇让我满意的系统全面的教程。后来我直接去看了官方文档,认识到这个库远比网上文章里介绍的强大得多,所以决定自己来写,既可以当做笔记,也能帮助大家更全面地了解这个库的用法。
关于Python编译器和xlwings库的安装和配置可以看下面篇文章,这里就不做说明了。
办公自动化系列(1) | Python与Excel交互教程 - 环境搭建
在正式介绍xlwings的用法之前,我们先明确几个概念:
- 新建:创建一个不存在的工作薄或者工作表
- 打开:打开一个已经存在的工作薄
- 引用:就是告诉程序,你要操作哪个对象。比如你打开了A、B、C三个工作薄,现在你想操作B工作薄,就要先引用B
- 激活:我们可以同时打开多个工作薄,但是一次只能操作一个工作簿,我们正在操作的这个工作薄称为当前活动工作薄,激活的意思就是将某一个对象(工作薄或工作表等)变成当前活动对象
这里重点要理解引用和激活的区别,当我们希望操作一个对象的时候,首先要引用这个对象,但引用工作薄并不会激活这个工作薄,比如我们先打开A工作薄,再打开B工作薄,那么当前活动工作薄是B,当我们对A进行引用之后,活动工作薄仍然是B,只有当我们对A进行操作之后,A才会变成活动工作薄。
啰嗦了这么多,就是希望大家先把这几个概念理解清楚,因为在xlwings中,很多操作都有多种实现方式,表面上看没有区别,但“内藏玄机”,概念理解不清晰,编写代码时就容易产生混乱。
在xlwings中
- Excel程序用App来表示,多个Excel程序集合用Apps表示;
- 单个工作簿用Book表示,工作簿集合用Books表示;
- 单个工作表用Sheet表示,工作表集合用Sheets表示;
- 区域用Range表示,既可以是一个单元格,也可以是一片单元格区域。
注意,在xlwings中是不区分大小写的,SHEET1和sheet1的含义一样。
我们这系列教程首先会按照「Apps - App - Books - Book - Sheets - Sheet - Range 」的顺序来介绍xlwings的相关用法,然后介绍xlwings和其他Python库的配合使用,最后再练习用xlwings来解决实际问题。
Apps
关于Apps这个概念,很多教程里提到过,但是都没有解释清楚。要理解Apps,首先要理解App,一个App对应一个Excel实例,注意,是Excel实例,不是工作簿。我们要创建工作簿,首先要创建App。一个App可以创建多个工作簿。也就是说,我们可以通过xlwings创建多个App,每个App又可以创建多个工作薄,这些App是相互独立的,只能管理它自己创建的工作簿。需要注意的是,当我们手动打开一个工作簿的时候,系统也会自动帮我们创建一个App。
不慌,关于Apps的理解,通过后面的实例大家会认识得更透彻。😜
1. 引用xlwings库
import xlwings as xw
2. 查看Apps包含的所有App
Apps = xw.apps
3. 返回App总数
count = xw.apps.count
4. 查看所有的PID:
keys = xw.apps.keys()
每个App对应一个PID值,可以看作是数字编号,用来识别不同的App
App
1. 创建App
app=xw.App()
这行代码默认打开Excel程序并且自动创建一个工作薄
我们可以传入参数对其进行自定义设置:
app=xw.App(visible=True,add_book=False)
visible用来设置程序是否可见,True表示可见(默认),Flase不可见。
add_book用来设置是否自动创建工作簿,True表示自动创建(默认),False不创建
当设置成add_book=False时,可以创建App,但是还未生成PID,只有当这个App创建了工作簿后,才会生成自己的PID
2. 查看PID
pid = app.pid
3. 引用App
app = xw.apps[1668]
[1668]
就是这个App的PID
返回当前活动App
app = xw.apps.active
4. 激活App
app.activate()
'传入参数'
app.activate(steal_focus=True)
当steal_focus=True
时, Excel程序变为最前台的应用,并且把焦点从Python切换到Excel
5. 退出App
app.kill():通过杀掉进程强制Excel app退出
app.quit():退出excel程序,不保存任何工作簿
通常情况下,推荐用app.quit()
6. 重新计算一遍所有工作簿里的公式
app.calculate()
7. 设置屏幕更新
打开屏幕更新,我们可以看到xlwings对Excel进行操作的过程,关闭更新可以加速脚本运行。默认是打开的。
'返回屏幕更新状态'
app.screen_updating
'关闭屏幕更新'
app.screen_updating = False
脚本运行完毕之后,记住把screen_updating属性值改回 True
8. App是否可见设置
'返回App可见性'
app.visible
'设置App为可见'
app.visible = True
9. 设置提醒信息是否显示
在使用Excel的过程中,经常会遇到一些提醒信息,比如关闭前的保存提示、数据有效性的警告窗口,若想隐藏这些窗口,可进行如下设置
app.display_alerts=False
如果提醒信息是需要反馈的,Excel会选择默认的方式
Books
1. App包含的所有的Book
'当前活动App的工作簿集合'
books = xw.books
'指定App的所有工作簿的集合'
books = app.books
Book
操作
1. 新建
wb = app.books.add()
'或者'
wb = xw.Book()
很多教程在提到新建App时都说这两种方式是一样的,实际上是有区别的,方式1是在当前App下新建一个Book,方式2是创建一个新的App,并在新App中新建一个Book
2. 打开
打开代码所在路径下的文件
wb = app.books.open('test.xlsx')
'或者'
wb = xw.Book('test.xlsx')
打开绝对路径下的文件
wb = app.books.open(r'C:\Users\zhoux\Desktop\test.xlsx')
'或者'
wb = xw.Book(r'C:\Users\zhoux\Desktop\test.xlsx')
为了避免路径被转义,在 Windows 上指定文件路径时,您应该通过将 r 放在字符串前面来使用原始字符串,或者使用像这样的双反斜杠:
C:\\path\\to\\file.xlsx
参数 打开文件时除了传入路径,还有多种参数可设置
Book(fullname=None, update_links=None, read_only=None, format=None,
password=None, write_res_password=None, ignore_read_only_recommended=None,
origin=None, delimiter=None, editable=None, notify=None, converter=None,
add_to_mru=None, local=None, corrupt_load=None, impl=None)
关于参数的具体用法,请参考此处
3. 引用
wb = app.books('test.xlsx')
'或者'
wb = xw.Book('test.xlsx')
也可以用数字来代替文件名,比如wb = app.books(1)
表示当前app打开的第一个工作簿,可能有人也看到过使用中括号的引用方式,那么中括号和小括号有什么区别呢?
小括号的序号是从1开始的,中括号(切片)是从0开始计数,也就是说,app.books(1)
等同于 app.books[0]
,后面在工作表和区域引用的时候会经常遇到这种方式,大家不要混淆了。
大家可能发现了,xw.Book('test.xlsx')
既可以打开工作薄也可以引用工作簿。也就是说,当工作簿未打开时,它可以打开工作薄,当工作簿处于打开状态时,它可以引用工作簿。而app.books('test1.xlsx')
只可以引用工作簿。
xw.Book 提供了连接到工作簿的最简单的方法: 它在所有的app实例中查找指定的工作簿,如果同一个工作簿在多个app实例中存在,就会返回一个错误信息。
以上为官方的一段说明,我这里稍微解释一下。我们前面讲到了,每个App都可以打开属于自己的工作簿,两个不同的App可以打开同一个工作簿。当我们使用App1和App2都打开了test.xlsx工作簿时,使用app.books('test1.xlsx')
的方式引用test1.xlsx当然没有问题,因为每个App都知道哪个test1是属于自己的,但是当我们使用xw.Book('test1.xlsx')
的方式引用工作簿就会产生问题,因为这种方式会从App1和App2中找到两个test1,然而它并不知道我们想要引用的是哪一个,此时就会报错。
引用活动工作薄
wb = app.books.active
4. 激活
wb.activate()
wb.activate(steal_focus=True)
如果steal_focus=True
, 则把窗口显示到最上层,并且把焦点从Python切换到Excel
5. 保存
wb.save()
默认保存在工作薄所在的路径
另存为
wb.save(r'D:\test.csv')
另存为时,我们不仅能够指定保存的位置,还可以指定保存的格式
同名文件会在没有提示的情况下被直接覆盖
6. 关闭
wb.close()
这种方式会直接关闭工作簿,不会进行保存。 关闭所有的工作薄后,记得执行一遍 app.quit()
清理一下Excel程序
属性
1. 获取工作簿的绝度路径
wb.fullname
2. 获取工作薄名称(带扩展名)
wb.name
3. 获取创建工作簿的App
wb.app
4. 返回工作薄中定义过的所有命名区域
wb.names
命名区域可在公式 - 名称管理器中查看
5. 更改计算模式
wb.app.calculation = 'manual'
calculation的值表示了工作簿的计算模式,有: manual(手动) , automatic(自动) , semiautomatic(半自动)三种方式
Sheets
1. 工作簿包含的所有Sheet
'当前活动工作薄'
sheets = xw.sheets
'指定工作薄'
sheets = wb.sheets
包括隐藏工作表及深度隐藏工作表
Sheet
操作
1. 新建
sht = wb.sheets.add('test',after='sheet2')
参数1为工作表名称,省略的话为Excel默认名称
参数2为插入位置,可选before
或者after
,示例中的代码表示插入到sheet2之后,省略的话插入到当前活动工作表之前
工作表名称重复的话会报错
2. 引用
sht = wb.sheets('sheet1')
'或者'
sht = wb.sheets(1)
当前活动工作表
sht = xw.sheets.active
3. 激活
sht.activate()
4.清除
'清除工作表所有内容和格式'
sht.clear()
'清除工作表的所有内容但是保留原有格式'
sht.clear_contents()
clear()不仅可以清除背景色等格式,还可以清除数据有效性和条件格式等
特别提醒:可以清除受保护的工作表的内容
5.删除
sht.delete()
可以删除隐藏的工作表,但是不能删除深度隐藏的工作表
6. 自动调整行高列宽
sht.autofit('c')
- 要做行自适应,用 rows 或 r;
- 要做列自适应,用 columns 或 c;
- 同时做行和列的自适应,不需要参数。
7. 选定工作表
sht.select()
只能在活动工作簿中选择
属性
1. 工作表名称
'返回工作表名称'
sht.name
'重命名工作表名称'
sht.name = 'rename'
2. 返回指定工作表所属的工作簿
sht.book
3. 工作表上所有单元格的区域对象
sht.cells
包括所有的单元格,不仅仅是那些正在使用中的单元格
4. 返回工作表的索引值
sht.index
按照Excel的方式,从1开始的
5. 返回所有与本工作表有关的命名区域
sht.names
6. 工作表中用过的区域
sht.used_range
如果整张表为空,则返回A1单元格
关于used_range的范围判定,我截取了网上的一段解释:
UsedRange属性返回工作表中所有已使用范围的单元格区域,而不管该区域数据间是否有空行或空格。特别注意:UsedRange属性返回工作表中所有已使用范围的单元格区域是指:单元格中有数值、公式、单元格格式化设置(例如:单元格字体设置、边框设置等等)
OK,第一篇文章到此为止,下一篇我们将继续介绍Range及其他对象的使用。