FPDF单元格消失问题求助:大文本适配时单元格丢失
问题:大段文本导致PDF单元格消失(Quizlet闪卡转换工具)
我开发了一个将Quizlet闪卡转为可打印大闪卡的工具,因为Quizlet官方移除了这个功能。工具基础功能正常,但处理大段文本时会出现异常:单元格直接消失(并非字体大小变为0)。我尝试过两种适配105宽度单元格的方案——缩小字体、按3个单词分组换行,但都没解决问题。问题截图显示原本应存在内容的单元格区域为空,无任何文本或边框。
以下是我尝试的两段代码:
第一段尝试代码:
from fpdf import FPDF import os, math, re, numpy def group_words(s, n): words = s.split() for i in range(0, len(words), n): yield ' '.join(words[i:i+n]) def printcell(text): #105 is the width of 1 cell width = pdf.get_string_width(text) pdf.set_font("Japanese", size = fontsize) if(width >= 104): pdf.set_font("Japanese", size = fontsize-5) print("splitting") words = numpy.array(list(group_words(text,3))) print(words) words.join('\n') print(words) pdf.cell(105, 74.25, words, 1, 1, 'C') else: pdf.cell(105, 74.25, text, 0, 1, 'C')
第二段尝试代码(早期版本,未做字体非0检查):
def printcell(text): while(pdf.get_string_width(text)>105): if (counter == fontsize): pass else: pdf.set_font("Japanese", size = fontsize-counter) counter+=1 pdf.cell(105, 74.25, text, 0, 1, 'C')
问题分析与修复方案
第一段代码的核心问题
- numpy数组无法被PDF单元格识别:你把分组后的文本转成了numpy数组,但
pdf.cell不支持数组类型参数,直接导致内容无法渲染,单元格看起来"消失"。 join方法使用错误:words.join('\n')不会修改原数组,需要将结果赋值给新变量;且numpy数组的join用法不符合字符串拼接逻辑,应该用普通列表处理。pdf.cell不支持多行文本:即使生成了带换行的文本,cell也不会自动换行,文本会溢出单元格导致显示异常。
修复后的第一段代码:
from fpdf import FPDF import os, math, re def group_words(s, n): words = s.split() for i in range(0, len(words), n): yield ' '.join(words[i:i+n]) def printcell(text): # 105是单个单元格的宽度 pdf.set_font("Japanese", size=fontsize) width = pdf.get_string_width(text) if width >= 104: pdf.set_font("Japanese", size=fontsize-5) print("splitting") # 用普通列表处理分组文本,无需numpy grouped_lines = list(group_words(text, 3)) # 正确生成带换行的文本 wrapped_text = '\n'.join(grouped_lines) print(wrapped_text) # 改用multi_cell支持多行文本渲染,第二个参数为每行高度 pdf.multi_cell(105, 15, wrapped_text, 1, 'C') else: pdf.cell(105, 74.25, text, 0, 1, 'C')
第二段代码的核心问题
counter未初始化:函数内使用了counter但未定义初始值,会直接抛出异常。- 死循环风险:如果缩小到极小字体后文本宽度仍超过105,会进入无限循环。
- 无字体下限限制:未设置最小字体大小,可能缩到负数或过小导致文本无法显示。
修复后的第二段代码:
def printcell(text): # 初始化计数器与最小字体限制 counter = 0 min_font_size = 8 current_font_size = fontsize pdf.set_font("Japanese", size=current_font_size) # 循环缩小字体,直到宽度符合要求或达到最小字体 while pdf.get_string_width(text) > 105 and current_font_size > min_font_size: current_font_size -= 1 pdf.set_font("Japanese", size=current_font_size) counter += 1 # 兜底逻辑:最小字体仍超宽时,自动切换到换行处理 if pdf.get_string_width(text) > 105: grouped_lines = list(group_words(text, 3)) wrapped_text = '\n'.join(grouped_lines) pdf.multi_cell(105, 15, wrapped_text, 0, 'C') else: pdf.cell(105, 74.25, text, 0, 1, 'C')
通用注意事项
- 确保全局变量
fontsize已正确定义(例如fontsize = 16)。 - 确认"Japanese"字体已正确加载,字体缺失也会导致文本不显示。
- 使用
multi_cell时,需根据字体大小调整每行高度参数,避免文本重叠。
内容的提问来源于stack exchange,提问作者Human
相关产品推荐
相关产品推荐

