如何在Python中读取和操作CSV文件中的数据?

5kgi1eie  于 2023-05-26  发布在  Python
关注(0)|答案(1)|浏览(111)

我的代码是给我多个答案,当我使用我的客户搜索功能,我不知道为什么。
我们需要使用csv图表中的信息。(我加了一张照片)
验证码:”

import csv
import os
import time
import subprocess

# Standard-Speicherort für Rechnungen (Download-Ordner)
output_folder_path = os.path.expanduser("~/Downloads")

# Pfad zur CSV-Datei im Download-Ordner
csv_file_path = os.path.expanduser("~/Downloads/bestellwerte.csv")

# Liste zum Speichern der gelesenen Daten
aggregated_data = []

# Daten aus der CSV-Datei lesen
with open(csv_file_path, 'r', newline='') as csvfile:
    reader = csv.reader(csvfile, delimiter=';')  # Trennzeichen auf Semikolon setzen
    headers = [header.strip() for header in next(reader)]  # Spaltennamen extrahieren und Leerzeichen entfernen

    #print(headers)

    for row in reader:
        order = {}
        for i, value in enumerate(row):
            order[headers[i]] = value
        aggregated_data.append(order)

# Funktion zum Erstellen der Rechnung
def write_invoice(orders, output_file):
    with open(output_file, 'w') as file:
        file.write("Rechnung\n\n")

        # Extrahiere den Namen und die Order-ID des ersten Auftrags
        customer_name = orders[0]['customername']
        order_id = orders[0]['orderid']

        # Schreibe den Namen und die Order-ID nur einmal in die Rechnung
        file.write("Kunde: {}\n".format(customer_name))
        file.write("Order-ID: {}\n".format(order_id))
        file.write("\n")

        # Schreibe die Details der einzelnen Aufträge in die Rechnung
        file.write("Bestellungen:\n")
        total_price = 0.0
        for order in orders:
            order_detail_id = order['orderdetailid']
            quantity = int(order['quantity'])
            price = float(order['price'])
            subtotal = quantity * price
            total_price += subtotal
            file.write("- Order-Detail-ID: {}\n".format(order_detail_id))
            file.write("  Anzahl: {}\n".format(quantity))
            file.write("  Preis: {}\n".format(price))
            file.write("  Teilsumme: {}\n".format(subtotal))
            file.write("\n")

        # Berechne Steuern und Gesamtpreis
        tax_rate = 0.19  # Steuersatz von 19%
        tax_amount = total_price * tax_rate
        total_price += tax_amount

        file.write("\n")
        file.write("Steuern ({}%): {}\n".format(tax_rate * 100, tax_amount))
        file.write("Gesamtpreis: {}\n".format(total_price))

        print("Die Rechnung für Order-ID {} wurde erfolgreich erstellt.".format(order_id))

    # Rechnung automatisch öffnen
    try:
        subprocess.Popen(['open', output_file])  # Für macOS
    except OSError:
        try:
            subprocess.Popen(['xdg-open', output_file])  # Für Linux
        except OSError:
            try:
                subprocess.Popen(['start', '', output_file], shell=True)  # Für Windows
            except OSError:
                print("Die Rechnung konnte nicht automatisch geöffnet werden.")

# Funktion zum Suchen einer Order-ID
def find_order_by_id(order_id):
    matching_orders = [order for order in aggregated_data if order['orderid'] == order_id]

    if len(matching_orders) == 0:
        print("Die angegebene Order-ID existiert nicht.")
    else:
        print("Folgende Bestellungen wurden gefunden:")
        for order in matching_orders:
            print("- Order-ID: {}, Kunde: {}".format(order['orderid'], order['customername']))
            print("  Order-Detail-ID: {}".format(order['orderdetailid']))
            print("  Anzahl: {}".format(order['quantity']))
            print("  Preis: {}".format(order['price']))
            print("-----------------------------")

# Funktion zum Suchen eines Kunden und Anzeigen der Bestellungen
def find_customer_by_name(customer_name):
    matching_customers = [customer for customer in aggregated_data if customer_name.lower() in customer['customername'].lower()]

    if len(matching_customers) == 0:
        print("Es wurden keine Kunden mit diesem Namen gefunden.")
    else:
        for customer in matching_customers:
            print("Kunde: {}".format(customer['customername']))

            # Bestellungen des aktuellen Kunden sammeln
            customer_orders = [order for order in aggregated_data if order['customername'] == customer['customername']]

            # Set zum Speichern der eindeutigen Order-IDs
            order_ids = set()

            for order in customer_orders:
                order_id = order['orderid']
                if order_id not in order_ids:
                    print("Bestellungen:")
                    order_ids.add(order_id)
                print("- Order-ID: {}".format(order_id))
                print("  Order-Detail-ID: {}".format(order['orderdetailid']))
                print("  Anzahl: {}".format(order['quantity']))
                print("  Preis: {}".format(order['price']))
                print("-----------------------------")

