ReportLab 導出 PDF(頁面布局)

ReportLab 導出 PDF(文檔創建)
ReportLab 導出 PDF(頁面布局)
ReportLab 導出 PDF(圖文表格)

PLATYPUS - 頁面布局和排版

  • 1. 設計目標
  • 2. 開始
  • 3. Flowables
    • 3.1. Flowable.draw()
    • 3.2. Flowable.drawOn(canvas,x,y)
    • 3.3. Flowable.wrap(availWidth, availHeight)
    • 3.4. Flowable.split(self, availWidth, availheight)
  • 4. 流動定位的準則
  • 5. Frames
    • 5.1. Frame.addFromList(drawlist, canvas)
    • 5.2. Frame.split(flowable,canv)
    • 5.3. Frame.drawBoundary(canvas)
  • 6. 文檔和模板
    • 6.1. BaseDocTemplate.addPageTemplates(self,pageTemplates)
    • 6.2. BaseDocTemplate.build(self, flowables, filename=None,canvasmaker=canvas.Canvas)
    • 6.3. BaseDocTemplate.afterInit(self)
    • 6.4. BaseDocTemplate.afterPage(self)
    • 6.5. BaseDocTemplate.beforeDocument(self)
    • 6.6. BaseDocTemplate.beforePage(self)
    • 6.7. BaseDocTemplate.filterFlowables(self,flowables)
    • 6.8. BaseDocTemplate.afterFlowable(self, flowable)

1. 設計目標

Platypus 是"Page Layout and Typography Using Scripts"的縮寫。它是一個高水平的頁面布局庫, 讓你可以用最少的努力以編程方式創建復雜的文檔。
Platypus 的設計力求將 "高層次 "的布局決定與文檔內容盡可能分開 。例如,段落使用段落樣式,頁面使用頁面模板,目的是讓數百個有數千頁的文件可以按照不同的樣式規格重新格式化,只需在一個包含段落樣式和頁面布局規格的共享文件中修改幾行即可。
Platypus的整體設計可以認為有幾個層次,自上而下,這些是:
? DocTemplates 作為文檔的最外層容器。
? PageTemplates 作為各種頁面布局的規格。
? Frames 頁面中可包含流動文本或圖形的區域規格。
? Flowables 對應"flowed into the document"流入文檔的文本或圖形元素(即圖像、段落和表格等內容,但不包括頁腳或固定頁面圖形等內容)。
pdfgen.Canvas 為最終從其他圖層接收文檔繪畫的最低層。
在這里插入圖片描述
上面的插圖形象地說明了 DocTemplate、PageTemplate 和 Flowables 的概念 。然而,它具有欺騙性,因為每一個 PageTemplate 實際上可以指定任何數量的頁面的格式(而不是像從圖中推斷的那樣只指定一個)。
DocTemplate 包含一個或多個 PageTemplate,每個 PageTemplate 包含一個或多個Frame。
Flowables 是指可以 flowed(流入) Frame的東西,例如 Paragraph 或 Table。
要使用 platypus,你需要從 DocTemplate 類中創建一個文檔,并向其 build 方法傳遞一個 Flowables列表。document 的 build 方法知道如何將 flowable 列表處理成合理的東西。
在內部,DocTemplate 類使用各種事件來實現頁面布局和格式化。每個事件都有一個對應的處理方法,稱為 handle_XXX ,其中 XXX 是事件名稱。一個典型的事件是 frameBegin,它發生在機械開始第一次使用一個框架的時候。
Platypus 故事由一系列基本元素組成,這些元素被稱為 Flowables,它們驅動著數據驅動的 Platypus格式化引擎。為了修改引擎的行為,一種特殊的可流式元素 ActionFlowables 告訴布局引擎,例如,跳到下一列或者換成另一個 PageTemplate。

2. 開始

