xlwings使用

发布时间 2023-10-17 16:33:28作者: 南风丶轻语

安装

执行以下命令安装xlwings

python -m pip install xlwings

image-20231014094847269

使用方式1

打开文件

通过xw.Book(filename)可以打开已存在的文件,不存的文件会报错

import xlwings as xw
filename = "my_xls.xls"
wb = xw.Book(filename)

运行后会自动打开文件,使用默认的表格程序打开,就像手动操作一样。例如,我这里是默认使用WPS打开

image-20231014111729316

获取工作表

通过wb.sheet_names可以获取到所有的工作表

sheet_names = wb.sheet_names  # 获取所有的工作表的名称
print("工作簿的名称".center(50, '-'))
for name in sheet_names:
    print(f"name:{name}")

读取数据

读取数据可以按单元格读取,也可以按行读取

先选中工作表,然后才可以读取数据

sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表

按单元格读取

通过sheet.range(table).value可以按单元格读取数据

传递的单元格名称就是表格中的单元格名称,例如A1,A10,A100,AA1,AA10,AA100

读取到的数据就是一个数据,类型根据单元格中的数据有不同的类型,例如int、float、string、datetime等

print("获取单元格的值".center(50, '-'))
sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表
table = "A1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "A10"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "A100"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA10"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA100"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")

按行读取

通过sheet.range(table).expand().value可以按行读取数据

传递的单元格名称就是表格中的单元格名称,例如A1,A10,A100,AA1,AA10,AA100

读取到的数据是一个列表的集合

它会根据传递的单元格名称作为起点,然后按行读取,读取到第一个值是None的单元格

print("按行读取数据".center(50, '-'))
# 按行读取数据, 读取到行中第一个值是None的单元格
table = "A1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).expand().value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).expand().value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")

写入数据

和读取数据一样,写入数据也是分为按单元格写入和按行写入

先选中工作表,然后才可以写入数据

sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表

按单元格写入

通过sheet.range(table).value = xxx写入数据

传递的单元格名称就是表格中的单元格名称,例如A1,A10,A100,AA1,AA10,AA100

print("设置单元格的值".center(50, '-'))
sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表
table = "B1"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "B10"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "B100"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "AB1"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "AB10"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "AB100"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")

按行写入数据

写入的语法和按单元格写入一样,也是,通过sheet.range(table).value = xxx写入数据

唯一的区别就是写入的值,需要传递二维数组

它会根据传递的单元格名称作为起点,然后按行写入

print("按行写入数据".center(50, '-'))
table = "C1"  # 设置起始位置
values = [['a', 'b', 'c'], ['d', 'e', 'f'], [1, 2, 3], [4, 5, 6]]
value = sheet.range(table).value = values  # 一行一行写入数据
print(f"按行写入数据, 起始位置:{table}, 值为:{value}")
table = "AC1"  # 设置起始位置
value = sheet.range(table).value = values  # 一行一行写入数据
print(f"按行写入数据, 起始位置:{table}, 值为:{value}")

例如:以C1为起点,写入数据

image-20231014114416672

保存文件

保存为表格文件

通过wb.save("demo.xls")保存为xls或xlsx文件

保存为pdf文件

通过wb.to_pdf("demo.pdf")保存为pdf文件

关闭文件

如果不主动关闭文件,则需要手动关闭WPS

通过wb.app.quit()关闭程序

wb.app.quit()

完整示例代码

import xlwings as xw
from xlwings import Sheet

filename = "my_xls.xls"
wb = xw.Book(filename)  # 给定文件名, 会打开已经存在的文件中的工作簿 打开方式应该是用系统默认的软件 例如我的是WPS

sheet_names = wb.sheet_names  # 获取所有的工作表的名称
print("工作簿的名称".center(50, '-'))
for name in sheet_names:
    print(f"name:{name}")
print()

print("获取单元格的值".center(50, '-'))
sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表
table = "A1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "A10"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "A100"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA10"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA100"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
print()

print("设置单元格的值".center(50, '-'))
sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表
table = "B1"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "B10"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "B100"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "AB1"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "AB10"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
table = "AB100"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")
print()

print("按行写入数据".center(50, '-'))
table = "C1"  # 设置起始位置
values = [['a', 'b', 'c'], ['d', 'e', 'f'], [1, 2, 3], [4, 5, 6]]
value = sheet.range(table).value = values  # 一行一行写入数据
print(f"按行写入数据, 起始位置:{table}, 值为:{value}")
table = "AC1"  # 设置起始位置
value = sheet.range(table).value = values  # 一行一行写入数据
print(f"按行写入数据, 起始位置:{table}, 值为:{value}")
print()

print("按行读取数据".center(50, '-'))
# 按行读取数据, 读取到行中第一个值是None的单元格
table = "A1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).expand().value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
table = "AA1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).expand().value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")
print()

path = "demo.xls"
wb.save(path)
print(f"保存到文件:{path}")

wb.to_pdf("demo.pdf")

wb.app.quit()

使用方式2

​ 《使用方式1》中的操作都是可见的,也就是说,当使用时,屏幕一直会被占用显示,而我们一般都是想后台运行,而不关注界面。

因此,这里引入一个概念,就是app,我们可以这样理解:

  • xlwings 操作表格,其实就是调用默认的表格程序,例如:WPS,因此,每次打开表格文件,都是会启动一个进程。进程是默认程序的进程,我这里是WPS,可能还有微软的office,我这里没试验过office,所以都是以WPS进行说明。
  • 一个app就是一个默认的程序,会对应上打开的默认表格程序,我们可以获取到它的PID,通过任务管理器就能看到

