保存底部仅将最后一个条目保存到 excel sheet (tkinter)

Save bottom only saves the last entry into excel sheet (tkinter)

这里,我有两个 classes。第一个 (MedicalDevices.py) 具有我想在第二个 class (tkinter_devices.py) 上使用的功能。

我是 python 的新手,非常感谢您的帮助

我面临的问题: 我正在尝试将设备信息输入 excel sheet,但每次我输入多个设备的信息时,它只会保存我在 tkinter 运行 时输入的最后一个条目。

MedicalDevices.py

import datetime
import pandas as pd

# excel file path
f_path = "medical_devices_data.xlsx"
df = pd.read_excel(f_path, sheet_name="Sheet1")


class MedicalDevices:
    # class attributes: to keep truck the number of the objects that been made.
    num_of_devices = 0

    # initialization/ construction
    def __init__(self, name, sn, manufacture, model, supplier, department='In Store', warranty_expire="Expired"):
        # object attributes (to make private attribute, add __ before the name
        self.name = name
        self.sn = sn
        self.manufacture = manufacture
        self.model = model
        self.supplier = supplier
        self.department = department
        self.warranty_expire = warranty_expire
        # increase number of devices made with every initialization
        MedicalDevices.num_of_devices += 1

        # dunder (double underscore)method
        # override function to print string instead of printing the memory address of an object

    def __str__(self):
        return f"Name: {self.name}\nSerial#: {self.sn}\nManufacture: {self.manufacture}\n" \
               f"Model: {self.model}\nSupplier: {self.supplier}\nDepartment: {self.department}\n" \
               f"Warranty expire on: {self.warranty_expire}"

    def add_new_device(newDevice):

        SerA = df["Name"]
        SerB = df["Serial"]
        SerC = df["Manufacture"]
        SerD = df["Model"]
        SerE = df["Supplier"]
        SerF = df["Department"]
        SerG = df["Warranty"]

        # this must be Series type to be able to concatenate with DataFrame
        A = pd.Series(newDevice.name)
        B = pd.Series(newDevice.sn)
        C = pd.Series(newDevice.manufacture)
        D = pd.Series(newDevice.model)
        E = pd.Series(newDevice.supplier)
        F = pd.Series(newDevice.department)
        G = pd.Series(newDevice.warranty_expire)

        SerA = SerA.append(A)
        SerB = SerB.append(B)
        SerC = SerC.append(C)
        SerD = SerD.append(D)
        SerE = SerE.append(E)
        SerF = SerF.append(F)
        SerG = SerG.append(G)

        df2 = pd.DataFrame({"Name": SerA,
                            "Serial": SerB,
                            "Manufacture": SerC,
                            "Model": SerD,
                            "Department": SerE,
                            "Supplier": SerF,
                            "Warranty": SerG})

        df2.to_excel(f_path, index=False)
        print(f"A new device added with Serial#: {newDevice.sn}")
    #
    # def search_by_sn(self, sn):
    #     if sn in df.values:
    #         print("Got it. Here is the device(s) info: \n-------------------------------")
    #         print(df.loc[df.Serial == sn])
    #     else:
    #         print("Not found")
    #         newInput = input("Do you want to add a new device (yes/ no): ")
    #         if newInput == "yes":
    #             self.add_new_device(DC_1)
    #         else:
    #             print("Ok")

    # To check Warranty
    def check_warranty(self):
        date = datetime.datetime.strptime(self.warranty_expire, '%Y/%m/%d').date()
        if date >= datetime.date.today():
            print(self.name + " is still in Warranty\n" + "Warranty expires on " + self.warranty_expire)
        else:
            print("Attention, Warranty expired on " + self.warranty_expire)

tkinter_devices.py

import tkinter as tk
from tkinter import ttk
import pandas as pd
from MedicalDevices import MedicalDevices

font1 = ("Verdana", 12)
font2 = ("Verdana", 10)
pageSize = "500x300"
f_path = "medical_devices_data.xlsx"
df = pd.read_excel(f_path, sheet_name="Sheet1")


class MedicalDeviceApp(tk.Tk):
    # args=argument (any number of argument (unlimited))
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "Medical Devices Data")
        tk.Tk.wm_geometry(self, pageSize)  # (width x height)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (StartPage, AddDevice, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()


class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        label = ttk.Label(self, text="Start Page", font=font1)
        label.grid(row=0, column=5, sticky="nsew")

        bot1 = ttk.Button(self, text="Add a new device",
                          command=lambda: controller.show_frame(AddDevice))
        bot1.grid(row=1, column=0, sticky="nsew", columnspan=1, ipadx=5)

        bot2 = ttk.Button(self, text="Page Two",
                          command=lambda: controller.show_frame(PageTwo))
        bot2.grid(row=2, column=0, sticky="nsew")

        bot_exit = ttk.Button(self, text="Exit", command=lambda: controller.destroy())
        bot_exit.grid(row=3, column=0, sticky="nsew")