# Funktion zum Ändern des Speicherorts für Rechnungen
def change_output_folder(new_folder_path):
    global output_folder_path
    output_folder_path = new_folder_path

# User-Menü
while True:
    os.system('cls' if os.name == 'nt' else 'clear')  # Löscht die Konsolenausgabe

    # Benutzerinformationen anzeigen
    print("User Menu:")

    # Benutzermenü anzeigen
    print("[C]reate invoice, [f]ind OrderId, [S]earch Customer, Speicher[o]rt Festlegen, E[x]it")
    answer = input()

    # Rechnung erstellen
    if answer.lower() == "c":
        order_id_input = input("Geben Sie die Order-ID ein: ")
        matching_orders = [order for order in aggregated_data if order['orderid'] == order_id_input]

        if len(matching_orders) == 0:
            print("Die angegebene Order-ID existiert nicht.")
        else:
            print("Folgende Bestellungen wurden gefunden:")
            for order in matching_orders:
                print("- Order-ID: {}, Kunde: {}".format(order['orderid'], order['customername']))

            output_file = os.path.join(output_folder_path, 'Rechnung {}.txt'.format(order_id_input))
            write_invoice(matching_orders, output_file)

    # Order-ID suchen
    elif answer.lower() == "f":
        order_id_input = input("Geben Sie die Order-ID ein: ")
        find_order_by_id(order_id_input)

    # Kunde suchen
    elif answer.lower() == "s":
        customer_name_input = input("Geben Sie den Namen des Kunden oder einen Teil des Namens ein: ")
        find_customer_by_name(customer_name_input)


    # Speicherort ändern
    elif answer.lower() == "o":
        print("Möchten Sie den Speicherordner ändern? [y/n]")
        question2 = input("")
        if question2 == "y":
            print("Geben Sie den neuen Speicherordner-Pfad an:")
            new_folder_path = input(r"[Beispiel: C:\Users\tim-o\OneDrive\Desktop\Rechnung py] ")
            change_output_folder(new_folder_path)
            print("Speicherort geändert!")

    # Programm beenden
    elif answer.lower() == "x":
        answer = input("Wollen Sie das Menü wirklich beenden? [y/n]").lower()
        if answer == "y":
            print("Das Programm wird nun beendet")
            for i in range(20):
                print(".....", end='')
                time.sleep(0.05)
            break

如果你们能解决我的问题就太好了。(它是德语的,顺便说一句)我自己试过,在chatgpt的帮助下,似乎什么都不起作用。

hsgswve4

hsgswve41#

我没有读过你所有的代码,所以我不能确切地说问题可能在哪里。然而,我可以看到,目前我很难遵循逻辑和流程。
我会建议你做一个大的结构性改变:将大while-True循环放在main函数中,该函数获取用户输入并相应地执行操作;然后在try-except中调用main来处理用户使用Ctrl-C中止:

...

def main():
    data = get_data()

    while True:
        choice = get_menu_input()
        match choice:
            case "x":
                if confirm_exit():
                    break
            case "c":
                create_invoice(data)
            case "f":
                pass
            case "o":
                pass
            case "s":
                pass
            case _:
                pass  # unexpected menu choice; show menu again

...

try:
    main()
except KeyboardInterrupt:
    print("\nDas Programm wurde vom Benutzer unterbrochen")
    pass

我喜欢这样,因为我可以清楚地看到程序从哪里开始,并且只有退出的方法:1)用户确认的退出2)一些期望(其中KeyboardInterrupt被期望和处理)。
match-case依赖于Python 3.10+,但即使你有一个if-elifs序列... -else,我认为它看起来仍然非常清晰和容易理解。像get_menu_input()、confirm_exit()和create_invoice()这样的函数仍然有用户交互。我会尽量让main代码在开始时非常简洁,但你可能想把所有的用户输入都带到main代码中(在这种情况下,你不需要create_invoice(),你只需要在case "c":块中提示输入订单ID,然后调用write_invoice(...))。
这里有一个完整的示例,它至少可以在我的Mac上编写发票并在TextEdit中打开文本文件。我还重写了CSV阅读器以使用DictReader。我可以看到你需要首先修剪头部。如果你只需要跳过标题名称中的前导空格,只需要在DictReader中使用skipinitialspace=True选项就可以了。