考慮以下代碼序列,它為 Platypus 提供了一個非常簡單的 "hello world "例子。

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize
from reportlab.lib.units import inchPAGE_HEIGHT=defaultPageSize[1]
PAGE_WIDTH=defaultPageSize[0]styles = getSampleStyleSheet()
Title = "Hello world"
pageinfo = "platypus example"# 首頁
def myFirstPage(canvas, doc):canvas.saveState()# 標題canvas.setFont('Times-Bold',16)canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title)# 頁腳 填充固定字符canvas.setFont('Times-Roman',9)canvas.drawString(inch, 0.75 * inch, "First Page / %s" % pageinfo)canvas.restoreState()# 非首頁
def myLaterPages(canvas, doc):canvas.saveState()# 頁腳 填充頁碼canvas.setFont('Times-Roman',9)canvas.drawString(inch, 0.75 * inch, "Page %d %s" % (doc.page, pageinfo))canvas.restoreState()def main(filename: str):doc = SimpleDocTemplate(filename)# 與標題間隔Story = [Spacer(1, 2*inch)]style = styles["Normal"]for i in range(100):bogustext = ("This is Paragraph number %s. " % i) * 5p = Paragraph(bogustext, style)Story.append(p)# 段落之間間隔Story.append(Spacer(1, 0.2*inch))# 添加doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)if __name__ == '__main__':main(filename='example.pdf')

我們創建一個"store"并構建文檔。請注意,我們在這里使用的是"canned"(罐頭)文檔模板,它是預建的頁面模板。
我們還使用了預建的段落樣式 。
我們在這里只使用了兩種類型的"flowables"–Spacers和Paragraphs 。第一個Spacer確保段落跳過標題字符串。

在這里插入圖片描述在這里插入圖片描述在這里插入圖片描述

3. Flowables

Flowables 是可以被繪制的東西,它有wrap, draw和可能的split方法。Flowable 是一個抽象的基類,用于繪制事物,一個實例知道它的大小,并在它自己的坐標系中繪制(這需要基 API 在調用 Flowable.draw方法時提供一個絕對坐標系)。要獲得一個實例,使用 f=Flowable()。
注意: Flowable 類是一個抽象類,通常只作為基類使用.
為了說明使用 Flowables 的一般方式,我們將展示如何在畫布上使用和繪制衍生類 Paragraph。

def main(filename):from reportlab.lib.styles import getSampleStyleSheetfrom reportlab.platypus import Paragraphfrom reportlab.pdfgen.canvas import CanvasstyleSheet = getSampleStyleSheet()style = styleSheet['BodyText']P=Paragraph('This is a very silly example',style)canv = Canvas(filename)aW = 460 # available width and heightaH = 800w,h = P.wrap(aW, aH) # find required spaceif w<=aW and h<=aH:P.drawOn(canv,0,aH)aH = aH - h # reduce the available heightcanv.save()else:raise ValueError("Not enough room")if __name__ == '__main__':main(filename='example.pdf')

在這里插入圖片描述

3.1. Flowable.draw()

這將被調用來要求 flowable 實際渲染自己。Flowable類沒有實現draw。調用代碼應該確保 flowable 有一個屬性canv,它pdfgen.Canvas,它應該被繪制到Canvas上,并且Canvas處于一個適當的狀態(就翻譯、旋轉等而言)。通常這個方法只在內部被drawOn方法調用,派生類必須實現這個方法。派生類必須實現這個方法。

3.2. Flowable.drawOn(canvas,x,y)

這是控制引擎用來將flowable渲染到特定畫布的方法。它處理轉換為畫布坐標(x,y),并確保flowable有一個canv屬性,這樣draw方法(在基類中沒有實現)就可以在一個絕對坐標框架中渲染。

3.3. Flowable.wrap(availWidth, availHeight)

在詢問對象的大小、繪制或其他什么之前,這個函數將被包圍的框架調用。它返回實際使用的尺寸。

3.4. Flowable.split(self, availWidth, availheight)

當wrap失敗時,更復雜的框架會調用這個函數。愚蠢的flowables應該返回[],這意味著它們無法拆分。聰明的flowables應該自己拆分并返回一個flowables列表。客戶端代碼要確保避免重復嘗試拆分。如果空間足夠,拆分方法應該返回[self]。否則,flowable應該重新排列,并返回一個按順序考慮的flowable列表[f0,…]。實現的拆分方法應該避免改變self,因為這將允許復雜的布局機制在一個可流動的列表上進行多次遞。

