在Python中,可以使用xlwings模块处理Excel工作簿,该模块的名字由xl和wings(翅膀)构成,寓意给Excel文件添加翅膀,让Excel飞起来。由于xlwings模块是第三方模块,所以需要安装此模块。安装xlwings模块需要在Windows命令行窗口中输入的命令如下:
pip install xlwings-i https://pypi.tuna.tsinghua.edu.cn/simple
然后按Enter键,即可安装xlwings模块,如图1—14所示。
图1—14 安装xlwings模块
第三方模块xlwings模块是采用面向对象的思想编写而成的。该模块可以创建4个层次的对象,最顶层的对象是Excel应用程序(App)对象,对应Excel应用程序。第2层对象是工作簿(Book)对象,对应Excel工作簿;第3层的对象是工作表(Sheet)对象,对应Excel工作表;第4层的对象是单元格(Range)对象,对应Excel中的单元格。4个层次对象的逻辑结构如图1—15所示。
图1—15 xlwings模块中4个对象的逻辑结构图
在xlwings模块中,xlwings模块可以创建多个Excel应用程序(App)对象;每个App对象可以创建多个工作簿(Book)对象;每个Book对象可以创建多个工作表(Sheet)对象;每个Sheet对象可以创建多个单元格(Range)对象。
在xlwings模块中,可以使用函数xlwings.App()创建App对象,其语法格式如下:
import xlwings as xw app=xw.App(visible=False,add_book=False)
其中,visible表示创建的App对象是否可见;add_book表示是否在打开的工作簿中新增工作表。
在xlwings模块中,可以使用函数xlwings.Book()创建一个Book对象,也可以应用已创建的App对象的方法创建一个Book对象,其语法格式如下:
import xlwings as xw #第1种方法 wb1=xw.Book()#创建一个新的App对象,并在App对象中新建一个工作簿Book对象 #第2种方法 app2=xw.App(visible=False,add_book=False) wb2=app2.books.add() #创建一个新的工作簿Book对象 wb3=app2.books.open(path) #打开Excel工作簿并创建工作簿Book对象
其中,path表示Excel文件的路径。
在xlwings模块中,应用程序(App)对象常用的方法和属性见表1—5。
表1—5 App对象常用的方法和属性
在xlwings模块中,工作簿(Book)对象常用的方法和属性见表1—6。
表1—6 Book对象常用的方法和属性
在xlwings模块中,可以应用已创建的Book对象的方法选择工作表并创建Sheet对象,其语法格式如下:
import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open(path) sheet1=book.sheets[sheetname] #选择名称是sheetname的工作表 sheet2=book.sheets[num] #选择序号是num的工作表
其中,path表示Excel文档的路径;sheetname表示工作表的名称;num表示工作表的序号,初始数从0开始。
在xlwings模块中,可以应用已创建的Book对象的方法新增工作表并创建Sheet对象,其语法格式如下:
import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open(path) sheet1=book.add(new_sheet,after=old_sheet)
其中,new_sheet表示新增工作表的名称;old_sheet表示已有工作表的名称。
在xlwings模块中,工作表(Sheet)对象常用的方法和属性见表1—7。
表1—7 Sheet对象常用的方法和属性
【实例1-8】 在D盘test文件夹下有一个Excel文档(销售数据.xlsx),该文档中的工作表Sheet2如图1—16所示。
图1—16 销售数据.xlsx
使用xlwings模块创建并打印App对象、Book对象。使用两种方法创建Sheet对象,然后打印该对象,代码如下:
#===第1章代码1-8.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open('D:\\test\\销售数据.xlsx') sheet1=book.sheets['Sheet2'] sheet2=book.sheets[1] print(app) print(book) print(sheet1) print(sheet2) book.close() app.quit()
运行结果如图1—17所示。
图1—17 代码1-8.py的运行结果
在xlwings模块中,可以应用已创建的Sheet对象的方法选择指定的单元格并创建Range对象,其语法格式如下:
import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open(path) sheet=book.sheets[sheetname] #选择名称是sheetname的工作表 range1=sheet.range(str1) #使用Sheet对象的range()方法创建单元格对象 range2=sheet[str2] #使用列表的方式创建单元格对象 range3=sheet.cells(num1,num2) #使用Sheet对象的cell()方法创建单元格对象
其中,str1、str2表示工作表中单元格的地址,例如'A1'、'B3'、'C5';num1、num2表示工作表中单元格的行、列索引。在xlwings模块中,可以使用切片的方式获取某一区域的单元格对象,例如sheet['A1:C5']。
【实例1-9】 在D盘test文件夹下有一个Excel文档(销售数据.xlsx),该文档中的工作表Sheet2如图1—16所示。使用3种方法创建第1行第1列的单元格对象,然后打印该对象和对象的值,代码如下:
#===第1章代码1-9.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open('D:\\test\\销售数据.xlsx') sheet1=book.sheets['Sheet2'] data1=sheet1.range('a1') data2=sheet1['a1'] data3=sheet1.cells(1,1) print(data1) print(data2) print(data3) print(data1.value) print(data2.value) print(data3.value) book.close() app.quit()
运行结果如图1—18所示。
图1—18 代码1-9.py的运行结果
在xlwings模块中,单元格(Range)对象常用的方法和属性见表1—8。
表1—8 Range对象常用的方法和属性
注意: xlwings是一个很强大的模块,可以设置单元格的格式、边框样式、对齐设置,有兴趣的读者可以查看其官方文档。
在xlwings模块中,可以使用Range对象的expand()函数读取Excel工作簿中的数据。
【实例1-10】 在D盘test文件夹下有一个Excel文档(销售数据.xlsx),该文档中的工作表Sheet2如图1—16所示。遍历并打印工作表Sheet2中的数据,代码如下:
#===第1章代码1-10.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open('D:\\test\\销售数据.xlsx') sheet1=book.sheets['Sheet2'] range1=sheet1.range('a1') #从单元格A1开始读取工作表中的所有数据 data_list=range1.expand('table').value for row in data_list: print(row) book.close() app.quit()
运行结果如图1—19所示。
图1—19 代码1-10.py的运行结果
在xlwings模块中,可以使用Range对象的方法或属性向Excel工作簿中写入数据。
【实例1-11】 在D盘test文件夹下有一个Excel文档(销售数据.xlsx),该文档中的工作表Sheet2如图1—16所示。使用xlwings模块向工作表Sheet2中写入一组数据,代码如下:
#===第1章代码1-11.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open('D:\\test\\销售数据.xlsx') sheet1=book.sheets['Sheet2'] range1=sheet1.range('a8') range2=sheet1.range('b8') range3=sheet1.range('c8') range4=sheet1.range('d8') range5=sheet1.range('e8') range6=sheet1.range('f8') range1.value='8' range2.value='2022/9/30' range3.value='孙权' range4.value='电吹风' range5.value='16' range6.value='个' book.save() book.close() app.quit()
运行结果如图1—20所示。
图1—20 代码1-11.py的运行结果
注意: 在xlwings模块中,单元格的行坐标既可以使用大写字母,也可以使用小写字母表示。
【实例1-12】 在D盘test文件夹下有一个Excel文档(销售数据.xlsx),该文档中的工作表Sheet2如图1—20所示。使用xlwings模块向工作表Sheet2中写入一组数据,代码如下:
#===第1章代码1-12.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open('D:\\test\\销售数据.xlsx') sheet1=book.sheets['Sheet2'] data1=['9','2022/9/30','周瑜','洗衣机','23','台'] list1=['a','b','c','d','e','f'] for index,item in enumerate(list1): range1=sheet1.range(item+'9') print(range1) range1.value=data1[index] book.save() book.close() app.quit()
运行结果如图1—21和图1—22所示。
图1—21 代码1-12.py的运行结果
图1—22 代码1-12.py写入的数据
注意: 函数enumerate()是Python的内置函数,可以同时输出索引值和元素内容。
在xlwings模块中,可以批量替换Excel工作表中的单元格数据。
【实例1-13】 在D盘test文件夹下有一个Excel文档(3月销售数据.xlsx),该文档中的工作表Sheet1如图1—23所示。
使用xlwings模块将工作表中的“电冰箱”替换成“双门电冰箱”,代码如下:
图1—23 3月销售数据.xlsx
#===第1章代码1-13.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open('D:\\test\\3月销售数据.xlsx') sheet1=book.sheets['Sheet1'] data=sheet1['a2'].expand('table').value for index,val in enumerate(data): print(val) if val[2]=='电冰箱': val[2]='双门电冰箱' data[index]=val sheet1['a2'].expand('table').value=data book.save() book.close() app.quit()
运行结果如图1—24和图1—25所示。
图1—24 代码1-13.py的运行结果
图1—25 替换数据后的3月销售数据.xlsx
在xlwings模块中,可以将两个相同类型的工作表合并为一个工作表,并保存在一个新的工作簿中。
【实例1-14】 在D盘test文件夹下有两个Excel文档,其中一个是3月销售数据.xlsx,该文档中的工作表Sheet1如图1—25所示。另一个是4月销售数据.xlsx,该文档中的工作表Sheet1如图1—26所示。
图1—26 4月销售数据.xlsx
使用xlwings模块将两个工作表合并为一个工作表(两个月的销售数据),并保存在一个新的工作簿中,代码如下:
#===第1章代码1-14.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book1=app.books.open('D:\\test\\3月销售数据.xlsx') sheet1=book1.sheets['Sheet1'] book2=app.books.open('D:\\test\\4月销售数据.xlsx') sheet2=book2.sheets['Sheet1'] header=sheet1['a1:f1'].value all_data=[] data1=sheet1['a2'].expand('table').value data2=sheet2['a2'].expand('table').value all_data=data1+data2 print(header) print(all_data) new_book=xw.Book() new_sheet=new_book.sheets.add('两个月的销售数据') new_sheet['a1'].value=header new_sheet['a2'].value=all_data new_sheet.autofit() new_book.save('D:\\test\\合并两个月后的销售数据.xlsx') new_book.close() book1.save() book2.save() book1.close() book2.close() app.quit()
运行结果如图1—27和图1—28所示。
图1—27 代码1-14.py的运行结果
图1—28 合并后的工作表
在xlwings模块中,可以将一个工作表分拆成多个工作簿,并保存下来。
【实例1-15】 在D盘test文件夹下的demo1文件夹下有一个Excel文档(两个月的销售数据.xlsx),该文档中的工作表保存着的两个月的销售数据如图1—29所示。
将这个工作表按照产品名称把不同的数据分类整理到不同的工作簿中,并将这些工作簿保存在同一目录下的文件夹中,代码如下:
图1—29 两个月的销售数据.xlsx
#===第1章代码1-15.py===# from pathlib import Path import xlwings as xw src_file=Path('D:\\test\\demo1\\两个月的销售数据.xlsx') des_folder=Path('D:\\test\\demo1\\拆分后的表格') if des_folder.exists()==False: des_folder.mkdir(parents=True) app=xw.App(visible=False,add_book=False) book=app.books.open(src_file) sheet=book.sheets['两个月的销售数据'] header=sheet['a1:f1'].value data1=sheet.range('a2').expand('table').value data2=dict() #按产品名称对数据进行分类,并存储在data2中 for i in range(len(data1)): product_name=data1[i][2]#第3列是产品名称 if product_name not in data2: data2[product_name]=[] data2[product_name].append(data1[i]) #新建工作簿,保存分类后的数据 for key,val in data2.items(): new_book=xw.books.add() new_sheet=new_book.sheets.add(key) new_sheet['a1'].value=header new_sheet['a2'].value=val new_sheet.autofit() new_book.save(des_folder/f'{key}.xlsx') new_book.close() app.quit()
运行结果如图1—30和图1—31所示。
图1—30 代码1-15.py拆分的工作簿
图1—31 拆分后工作簿的数据
在xlwings模块中,可以在工作表中应用公式。
【实例1-16】 在D盘test文件夹下有一个Excel文档(电冰箱.xlsx),该文档中的工作表电冰箱的数据如图1—31所示。应用xlwings模块中类的属性或方法,在工作表最右下角单元格下的单元格中写入公式,计算销售总数,代码如下:
#===第1章代码1-16.py===# import xlwings as xw app=xw.App(visible=False,add_book=False) book=app.books.open('D:\\test\\电冰箱.xlsx') sheet=book.sheets['电冰箱'] #获取最右下角的单元格对象 last_cell=sheet['a1'].expand('table').last_cell last_row=last_cell.row last_column=last_cell.column #获取工作表最右边列的字母,字母A的ASCII码是65 last_column_letter=chr(64+last_column) #汇总求和的单元格地址 sum_name=f'{last_column_letter}{last_row+1}' #最右下角单元格地址 last_cell_name=f'{last_column_letter}{last_row}' #创建公式 formula=f'=SUM({last_column_letter}2:{last_cell_name})' sheet[sum_name].formula=formula sheet.autofit() book.save() book.close() app.quit()
运行结果如图1—32所示。
图1—32 代码1-16.py的运行结果
注意: 代码1-16.py主要应用于工作表的行数和列数未知的情况。对于已知的情况,代码会简单很多。