Mit for-Schleife in Excel Tabelle schreiben

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.
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Moin liebes Forum,

zur Zeit schreibe ich ein Script, das mir helfen soll aus einer Excel Tabelle Daten zu entnehmen und diese in eine neue Excel Vorlage nach einem bestimmte Muster zu sortieren.

Bisher bin ich ganz zufrieden mit meinem Script bzw. mit der Funktion und es macht auch das was es soll. Mein Problem liegt nur in der Anzahl der Signale. Ich würde mein Vorhaben gerne in eine Schleife packen aber ich weiß nicht, ob das in meinem Fall überhaupt möglich ist. Ich versuche erst einmal so gut es geht zu erklären, was mein Script machen soll.

In der ersten Abbildung seht ihr die Tabelle 1, die ich von einer Software in diesem Format erhalte und aus der die Informationen entnommen und in die Vorlage aus Abbildung 2 geladen werden soll. In Abbildung 3 seht ihr wie das Endergebnis aussehen soll. Ich habe die Zellen markiert, damit man besser erkennen kann an welche Stelle die Zellen aus Tabelle 1 in Tabelle 3 hinkommen sollen.

Generell geht es darum, dass mit einem Signal (zB Signal_1) bestimmte Tests durchgeführt werden. Das Skript soll prüfen, welche Tests (Spalte „G“, Tabelle 1) für das Signal aus Spalte „C“ (Tabelle 1) vorliegen. Wenn bspw. für Signal_1 der "Test F" vorliegt, hat dieser Test eine ID, die in Spalte „A“ (Tabelle 1) vorliegt. Wichtig ist nun, dass diese ID in die Vorlage an die richtige Stelle geladen wird.
Im Script sind Kommentare enthalten, die euch hoffentlich helfen zu verstehen was Sache ist.

Tabelle 1:Das ist die Tabelle, aus der die Daten in die Vorlage geladen werden sollen https://ibb.co/zQwJSsT
Tabelle 2: Das ist die Vorlage https://ibb.co/hDzHT9m
Tabelle 3: So soll das ganze am Ende aussehen https://ibb.co/37v1vsW


Code: Alles auswählen

 from openpyxl import Workbook, load_workbook

workbook_can = load_workbook('C:/Users/t3wa893/PycharmProjects/TestProject/venv/tab_1.xlsx')
signal_sheet = workbook_can['boolean']


template_workbook = load_workbook('C:/Users/t3wa893/PycharmProjects/TestProject/venv/'
                                  'Vorlage_Schnittstellentest_Eingang_Signalmatrix.xlsx')
template_sheet = template_workbook.active


# Signalbezeichnung "Signal_1" wird in die Vorlage geladen
template_sheet['C9'] = (signal_sheet['C1'].value)

# im folgenden wird geprüft, an welcher Stelle sich für Signal_1 der "Test A" befindet
# wenn der Test gefunden wird, wird die Test ID in die Vorlage in die entsprechende Zelle geladen

if signal_sheet['G1'].value == "Test A":
    print("Test A gefunden G1!")
    template_sheet['D9'] = (signal_sheet['A1'].value)      # Test_ID_1 wird in die Vorlage geladen
elif signal_sheet['G2'].value == "Test A":
    template_sheet['D9'] = (signal_sheet['A2'].value)
    print("Test A gefunden G2!")
elif signal_sheet['G3'].value == "Test A":
    template_sheet['D9'] = (signal_sheet['A3'].value)
    print("Test A gefunden G3!")
elif signal_sheet['G4'].value == "Test A":
    template_sheet['D9'] = (signal_sheet['A4'].value)
    print("Test A gefunden G4!")
elif signal_sheet['G5'].value == "Test A":
    template_sheet['D9'] = (signal_sheet['A5'].value)
    print("Test A gefunden G5!")
elif signal_sheet['G6'].value == "Test A":
    template_sheet['D9'] = (signal_sheet['A6'].value)
    print("Test A gefunden G6!")
elif signal_sheet['G7'].value == "Test A":
    template_sheet['D9'] = (signal_sheet['A7'].value)
    print("Test A gefunden G7!")
else:
    print("Test A nicht gefunden.")

# jetzt wird für das selbe Signal nach "Test B" gesucht

