python und dokumente

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.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Ich stehe gerade vor einem Problem und weiß nicht genau, wie ich anfangen soll. Ich möchte gerne eine Art Rundbrief programmieren. Das ganze soll so aussehen, das hinterher rtf, OpenOffice Dokumente dabei raus kommen. Jetzt weiß ich nicht genau, welche Anbindung für Python am besten ist. Ich habe einige Textbausteine, die zufällig zusammen gewürfelt werden ( das sollste für mich kein Problem sein ). Aber wie erstelle ich daraus ein OpenOffice Dokument oder eine rtf Datei? Ein Problem ist, das ich auch so etwas, wie ein Briefkopf in diesem Dokument haben möchte, wie zum Beispiel eine Datumsangabe, Name, Anschrift und so weiter. Ich kann mich erinnern, das man unter Word, Makros programmieren konnte und in dem Text Dokument befanden sich Variablen, die man dann per Makro beschreiben konnte. Ich würde das gerne unter Python programmieren, weiß aber nicht genau, wie und mit welchen Modulen das möglich wäre. Die Dokumente sollen bearbeitbar sein wenn sie erstellt worden sind und da würde das pdf Format raus fallen.
Ist es also möglich, aus einer rtf Vorlage, mehere Dokumente zu erstellen, in dem man Text und Anschrift usw. per Python ändern kann?
Vielleicht hat jemand von Euch so was schon gemacht.

Sven
BlackJack

@The Hit-Man: Zum programmatischen erstellen von OpenOffice-Dokumenten gab's hier neulich schon einmal ein Thema von jemandem der Reports erstellen wollte. Schmeiss mal die Suche an.

Man kann Makros für OpenOffice neben StarBASIC und Java auch in Python programmieren. Die nötigen Schnittstellen sollten eigentlich bei OO schon dabei sein!? Ist aber IMHO recht hässlich weil die API ziemlich umständlich ist und sehr stark nach Java riecht. Da würde ich dann doch eher gleich Java nehmen als "javaesque" in Python programmieren zu müssen.

Es gibt soweit ich weiss mindestens zwei Python-Module die zum verarbeiten von ODF-Dateien ohne OO geschrieben wurden. Eins davon ist odfpy, das andere fällt mir leider gerade nicht ein. :-(

Ansonsten sind die Dokumente hauptsächlich XML-Dateien in einem ZIP-Archiv. Man kann also auch direkt das XML bearbeiten, wenn das einfacher erscheint. Also zum Beispiel im OO-Writer die von Dir schon erwähnten Variablen verwenden und auf Dummy-Werte setzen und die verschiedenen Textblöcke einfach hinschreiben und ihnen eine jeweils entsprechend benannte Absatzformatierung verpassen. Dann kann man im XML schauen wie die Variablenwerte gespeichert werden und sie ersetzen, und die Absätze anhand der Absatzformatierung identifizieren und alle Varianten löschen, die man nicht im generierten Dokument haben möchte.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

das hört sich so weit schon mal ganz gut an, das die OO Dokumente aus xml bestehen. Ist ne gute Idee nen Dummy zu erstellen ( ist ja dann das Vorlagendokument ) und dann zu schauen, wo was abgespeichert wird. Dann muß ich mich mal nen bischen schlau machen im OpenOffice, denn ich persönlich kann da gerade mal nen Brief oder so drin schreiben ;)
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

wenn es ein Rundschreiben werden soll, würde ich (...) PDF nehmen. Oder muss es vom Empfänger editierbar sein?

PDF hat den grandiosen Vorteil, dass du es mit Python + ReportLab schön einfach erstellen kannst.

Gruß, noisefloor
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Oder den Weg über LaTeX mit einer Template-Engine (und der scrlttr2 Klasse).
Dies hat den Vorteil, dass die Schreiben typografisch wirklich perfekt sind.

Das könntest du sogar ohne Python-Umweg lösen, mit LaTeX hat man unter anderem auch die Möglichkeit, Serienbriefe mit Hilfe eines Datenbankzugriffes automatisch zu generieren.
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
BlackJack

Ich möchte noch einmal auf folgenden Satz aus dem ersten Beitrag hinweisen: "Die Dokumente sollen bearbeitbar sein wenn sie erstellt worden sind und da würde das pdf Format raus fallen."

LaTeX ist auch nur bedingt bearbeitbar, zum Beispiel für die durchschnittliche Büroschreibkraft eher nicht.
problembär

The Hit-Man hat geschrieben:Aber wie erstelle ich daraus ein OpenOffice Dokument ... ? Ein Problem ist, das ich auch so etwas, wie ein Briefkopf in diesem Dokument haben möchte, wie zum Beispiel eine Datumsangabe, Name, Anschrift ...
1. Mit OpenOffice eine Dokumentvorlage (.odt) erstellen.
2. Dabei Textmarken einfügen.
3. Diese per Python-Skript anspringen und Text einfügen. Dazu dies lesen und ggf. verwenden.
Ist es also möglich, aus einer rtf Vorlage, mehere Dokumente zu erstellen, in dem man Text und Anschrift usw. per Python ändern kann?
rtf scheint mir nicht so geeignet, um Daten bereitzustellen. Verwende dafür lieber reine Textdateien.

