关键词:openpyxl、Excel 写入空行、数据偏移、merge_cells、current_row 不同步
🧩 一、问题描述
在使用 Python 的 openpyxl 模块向 Excel 表格写入数据时,出现了以下问题:
- 表头与第一行数据之间多了一个空行
- 某些数据本应写入第 2 行,实际却出现在第 3 行
- 合并单元格后,表格整体内容下移
这些问题导致最终生成的 Excel 文件格式错乱、样式不对齐、数据偏移,影响后续使用。
🔍 二、问题原因分析
1. merge_cells() 使用顺序错误
你原本的逻辑是:
start_row = current_row
end_row = current_row + len(group) - 1
self.merge_and_fill_cell(ws, start_row, end_row, chinese_param_category)
for _, row in group.iterrows():
ws.append([None] + row.tolist())
current_row += 1
❌ 错误点:先调用
merge_cells(),再写入数据
虽然 merge_cells() 本身不会插入空行,但在没有实际数据时就合并单元格,某些 Excel 渲染器(如 Microsoft Excel)会自动插入空行来保持结构美观,导致数据下移。
✅ 正确做法:先写入数据,再执行 merge_cells()
2. 手动维护 current_row 与实际行号不同步
你使用了:
current_row = 2
...
current_row += 1
而 ws.append() 本身就会自动新增一行。你又手动维护了 current_row,导致:
start_row和end_row的计算出现偏差- 最终合并区域与实际数据不一致
✅ 推荐做法:使用 ws.max_row 自动管理行号
3. 原始数据中存在空行或 NaN 值
在 row.tolist() 中,某些行可能包含:
[None] + [nan, nan, nan, ...]
这会导致写入 [None, nan, nan, nan, ...],看起来像一个“空行”。
✅ 解决方案:写入前过滤空行
if any(pd.notna(x) for x in row):
ws.append([None] + row.tolist())
✅ 三、最终解决方案
✅ 修改后的写入逻辑(推荐使用)
for param_category, group in grouped:
# 先写入数据
for _, row in group.iterrows():
if any(pd.notna(x) for x in row): # 跳过空行
ws.append([None] + row.tolist())
# 获取实际写入的行号范围
end_row = ws.max_row
start_row = end_row - len(group) + 1
chinese_param_category = self.param_category_mapping.get(param_category, param_category)
# 再合并单元格
self.merge_and_fill_cell(ws, start_row, end_row, chinese_param_category)
self.apply_borders(ws, start_row, end_row)
🧪 四、推荐加入的打印语句(调试用)
print(f"📌 合并单元格: A{start_row}:A{end_row} → 内容: {chinese_param_category}")
print(f"📝 写入行数据 (第 {ws.max_row + 1} 行): {[None] + row.tolist()}")
print(f"📊 当前总行数: {ws.max_row}")
📌 五、merge_and_fill_cell 函数说明
def merge_and_fill_cell(self, ws: Any, start_row: int, end_row: int, value: str) -> None:
ws.merge_cells(start_row=start_row, start_column=1, end_row=end_row, end_column=1)
cell = ws.cell(row=start_row, column=1, value=value)
cell.alignment = Alignment(horizontal="center", vertical="center")
cell.font = Font(bold=True)
- ✅ 必须在写入数据后调用
- ✅ 只写入合并区域左上角单元格内容即可
📚 六、总结一句话
“空行”和“数据偏移”问题的根本原因是:
merge_cells()被提前调用、current_row计数不准确、或原始数据中存在空值。
343

被折叠的 条评论
为什么被折叠?