if signal_sheet['C2'].value == signal_sheet['C1'].value:    # If-Abfrage, ob das Signal noch das selbe ist
    if signal_sheet['G1'].value == "Test B":
        print("Test B gefunden G1!")
        template_sheet['E9'] = (signal_sheet['A1'].value)
    elif signal_sheet['G2'].value == "Test B":
        template_sheet['E9'] = (signal_sheet['A2'].value)
        print("Test B gefunden G2!")
    elif signal_sheet['G3'].value == "Test B":
        template_sheet['E9'] = (signal_sheet['A3'].value)
        print("Test B gefunden G3!")
    elif signal_sheet['G4'].value == "Test B":
        template_sheet['E9'] = (signal_sheet['A4'].value)
        print("Test B gefunden G4!")
    elif signal_sheet['G5'].value == "Test B":
        template_sheet['E9'] = (signal_sheet['A5'].value)
        print("Test B gefunden G5!")
    elif signal_sheet['G6'].value == "Test B":
        template_sheet['E9'] = (signal_sheet['A6'].value)
        print("Test B gefunden G6!")
    elif signal_sheet['G7'].value == "Test B":
        template_sheet['E9'] = (signal_sheet['A7'].value)
        print("Test B gefunden G7!")
    else:
        print("Test B nicht gefunden.")

## Das muss ich nun für das selbe Signal mehrmals tun bis ich bei "Test F" angekommen bin

## Anschließend muss ich prüfen, ob ein weiteres Signal vorhanden ist. Wenn dies der Fall ist,
## wird dies in der Vorlage in die nächste Zeile geschrieben und der Vorgang wird für alle Tests wiederholt

if signal_sheet['C8'].value is None:                                     ######## If-Abfrage, ob weiteres Signal bei boolean vorhanden ist
    print("kein zweites Signal bei boolean vorhanden")
else:
    template_sheet['C10'] = (signal_sheet['C8'].value)               # Signalbezeichnung "Signal_2" wird in die Vorlage geladen
    if signal_sheet['G8'].value == "Test A":
        print("Test A gefunden G8!")
        template_sheet['D10'] = (signal_sheet['A8'].value)
    elif signal_sheet['G9'].value == "Test A":
        template_sheet['D10'] = (signal_sheet['A9'].value)
        print("Test A gefunden G9!")
    elif signal_sheet['G10'].value == "Test A":
        template_sheet['D10'] = (signal_sheet['A10'].value)
        print("Test A gefunden G10!")
    elif signal_sheet['G11'].value == "Test A":
        template_sheet['D10'] = (signal_sheet['A11'].value)
        print("Test A gefunden G11!")
    elif signal_sheet['G12'].value == "Test A":
        template_sheet['D10'] = (signal_sheet['A12'].value)
        print("Test A gefunden G12!")
    elif signal_sheet['G13'].value == "Test A":
        template_sheet['D10'] = (signal_sheet['A13'].value)
        print("Test A gefunden G13!")
    elif signal_sheet['G14'].value == "Test A":
        template_sheet['D10'] = (signal_sheet['A14'].value)
        print("Test A gefunden G14!")
    else:
        print("Test A für das 2. Signal nicht gefunden.")

# An der Stelle würde anschließend weitergehen mit der Suche nach Test B, C, D, E und F

template_workbook.save('C:/Users/t3wa893/PycharmProjects/TestProject/venv/Ergebnis.xlsx')

Wenn man ein wenig verstanden hat, was ich hier vorhabe, bemerkt man schnell, dass das Skript bei z.B. 20 verschiedenen Signalen sehr lang werden würde.
Ich hoffe, dass ich das halbwegs vernünftig geschildert habe
Da ich nun immer genaue Zellen "ansprechen" muss, weiß ich nicht, ob es möglich ist mein Vorhaben in eine for-Schleife zu stecken.
Habt ihr da vielleicht eine Idee?

Vielen Dank im Voraus!!
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krystek: Ich finde das ziemlich unübersichtlich und der Code passt ”optisch” so überhaupt nicht zur Ausgangsdatei. Das scheint ja eine saubere, im Sinne von „tidy data“, Tabelle zu sein, die man erst einmal einfach zeilenweise *auslesen* könnte in eine entsprechende Datenstruktur. Und dann ist das mit der Eingabedatei gegessen. Die braucht man dann nicht mehr.

Als nächstest müsste man schauen die die Datenstruktur aussehen muss, damit sie zum füllen der Vorlage geeignet ist und dann entsprechend so eine Struktur erstellen.

