当前位置: 首页 > 后端技术 > Python

用Python处理Excel

时间:2023-03-25 21:50:01 Python

Excel是Windows环境下一个功能强大的电子表格程序。Python提供了许多用于处理Excel文件的工具包。在这篇文章中,我们总结了openpyxl(处理xlsx文件)、xlrd和xlwt(处理xls文件)这三个工具包的基本应用方法。下面使用的两个数据集example.xlsx和censuspopdata.xlsx可以从AutomatetheBoringStuffwithPython下载。Excel文档Excel电子表格文件称为工作簿,工作簿保存在扩展名为.xlsx(或.xls)的文件中。每个工作簿可以包含多个工作表。用户当前正在查看的工作表或关闭Excel前最后一次查看的工作表称为活动工作表。每个表都有一些列(column)和一些行(row),列的地址是从A开始的字母,行的地址是从1开始的数字。指定列号和行号可以组合成一个明确指向一个单元格的坐标,每个单元格包含一个数字或文本值。使用openpyxl处理Excel并导入openpyxl模块后,将Excel文档的路径传入openpyxl.load_workbook()函数即可打开文档,并返回一个Workbook对象。importopenpyxlwb=openpyxl.load_workbook('./data/example.xlsx')print(type(wb))#这个WorkBook对象包含了整个Excel文件的所有信息,我们可以从中进一步获取Worksheets:工作表。worksheet.Worksheet'>print(ws.title)#Sheet1active_ws=wb.activeprint(active_ws)#每个工作表由一个Worksheet对象表示,可以索引到Workbook(使用表名字符串)得到.工作簿中的活动工作表可以通过Workbook对象的active属性获取。获取Worksheet对象后,可以通过title属性获取或修改其标题。更进一步,我们可以从Worksheet对象中获取每个单元格对应的Cell对象:c=ws['A1']print(c)#print(c.value)#2015-04-0513:34:02print((c.row,c.column,c.coordinate))#(1,1,'A1')最直接的获取Cell对象的方法就是把列号和行号合并成A直接使用字符串(即坐标)作为Worksheet的索引,可以通过Cell对象的value属性获取单元格中的值,Cell对象中还包含了对应的行列信息单元格(均从1个有序整数开始计数)和坐标。cell=ws.cell(row=1,column=2)print(cell)#print(cell.value)#Applesprint((ws.max_column,ws.max_row))#(3,7)还有一种获取单元格的方法,就是在调用表格的cell()方法时,传入一个整数作为行和列参数的值。此外,Worksheet对象还包含max_column和max_row属性来确定表格的大小。我们看到表格中的列号都是用字母表示的,不利于计算。我们可以调用column_index_from_string函数将字母转换为数字;类似的,还有一个接口get_column_letter()将数字转换为字母:fromopenpyxl.utilsimportget_column_letter,column_index_from_stringprint(get_column_letter(27))#AAprint(column_index_from_string('AB'))#28Worksheet对象也支持切片操作,getall表格中一行、一列或一个矩形区域中的单元格对象,然后可以循环遍历这个切片中的所有单元格,进行相应的数据处理和分析:print(ws['A1':'C3'])#((,,),(,,),(,,))forrow_cellsinws['A1':'C3']:对于row_cells中的单元格:print(cell.coordinate,cell.value)'''A12015-04-0513:34:02B1ApplesC173A22015-04-0503:41:23B2CherriesC285A32015-04-0612:46:51B3PearsC314'''可以看到,切片操作返回一个metaGroup,元组中的每个元素代表Worksheet的一行,the元素是一个元组,它的元素是按列展开的Cell对象,遍历的时候要按照这个嵌套关系循环。print(ws[1])#(,,)print(ws['B'])#(,,,,,,)如果切片操作给单个数字,则可以得到对应的行;同样给定单个字母,可以得到对应的列;返回的数据类型是一个元组,其元素是Cell对象。在读取Excel进行数据处理和分析后,我们可能需要将分析结果写入Excel文件,以便于展示。这时,我们只需要新建一个空的Workbook对象,并将相应的数据封装到Workbook对象中的表格、单元格等子对象中:wb=openpyxl.Workbook()print(wb.sheetnames)#['Sheet']sheet=wb.activeprint(sheet.title)#Sheetsheet.title='FirstSheet'print(wb.sheetnames)#['FirstSheet']sheet=wb['FirstSheet']sheet['A1']="Helloworld"print(sheet['A1'].value)#Helloworldwb.save('./demo.xlsx')完成对Workbook对象或其工作表和单元格的所有操作后,调用save()方法将工作簿另存为Excel文件。wb.create_sheet()print(wb.sheetnames)#['FirstSheet','Sheet']wb.create_sheet(index=1,title='SecondSheet')print(wb.sheetnames)#['FirstSheet','SecondSheet','Sheet']wb.remove(wb['SecondSheet'])print(wb.sheetnames)#['FirstSheet','Sheet']创建工作簿自然得到一个活动工作表,我们可以也继续通过create_sheet()方法创建新的工作表。新建的工作表默认排在最后。我们可以通过index参数指定它的位置,通过title参数指定它的名字。不需要的工作表可以通过remove()方法删除,但是需要注意的是这个方法的参数是一个Worksheet对象,而不是一串工作表名称。至此,我们介绍了使用openpyxl操作Excel文档的基本方法。下面我们通过一个例子来演示我们最常用的Excel处理分析场景,即遍历Excel文档的行列数据,取出指定单元格的数据进行统计分析。:importpprintwb=openpyxl.load_workbook('./data/censuspopdata.xlsx')sheet=wb['PopulationbyCensusTract']#存储人口普查区的数量和人口数据countryData={}forrowinrange(2,sheet.max_row+1):state=sheet['B'+str(row)].value#statecountry=sheet['C'+str(row)].value#countypop=sheet['D'+str(row)].value#PopulationcountryData.setdefault(state,{})countryData[state].setdefault(country,{'tracts':0,'pop':0})#州县对应countryData[state][country]['tracts']+=1#统计每个县的人口普查区数countryData[state][country]['pop']+=int(pop)#统计每个县的总人口pprint.pprint(countryData,indent=4)'''{'AK':{'AleutiansEast':{'pop':3141,'tracts':1},'AleutiansWest':{'pop':5561,'tracts':2},'Anchorage':{'pop':291826,'tracts':55},'Bethel':{'pop':17013,'tracts':3},......'''当我们使用循环语句批量处理Excel文件时,需要处理关闭文件的操作就好了。由于wb.save()函数中包含了关闭文件的操作,所以只需要在文件读取操作的最后添加一行代码关闭文件wb.close()即可。使用xlrd和xlwt处理Excel。首先申明,虽然老版本(1.2.0之前)的xlrd包支持读取和处理xlsx文件,但是我们仍然推荐使用openpyxl来处理xlsx文件,使用xlrd和xlwt来处理xls文件。使用xlrd和xlwt处理Excel文档的思路和前面的介绍是一致的。虽然对应的对象定义不同,但仍然遵循工作簿->工作表->单元格的嵌套关系:获取工作簿对象:book=xlrd.open_workbook('./data/example.xlsx')获取所有工作表名称:names=book.sheet_names(),结果工作表名称列表根据索引获取工作表对象:sheet=book.sheet_by_index(0),即sheet.name=='Sheet1'按名称获取工作表对象:sheet=book.sheet_by_name('Sheet1')获取sheet行数:rows=sheet.nrows获取sheet列数:cols=sheet.ncolsgetwork表格中一行的内容:row=sheet.row_values(1),结果为列表ofdatainthespecifiedrow获取工作表中某列的内容:col=sheet.col_values(2),结果为指定列中数据的列表获取工作表中某个单元格的内容:cell=sheet.cell_value(1,2),结果为指定单元格的内容(1行2列)。另外,还有一种获取单元格的方法:sheet.cell(m,n).value或sheet.row(m)[n].value或sheet.col(n)[m].value(联合索引与函数加方括号)。可以看出xlrd中每个对象的索引都提供了一种按数值顺序排列的索引方式,从0开始计数。这样的设计比较符合我们常规处理二维数组的概念,所以上面的US人口普查数据处理场景可以实现如下:importxlrd,pprintwb=xlrd.open_workbook('./data/censuspopdata.xlsx')sheet=wb.sheet_by_name('PopulationbyCensusTract')#storethenumberofcensusareas和人口数据countryData={}forrowinrange(2,sheet.nrows):state=sheet.cell_value(row,1)#statecountry=sheet.cell_value(row,2)#countypop=sheet.cell_value(row,3)#populationcountryData.setdefault(state,{})countryData[state].setdefault(country,{'tracts':0,'pop':0})#州县对应关系countryData[state][country]['tracts']+=1#统计每个县的普查区数量countryData[state][country]['pop']+=int(pop)#统计每个县的总人口pprint.pprint(countryData,indent=4)如果我们要输出Excel文档,需要导入xlwt模块,只能保存为.xls文件(最多65536行数据):创建工作簿:book=xlwt.Workbook(),可以设置编码参数创建工作表:sheet=book.add_sheet('Sheet1')向单元格写入内容:sheet.write(1,2,'Helloworld')保存工作簿:book.save('./demo.xls')上面提到了xlwt模块的保存()函数内置了关闭文件的操作,所以我们只需要在最后使用xlrd模块读取Excel文件即可完成关闭文件的操作,但是xlrd没有提供类似的close()函数,我们需要使用下面两行代码来实现关闭文件book.release_resources()delbook的功能