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

Python PyFPDF库使用Multicell方法时自动分页异常问题

FPDF双列翻译对照表分页错位问题修复

问题描述

开发基于Python FPDF模块的语言翻译对照表生成程序,通过调用pdf.multicell()方法实现双列布局,左列放置非英语词汇、右列放置对应英文译文。配置pdf.set_auto_page_break()方法后,预期内容达到页面边界时自动新建页面,但实际运行出现异常:自动分页总是在新页面写入一行内容后才触发,导致翻译条目对应关系错位,页面存在大量空白。

问题复现代码

data = [['le bus', 'the bus'], ['le train', 'the train'], ['la gare', 'the train station']] # 其余翻译条目按格式补充

def write_to_pdf(data):
    pdf = FPDF()
    pdf.set_auto_page_break(True, 2)
    pdf.add_page()
    pdf.add_font('DejaVu', '', 'filepath/font', uni=True)
    pdf.set_font('DejaVu', '', 14)
    
    pdf.cell(200, 10, txt = title,ln = 1, align = 'C')
    pdf.cell(200, 10, txt = subtitle,ln = 2, align = 'C')
    pdf.set_font('DejaVu', '', 10)

    for section in data:
        try:
            top = pdf.y
    
            offset = pdf.x + 100

            pdf.multi_cell(100,10,section[0],0,'L')

            pdf.y = top

            pdf.x = offset 
           
            pdf.multi_cell(100,10,section[1],0,'R')

        except:
            pass

    pdf.output("Output.pdf") 

故障根因

  • 双列布局实现逻辑存在缺陷:写入左列内容前记录当前Y轴坐标,左列写完后强制将Y轴重置回记录值再写右列,该操作直接绕过了FPDF内置的自动分页校验逻辑。当左列内容触发自动分页时,FPDF已经完成新页跳转,但代码立刻将Y轴改回分页前的旧坐标,导致分页位置判断完全失准。
  • 自动分页预留边距设置过小:set_auto_page_break第二个参数仅设为2,没有给双列内容的高度计算预留容错空间,极易触发边界判断异常。
  • 裸except语句直接吞掉了所有坐标越界、分页触发类的运行时异常,导致错位问题无法被及时感知和定位。

修复方案

修复核心逻辑为提前预判分页位置,避免写入过程中被动触发自动分页,具体调整点如下:

  • 写入每一组翻译条目前,先通过split_only=True参数预计算左右两列内容折行后的行数,得到当前条目渲染需要的总高度
  • 校验当前页剩余可渲染高度是否足够容纳当前条目,高度不足时主动调用add_page()新建页面,避免multi_cell写入过程中被动触发分页
  • 移除强制重置Y轴坐标的逻辑,左右列内容都从预校验后的同一起始Y坐标开始写入,写完后将Y轴统一移动到当前条目下方,作为下一条目的渲染起点
  • 调整自动分页预留边距到合理值(15mm),删除吞异常的裸except语句

修复后完整代码

from fpdf import FPDF

# 翻译数据集,格式为[原语言词汇, 对应英文译文]
data = [['le bus', 'the bus'], ['le train', 'the train'], ['la gare', 'the train station']]
title = "外语-英语翻译对照表"
subtitle = "核心词汇汇总"

def write_to_pdf(data):
    pdf = FPDF()
    # 配置自动分页,页脚预留15mm边距
    pdf.set_auto_page_break(True, 15)
    pdf.add_page()
    pdf.add_font('DejaVu', '', 'filepath/font', uni=True)
    
    # 写入标题区
    pdf.set_font('DejaVu', '', 14)
    pdf.cell(0, 10, txt=title, ln=1, align='C')
    pdf.cell(0, 10, txt=subtitle, ln=2, align='C')
    pdf.set_font('DejaVu', '', 10)

    col_width = 90  # 单列内容宽度
    line_height = 10  # 单行文字高度
    col_gap = 10  # 左右两列中间的间距

    for left_text, right_text in data:
        start_x = pdf.l_margin  # 左列起始X坐标为页面左边距
        start_y = pdf.get_y()
        right_col_x = start_x + col_width + col_gap  # 右列起始X坐标

        # 预计算左右列折行数,得到当前条目总高度
        left_line_count = len(pdf.multi_cell(col_width, line_height, left_text, border=0, align='L', split_only=True))
        right_line_count = len(pdf.multi_cell(col_width, line_height, right_text, border=0, align='R', split_only=True))
        entry_height = max(left_line_count, right_line_count) * line_height

        # 剩余高度不足时主动分页
        if start_y + entry_height > pdf.page_break_trigger:
            pdf.add_page()
            start_y = pdf.get_y()

        # 写入左列内容
        pdf.set_xy(start_x, start_y)
        pdf.multi_cell(col_width, line_height, left_text, border=0, align='L')
        # 写入右列内容
        pdf.set_xy(right_col_x, start_y)
        pdf.multi_cell(col_width, line_height, right_text, border=0, align='R')

        # 将光标移动到当前条目下方,准备写入下一条
        pdf.set_y(start_y + entry_height)

    pdf.output("Output.pdf")

内容的提问来源于stack exchange,提问作者Max Davies

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:39:18