办公自动化系列(3)| 全网最详细的xlwings库解析-上篇

最近在尝试用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及其他对象的使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容