4. 流動定位的準則

有兩種方法,默認情況下返回零,為可流動物的垂直間距提供指導。
Flowable.getSpaceAfter(self):
Flowable.getSpaceBefore(self):
這些方法會返回flowable后面或前面應該有多少空間。這些空間不屬于flowable本身,也就是說,flowable的draw方法在渲染時不應該考慮它。控制程序將使用返回的值來確定上下文中特定flowable需要多少空間。
所有的flowables都有一個hAlign屬性:(‘LEFT’,‘RIGHT’,‘CENTER’或’CENTRE’)。對于占滿整個框架寬度的段落,這個屬性沒有影響。對于小于框架寬度的表格、圖像或其他對象,這決定了它們的水平位置。
下面的章節將涵蓋最重要的特定類型的可流動文件,段落和表格。

5. Frames

Frames是活動的容器,它本身就包含在PageTemplate中,Frames有一個位置和大小,并保持一個剩余可繪制空間的概念。如:

Frame(x1, y1, width, height, leftPadding=6, bottomPadding=6, rightPadding=6, topPadding=6, id=None, showBoundary=0)

創建一個左下角坐標為(x1,y1)的Frame實例(在使用時相對于畫布),尺寸為 width x height。Padding參數是用于減少繪畫空間的正量。參數id是運行時使用的標識符,例如"LeftColumn"或"RightColumn"等。如果showBoundary參數是非零,那么框架的邊界將在運行時被繪制出來(這有時很有用)。
Frames可以直接與canvases和flowables一起使用來創建文檔。Frame.addFromList方法為你處理wrap 和 drawOn調用。你不需要所有的Platypus引擎來獲得有用的東西到PDF中。

def main(filename): from reportlab.pdfgen.canvas import Canvasfrom reportlab.lib.styles import getSampleStyleSheetfrom reportlab.lib.units import inchfrom reportlab.platypus import Paragraph, Framestyles = getSampleStyleSheet()styleN = styles['Normal']styleH = styles['Heading1']story = []#add some flowablesstory.append(Paragraph("This is a Heading",styleH))story.append(Paragraph("This is a paragraph in <i>Normal</i> style.",styleN))c = Canvas(filename)f = Frame(inch, inch, 6*inch, 9*inch, showBoundary=1)f.addFromList(story,c)c.save()if __name__ == '__main__':main(filename='example.pdf')

在這里插入圖片描述

5.1. Frame.addFromList(drawlist, canvas)

消耗drawlist前面的Flowables,直到幀滿為止。如果不能容納一個對象,則引發一個異常。

5.2. Frame.split(flowable,canv)

要求flowable使用可用空間進行分割,并返回flowable的列表。

5.3. Frame.drawBoundary(canvas)

將框架邊界畫成一個矩形(主要用于調試)。

6. 文檔和模板

BaseDocTemplate類
實現了文檔格式化的基本機制。該類的一個實例包含了一個或多個PageTemplate的列表,這些PageTemplate可用于描述單頁信息的布局。build方法可用于處理Flowables列表,以生成一個PDF文檔。