打开表格程序

通过xw.App() 即可打开一个表格程序

通过app.pid获取程序的pid

app = xw.App()  # 会打开一个默认表格程序, 例如WPS 一个app就是一个进程
pid = app.pid  # 进程的PID, 可以通过任务管理器看到对应的进程
print(f'pid:{pid}')

运行后,WPS会启动一个进程,例如:pid是18772

image-20231014134059846

默认打开app时,会自动创建一个工作簿

image-20231014140230528

可以通过传递add_book=False取消自动创建,但后面需要打开一个文件,否则会闪退,即启动程序失败

一般使用场景就是打开一个已存在的文件

app = xw.App(add_book=False)  # 会打开一个默认表格程序, 例如WPS 一个app就是一个进程
filename = "my_xls.xls"
wb: Book = app.books.open(filename)

隐藏表格程序

默认的表格程序,是默认显示的,就像人手动操作一样,我们可以通过设置visible属性,隐藏该程序的UI界面

app.visible = False  # 设置为不显示WPS界面

也可以打开程序的时候,默认就设置为不显示界面

app = xw.App(visible=False)  # 会打开一个默认表格程序, 例如WPS 一个app就是一个进程 默认不显示界面
pid = app.pid  # 进程的PID, 可以通过任务管理器看到对应的进程
print(f'pid:{pid}')
visible = app.visible  # 是否显示WPS界面
print(f"visible:{visible}")

PS:可以测试的时候,先显示界面,后续开发完成后,再修改为不显示界面

打开文件

类似《使用方式1》中,打开一个已存在的文件

通过app.books.open(filename)可以打开已存在的文件,不存的文件会报错

filename = "my_xls1.xls"
wb: Book = app.books.open(filename)

读取写入数据

读取写入数据和《使用方式1》一样

保存文件

保存文件和《使用方式1》一样

关闭程序

因为我们隐藏了界面,所以最后一定要关闭进程 否则会变成孤儿进程 只能去任务管理器中停止

app.quit()  # 最后一定要关闭进程 否则会变成孤儿进程 只能去任务管理器中停止

完整示例代码

import xlwings as xw
from xlwings import Book, Sheet

app = xw.App()  # 会打开一个默认表格程序, 例如WPS 一个app就是一个进程
# app = xw.App(visible=False)  # 会打开一个默认表格程序, 例如WPS 一个app就是一个进程 默认不显示界面
pid = app.pid  # 进程的PID, 可以通过任务管理器看到对应的进程
print(f'pid:{pid}')
visible = app.visible  # 是否显示WPS界面
print(f"visible:{visible}")
app.visible = False  # 设置为不显示WPS界面

filename = "my_xls.xls"
wb: Book = app.books.open(filename)  # 给定文件名, 会打开已经存在的文件中的工作簿 打开方式应该是用系统默认的软件 例如我的是WPS
sheet_names = wb.sheet_names  # 获取所有的工作表的名称
print("工作簿的名称".center(50, '-'))
for name in sheet_names:
    print(f"name:{name}")
print()

print("获取单元格的值".center(50, '-'))
sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表
table = "A1"  # 直接传递单元格的名称即可获取单元格的值
value = sheet.range(table).value  # 读取单元格的值
print(f"单元格:{table}的值是:{value}")

print("设置单元格的值".center(50, '-'))
sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表
table = "B1"
value = sheet.range(table).value = table
print(f"设置单元格:{table}的值为:{value}")

wb.save('demo2.xls')  # 保存为Excel文件
wb.to_pdf("demo2.pdf")
app.quit()  # 最后一定要关闭进程 否则会变成孤儿进程 只能去任务管理器中停止

使用方式3

这里记录一些方法

清空表格

通过sheet.clear_contents()清空表格

写入数据

写入数据还有一种写法,通过sheet.cells获取到Range对象,然后再写入。本质还是Range

print("设置单元格的值".center(50, '-'))
data = [[1, 2, 3], [4, 5, 6]]
for x, row in enumerate(data):
    for y, value in enumerate(row):
        obj: Range = sheet.cells(x + 1, y + 1)
        obj.value = value

读取所有表格数据

通过sheet.used_range获取已使用的单元格

通过value = sheet.range(sheet.used_range).value 读取所有的数据

value = sheet.range(sheet.used_range).value  # 获取所有的数据

完整示例代码

import xlwings as xw
from xlwings import Book, Sheet

app = xw.App(add_book=False, visible=False)  # 会打开一个默认表格程序, 例如WPS 一个app就是一个进程

filename = "my_xls.xls"
wb: Book = app.books.open(filename)  # 给定文件名, 会打开已经存在的文件中的工作簿 打开方式应该是用系统默认的软件 例如我的是WPS
sheet_names = wb.sheet_names  # 获取所有的工作表的名称
print("工作簿的名称".center(50, '-'))
for name in sheet_names:
    print(f"name:{name}")
print()

sheet_name = sheet_names[0]  # 第一个工作表的名称
sheet: Sheet = wb.sheets[sheet_name]  # 根据表名获取工作表
print("所有的数据".center(50, '-'))
value = sheet.range(sheet.used_range).value  # 获取所有的数据
print(f"value:{value}")

app.quit()

链接

首页 · xlwings中文文档 · 看云 (kancloud.cn)

Quickstart - xlwings Documentation

Python操作Excel的Xlwings教程(一) - 知乎 (zhihu.com)