xlrd是Python中常用的Excel读取库,但版本差异会直接影响能否打开.xlsx文件。原文先遇到xlrd新版本打开.xlsx报错,再回退版本,最后用xlrd读取单元格并写成分片文本文件。下面按报错处理、对象模型、单元格类型和实际脚本四部分整理。
一、xlrd版本兼容与xlsx报错处理
原文明确指出:xlrd 2.0.1版本移除了对.xlsx格式的支持,只支持.xls格式。此时打开.xlsx会抛出类似错误:XLRDError: Excel xlsx file; not supported。堆栈中可以看到open_workbook内部执行raise XLRDError(FILE_FORMAT_DESCRIPTIONS[file_format]+'; not supported')。解决方法是把xlrd回退到1.2.0版本,用旧版本继续支持.xlsx格式。原文给出的命令是:- pip3 uninstall xlrd
- pip3 install xlrd=1.2.0
复制代码 这里保留原文命令形式;实际pip版本约束通常使用双等号,可按环境写成pip3 install xlrd==1.2.0。回退后即可继续编写读取Excel的代码。
二、xlrd读取Excel的对象模型
导入模块使用import xlrd。打开指定Excel文件用data = xlrd.open_workbook(file),返回data对象。通过data对象可以取得各个sheet对象,一个Excel文件可以有多个sheet,每个sheet就是一张表格。获取sheet的方式包括:data.sheet_by_index(0)按索引顺序获取;data.sheet_by_name(u'sheet1')按名称获取;data.sheets()[0]也按索引顺序获取。data.nsheets返回sheet的数目,data.sheets()返回所有sheet对象的列表,data.sheet_names()返回所有sheet对象名字的列表。
通过sheet对象可以获取各个单元格,每个单元格是一个cell对象。sheet1.name返回sheet1的名称,sheet1.nrows返回行数,sheet1.ncols返回列数。sheet1.cell_type(x,y)返回cell的对象类型,sheet1.cell(x,y).ctype也返回cell的对象类型。sheet1.cell_value(x,y)返回cell的值,sheet1.cell(x,y).value也返回cell的值。sheet1.row(x)获取指定行并返回cell对象列表,sheet1.row_values(x)获取指定行并返回列表;sheet1.col(x)获取指定列并返回cell对象列表,sheet1.col_values(x)获取指定列并返回列表。以下是原文API的集中整理:- import xlrd
- data = xlrd.open_workbook(file)
- Sheet1 = data.sheet_by_index(0)
- Sheet1 = data.sheet_by_name(u'sheet1')
- Sheet1 = data.sheets()[0]
- num = data.nsheets
- sheet_list = data.sheets()
- sheet_name_list = data.sheet_names()
- name = Sheet1.name
- nrows = Sheet1.nrows
- ncols = Sheet1.ncols
- sheet1.cell_type(x, y)
- sheet1.cell(x, y).ctype
- sheet1.cell_value(x, y)
- sheet1.cell(x, y).value
- sheet1.row(x)
- sheet1.row_values(x)
- sheet1.col(x)
- sheet1.col_values(x)
复制代码
三、单元格ctype类型与数字、日期处理
python读取Excel中单元格的内容返回的有5种类型:ctype为0表示empty,1表示string,2表示number,3表示date,4表示boolean,5表示error。一般情况下读取Excel中的数字会自动转换为浮点数,若想判断读取为浮点数,原文使用ctype == 2 and cell % 1 == 0.0,也就是ctype为2且为浮点。日期单元格的ctype=3,这时需要使用xlrd的xldate_as_tuple来处理为date格式;应先判断表格的ctype=3时xldate才能开始操作。这个判断顺序是后续处理日期值的关键。
四、实践案例:按F列筛选并按1000行分片写入txt
原文案例有一张表,目标是从F列取数据。F列对应索引5,因此先用sheet.col_values(5)取出整列值。随后按每1000行切分,循环67轮,b从0开始,每轮处理后b增加1000。每轮内部把当前分片中的单元格值转成字符串,判断是否包含jet、JC或JSB,把命中的值追加到id列表;再把列表转成字符串,并去掉方括号和单引号,打印后写入movieid/test{a}.txt。整理后的代码如下,变量名contenct保留原文拼写:- import xlrd
- excel = xlrd.open_workbook(r'C:/Users/siyu.guan/Desktop/删除节目单20230119.xlsx')
- sheet = excel.sheet_by_index(0)
- contenct = sheet.col_values(5)
- print(type(contenct))
- b = 0
- for a in range(67):
- id = []
- for i in range(b, b + 1000):
- contenct[i] = str(contenct[i])
- if 'jet' in contenct[i] or 'JC' in contenct[i] or 'JSB' in contenct[i]:
- id.append(contenct[i])
- id = str(id)
- id = id.replace('[', '').replace("'", '').replace(']', '')
- print(id)
- with open(f'movieid/test{a}.txt', 'w') as file:
- file.write(id)
- file.close()
- b = b + 1000
复制代码 从这段代码逻辑看,使用前要保证movieid目录存在,否则写入会失败;同时原文示例按固定67轮、每轮1000行处理,实际表格行数不足67*1000时,直接访问contenct会出现索引越界,应按列长度调整循环边界。案例还体现了xlrd读取整列、字符串筛选、列表转字符串和分片落盘的基本流程,适合处理旧版.xls或已回退到1.2.0后的.xlsx读取场景。
小结:使用xlrd读取Excel时,先确认版本是否支持目标格式,再按open_workbook、sheet、cell的层级取值;数字和日期要结合ctype判断,列索引从0开始,F列对应5。原文案例的重点是col_values取整列、按1000行分片筛选并写入多个txt文件,实际运行时补齐目录和行数边界检查即可。 |