Und damit kann man dann die Vorlage füllen.

Das wären also mindestens schonmal drei kleine Funktionen die jeweils eine sauber getrennte Aufgabe erfüllen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Vielen Dank für deine Antwort.

Ja du hast recht. Der Code passt nicht zum Ergebnis aus der Abbildung, da ich diesen gekürzt habe. Durch die vielen Test wäre der Code sehr lang gewesen.
Das Ergebnis sieht so aus https://ibb.co/jghXm0T

Und meinst du meinen Code unübersichtlich oder meine Beschreibung?
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krystek: Der Code ist unübersichtlich. Wenn ich die Ausgangstabelle nicht gesehen hätte, wäre ich durch kurzes drauf schauen auf den Code nicht darauf gekommen wie regelmässig die Tabelle aufgebaut ist. Da hätte ich gedacht die muss megakompliziert/unregelmässig aufgebaut sein, wenn man da so viele ``if``-Anweisungen braucht. Die braucht man ja letztlich auch gar nicht, wenn man da nicht so komisch/umständlich dran gehen würde, sondern die einfach erst einmal Zeilenweise ausliest und in eine passende Datenstruktur steckt. Beispielsweise ein Wörterbuch das Signalnamen auf Wörterbücher abbildet die Werte aus der letzten Spalte auf IDs aus der ersten Spalte abbildet. `collections.defaultdict` könnte ein Baustein in so einem Ansatz sein.

Oder, falls die Signalnamen immer in Blöcken zusammen stehen, kann man sich eine Funktion schreiben welche die Zeilendaten generiert und benutzt dann `itertools.groupby()` um die Blöcke zu gruppieren. Dann hat man das Problem „eine Tabelle mit verschiedenen Signalnamen und Testnamen und IDs“ auf „ein Signalname mit dazugehörigen Testnamen und IDs“ reduziert und kann Code schreiben der *einen* Block abarbeitet und den dann einfach auf alle Blöcke anwenden. Eine immer wiederkehrende Tätigkeit beim Programmieren ist Probleme in kleinere, einfachere Teilprobleme zu zerlegen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Ich habe so viele if-Anweisungen, weil es sein kann, dass die Reihenfolge der Tests mal ganz anders ist. Oder es könnte auch vorkommen, dass für ein Signal nur 2 oder 3 Test vorhanden sind. Und das war nun meine Lösung abzufragen welche Tests vorhanden sind und an welcher Stelle sich die dazugehörigen IDs befinden, damit diese anschließend an die richtige Stelle in die Vorlage geladen werden können. Die Sache ist die, dass die Tabelle von mir jetzt für diesen Beitrag gekürzt und ein wenig vereinfacht worden ist.

Dann werde ich mal versuchen mich in deine Stichwörter einzulesen aber ehrlich gesagt habe ich deine Idee nicht wirklich verstanden.

Aber trotzdem vielen Dank!
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krystek: Dem Code muss Anzahl und Reihenfolge der Tests egal sein. Der muss das unabhängig davon verarbeiten können ohne ``if`` und schon gar nicht mit so vielen, die irgendwie versuchen jegliche mögliche Variante als Test hart in den Code zu schreiben. Gleiches für die Koordinaten. Es sollten keine festen Koordinaten vorkommen die nicht als Ankerpunkt für die Ermittlung der tatsächlich gemeinten Zelle(n) dient. Und zum auslesen braucht man bei dem Beispiel keine Koordinaten, jedenfalls nicht für die Zeilen, denn da iteriert man einfach über `rows` von dem Arbeitsblatt.

Kann man denn davon ausgehen, dass die Eingabedaten nach Signalen sortiert sind? Also in Spalte C die Signale in zusammenhängenden Blöcken stehen?

Und muss es tatsächlich eine Vorlagendatei geben? Das sieht doch da auch recht regelmässig aus und könnte per Code generiert werden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Genau! Die Signale stehen in zusammenhängenden Blöcken.

Und eine Vorlagedatei muss es nicht geben. Wenn die fertige Tabelle am Ende genauso aufgebaut ist wie im Screenshot, dann ist das egal, ob mit Vorlage oder nicht.