import csv
import os
import platform
import subprocess

Output_Folder_Path = os.path.expanduser("~/Downloads")
Input_Path = "input.csv"

Data = list[dict[str, str]]

def main():
    data = get_data()

    while True:
        choice = get_menu_input()
        match choice:
            case "x":
                if confirm_exit():
                    break
            case "c":
                create_invoice(data)
            case "f":
                pass
            case "o":
                pass
            case "s":
                pass
            case _:
                pass  # unexpected menu choice; show menu again

def get_data() -> Data:
    with open(Input_Path, "r", newline="") as f:
        # Read just the header, normalize fieldnames
        r = csv.reader(f, delimiter=";")
        header = next(r)
        header = [x.strip() for x in header]

        # The file is still open; the file's "line iterator" is still on line 2...

        # Read w/DictReader for actual data
        r = csv.DictReader(f, delimiter=";", fieldnames=header)

        return list(r)

def get_menu_input() -> str:
    # Löscht die Konsolenausgabe
    os.system("cls" if os.name == "nt" else "clear")

    # Benutzermenü anzeigen
    print("User Menu:")
    print("[C]reate invoice, [f]ind OrderId, [S]earch Customer, Speicher[o]rt Festlegen, E[x]it")

    return input().lower().strip()

def confirm_exit() -> bool:
    answer = input("Wollen Sie das Menü wirklich beenden? [y/n] ").lower().strip()
    if answer != "y":
        return False

    print("Das Programm wird nun beendet")
    return True

def create_invoice(data: Data):
    order_id = input("Geben Sie die Order-ID ein: ")
    matching_orders = [order for order in data if order["orderid"] == order_id]

    if len(matching_orders) == 0:
        print("Die angegebene Order-ID existiert nicht.")
        return

    print("Folgende Bestellungen wurden gefunden:")
    for order in matching_orders:
        print("- Order-ID: {}, Kunde: {}".format(order["orderid"], order["customername"]))

    output_file = os.path.join(Output_Folder_Path, "Rechnung {}.txt".format(order_id))
    write_invoice(matching_orders, output_file)

# Funktion zum Erstellen der Rechnung
def write_invoice(orders: Data, output_file: str):
    with open(output_file, "w") as file:
        file.write("Rechnung\n\n")

        # Extrahiere den Namen und die Order-ID des ersten Auftrags
        customer_name = orders[0]["customername"]
        order_id = orders[0]["orderid"]

        # Schreibe den Namen und die Order-ID nur einmal in die Rechnung
        file.write("Kunde: {}\n".format(customer_name))
        file.write("Order-ID: {}\n".format(order_id))
        file.write("\n")

        # Schreibe die Details der einzelnen Aufträge in die Rechnung
        file.write("Bestellungen:\n")
        total_price = 0.0
        for order in orders:
            order_detail_id = order["orderdetailid"]
            quantity = int(order["quantity"])
            price = float(order["price"])
            subtotal = quantity * price
            total_price += subtotal
            file.write("- Order-Detail-ID: {}\n".format(order_detail_id))
            file.write("  Anzahl: {}\n".format(quantity))
            file.write("  Preis: {}\n".format(price))
            file.write("  Teilsumme: {}\n".format(subtotal))
            file.write("\n")

        # Berechne Steuern und Gesamtpreis
        tax_rate = 0.19  # Steuersatz von 19%
        tax_amount = total_price * tax_rate
        total_price += tax_amount

        file.write("\n")
        file.write("Steuern ({}%): {}\n".format(tax_rate * 100, tax_amount))
        file.write("Gesamtpreis: {}\n".format(total_price))

        print("Die Rechnung für Order-ID {} wurde erfolgreich erstellt.".format(order_id))

    # Rechnung automatisch öffnen
    match platform.system():
        case "Darwin":  # macOS
            subprocess.Popen(["open", output_file])
        case "Linux":
            subprocess.Popen(["xdg-open", output_file])
        case "Windows":
            subprocess.Popen(["start", "", output_file], shell=True)
        case _:
            print("Die Rechnung konnte nicht automatisch geöffnet werden.")

try:
    main()
except KeyboardInterrupt:
    print("\nDas Programm wurde vom Benutzer unterbrochen")
    pass

相关问题