Hilfe zum 1 x 1 für reportlab

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.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,

ich würde mich über Eure Hilfe zum Thema reportlab freuen. Grund sind meine fehlende Englischkenntnisse, die das Verstehen der Dokumentation von reportlab äußerst erschwert.
Ich verwende Linux Kubuntu 14.04 und habe mir in diesem Wiki http://wiki.ubuntuusers.de/ReportLab diesen Code als Einstieg ausgewählt:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph, SimpleDocTemplate, PageBreak

#Definieren der Styles
style = getSampleStyleSheet()
#Anlegen einer Liste, welche den Seiteninhalt enthält
story = []
#Generieren von Inhalt
story.append(Paragraph('Überschrift 1',style['Heading1']))
story.append(Paragraph('''Das ReportLab Toolkit ist ein Python-Modul zum
generieren von PDF Dokumenten. Es bietet zahlreiche Klassen und Funktionen
zur detaillierten Kontrolle des Inhalts und des Layouts. Weiterhin gibt es 
Klassen zur Generierung von Diagrammen.''',style['BodyText']))
story.append(PageBreak())
story.append(Paragraph('Überschrift 2',style['Heading2']))
story.append(Paragraph(''' Das ReportLab Toolkit steht unter einer freien 
OpenSource Lizenz.''',style['BodyText']))
#Anlegen des PDFs
pdf = SimpleDocTemplate('mein_pdf4.pdf',pagesize=A4)
pdf.build(story)
Ich verwende Geany als Editor und das Paket 'python-reportlab' ist installiert.
Beim Ausführen obigen Codes, kommen keine Fehler.

Grüße Nobuddy
BlackJack

@Nobuddy: Und was ist jetzt die konkrete Frage‽
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo BlackJack,

sorry ... die ist wohl untergegangen. :wink:

Ich möchte Rechnung und Lieferschein nach dem Layout erstellen, das ich schon vor langem in MS Access erstellt habe und benutze.

Was mich zuerst interessiert:
- Gibt es ausführliche Infos zu den verschiedenen Styls (Layouts)?

Es kommen da bestimmt noch etliche Fragen, aber zuerst ein Schritt nach dem anderen. :wink:

Grüße Nobuddy
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Nach etwas Einarbeitung in reportlab, gibt es schon erste Erfolge. :)

Wo ich jetzt Hilfe bräuchte, wäre das Ändern der Schriftart und Schriftgröße.
Beispiel:

Code: Alles auswählen

        self.story.append(Paragraph('{}, {}, {} {}'.format(FIRMA,
            FIRMA_STREET, FIRMA_PLZ, FIRMA_ORT),
            self.style['Normal']))

So funktioniert die Ausgabe, mit 'self.style['Normal'].fontSize['Helvetica', 8]' aber nicht.

Grüße Nobuddy
BlackJack

@Nobuddy: „Funktioniert nicht” ist keine ausreichende Fehlerbeschreibung.

Code: Alles auswählen

In [56]: style['Normal'].fontSize['Helvetica', 8]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-56-65829e074c0f> in <module>()
----> 1 style['Normal'].fontSize['Helvetica', 8]

TypeError: 'int' object is not subscriptable
Also mal schauen wie die einzelnen Zwischenergebnisse aussehen:

Code: Alles auswählen

In [57]: style['Normal']
Out[57]: <ParagraphStyle 'Normal'>

In [58]: style['Normal'].fontSize
Out[58]: 10
Und schon ist klar was da schief läuft: ``10['Helvetica', 8]`` ist kein sinnvoller Ausdruck weil man, wie die Ausnahme ja deutlich sagt, auf ganze Zahlen in Python nicht per [] zugreifen kann. Und selbst wenn man das könnte (es gibt Sprachen wo man so die einzelnen Bits abfragen kann) macht das Tupel ``'Helvetica, 8`` sehr wenig Sinn. Was sollte da auch als Ergebnis heraus kommen?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Sorry, daß ich das hier 'TypeError: 'int' object is not subscriptable' vorenthalten habe.

