docxtpl, xml Teil nimmt nur den Wert vom ersten durchlauf einer Schleife

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
Mueller.D
User
Beiträge: 33
Registriert: Freitag 13. Januar 2017, 10:04

Hallo ich bin es wieder :D,

ich möchte mit meinem py Programm eine Word Datei bearbeiten. So weit alles funktionsfähig.
Im XML Teil 'content' übernimmt er nur den Wert des ersten Durchlaufs.
Wie geht es, dort auch die anderen werte zu bekommen?

Kurz zu meinem Programm:
Aus einer Datenbank bekomme ich werte. Für jeden Wert wird eine neue docx erstellt. Der Wert IN der docx soll gleich heißen, als der Name der docx.

Meine Lösung Beispiel:
1_Test.docx --> 1. Zeile steht 1
2_Test.docx --> 1. Zeile steht 1
3_Test.docx --> 1. Zeile steht 1
4_Test.docx --> 1. Zeile steht 1

Meine Lösung Ziel:

1_Test.docx --> 1. Zeile steht 1
2_Test.docx --> 1. Zeile steht 2
3_Test.docx --> 1. Zeile steht 3
4_Test.docx --> 1. Zeile steht 4

Mein Beispiel Code:

Code: Alles auswählen

from docxtpl import DocxTemplate
import cx_Oracle

doc = DocxTemplate('tpl.docx')

con = cx_Oracle.connect('......')
cur = con.cursor()

i = 0
j = 10 #Es sollen 9 docx erstellt werden
k = j - 1

eintrag = cur.execute('.......')
result = cur.fetchall()
cur.close()

nummern = []

while i < k:

    for data in result:
        nummern.append(str(data[0]))
    
    artikel = materialnummern[i]
         
    #docxtpl
    context = {
        'article' : artikel,
    }
    
    doc.render(context)
    
    #abspeichern
    alterNamedocx = '_tpl.docx'
    neuerNamedocx =  artikel + alterNamedocx
    doc.save(neuerNamedocx)
    
    i = i + 1 


Ich hoffe es ist einigermaßen ersichtlich was ich machen möchte.
Zuletzt geändert von Anonymous am Freitag 20. Januar 2017, 15:45, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

Die Datenbankverbindung wird nicht wieder geschlossen. An der Stelle bietet sich die ``with``-Anweisung zusammen mit `contextlib.closing()` an.

Warum ist j = 10 mit der zusätzlichen Bemerkung das 9 Dokumente erzeugt werden sollen. Würde es da nicht Sinn machen `j` nicht an 10 sondern an 9 zu binden und vielleicht `document_count` zu nennen, damit man sich den Kommentar sparen kann?

Anstelle der ``while``-Schleife würde man eine Schleife über die Elemente von `materialnummern` schreiben, oder zumindest über die ersten 9 Elemente davon (`itertools.islice()`).

Sollte `materialnummern` nicht eigentlich `nummern` heissen? Oder umgekehrt? Und welchen Sinn macht das *innerhalb* der Schleife in der die Dokumente erzeugt werden immer wieder `nummern` um das gleiche Datenbankergebnis zu erweitern‽

Der Code sollte wahrscheinlich eher irgendwie so aussehen:

Code: Alles auswählen

from contextlib import closing
from itertools import islice
import cx_Oracle
from docxtpl import DocxTemplate


def main():
    document_count = 9
    
    with closing(cx_Oracle.connect('......')) as connection:
        with closing(connection.cursor()) as cursor:
            cursor.execute('.......')
            materialnummern = [str(row[0]) for row in cursor.fetchall()]
     
    document = DocxTemplate('tpl.docx')
    for artikel in islice(materialnummern, document_count):
        document.render({'article': artikel})
        document.save(artikel + '_tpl.docx')


if __name__ == '__main__':
    main()
Wobei ich die Dokumentanzahl wahrscheinlich bei der Datenbankabfrage schon berücksichtigen würde falls Oracle so etwas wie LIMIT unterstützt.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Zumindest `islice` könnte man vorziehen:

Code: Alles auswählen

def main():
    document_count = 9
   
    with closing(cx_Oracle.connect('......')) as connection:
        with closing(connection.cursor()) as cursor:
            cursor.execute('.......')
            materialnummern = [str(row[0]) for row in islice(cursor, document_count)]
     
    document = DocxTemplate('tpl.docx')
    for artikel in materialnummern:
        document.render({'article': artikel})
        document.save(artikel + '_tpl.docx')
Mueller.D
User
Beiträge: 33
Registriert: Freitag 13. Januar 2017, 10:04

Danke für eure Antworten, allerdings kommt bei euren Codes das gleiche raus als bei mir.

Ich weiß nicht ob ich es doch falsch erklärt habe. Mein Ziel ist es mehrere Rechnungen auszudrucken / abzuspeichern. In einer Datenbank sind beispielsweise zehn Rechnungen hinterlegt. Die sollen automatisch generiert werden. Damit ich die Rechnung wieder finde, soll es mir in den Namen die Rechnungsnummer abspeichern (bsp. nr101.docx, nr102.docx, ....). Das funktioniert ja soweit. Allerdings soll in dem Dokument wieder die gleiche Rechnungsnummer stehen, also genau so wie das Dokument heißt. So kann beispielsweiße ein Kunde mir seine Rechnungsnummer sagen und ich kann die .docx Datei in meinem Ordner suchen. Aktuell steht in jedem Dokument die gleiche Nummer.
BlackJack

@Mueller.D: Dann vermute ich mal das man mit `render()` die Platzhalter in dem Dokument ersetzt. Die sind danach weg und durch die Werte ersetzt. Ein weiteres `render()` auf dem selben Objekt würde dann natürlich keinen Effekt haben.
Antworten