ReportLab中如何禁止段落跨页拆分?
如何在ReportLab中禁止段落内分页
嘿,我刚好之前处理过类似的需求,ReportLab完全支持让段落不被跨页拆分——要么整个段落留在当前页,要么自动跳到下一页完整显示。
实现起来很简单,主要有两种方式:
方法1:通过ParagraphStyle全局设置
你可以直接在定义段落样式的时候添加keepTogether=True属性,这样所有使用这个样式的段落都会自动保持完整性,不会被分页拆分:
from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import ParagraphStyle from reportlab.platypus import SimpleDocTemplate, Paragraph height, width = A4 doc = SimpleDocTemplate("image.pdf", pagesize=A4) # 修改样式,添加keepTogether=True让段落保持完整 style = ParagraphStyle('Normal', keepTogether=True) parts = [] # 以下段落代码保持不变 parts.append(Paragraph('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla tincidunt nulla tincidunt dignissim finibus. Quisque in nibh id orci convallis bibendum. Cras maximus, mi sed commodo lacinia, sapien elit facilisis mi, nec volutpat mauris mi at mauris. Fusce tincidunt congue sapien, a cursus ex aliquam quis. Sed id sapien commodo, dapibus quam eu, eleifend dui. Fusce gravida porta ultricies. Pellentesque hendrerit quis ante quis congue. Proin vel lobortis tortor, a vestibulum nibh. Nullam accumsan elementum vehicula. Ut eu magna varius neque finibus congue. Curabitur rhoncus, orci eu sagittis viverra, est urna eleifend augue, quis fermentum erat dui in massa. Integer vitae dignissim elit. Praesent vitae nibh vitae eros eleifend tempus non a purus.', style)) parts.append(Paragraph('Sed dapibus, eros at porta interdum, lorem felis tincidunt lectus, non malesuada elit mauris at lacus. Pellentesque mollis accumsan dolor, non bibendum enim fermentum ac. Duis gravida dolor in sem fermentum, at gravida erat malesuada. Quisque vehicula, eros eget euismod ultricies, nisi libero semper odio, in maximus arcu quam congue odio. Pellentesque quis est sem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam vulputate rhoncus nisl, a sodales metus viverra eu. ', style)) parts.append(Paragraph('Fusce ultricies tincidunt laoreet. Aliquam commodo id nisi non hendrerit. Aenean dapibus, nibh at feugiat vestibulum, odio erat fringilla nunc, et sagittis nulla lacus ut risus. Duis sit amet orci dignissim, vestibulum erat nec, eleifend leo. Nullam suscipit pellentesque urna id rutrum. Nunc nunc ex, blandit id porta ut, tincidunt at libero. Cras orci augue, mollis vitae magna aliquet, tristique volutpat nunc. Sed sit amet vehicula purus, id sollicitudin libero. Nullam efficitur pretium maximus. Donec eget congue diam. ', style)) parts.append(Paragraph('Phasellus ut ex nisl. Quisque interdum cursus nunc et convallis. Nam quis odio venenatis, aliquam nulla in, faucibus turpis. Fusce placerat erat id lectus ultrices blandit. Aliquam erat volutpat. Cras varius finibus eros a accumsan. Curabitur ultricies diam at justo pellentesque, et maximus dui dictum. Quisque euismod turpis vel interdum ultrices. Sed elementum congue lectus id sollicitudin. Nullam et pharetra orci. Nulla dignissim consectetur orci, sit amet euismod eros tristique non. In dignissim dictum tellus, eleifend congue dolor sodales in. Mauris feugiat turpis a faucibus pretium. Sed ut urna vitae purus porta porttitor id nec orci. Suspendisse felis risus, suscipit in orci nec, porta eleifend orci. In vel porttitor sem, eu cursus lectus. ', style)) parts.append(Paragraph('Aenean finibus feugiat arcu eget suscipit. Donec et blandit dui. Donec varius metus eget turpis faucibus, sed fermentum dui vestibulum. Nulla id risus in lorem ornare iaculis vestibulum eget nunc. Maecenas lobortis accumsan porttitor. In felis libero, dictum id posuere quis, suscipit in risus. Quisque tincidunt scelerisque nibh. Ut at nunc massa. Nam porttitor elit nec tortor luctus congue. Sed tristique volutpat pretium. Vestibulum suscipit augue et lectus consequat, sed sodales justo finibus. Curabitur vehicula bibendum ante eu interdum. ', style)) parts.append(Paragraph('Curabitur cursus, mi et euismod condimentum, erat ex suscipit nisi, eget aliquam nibh velit ultricies nulla. Etiam faucibus elit eu iaculis auctor. Phasellus at ultrices enim. Donec interdum odio sed dui dapibus, eget auctor orci elementum. Vestibulum maximus ipsum eu est consectetur, quis molestie nisi interdum. Ut congue a nibh vitae sagittis. Morbi eu elit ullamcorper, consequat quam sit amet, viverra nulla. ', style)) parts.append(Paragraph('Nullam aliquam nunc sit amet maximus egestas. Etiam non cursus sapien. Vestibulum non erat et sapien tincidunt congue id quis nibh. Nulla gravida diam diam, a consectetur erat tincidunt sit amet. Sed quis sagittis est. Cras condimentum purus mi, non volutpat neque pellentesque quis. Phasellus mattis fermentum nisi, id tempus odio pretium vitae. Nullam interdum, urna ut volutpat porta, orci erat vehicula nisl, et pretium enim urna vel ante. ', style)) parts.append(Paragraph('Fusce nec efficitur nibh, quis feugiat augue. Vivamus eget ligula convallis magna bibendum gravida non id libero. Suspendisse sed suscipit nunc. Suspendisse sed urna sit amet risus viverra hendrerit. Ut sodales enim in mauris porttitor tristique. Quisque maximus posuere mi in consectetur. Fusce pellentesque elementum nulla, id vestibulum eros aliquam ac. Cras tempus leo vel urna interdum mollis. Praesent elit nisl, posuere eu sodales in, tempus sit amet sem. Etiam a posuere sapien. Fusce lectus elit, ornare sed venenatis eu, interdum vel massa. Integer faucibus tortor nec consectetur ultricies. Cras egestas vitae purus vel dictum. Mauris lorem ex, ultrices eget metus nec, accumsan dapibus leo. Aenean quis egestas sapien, a fringilla ante. ', style)) parts.append(Paragraph('Duis dictum neque vel enim rutrum, in porta orci accumsan. Nulla vitae consectetur ex. Curabitur elementum nisl non sapien pellentesque bibendum. Curabitur sit amet massa quis arcu volutpat dapibus eget nec urna. Donec in posuere dui. Sed eleifend sem vel sapien tincidunt sodales. Suspendisse urna ipsum, tristique cursus mauris eget, pharetra efficitur nulla. ', style)) parts.append(Paragraph('Phasellus porttitor enim finibus, lobortis ex nec, condimentum risus. Donec vitae enim et tellus ornare pharetra et vitae massa. Proin porta luctus ultricies. Nam sed ultricies massa. Sed consectetur condimentum sem in ultrices. Nunc arcu justo, consequat et tortor at, dapibus convallis lorem. Quisque ut dapibus justo, vel porta justo. In consectetur nunc at sem placerat maximus. Donec malesuada nisi porta, cursus ligula vel, cursus turpis. Vestibulum eget tincidunt lorem. Aliquam sed scelerisque quam. Sed in dui in elit sodales lobortis vel eu risus. Suspendisse pretium erat orci, vel tristique ligula auctor sit amet. Proin accumsan rutrum felis ac gravida. Aenean hendrerit eleifend augue, at tristique nunc luctus sit amet. ', style)) parts.append(Paragraph('Nunc eget nisl vitae neque malesuada facilisis vitae non tellus. Integer posuere nulla non bibendum hendrerit. Morbi pulvinar urna in placerat cursus. Mauris in vehicula enim. In dignissim vehicula sagittis. Curabitur faucibus tincidunt nulla, eget dignissim nunc dapibus eget. Donec quis lorem et eros pellentesque lacinia. Mauris elementum eget sapien eget tempor. Suspendisse a hendrerit leo. Suspendisse dictum neque id tristique euismod. Vivamus interdum ex posuere egestas semper. Mauris et turpis ac urna ullamcorper suscipit eget vel sem. Nulla in finibus nunc. ', style)) doc.build(parts)
方法2:给单个Paragraph单独设置
如果你只想让特定段落不被拆分,而不是全局生效,可以在创建Paragraph实例时传入allowSplitting=False参数:
# 仅让这个段落不被拆分 parts.append(Paragraph('Sed dapibus, eros at porta interdum...', style, allowSplitting=False))
效果说明
两种方式都能实现相同的核心效果:当段落无法在当前剩余页面空间完整显示时,ReportLab会自动将整个段落移到下一页,而不会把段落拆分成两部分跨页显示。
需要注意的是,如果单个段落的长度超过了整页的高度(比如一个超级长的段落),即使设置了这些属性,ReportLab还是会被迫拆分它——毕竟没有足够的空间容纳整个段落,这种情况属于极端场景,一般很少遇到。
内容的提问来源于stack exchange,提问作者chindit