Wenn ich das richtig verstehe, müßte bei 'self.style['Normal']', 'Normal' durch Small, Little oder so ersetzt werden.
Habe dies mal versucht, komme da aber auf keinen grünen Zweig.
Wenn dies auch nicht der richtige Weg ist, wie dann ... ?

PS: Nachtrag
Hab dies hier http://docutils.sourceforge.net/sandbox ... lesheet.py gefunden, was mir weiter geholfen hat.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

nee, falsch verstanden.

"Normal", "BodyText" etc. sind die Namen der vordefinerten Styles.

Deren Attribute kannst du z.B. ändern, wie von BlackJack gezeigt. Wenn du _zusätzliche_ Styles brauchst, dann musst du die selber anlegen. Das ist aber recht einfach, siehe z.B.: http://thejaswi.info/tech/blog/2010/11/ ... reportlab/.

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

Danke für Deine Info,

das mit den Attributen ändern, habe ich jetzt verstanden.

Schriftgröße ändern:

Code: Alles auswählen

self.style['Normal'].fontSize = 12
Das geht dann auch wohl mit:
self.style['Normal'].fontName = '*****'
self.style['Normal'].leading = **
self.style['Normal'].spaceBefore = *
self.style['Normal'].spaceAfter = *)
Das mit den zusätzlichen Styles, da muß ich mich noch etwas mehr einarbeiten.
Werde da aber später nochmals darauf zurück kommen.

Grüße Nobuddy
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Als nächstes stehe ich vor dem Problem, Rechnungsdaten tabellarisch auszugeben.
Insgesamt sind es 7 Spalten.
Dabei ist in einer Spalte, langer Text der Zeilenumbruch erfordert, was sich ja mit 'Paragraph' realisieren lässt.
Zusätzlich werden horizontale und vertikale Linien, wie in einer Tabelle zur Texteingrenzung benötigt.
Mit tkinter und Canvas, wäre das kein Problem, nur wie muß ich das in reportlab umsetzen?

Grüße Nobuddy
BlackJack

@Nobuddy: `reportlab.platypus.Table` hast Du Dir schon angesehen?
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Nein, habe ich noch nicht, werde dies gleich tun!

Danke :wink:
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

In der Dokumentation von reportlab, komme ich bei 'reportlab.platypus.Table' zu keinem Ergebnis.
Problematisch ist diese Doku auch, da keine aktuelle Python-Version verwendet wird.

Hier http://www.blog.pythonlibrary.org/2010/ ... th-python/ aber ist ein schönes Beispiel.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

Chapter 7 in der ReportLab Doku befasst sich nur mit Tabellen. Da gibt auch viele Beispiele.

Wobei ich immer länger gebraucht habe, die Styles für die Tabelle fest zu legen als sonst was. Wie bei anderen Sachen auch kennt ReportLab da bergeweise Optionen.

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

noisefloor Danke,

beim Suchen, bin ich bei Chapter 9 gelandet, das war wohl nicht das Richtige. :wink:

Werde mal das Kapitel durcharbeiten, das sieht schon eher aus, was ich brauche.

Grüße Nobuddy
BlackJack

Ich hab's selbst noch nicht benutzt, aber es gibt von den Zope-Leuten eine Implementierung von RML unter der ZPL.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ich benutzte RL (also die Open Source Version) für ein Tool, was wir im Intranet in der Firma einsetzen. Produziert sehr schöne PDFs :-)

Die RML ist doch AFAIK nur in RL Plus enthalten, was kostenpflichtig ist?

Das eigentlich Problem mit ReportLab ist IMHO so wie so die Doku. Die ist zwar weitestgehend vollständig, aber in Sachen Struktur, Verständlichkeit und Beispielen manchmal ein bisschen durchschnittlich. Das macht gerade den Einstieg nicht unbedingt einfacher.

Gruß, noisefloor
BlackJack

