Reportlab - Y-Position von letzter Tabellenzeile

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,

ich erstelle mit Reportlab PDF-Dokumente (Rechnung, Lieferschein ...).
Die Auflistung der Daten, setze ich mittels einer Tabelle um, die auch über mehrere Seiten gehen können.
Die Erstellung der Dokumente mittels Reportlab, funktioniert problemlos.
Um ein Problem zu lösen, benötige ich bei der letzten Seite die Y-Position der letzten Tabellenzeile.

Gibt es eine Möglichkeit, diese Information zu erhalten?
BZW. welches Werkzeug von Reportlab ist dafür geeignet?

Grüße Nobuddy
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

ich beschäftige mich auch grad damit.
hab auch keine ahnung, wie ich eine normale ausgabetabelle in tkinter in reportlab übersetzen soll.
ziemlich enttäuschend, dass man das noch nicht standardisiert hat!
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Nobuddy: was hast Du denn bereits? Und was willst Du genau mit der y-Position anfange?
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ReportLab ermittelt beim bauen des Dokuments defintiv diese Wert, da diese für die Positionierung des Flowables währendc der Generierung benötigt werden.

Du musst auch das PDF-Dokument 1x bauen, um an die Position überhaupt ran zu kommen. Aber das _wie_ ist mir auch noch nicht klar. Aber ich bin mir sicher, dass es geht :-)
Und was willst Du genau mit der y-Position anfange?
Genau - warum brauchst du das? Wenn du mit Flowables arbeitest sollte diese Abfrage eigentlich nicht nötig sein...

Gruß, noisefloor
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

habe mal ein bisschen rum gespielt: man kann den verbleibenden Platz berechnen und zwar so:

Jedes Flowable hat nach dem Bauen des PDFs ein `height` bzw. `_height`-Attribute. Das in Summe mit dem reservierten Platz vor und hinter dem Flowable gibt den Gesamtplatzbedarf pro Flowable.
Auf deiner Seite sind im einfachsten Fall Seitenhöhe minus (Rand unten + Rand oben) Platz. Davon die Summe des Platzbedarfs aller im Dokument enthalten Flowables abgezogen erhält man den restlichen freien Platz.

Praktisch sieht das z.B. so aus:

Code: Alles auswählen

>>> from reportlab.platypus import Paragraph, Table, SimpleDocTemplate
>>> from reportlab.lib.styles import getSampleStyleSheet
>>> style = getSampleStyleSheet()
>>> table_data = [['foo', 'bar'], ['spam', 'egg']]
>>> p1 = Paragraph('foobarspamegg', style['Normal'])
>>> p1.spaceAfter = 10
>>> t = Table(table_data)
>>> t.spaceBefore = 5
>>> t.spaceAfter = 5
>>> p2 = Paragraph('Foo!'*150, style['Normal'])
>>> p2.spaceBefore = 10
>>> doc = SimpleDocTemplate('space_test.pdf')
>>> story = [p1, t, p2]
>>> doc.build(story)
>>> doc_available_space = doc.height-doc.topMargin-doc.bottomMargin
>>> doc_available_space
553.8897637795275
>>> p1_space_comsumed = p1.getSpaceBefore()+p1.height+p1.getSpaceAfter()
>>> p1_space_comsumed
22
>>> p1.height
12
>>> t._height
36
>>> t_space_consumed = t.getSpaceBefore()+t._height+t.getSpaceAfter()
>>> p2_space_comsumed = p2.getSpaceBefore()+p2.height+p2.getSpaceAfter()
>>> remainig_space = doc_available_space - p1_space_consumed - t_space_comsumed - p2_space_comsumed
>>> remainig_space
391.88976377952747
>>> 
Wenn man Kopf- und Fusszeilen, Frames oder mehrseitige Dokumente hat, wird das ganze ein wenig aufwendiger, das Prinzip bleibt aber das gleiche.

Wenn man übrigens nur will, dass das der Tabelle folgende Flowable auf jeden Fall unter der Tabelle bleiben soll, dann gibt für Flowables das `keepWithNext` Attribut, was man auf `True` setzt.

Gruß, noisefloor
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo noisefloor,

ist zwar schon ein wenig her, habe aber eine Frage zu Deinem Code-Beispiel.
Ich möchte das Beispiel aufgreifen.

Code: Alles auswählen

p1 = Paragraph('foobarspamegg', style['Normal'])
p1.spaceAfter = 10
p1_space_comsumed = p1.getSpaceBefore()+p1.height+p1.getSpaceAfter()
Bei mir sieht das im Test so aus:

Code: Alles auswählen

text = 'Erste Zeile\nZweite Zeile blablabalbalabalanalanalan'
p1 = Paragraph('foobarspamegg', style['Normal'])
p1.spaceAfter = 10
p1_space_comsumed = p1.getSpaceBefore()+p1.height+p1.getSpaceAfter()
Ich erhalte dann die Fehlermeldung:
p1_space_comsumed = p1.getSpaceBefore()+p1.height+p1.getSpaceAfter()
AttributeError: 'Paragraph' object has no attribute 'height'
Wo liegt der Fehler?
Evtl. bei dem formatierten Text mit Newline, oder doch was ganz anderes?

Grüße Nobuddy
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

das `height` Attribute hat ein Flowable _nur_, wenn du das PDF-Dokument einmal gebaut hast.

Geht auch nicht anders, da ReportLab ja vor dem bauen eines PDFs nicht weiß, wie viel Platz in der Breite ist, was ja auch einen Einfluß auf die Höhe des Flowables haben kann (z.B. breite Seite -> viel Text pro Zeile -> weniger Zeilen).

Im obigen Code rufe ich `flowable.height` ja auch erst das 1. Mal auf, nachdem `doc.build()` gelaufen ist :-)

Gruß, noisefloor
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo und Danke für die schnelle Antwort!
Nobuddy hat geschrieben:Im obigen Code rufe ich `flowable.height` ja auch erst das 1. Mal auf, nachdem `doc.build()` gelaufen ist
Das hatte ich wohl total ignoriert ... :wink:

Grüße Nobuddy
Antworten