Wenn man sich die Reihenfolge der Signale in der Eingabedatei anschaut, erkennt man, dass die Reihenfolge der Tests in Spalte G der Reihe nach von A bis F geht. Es kann aber auch vorkommen, dass die Reihenfolge anders ist oder ein Test nicht vorhanden ist.
In der Ergebnisdatei MUSS die Reihenfolge allerdings wie folgt aussehen. A,B,C,E,D,G,F Wie löst man das dann ohne feste Koordinaten?

Daher hatte ich so viele If-Anweisungen, um die Positionen der Tests zu ermitteln, da die Reihenfolge nicht zwingend immer die gleiche ist.
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krystek: Heissen die Tests tatsächlich so, oder sind das Platzhalter für unregelmässigere Namen? Denn die Texte "Test A" bis "Test F" und auch die dazugehörigen Spalten im Zieldokument könnte man ja einfach im Programm generieren/berechnen. Ansonsten würde man die Namen ins Programm schreiben und die (relative) Zielspaltenposition mit der `list.index()`-Methode ermitteln können. Oder man erstellt sich ein Wörterbuch das Namen auf (relative) Zielspaltenposition abbildet.

Oder das löst sich ”von alleine” wenn man in dem Punkt angekommen ist wo man die Daten in das Zieldokument einträgt und eine Schleife über die Testnamen schreibt und die dazugehörige ID aus der Datenstruktur holt. In der Schleife kann man die Zielspaltenposition dann einfach per `enumerate()` mitgenerieren.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Die Tests haben andere Namen und können nicht generiert werden.
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Würdest du mir mit dem Wissen, das du hast, empfehlen eine Lösung mit itertools.groupby()` zu suchen?
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich weiss nicht, ob ich die Frage richtig verstehe. Programmieren ist ja zum grossen Teil Probleme in kleinere Teilprobleme zu zerlegen. Und das Problem die Quelldaten auszulesen und zu verarbeiten, kann man anscheinend ganz gut aufteilen in auslesen der Daten in eine ”2D”-Liste oder eine Liste mit Datenobjekten, damit man Attributnamen statt magischer Indexzahlen für die einzelnen Werte hat. Wenn man diesen ersten Schritt umgesetzt hat, ist man die Eingabedatei los, die spielt dann keine Rolle mehr.

Dann hat man also die ganzen Daten in einer Liste (oder einem Generator). Ein kleineres Teilproblem wäre dann sich nur die Daten für *ein* Signal anzuschauen. Denn was man da machen muss, ist für alle Signale gleich, also kann man das einmal in einer Funktion lösen, und diese Funktion dann auf alle Signale anwenden. Und dazu müsste man die Daten nach Signal gruppieren. Und dazu wäre `itertools.groupby()` ganz praktisch weil das genau für so eine Aufgabe gedacht ist.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import namedtuple
from itertools import groupby
from pathlib import Path
from pprint import pprint

from openpyxl import load_workbook

BASE_PATH = Path("C:/Users/t3wa893/PycharmProjects/TestProject/venv")
SOURCE_PATH = BASE_PATH / "tab_1.xlsx"

Test = namedtuple("Test", "id name signal_name")


def iter_tests(file_path):
    workbook = load_workbook(file_path)
    sheet = workbook["boolean"]
    return (
        Test(test_id_cell.value, test_name_cell.value, signal_name_cell.value)
        for (
            test_id_cell,
            _,
            signal_name_cell,
            _,
            _,
            _,
            test_name_cell,
        ) in sheet.rows
    )


def process_tests(tests):
    return (
        (signal_name, {test.name: test.id for test in tests})
        for signal_name, group in groupby(tests, lambda test: test.signal_name)
    )


def main():
    for signal_name, test_name_to_id in iter_tests(SOURCE_PATH):
        print(">", signal_name)
        pprint(test_name_to_id)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Hallo,

vielen Dank für deine Mühe!!

Leider verstehe ich noch nicht ganz was dein Code macht.

Wenn ich ihn teste, kommt folgende Fehlermeldung.

Traceback (most recent call last):
File "[/color]C:\Users\t3wa893\PycharmProjects\TestProject\main.py", line 45, in <module>
main()
File "C:\Users\t3wa893\PycharmProjects\TestProject\main.py", line 39, in main
for signal_name, test_name_to_id in iter_tests(SOURCE_PATH):
ValueError: too many values to unpack (expected 2)

weißt du was das zu bedeuten hat?
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Gut das ich da immer „ungetestet“ dazu schreibe wenn ich was nicht getestet habe. Da wird ja nirgends die `process_tests()`-Funktion aufgerufen. Die Zeile müsste so aussehen (ungetestet):

Code: Alles auswählen

    for signal_name, test_name_to_id in process_tests(iter_tests(SOURCE_PATH)):
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Vielen Dank für die Korrektur!

Ich versuche gerade zu verstehen, was dein Code genau macht.

Denn das Ergebnis ist folgendes:

> Signal_1
{'Test A': 'Test_ID_14',
'Test B': 'Test_ID_22',
'Test C': 'Test_ID_38',
'Test D': 'Test_ID_47',
'Test E': 'Test_ID_54',
'Test F': 'Test_ID_60',
'Test G': 'Test_ID_74'}

Wenn man sich Tabelle 1 anschaut, müsste Signal_3 dort stehen, da dies die Test ID für Signal 3 sind.
Kannst du mir vielleicht kurz erklären, warum das Ergebnis genau so aussieht und warum nicht z.B. die anderen Test IDs ausgegeben werden.

Das wäre sehr nett!
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krystek: Weil in `process_tests()` das Wörterbuch über alle `tests` erstellt wird und nicht nur für die Gruppe. Also noch mal komplett (und dieses mal getestet):

Code: Alles auswählen

#!/usr/bin/env python3
from collections import namedtuple
from itertools import groupby
from pathlib import Path
from pprint import pprint

from openpyxl import load_workbook

BASE_PATH = Path("C:/Users/t3wa893/PycharmProjects/TestProject/venv")
SOURCE_PATH = BASE_PATH / "tab_1.xlsx"
SOURCE_PATH = Path("test.xlsx")

Test = namedtuple("Test", "id name signal_name")


def iter_tests(file_path):
    workbook = load_workbook(file_path)
    print(workbook.sheetnames)
    sheet = workbook["boolean"]
    return (
        Test(test_id_cell.value, test_name_cell.value, signal_name_cell.value)
        for (
            test_id_cell,
            _,
            signal_name_cell,
            _,
            _,
            _,
            test_name_cell,
        ) in sheet.rows
    )


def process_tests(tests):
    return (
        (signal_name, {test.name: test.id for test in group})
        for signal_name, group in groupby(tests, lambda test: test.signal_name)
    )


def main():
    for signal_name, test_name_to_id in process_tests(iter_tests(SOURCE_PATH)):
        print(">", signal_name)
        pprint(test_name_to_id)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Vielen Dank für deine weitere Hilfe.

Was passiert bei dir in folgender Zeile?

Code: Alles auswählen

SOURCE_PATH = Path("test.xlsx")
Legst du hier einen neuen Namen fest? Zusammen mit dieser Zeile bekomme ich eine Fehlermeldung, die ich leider nicht verstehe.

Redeclared 'SOURCE_PATH' defined above without usage

File "C:\Users\t3wa893\PycharmProjects\TestProject\main.py", line 48, in <module>
main()
File "C:\Users\t3wa893\PycharmProjects\TestProject\main.py", line 42, in main
for signal_name, test_name_to_id in process_tests(iter_tests(SOURCE_PATH)):
File "C:\Users\t3wa893\PycharmProjects\TestProject\main.py", line 17, in iter_tests
workbook = load_workbook(file_path)
File "C:\Users\t3wa893\AppData\Local\Programs\Python\Python310\lib\site-packages\openpyxl\reader\excel.py", line 315, in load_workbook
reader = ExcelReader(filename, read_only, keep_vba,
File "C:\Users\t3wa893\AppData\Local\Programs\Python\Python310\lib\site-packages\openpyxl\reader\excel.py", line 124, in __init__
self.archive = _validate_archive(fn)
File "C:\Users\t3wa893\AppData\Local\Programs\Python\Python310\lib\site-packages\openpyxl\reader\excel.py", line 96, in _validate_archive
archive = ZipFile(filename, 'r')
File "C:\Users\t3wa893\AppData\Local\Programs\Python\Python310\lib\zipfile.py", line 1240, in __init__
self.fp = io.open(file, filemode)
FileNotFoundError: [Errno 2] No such file or directory: 'test.xlsx'



Ohne die oben genannte Zeile sieht es wie folgt aus:

> Signal_1
{'Test A': 'Test_ID_1',
'Test B': 'Test_ID_2',
'Test C': 'Test_ID_3',
'Test D': 'Test_ID_4',
'Test E': 'Test_ID_5',
'Test F': 'Test_ID_6',
'Test G': 'Test_ID_7'}
> Signal_2
{'Test A': 'Test_ID_12',
'Test B': 'Test_ID_23',
'Test C': 'Test_ID_33',
'Test D': 'Test_ID_47',
'Test E': 'Test_ID_53',
'Test F': 'Test_ID_69',
'Test G': 'Test_ID_71'}
> Signal_3
{'Test A': 'Test_ID_14',
'Test B': 'Test_ID_22',
'Test C': 'Test_ID_38',
'Test D': 'Test_ID_47',
'Test E': 'Test_ID_54',
'Test F': 'Test_ID_60',
'Test G': 'Test_ID_74'}
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krystek: Na ich habe halt Deinen Pfad nicht, also hatte ich mir eine Testdatei im aktuellen Arbeitsverzeichnis angelegt. Und dann halt vergessen das aus dem Programm wieder raus zu nehmen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

na logisch.... :oops:
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Moin,

ich bräuchte da noch einmal ein wenig Hilfe :oops:

Deine Lösung gefällt mir wirklich gut. Allerdings habe ich jetzt das Problem, dass ich die IDs in die entsprechenden Zeilen schreiben muss.
Ich habe in def main() ein for-Schleife hinzugefügt. Das ist mein Ansatz um das Problem zu lösen aber ich weiß nicht, ob mit dieser Schleife eine Lösung meines Problems möglich ist

Code: Alles auswählen

 
 
#!/usr/bin/env python3
from collections import namedtuple
from itertools import groupby
from pathlib import Path
from pprint import pprint

from openpyxl import Workbook, load_workbook
from openpyxl.utils import get_column_letter, column_index_from_string, coordinate_to_tuple

BASE_PATH = Path("C:/Users/t3wa893/PycharmProjects/TestProject/venv")
SOURCE_PATH = BASE_PATH / "tab_1.xlsx"

Test = namedtuple("Test", "id name signal_name")
print("ANFANG")
print(Test)
print("ENDE")
def iter_tests(file_path):
    workbook = load_workbook(file_path)
    print(workbook.sheetnames)
    sheet = workbook["boolean"]
    return (
        Test(test_id_cell.value, test_name_cell.value, signal_name_cell.value)
        for (
            test_id_cell,
            _,
            signal_name_cell,
            _,
            _,
            _,
            test_name_cell,
        ) in sheet.rows
    )


def process_tests(tests):
    return (
        (signal_name, {test.name: test.id for test in group})
        for signal_name, group in groupby(tests, lambda test: test.signal_name)
    )


def main():
    tab1_workbook = load_workbook('C:/tab_1.xlsx')
    tab_1_sheet = tab1_workbook.active

    template_workbook = load_workbook('C:/template.xlsx')
    template_workbook_sheet = template_workbook.active
    #template_workbook['D9'] = test_name_to_id["Test A"]


    for signal_name, test_name_to_id in process_tests(iter_tests(SOURCE_PATH)):
        print(">", signal_name)
        pprint(test_name_to_id)
        print(test_name_to_id["Test A"])
    

    
    for row in template_workbook_sheet.iter_rows(min_row=8, min_col=4, max_row=12, max_col=4):
        for cell in row:
            #print(cell.value, end=" ")
             template_workbook_sheet[D9] = test_name_to_id["Test A"]    	#Wie kann hier D9 als erste Zelle festgelegt werden? Im nächsten Schritt muss dann die ID von Test A und Signal 2 in D10 geschrieben werden usw.
        

    template_workbook.save('C:/tab_2.xlsx')

if __name__ == "__main__":
    main()
    
    
    
VG
Krystek
Krystek
User
Beiträge: 23
Registriert: Mittwoch 10. November 2021, 10:12

Ah und mir fällt ein, dass ich in Abhängigkeit der Anzahl der Signal neue Zeilen in die Vorlage laden muss.
Dementsprechend muss folgendes wohl auch in irgendeiner Form in die Schleife mit eingebunden werden.
Bzw. hast du mir beigebracht die Probleme einzeln zu betrachten und zu lösen. Daher sollte das vielleicht separat betrachtet werden

template_workbook.insert_rows(9)
Antworten