@noisefloor: Das RML von reportlab.com ist kostenpflichtig, die Implementierung von den Zope-Leuten nicht. ;-) Ich weiss halt nicht wie vollständig die RML implementiert haben und/oder ob es andere Unterschiede gibt die problematisch sein können. Ich hatte mir das nur mal notiert das ich mir das anschaue wenn ich irgendwann mal wieder PDFs mit `reportlab` generieren muss.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ja, .... das dauert etwas, bis man in reportlab den Durchblick hat. :wink:

Habe mal hier was zusammengestellt, zuerst mal ohne class & Co.

Code: Alles auswählen

from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, cm
from reportlab.platypus import Paragraph, SimpleDocTemplate, Table
from reportlab.lib.styles import getSampleStyleSheet

filename = "/pfad/zu/reportlab/table.pdf"
#Definieren der Styles
style = getSampleStyleSheet()
doc = SimpleDocTemplate(filename, pagesize=A4)
# Daten für Tabelle
data= [['001', '50', 'STÜCK', 'TEST', 'TEST ENTHÄLT TEXT, DER SEHR LANG IST UND WEIL ERSO LANG IST, MUSS DIESER UMGEBROCHEN WERDEN', '0.75', '37.50'],
       ['002', '5', 'STÜCK', '4711ABC', 'KARTOFFELCHIPS', '0.75', '3.75'],
       ['003', '50', 'STÜCK', '9999ABC', 'BLEISTIFT HB', '0.25', '12.50'],
       ['004', '1', 'PALETTE', '750089123', 'KOPIERPAPIER A4', '700.00', '700.00']]
# Formatierung bei überlangem Text
data_format = list()
for pos, me, ve, article, text, vk, vk_ges in data:
    text = Paragraph(text,  style["BodyText"])
    data_format.append([pos, me, ve, article, text, vk, vk_ges])
# Erstellen von Tabellengitter, Ausrichtung der Spalten und Zeilen
t=Table(data_format, style=[
    ('GRID',(0,0),(-1,-1),0.5,colors.black),
    ('VALIGN',(0,0),(-1,-1),'TOP'),
    ('ALIGN',(1,0),(1,-1),'RIGHT'),
    ('ALIGN',(5,0),(5,-1),'RIGHT'),
    ('ALIGN',(6,0),(6,-1),'RIGHT'),
    ])
# Definition der Breite zu den einzelnen Spalten
t._argW[0]=1*cm
t._argW[1]=1.5*cm
t._argW[2]=2*cm
t._argW[3]=3*cm
t._argW[4]=7*cm
t._argW[5]=2*cm
t._argW[6]=2*cm
# container for the 'Flowable' objects
elements = []
elements.append(t)
# write the document to disk
doc.build(elements)
Die Spalten und Zeilen sind entsprechend ausgerichtet.

Bis ich dann, das Ganze so habe, wie ich es benötige, wird noch ein Weilchen dauern. :wink:

Für Tips habe ich immer ein offenes Ohr.

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

Hallo,

du kannst du Breite der Spalten auch direkt beim Aufruf der `Table()` Funktion übergeben.

Folgendes sollten Funktionieren (ungetestet):

Code: Alles auswählen

...
widths=(1*cm, 1.5*cm , 2*cm, 3*cm, 7*cm, 2*cm, 2*cm)
t=Table(data, colWidths=widths, style=[...])
...
Ist IMHO eleganter als deine aktuelle Lösung.

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

Ja, das hat mich auch schon gestört.
Danke für den Tip, funktioniert. :wink:

Was mich noch beschäftigt.
Ich habe eine Standard-PDF mit reportlab gebaut, wo Firmenlogo, Absende-, Ziel- und Liefer-Adresse, sowie eine Fußzeile mit den Firmendaten in einem Canvas erstellt.

Code: Alles auswählen

self.pdf = Canvas(self.filename, pagesize=self.print_format(format))
Nun ist mir noch nicht klar, wie ich die erstellte Tabelle, da übergeben kann.

Grüße Nobuddy
Antworten