2016-09-01 3 views
1

파이썬에서 으로 배송 목록을 생성하려고했습니다. Platypus Frames을 사용하여 모든 부분 (발신자 주소, 수신자 주소, 표 등)을 제자리에 넣으려고했습니다.Python Reportlab의 다이나믹 프레임 크기

첫 번째 문제은 내가 옳은 방향으로 모든 것을 배치하기 위해 많은 Frames을 필요로한다는 것을 알아 냈습니다. 더 이상 오리너구리를 사용하는 것이 더 낫습니까? 발신자 주소와 주소가 동일한 높이가되도록하고 싶기 때문에 주소를 story = []에 추가하면 다른 주소 아래에 정렬됩니다.

다음 문제 내가 그리기있어 테이블의 크기는 동적이다 그리고 내가 Frame (I 테이블이 가고 싶은 공간)의 끝에 도달 할 때 그것은 단지 FrameBreak과 다음 프레임의 연속을한다 . 그렇다면 Frame (내 테이블을위한 공간)을 어떻게 동적으로 만들 수 있습니까?

+0

새로운 사용자이므로 질문과 답변에 대해 조금만 알아 보시기 바랍니다. 답변으로 문제가 해결되면 득표 수 밑에있는 녹색 체크 표시를 클릭하십시오. 이 방법으로 모든 사람이 그 질문에 답을 얻었고 응답자는 그의 노력에 대한 명성을 얻었습니다. :) – B8vrede

답변

2

당신의 유스 케이스는 정말 일반적인 것이므로, Reportlab은 당신을 도와 줄 시스템을 가지고 있습니다. 당신이 platypus에 대한 사용자 설명서를 읽으면

는 4 개 주요 개념을 소개합니다 :

DocTemplates 문서의 바깥 쪽 용기;

PageTemplates 다양한 종류의 페이지 레이아웃에 대한 사양;

Frames 흐르는 텍스트 나 그래픽을 포함 할 수있는 페이지의 영역 지정.

Flowables PageTemplates을 사용하면 예를 들어 로고, 주소 등과 같이 현명한 방식으로 페이지에서 정적 콘텐츠와 동적 콘텐츠를 결합 할 수 있습니다.

당신은 이미 FlowablesFrames을 발견하지만 propably 아직 공상 PageTemplates 또는 DocTemplates에 시작되지 않았습니다. 이는 대부분의 단순한 문서에서 필요하지 않기 때문에 의미가 있습니다. 슬프게도 출하 목록은 간단한 문서가 아니며 모든 페이지에 있어야하는 주소, 로고 및 중요한 정보를 담고 있습니다. 여기가 PageTemplates입니다.

어떻게 이러한 템플릿을 사용합니까? 개념은 간단합니다. 각 페이지는 페이지마다 다를 수있는 특정 구조를 가지고 있습니다. 예를 들어, 페이지 1에 주소를 넣고 테이블을 시작하고 두 번째 페이지에는 원하는 테이블 만 있으면됩니다.이 같은이 될 것 무언가 :

1 페이지 : enter image description here

2 페이지 :enter image description here

예는 다음과 같이 보일 것이다 :

(이 완벽 할 것 Reportlab 용 SO 문서의 경우

)
from reportlab.lib.pagesizes import A4 
from reportlab.lib.styles import getSampleStyleSheet 
from reportlab.lib.units import cm 
from reportlab.lib import colors 
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, NextPageTemplate, Paragraph, PageBreak, Table, \ 
    TableStyle 


class ShippingListReport(BaseDocTemplate): 
    def __init__(self, filename, their_adress, objects, **kwargs): 
     super().__init__(filename, page_size=A4, _pageBreakQuick=0, **kwargs) 
     self.their_adress = their_adress 
     self.objects = objects 

     self.page_width = (self.width + self.leftMargin * 2) 
     self.page_height = (self.height + self.bottomMargin * 2) 


     styles = getSampleStyleSheet() 

     # Setting up the frames, frames are use for dynamic content not fixed page elements 
     first_page_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width, self.height - 6 * cm, id='small_table') 
     later_pages_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width, self.height, id='large_table') 

     # Creating the page templates 
     first_page = PageTemplate(id='FirstPage', frames=[first_page_table_frame], onPage=self.on_first_page) 
     later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame], onPage=self.add_default_info) 
     self.addPageTemplates([first_page, later_pages]) 

     # Tell Reportlab to use the other template on the later pages, 
     # by the default the first template that was added is used for the first page. 
     story = [NextPageTemplate(['*', 'LaterPages'])] 

     table_grid = [["Product", "Quantity"]] 
     # Add the objects 
     for shipped_object in self.objects: 
      table_grid.append([shipped_object, "42"]) 

     story.append(Table(table_grid, repeatRows=1, colWidths=[0.5 * self.width, 0.5 * self.width], 
          style=TableStyle([('GRID',(0,1),(-1,-1),0.25,colors.gray), 
              ('BOX', (0,0), (-1,-1), 1.0, colors.black), 
              ('BOX', (0,0), (1,0), 1.0, colors.black), 
              ]))) 

     self.build(story) 

    def on_first_page(self, canvas, doc): 
     canvas.saveState() 
     # Add the logo and other default stuff 
     self.add_default_info(canvas, doc) 

     canvas.drawString(doc.leftMargin, doc.height, "My address") 
     canvas.drawString(0.5 * doc.page_width, doc.height, self.their_adress) 

     canvas.restoreState() 

    def add_default_info(self, canvas, doc): 
     canvas.saveState() 
     canvas.drawCentredString(0.5 * (doc.page_width), doc.page_height - 2.5 * cm, "Company Name") 

     canvas.restoreState() 


if __name__ == '__main__': 
    ShippingListReport('example.pdf', "Their address", ["Product", "Product"] * 50)