class AddDevice(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        # Labels
        label1 = ttk.Label(self, text="Enter a new device information", font=font1)
        label1.grid(row=0, column=1)

        label2 = ttk.Label(self, text="Required information with *")
        label2.grid(row=1, column=1, pady=5)

        label_name = ttk.Label(self, text="Device Name:", font=font2)
        label_name.grid(row=2, column=0, sticky="w")

        label_serial = ttk.Label(self, text="Serial Number:", font=font2)
        label_serial.grid(row=3, column=0, sticky="w")

        label_manf = ttk.Label(self, text="Manufacture:", font=font2)
        label_manf.grid(row=4, column=0, sticky="w")

        label_model = ttk.Label(self, text="Model:", font=font2)
        label_model.grid(row=5, column=0, padx=2, sticky="w")

        label_supplier = ttk.Label(self, text="Supplier:", font=font2)
        label_supplier.grid(row=6, column=0, padx=2, sticky="w")

        label_depart = ttk.Label(self, text="Department:", font=font2)
        label_depart.grid(row=7, column=0, padx=2, sticky="w")

        label_expire = ttk.Label(self, text="Expire Date:", font=font2)
        label_expire.grid(row=8, column=0, padx=2, sticky="w")

        # Entries
        self.entry_name = ttk.Entry(self)
        self.entry_name.grid(row=2, column=1, ipadx=20, pady=5)

        self.entry_serial = ttk.Entry(self)
        self.entry_serial.grid(row=3, column=1, ipadx=20, pady=5)

        self.entry_manf = ttk.Entry(self)
        self.entry_manf.grid(row=4, column=1, ipadx=20, pady=5)

        self.entry_model = ttk.Entry(self)
        self.entry_model.grid(row=5, column=1, ipadx=20, pady=5)

        self.entry_supplier = ttk.Entry(self)
        self.entry_supplier.grid(row=6, column=1, ipadx=20, pady=5)

        self.entry_depart = ttk.Entry(self)
        self.entry_depart.grid(row=7, column=1, ipadx=20, pady=5)

        self.entry_expire = ttk.Entry(self)
        self.entry_expire.grid(row=8, column=1, ipadx=20, pady=5)

        # Bottoms
        self.bot_save = ttk.Button(self, text="Save", command=self.save)
        self.bot_save.grid(row=2, column=2, ipadx=20, pady=5, columnspan=1)

        self.bot_clear = ttk.Button(self, text="Clear", command=self.delete)
        self.bot_clear.grid(row=4, column=2, ipadx=20, pady=2, columnspan=1)

        self.bot_back = ttk.Button(self, text="Back to Home",
                                   command=lambda: controller.show_frame(StartPage))
        self.bot_back.grid(row=6, column=2, ipadx=20)

        self.bot_exit = ttk.Button(self, text="Exit", command=lambda: controller.destroy())
        self.bot_exit.grid(row=8, column=2, ipadx=25)

    def delete(self):
        self.entry_name.delete(0, 'end')
        self.entry_serial.delete(0, 'end')
        self.entry_manf.delete(0, 'end')
        self.entry_model.delete(0, 'end')
        self.entry_supplier.delete(0, 'end')
        self.entry_depart.delete(0, 'end')
        self.entry_expire.delete(0, 'end')

    def save(self):
        if int(self.entry_serial.get()) in df.values:
            print("found it ")
            self.delete()
        else:
            device = MedicalDevices(self.entry_name.get(), self.entry_serial.get(), self.entry_manf.get(),
                                    self.entry_model.get(), self.entry_supplier.get(), self.entry_depart.get(),
                                    self.entry_expire.get())
            MedicalDevices.add_new_device(device)
            self.delete()


class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        label = ttk.Label(self, text="Page Tow", font=font1)
        label.pack(pady=10, padx=10)

        bot1 = ttk.Button(self, text="Back to Home",
                          command=lambda: controller.show_frame(StartPage))
        bot1.pack()


app = MedicalDeviceApp()
app.mainloop()

add_new_device() 中,您从全局 df 复制系列并附加新记录,然后使用新系列创建一个新数据帧 df2 并保存到文件。但是您忘记更新全局 df 以使其不包含新设备。下次要添加另一个新设备时,您再次从全局 df 复制系列,其中没有以前添加的设备,附加当前的新设备并保存到文件。然后将在没有先前添加的设备的情况下覆盖该文件。

要解决此问题,您需要更新全局 df 而不是创建新数据框 df2。还建议将全局 df 作为 class 变量移动到 MedicalDevices 中:

class MedicalDevices:
    # excel file path
    f_path = "medical_devices_data.xlsx"
    df = pd.read_excel(f_path, sheet_name="Sheet1")

    ...

    def add_new_device(newDevice):
        # update class dataframe `df` instead of creating new one
        MedicalDevices.df = MedicalDevices.df.append({
            "Name": newDevice.name,
            "Serial": newDevice.sn,
            "Manufacture": newDevice.manufacture,
            "Model": newDevice.model,
            "Supplier": newDevice.supplier,
            "Department": newDevice.department,
            "Warranty": newDevice.warranty_expire
        }, ignore_index=True)
        # export to file
        MedicalDevices.df.to_excel(MedicalDevices.f_path, index=False)

        print(f"A new device added with Serial#: {newDevice.sn}")