Gruß

P.S.: Ich für mich bin inzwischen auf LaTeX/scrlttr2 umgestiegen.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Ich werde es dann mit dem OO xml Format versuchen. Bin mir nur noch nicht ganz sicher, ob ich jetzt Python oder C# nehme. Hatte gestern mit nem Kollegen telefoniert, falls ich da mal hängen würde, könnte er mir dann helfen, allerdings in C#. Ich hatte die Tage mal mit Python und xml herumgespielt. Das anlegen von xml Dokumenten und einfügen von Knoten und so weiter, ist unter Python kein Thema, aber hatte keine vernünftige Anleitung dazu gefunden, die Atribute, wenn sie dann im xml Dokument sind, auszutauschen. Die Beispiele, die ich gefunden hatte, haben nur das komplette xml immer ausgelesen, aber keine Werte gesetzt.

Sven
BlackJack

@The Hit-Man: De Facto-Standard ist bei XML-Verarbeitung in Python die `lxml`-Bibliothek. Damit geht das ganz einfach:

Code: Alles auswählen

In [1154]: doc = etree.XML('<root><tag answer="23" /></root>')

In [1155]: etree.dump(doc)
<root>
  <tag answer="23"/>
</root>

In [1156]: doc.find('tag').get('answer')
Out[1156]: '23'

In [1157]: doc.find('tag').set('answer', '42')

In [1158]: etree.dump(doc)
<root>
  <tag answer="42"/>
</root>
Der Inhalt eines Tags ist als `text`-Attribut auf den Element-Objekten. Das Attribut kann man einfach abfragen oder auch neue Werte zuweisen.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Danke. Das ist ja einfach ;)

EDIT:
ja, in meinen Beispielen haben, die immer den miniDom genommen und dann mit regulären Ausdrücken da rum gewurschelt. Hatte mich schon gewundert, das ist ja bei xml gar nicht nötig.
Ähm, wird der Tag eigentlich auch gefunden, wenn dieser im Unterknoten liegt? Also in deinem Beispiel unter root mein knoten answer?
problembär

Find' ich nicht schwieriger und berücksichtigt mehrere Tags 'tag':

Code: Alles auswählen

>>> import xml.dom.minidom
>>> doc = xml.dom.minidom.parseString('<root><tag answer="23" /></root>')
>>> print doc.toprettyxml()
<?xml version="1.0" ?>
<root>
        <tag answer="23"/>
</root>

>>> print doc.getElementsByTagName('tag')[0].getAttribute('answer')
23
>>> doc.getElementsByTagName('tag')[0].setAttribute('answer', '42')
>>> print doc.toprettyxml()
<?xml version="1.0" ?>
<root>
        <tag answer="42"/>
</root>
IMHO bleibt XML aber trotzdem immer irgendwie Krampf.

@The Hit-Man: Viel Spaß, wenn Du einen komplexen OpenOffice-Briefkopf direkt über XML erzeugen willst. Oben gab's ja schon den Hinweise auf speziellere Module wie odfpy usw.. In Deinem Fall nach meiner Meinung aber immer noch unnötig. Was glaubst Du wohl, warum sie extra so'ne große Oberfläche und so'n Riesenpaket genannt OpenOfficeWriter gebaut haben, um solchen XML-Code zu erzeugen, wenn man diesen Code genauso leicht über Python mit XML erzeugen könnte?

Gruß
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

problembär hat geschrieben:IMHO bleibt XML aber trotzdem immer irgendwie Krampf.
Mit DOM sicherlich, mit lxml ist XML eigentlich ein recht annehmbares hierarchisches Datenformat.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@The Hit-Man: Deine Nachfrage verstehe ich nicht so ganz, weil `answer` ja bei lxml kein Knoten ist, sondern einfach nur ein Attribut auf dem jeweiligen Objekt, welches das Element repräsentiert.

Wenn ein einfaches `find()` nicht ausreicht, würde ich auf XPath zum identifizieren der gewünschten Knoten umsteigen.

Code: Alles auswählen

In [1172]: etree.dump(doc)
<root>
  <tag answer="23"/>
  <spam>
    <tag answer="42"/>
  </spam>
  <tag/>
  <eggs answer="parrot"/>
</root>

In [1173]: doc.xpath('//tag')
Out[1173]: [<Element tag at 9ac7874>, <Element tag at 9ac7a04>, <Element tag at 9ac7fa4>]

In [1174]: doc.xpath('//tag[@answer]')
Out[1174]: [<Element tag at 9ac7874>, <Element tag at 9ac7a04>]