from reportlab.lib.pagesizes import A4
from reportlab.platypus import BaseDocTemplate
from reportlab.lib.units import inchBaseDocTemplate(filename,pagesize=A4,pageTemplates=[],showBoundary=0,		# 控制是否繪制Frame的邊界,這對于調試來說是很有用的leftMargin=inch,rightMargin=inch,topMargin=inch,bottomMargin=inch,allowSplitting=1,	# allowSplitting參數決定了內置方法是否應該嘗試split單個Flowables跨越Frametitle=None,author=None,_pageBreakQuick=1,	# 參數決定了在結束頁面之前,是否應該嘗試結束頁面上的所有框架encrypt=None		# encrypt 參數決定了是否對文檔進行加密,以及如何加密)

創建一個適合創建基本文檔的文檔模板。它帶有相當多的內部機制,但沒有默認的頁面模板。所需的filename可以是一個字符串,一個用于接收創建的PDF文檔的文件名;也可以是一個有write方法的對象,如 BytesIO 或 file 或 socket。
showBoundary控制是否繪制Frame的邊界,這對于調試來說是很有用的。
allowSplitting參數決定了內置方法是否應該嘗試split單個Flowables跨越Frame。
_pageBreakQuick參數決定了在結束頁面之前,是否應該嘗試結束頁面上的所有框架。
encrypt 參數決定了是否對文檔進行加密,以及如何加密。默認情況下,文檔是不加密的。如果encrypt是一個字符串對象,那么它將作為pdf的用戶密碼。如果encrypt是一個reportlab.lib.pdfencrypt.StandardEncryption的實例,那么這個對象就被用來加密pdf。這允許對加密設置進行更精細的控制。

PageTemplate類
是一個語義相當簡單的容器類。每個實例都包含一個Frames的列表,并且有一些方法應該在每個頁面的開始和結束時被調用。

PageTemplate(id=None, frames=[], onPage=_doNothing, onPageEnd=_doNothing)

用于初始化一個實例,frames參數應該是一個Frames的列表,而可選的onPageonPageEnd參數是可調用的,它們的簽名應該是 def XXX(canvas,document),其中canvas和document是正在繪制的畫布和文檔。這些例程的目的是用來繪制頁面的非流動(即標準)部分。
這些屬性函數與純虛擬方法 PageTemplate.beforPage 和 PageTemplate.afterPage完全平行,這兩個方法的簽名是 beforPage(self,canvas,document)。這些方法允許使用類派生來定義標準行為,而屬性則允許改變實例。在運行時,id 參數用于執行 PageTemplate 的切換,所以 id=‘FirstPage’ 或 id='TwoColumns’是典型的。

6.1. BaseDocTemplate.addPageTemplates(self,pageTemplates)

此方法用于在現有文檔中添加一個或一系列PageTemplate。

6.2. BaseDocTemplate.build(self, flowables, filename=None,canvasmaker=canvas.Canvas)

這是應用程序程序員感興趣的主要方法。假設文檔實例被正確設置,build方法將story以flowables
列表的形式接收(flowables參數),并在列表中循環,將flowables列表一次一個地強制通過格式化
機制。實際上,這使得BaseDocTemplate實例發出對實例handle_XXX方法的調用來處理各種事件。

6.3. BaseDocTemplate.afterInit(self)

這個方法在基類初始化后被調用;派生類可以覆蓋該方法來添加默認的PageTemplates。

6.4. BaseDocTemplate.afterPage(self)

這是在頁面處理后,緊接著當前頁面模板的afterDrawPage方法被調用。一個派生類可以使用這個方
法來做一些依賴于頁面信息的事情,比如字典頁面上的首字和尾字。

6.5. BaseDocTemplate.beforeDocument(self)

在對文檔進行任何處理之前,但在處理機制準備好之后,就會調用這個函數,因此它可以用來對實
例的pdfgen.canvas等進行處理。因此,它可以用來對實例的pdfgen.canvas等進行操作。

6.6. BaseDocTemplate.beforePage(self)

這是在頁面處理開始時,在當前頁面模板的beforeDrawPage方法之前調用的。它可以用來重置頁面
特定的信息持有者。

6.7. BaseDocTemplate.filterFlowables(self,flowables)

在主 handle_flowable 方法開始時,調用這個函數來過濾flowables。在返回時,如果flowables[0]
被設置為None,則會被丟棄,主方法立即返回。

6.8. BaseDocTemplate.afterFlowable(self, flowable)

在flowable被渲染后調用。有興趣的類可以使用這個鉤子來收集特定頁面或框架上存在的信息。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76057.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76057.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76057.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ubuntu下安裝Intel MKL完整指南

&#x1f9e0; Intel MKL 安裝指南&#xff08;Ubuntu 完整版&#xff09; 適用平臺&#xff1a;Ubuntu 18.04 / 20.04 / 22.04 更新時間&#xff1a;2025 年最新版&#xff08;適配 Intel oneAPI 2024&#xff09; ? 一、安裝方式選擇 安裝方式適合用戶群體特點推薦程度&…

HackMyVM Gigachad.

Gigachad 信息搜集 ┌──(root?kali)-[/home/kali] └─# nmap 192.168.214.85 Starting Nmap 7.95 ( https://nmap.org ) at 2025-04-16 07:42 EDT Nmap scan report for 192.168.214.85 Host is up (0.00011s latency). Not shown: 997 closed tcp ports (reset) PORT S…

大模型全景解析:從技術突破到行業變革

目錄 一、引言&#xff1a;人工智能的新紀元 二、大模型發展歷史與技術演進 1. 早期探索期&#xff08;2015-2017&#xff09;&#xff1a;從"人工智障"到初具規模 RNN/LSTM架構時代&#xff08;2013-2017&#xff09; Transformer革命&#xff08;2017&#xf…

49、Spring Boot 詳細講義(六)(SpringBoot2.x整合Mybatis實現CURD操作和分頁查詢詳細項目文檔)

項目文檔:銀行借據信息CURD操作和分頁查詢 一、項目概述 1. 項目簡介 本項目旨在使用Spring Boot框架整合MyBatis連接Mysql數據庫實現借據信息的增加、刪除、修改和查詢功能,同時支持分頁查詢,并提供對應的Restful風格的接口。 2.環境準備 2.1.工具和軟件準備 JDK(建議…

youtube視頻和telegram視頻加載原理差異分析

1. 客戶側緩存與流式播放機制?? 流式視頻應用&#xff08;如 Netflix、YouTube&#xff09;通過??邊下載邊播放??實現流暢體驗&#xff0c;其核心依賴以下技術&#xff1a; ??緩存預加載??&#xff1a;客戶端在后臺持續下載視頻片段&#xff08;如 DASH/HLS 協議的…

把城市變成智能生命體,智慧城市的神奇進化

智能交通系統的建立與優化 智能交通系統&#xff08;ITS&#xff09;是智慧城市建設的核心部分之一&#xff0c;旨在提升交通管理效率和安全性。該系統利用傳感器網絡、GPS定位技術以及實時數據分析來監控和管理城市中的所有交通流動。例如&#xff0c;通過部署于道路兩側或交…

Oracle 23ai Vector Search 系列之5 向量索引(Vector Indexes)

文章目錄 Oracle 23ai Vector Search 系列之5 向量索引Oracle 23ai支持的向量索引類型內存中的鄰居圖向量索引 (In-Memory Neighbor Graph Vector Index)磁盤上的鄰居分區矢量索引 (Neighbor Partition Vector Index) 創建向量索引HNSW索引IVF索引 向量索引示例參考 Windows 環…

cas 5.3單點登錄中心開發手冊

文檔格式PDF 只讀文檔。 代碼源碼。 一、適用對象 需要快速上手出成果的服務端開發人員&#xff0c;具備3年經驗java 開發&#xff0c;熟悉數據庫&#xff0c;基本的Linux操作系統配置。 工期緊張需要快速搭建以cas為基礎的統一登錄中心&#xff0c;遇到技術瓶頸&#xff0c…

行星際激波在日球層中的傳播:Propagation of Interplanetary Shocks in the Heliosphere (第一部分)

行星際激波在日球層中的傳播&#xff1a;Propagation of Interplanetary Shocks in the Heliosphere &#xff08;第二部分&#xff09;- Chapter 3: Solar and heliospheric physics 行星際激波在日球層中的傳播&#xff1a;Propagation of Interplanetary Shocks in the Hel…

Linux——消息隊列

目錄 一、消息隊列的定義 二、相關函數 2.1 msgget 函數 2.2 msgsnd 函數 2.3 msgrcv 函數 2.4 msgctl 函數 三、消息隊列的操作 3.1 創建消息隊列 3.2 獲取消息隊列并發送消息 3.3 從消息隊列接收消息recv 四、 刪除消息隊列 4.1 ipcrm 4.2 msgctl函數 一、消息…

藍橋杯常考排序

1.逆序 Collections.reverseOrder() 方法對列表進行逆序排序。通過 Collections.sort() 方法配合 Collections.reverseOrder()&#xff0c;可以輕松實現從大到小的排序。 import java.util.ArrayList; // 導入 ArrayList 類&#xff0c;用于創建動態數組 import java.util.C…

ILGPU的核心功能使用詳解

什么是ILGPU? ILGPU 是一種用于高性能 GPU 程序的新型 JIT&#xff08;即時&#xff09;編譯器 &#xff08;也稱為 kernels&#xff09;編寫的 .基于 Net 的語言。ILGPU 完全 用 C# 編寫&#xff0c;沒有任何原生依賴項&#xff0c;允許您編寫 GPU 真正可移植的程序。…

金融的未來

1. DeFi的爆發式增長與核心使命 DeFi&#xff08;去中心化金融&#xff09;的使命是重構傳統金融基礎設施&#xff0c;通過區塊鏈技術實現更高的透明度、可訪問性、效率、便利性和互操作性。其增長數據印證了這一趨勢&#xff1a; TVL&#xff08;總鎖定價值&#xff09;爆炸…

在Vue項目中查詢所有版本號為 1.1.9 的依賴包名 的具體方法,支持 npm/yarn/pnpm 等主流工具

以下是 在Vue項目中查詢所有版本號為 1.1.9 的依賴包名 的具體方法&#xff0c;支持 npm/yarn/pnpm 等主流工具&#xff1a; 一、使用 npm 1. 直接過濾依賴樹 npm ls --depth0 | grep "1.1.9"說明&#xff1a; npm ls --depth0&#xff1a;僅顯示直接依賴&#xf…

其利天下即將亮相第21屆(順德)家電電源與智能控制技術研討會

2025年4月25日&#xff0c;第21屆&#xff08;順德&#xff09;家電電源與智能控制技術研討會即將拉開帷幕&#xff0c;其利天下應大比特之邀&#xff0c;確認將參加此次研討會。 本次研討會&#xff0c;我司委派研發總監馮建武先生圍繞《重新定義風扇驅動&#xff1a;一套算法…

阿里云OSS

目錄 第三方服務-通用思路 SDK 準備工作 阿里云OSS-入門程序 .putObject 如何拿到文件對應的字節數組&#xff1f; .readAllBytes&#xff08;&#xff09; 集成阿里云OSS完成文件上傳 引入阿里云OSS文件上傳的工具類 上傳文件接口開發 .getOriginalFilename() 程序…

李宏毅NLP-4-語音識別part3-CTC

Connectionist Temporal Classification&#xff5c;CTC 基于連接主義時間分類&#xff08;CTC&#xff09;的語音識別架構&#xff0c;具體描述如下&#xff1a; 輸入層&#xff1a;底部的 x 1 , x 2 , x 3 , x 4 x^1, x^2, x^3, x^4 x1,x2,x3,x4代表輸入的語音信號分幀數據…

如何構建類似云數據倉庫 Snowflake 的本地數據倉庫?

目錄 一、Snowflake 架構的三大核心價值 二、本地數據倉庫要“像 Snowflake”&#xff0c;關鍵在數據服務化 三、SQL2API&#xff1a;本地數據服務共享的核心引擎 ? 什么是 SQL2API&#xff1f; ? 為什么是構建本地類 Snowflake 架構的關鍵&#xff1f; 四、QuickAPI&a…

設計模式 - 單例模式

一個類不管創建多少次對象&#xff0c;永遠只能得到該類型一個對象的實力 常用到的&#xff0c;比如日志模塊&#xff0c;數據庫模塊 餓漢式單例模式&#xff1a;還沒有獲取實例對象&#xff0c;實例對象就已經產生了 懶漢式單例模式&#xff1a;唯一的實例對象&#xff0c;…

【Windows Cmake工程配置Boost庫】

Windows Cmake工程配置Boost庫 背景配置流程1. 下載Boost庫2. 配置環境變量3. 修改CmakeLists背景 Windows環境下使用cmake開發程序,如圖需要用到boost庫,但是從官網下載的boost庫源碼沒有編譯成功,于是從網上下載boost預編譯庫,直接配置。 配置流程 1. 下載Boost庫 官…