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

Time:03-11

Here, I have two classes. First one (MedicalDevices.py) has the functions that I wanna use on the second class (tkinter_devices.py).

I am new to python and the help is appreciate it

Issue I am facing: I am trying to enter information of devices to excel sheet, but every time I entered more than one device's information, it only save the last entries that I entered while the tkinter running.

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()

CodePudding user response:

Inside add_new_device(), you copy serise from the global df and append the new record, then create a new dataframe df2 with the new series and save to file. However you forget to update the global df so that it does not include the new device. Next time another new device is to be added, you copy series from the global df again which does not have the previously added device, append the current new device and save to file. The file will then be overwritten without the previously added device.

To fix that you need to update the global df instead of creating a new dataframe df2. Also suggest to move the global df into MedicalDevices as a class variable:

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}")
  • Related