In [1175]: doc.xpath('//tag[@answer=42]')
Out[1175]: [<Element tag at 9ac7a04>]

In [1176]: doc.xpath('//tag[@answer=$n]', n=42)
Out[1176]: [<Element tag at 9ac7a04>]

In [1177]: doc.xpath('//*[@answer]')
Out[1177]: [<Element tag at 9ac7874>, <Element tag at 9ac7a04>, <Element eggs at 9ac789c>]
1173: Alle `tag`-Elemente.
1174: Alle `tag`-Elemente die ein `answer`-Attribut besitzen.
1175: Alle `tag`-Elemente bei denen `answer` den Wert 42 hat.
1176: Wie 1175 nur mit einer Variablen.
1177: Alle Elemente die ein `answer`-Attribut besitzen.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

ich habe gerade Zeit gehabt, mir ein entpacktes .odt anzuschauen. Oh jeeee, das sieht ja mal echt kompliziert aus. Ich habe mir in das Dokument, Variablem per OpenOffice gesetzt, dann das content.xml geöffnet. Die ganze Beschreibung, liegt in einer Zeile und sieht ziemlich unübersichtlich aus. Ich habe meine Variablen in der content.xml gefunden, allerdings, habe ich jetzt mal keine Ahnung, wie ich die Variablen austauschen soll :(
BlackJack

@The Hit-Man: In den Optionen von OpenOffice gibt es unter Laden/Speichern→Allgemein ein Häkchen `XML Format auf Grösse optimieren`. Wenn man das wegnimmt, gibt's mehr Zeilen in der XML-Datei. Ansonsten lohnt es sich bei grösseren XML-Dateien einen spezialisierten Editor zu verwenden, der zum Beispiel auch die Baumstruktur anzeigt und damit die Navigation erleichtert.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Unter Datei -> Speichern unter? Da finde ich nichts.
BlackJack

@The Hit-Man: Nein bei den ganzen Programmoptionen: `Extras→Optionen…`.

Ich habe mir mal so ein Dokument angeschaut und einem Absatz eine neue, von dem normalen Textkörper erbende Textvorlage mit dem Namen "Speziell" verpasst, und ausserdem eine Variable mit dem Namen "antwort" verwendet. Folgendes Programm:

Code: Alles auswählen

from contextlib import closing
from zipfile import ZipFile
from lxml import etree


def main():
    with closing(ZipFile('test.odt')) as odt_file:
        doc = etree.fromstring(odt_file.read('content.xml'))
    
    paragraph_node = doc.xpath('//text:p[@text:style-name="Speziell"]',
                               namespaces=doc.nsmap)[0]
    print paragraph_node.text
    
    variable_nodes = doc.xpath('//text:variable-set', namespaces=doc.nsmap)
    for variable_node in variable_nodes:
        name = variable_node.get('{%s}name' % doc.nsmap['text'])
        value = variable_node.get('{%s}value' % doc.nsmap['office'])
        print '%s = %r' % (name, value)
Hat diese Ausgabe mit dem Dokument:

Code: Alles auswählen

$ python forum5.py
Und noch ein Absatz.
antwort = '23'
XML-Namensräume sind ein wenig nervig, aber das kann man ja Notfalls in eigene Funktionen kapseln.
problembär

The Hit-Man hat geschrieben:ich habe gerade Zeit gehabt, mir ein entpacktes .odt anzuschauen. Oh jeeee, das sieht ja mal echt kompliziert aus.
Sag' ich ja ;).
BlackJack hat geschrieben:Ansonsten lohnt es sich bei grösseren XML-Dateien einen spezialisierten Editor zu verwenden, der zum Beispiel auch die Baumstruktur anzeigt und damit die Navigation erleichtert.
Unter Linux nutze ich "kxmleditor". Gefällt mir ganz gut. Ist allerdings insoweit recht rabiat, als er gar nicht erst startet, wenn er meint, die xml-Datei sei nicht "wohlgeformt".

Gruß
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

@BlackJack
ich habe dein Beispiel mal ausprobiert und an mein odt angepaßt. sprich, bei mir heißt das dann nicht "Speziell", sondern "Standart". Allerdings bekomme ich schon da ein "out of range", obwohl der Tag vorhanden ist. Die Variablen hatte ich dann erst mal auskommentiert, zum testen.
BlackJack

@The Hit-Man: Ich gehe mal davon aus, dass das jetzt nur ein Tippfehler war und Du eigentlich "Standard" meintest. Die bereits vorhandenen Formate haben in der GUI allerdings andere Namen als im XML. Ich nehme mal an, damit die Namen im XML unabhängig von der Sprache sind. Also damit der typische Text in der Datei immer den gleichen Formatnamen hat, in der GUI aber je nach eingestellter Systemsprache zum Beispiel als "text body" oder "Textkörper" angezeigt wird. Du müsstest also schon im XML mal nachschauen was da wirklich als Name steht.
Antworten