You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 07:01:01