Python中len统计Excel工作表行数与实际不符问题排查
问题:Python统计ZIP压缩包中Excel行数与手动统计结果不一致
我编写了一段Python代码,用于统计ZIP压缩包内Excel文件各工作表的行数,但Python返回的统计结果和手动打开Excel统计的行数始终对不上。
统计核心代码片段
row_counts = [] for sheet in list(data_mapping.keys()): row_counts.append(len(data_mapping.get(sheet))) print(len(data_mapping.get(sheet)))
Python输出的行数
65521 65519 65519 65519 65519 65519 65519 65519 65519 65519 65519 25426
手动打开Excel统计的行数
65520 , this has a header and data starts on row 3 65520 , no header data starts on row 1 65520 , no header data starts on row 1 65520 , no header data starts on row 1 65520 , no header data starts on row 1 65520, no header data starts on row 1 65520, no header data starts on row 1 65520, no header data starts on row 1 65520, no header data starts on row 1 65520, no header data starts on row 1 65520, no header data starts on row 1 25427, no header data starts on row 1
完整代码
from io import BytesIO from pathlib import Path from zipfile import ZipFile import os import pandas as pd from os import walk def process_files(files: list) -> pd.DataFrame: file_mapping = {} for file in files: #data_mapping = pd.read_excel(BytesIO(ZipFile(file).read(Path(file).stem)), sheet_name=None) archive = ZipFile(file) # find file names in the archive which end in `.xls`, `.xlsx`, `.xlsb`, ... files_in_archive = archive.namelist() excel_files_in_archive = [ f for f in files_in_archive if Path(f).suffix[:4] == ".xls" ] # ensure we only have one file (otherwise, loop or choose one somehow) assert len(excel_files_in_archive) == 1 # read in data data_mapping = pd.read_excel( BytesIO(archive.read(excel_files_in_archive[0])), sheet_name=None, ) row_counts = [] for sheet in list(data_mapping.keys()): row_counts.append(len(data_mapping.get(sheet))) print(len(data_mapping.get(sheet))) file_mapping.update({file: sum(row_counts)}) frame = pd.DataFrame([file_mapping]).transpose().reset_index() frame.columns = ["file_name", "row_counts"] return frame zip_files = [] for root, dirs, files in os.walk(dir_path): for file in files: if file.endswith('.zip'): zip_files.append(os.path.join(root, file)) df = process_files(zip_files)
问题排查与解决思路
1. 表头识别逻辑差异
这是最可能的原因:
- 对于无表头、数据从第1行开始的工作表,
pd.read_excel默认会把第一行当作表头(header=0),因此len(df)统计的是数据行数(不含表头行),而你手动统计的是包含第一行(实际为数据)的总行数,所以会差1(比如手动统计65520行,Python返回65519行)。 - 解决:读取这类工作表时添加
header=None参数,让pandas把第一行当作数据行处理。
2. 起始行未正确跳过
第一个工作表有表头、数据从第3行开始,你没有设置skiprows参数,pandas会从第1行开始读取。如果前两行有内容(比如表头或说明文本),pandas会将其纳入读取范围,导致统计行数比手动统计的实际数据行多1(手动统计65520行,Python返回65521行)。
- 解决:针对该工作表设置
skiprows=2,跳过前两行,只读取实际数据区域。
3. 修改后的读取代码示例
可以针对性调整Excel读取逻辑,适配不同工作表的结构:
# 替换原读取数据的代码块 archive = ZipFile(file) files_in_archive = archive.namelist() excel_files_in_archive = [ f for f in files_in_archive if Path(f).suffix[:4] == ".xls" ] assert len(excel_files_in_archive) == 1 # 先获取所有工作表名称 excel_file = pd.ExcelFile(BytesIO(archive.read(excel_files_in_archive[0]))) sheet_names = excel_file.sheet_names data_mapping = {} row_counts = [] for idx, sheet in enumerate(sheet_names): if idx == 0: # 第一个工作表:跳过前2行,使用第3行作为表头 df = pd.read_excel(excel_file, sheet_name=sheet, skiprows=2) else: # 其他工作表:无表头,全部作为数据行 df = pd.read_excel(excel_file, sheet_name=sheet, header=None) data_mapping[sheet] = df count = len(df) row_counts.append(count) print(count) file_mapping.update({file: sum(row_counts)})
内容的提问来源于stack exchange,提问作者Jonnyboi
相关产品推荐
相关产品推荐

