2012-06-17 28 views
7

Reportlab platypusでPDF表を作成しています。ダイナミックコンテンツのためにページがいっぱいになったときはわかりません。私がページの最後にいたら、どうすればチェックアウトできますか?reportlabの条件付きページ区切り

ページの終わりを確認するためのプラチナの方法はありますか?

私は企業のリストを持っており、各企業には複数の事業部門があります。

companies = [('company1', 'businessunit1', 500), 
       ('company1', 'businessunit2',400), 
       ('company2', 'businessunit3',200), 
       ('company2', 'businessunit4', 700), 
       ('company3', 'businessunit5', 800) 
       ] 

上記のリストは、一社の企業のための3つのテーブルごとに生成する必要がありますが、このリストは意志が複数のテーブルを生成し、複数の企業を持っている場合と、任意のテーブルが破壊されるページの最後に達した場合。

 fields = ['company name', 'business unit name', 'charge'] 
     for i, comp in enumerate(companies): 
      charges = [] 
      document.append(Paragraph("<b>%s</b>" %comp[i][0], STYLES['COMPANY_NAME'])) 
      document.append(Spacer(1, 5)) 
      charges.append(comp[i][0]) 
      charges.append(comp[i][1]) 
      charges.append(comp[i][2]) 
      charges_table = LongTable([fields] + charges, colWidths=(30,150,100)) 
      charges_table.setStyle(TableStyle([ 
          ('BACKGROUND', (0, 0), (-1, 0), colors.gray), 
          ('FONTSIZE', (0, 0), (-1, 0), 6), 
          ('GRID', (0, 0), (-1, -1), 1, colors.gray), 
          ('FONTSIZE', (0, 0), (-1, -1), 7), 
          ('TEXTCOLOR',(0,-1),(-1,-1),'#FF4500'), 
          ]) 
         ) 

      charges_table.hAlign = 'CENTER' 
      document.append(charges_table) 
+0

iは任意の解決策を得ることができますか? – Asif

+0

あなたの質問を編集*しない限りあなたのコメントが表示されます。また、[faq#bounty]の他のオプションも参照して回答を得てください。 –

答えて

4

私たちはあなたが達成しようとしていることを知るために、いくつかのサンプルコードを提供する必要があります。なぜページが終了したのか知りたいのですか?新しいコンテンツを作成するには?診断情報を印刷するには?

ページがレンダリングされた後に何かを描画すると仮定すると、BaseDocTemplateクラスで提供されるafterPage()メソッドを使用できます。 ReportLabのドキュメントから:

これは、ページ処理後、および現在のページテンプレートのafterDrawPageメソッドの直後に呼び出されます。派生クラスはこれを使用して、辞書のページ上の最初と最後の単語など、ページ内の情報に依存するものを行うことができます。

基本的には、ページが描画された後にBaseDocTemplateによって呼び出されます。ソースコードにはBaseDocTemplateクラスの一部としてselfが含まれていますので、キャンバスにアクセスできます。

独自のスクリプトでクラスをオーバーライドし、キャンバスに直接描画することができます。

from reportlab.platypus import BaseDocTemplate 
from reportlab.lib.styles import getSampleStyleSheet 
from reportlab.lib.units import inch 
from reportlab.lib.pagesizes import A4 
from reportlab.platypus import Paragraph 

class MyDocTemplate(BaseDocTemplate): 
    """Override the BaseDocTemplate class to do custom handle_XXX actions""" 

    def __init__(self, *args, **kwargs): 
     BaseDocTemplate.__init__(self, *args, **kwargs) 

    def afterPage(self): 
     """Called after each page has been processed""" 

     # saveState keeps a snapshot of the canvas state, so you don't 
     # mess up any rendering that platypus will do later. 
     self.canv.saveState() 

     # Reset the origin to (0, 0), remember, we can restore the 
     # state of the canvas later, so platypus should be unaffected. 
     self.canv._x = 0 
     self.canv._y = 0 

     style = getSampleStyleSheet() 

     p = Paragraph("This is drawn after the page!", style["Normal"]) 

     # Wraps and draws the paragraph onto the canvas 
     # You can change the last 2 parameters (canv, x, y) 
     p.wrapOn(self.canv, 2*inch, 2*inch) 
     p.drawOn(self.canv, 1*inch, 3*inch) 

     # Now we restore the canvas back to the way it was. 
     self.canv.restoreState() 

今、あなたはあなたのメインのロジックでBaseDocTemplateを使用するMyDocTemplate同じように使用することができます。

if __name__ == "__main__": 

    doc = MyDocTemplate(
     'filename.pdf', 
     pagesize=A4, 
     rightMargin=.3*inch, 
     leftMargin=.3*inch, 
     topMargin=.3*inch, 
     bottomMargin=.3*inch 
    ) 

    elements = [ 
     # Put your actual elements/flowables here, however you're generating them. 
    ] 

    doc.addPageTemplates([ 
     # Add your PageTemplates here if you have any, which you should! 
    ]) 

    # Build your doc with your elements and go grab a beer 
    doc.build(elements) 
+0

BaseDocTemplateから\ _ \ _ init \ _ \ _を継承できるだけの理由で、MyDocTemplateがnull \ _ \ _ init \ _ \ _拡張を定義する理由を聞いてもよろしいですか?私はこのパターンをかなり見てきましたが、達成するはずのものは決して確実ではありません。 – holdenweb

+0

@holdenweb正直なところ、この例では目的はありません。私は自分のスクリプトの1つからこれをコピーしたので、そこに残したと思う。私はいくつかのカスタム属性を子クラスに割り当てていたので、 '__init__'をオーバーライドしなければなりませんでした。私はそれがどんな悪い結果もなく取り除くことができたと確信しています。 – Nitzle

0

あなたがラインを自分で使用カウントする必要があります。

lin += inc 
if lin > 580: 
    doc.append(PageBreak()) 
    lin = 5 

をテーブルには、ページの残りの部分に収まるかどうかを知ることができます使用していますどのように多くの行知ることによって: は、私は、プロシージャを使用します。

私は 'ポイント'を使用しているので、異なる高さの線を扱うことができます。

+0

一般的に、表のセルにはテキスト以外のFlowableが含まれている可能性があります。したがって、内容からセルの高さを追跡する必要があり、ReportLabライブラリ内の多くの作業を複製する可能性があります。テキストを設定するときでさえ、パラグラフがどれくらいの垂直スペースを占めるかを知ることは容易ではありません。 – holdenweb

0

自動分割longtableは、次のように:

from reportlab.platypus import LongTable, TableStyle, BaseDocTemplate, Frame, PageTemplate 
from reportlab.lib.pagesizes import letter 
from reportlab.lib import colors 


def test(): 
    doc = BaseDocTemplate(
     "test.pdf", 
     pagesize=letter, 
     rightMargin=72, 
     leftMargin=72, 
     topMargin=72, 
     bottomMargin=18, 
     showBoundary=True) 

    elements = [] 
    datas = [] 
    for i, x in enumerate(range(1, 50)): 
     datas.append([i, x]) 
    t = LongTable(datas) 

    tableStyle = [ 
     ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), 
     ('BOX', (0, 0), (-1, -1), 0.25, colors.black), 
    ] 
    t.setStyle(TableStyle(tableStyle)) 
    elements.append(t) 

    frame = Frame(
     doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal') 
    doc.addPageTemplates([PageTemplate(id='longtable', frames=frame)]) 
    doc.build(elements) 


if __name__ == '__main__': 
    test()