0

I am trying to create a GUI which has a combobox of choices a user can choose from, 2 buttons which open the file explorer for a user to choose 2 files from and, one 'generate' button which (depending on the choice) determine what ipynb file will be imported to run functions on the two files.

I have a ipynb file called Month_Month_GUI which contains all the methods and functions needed to initialize the GUI. Then there is a Month_to_Month_Scots ipynb file which contains specific methods needed to be run on files uploaded by the user.

The methods that will be run on the 2 (excel or csv) files from the Month_to_Month_Scots have the purpose of saving an excel file to the user's download folder containing only differences between the two uploaded files (Multiple columns will be compared based on the name/ ID field of teach uploaded file.

Here is my code for the Month_Month_GUI:

############################## CODE #####################################

# Import standard built-in Python packages
import re
import os
# Import installable data structure Python packages
import pandas as pd
import numpy as np
from openpyxl import load_workbook
from openpyxl.styles import PatternFill
import import_ipynb
from datetime import date

# Import installable GUI Python packages
import tkinter as tk
from tkinter import filedialog, messagebox
from CTkMessagebox import CTkMessagebox
import customtkinter as ctk

# Import created Python files
from Month_to_Month_Scots import SCOTS


##### GLOBAL VARIABLES ####
OPTIONS = ["Scots"]
FILES = []

# Dimensions of the window
appWidth, appHeight = 500, 400

# Sets the appearance mode of the application
# "System" sets the appearance same as that of the system
ctk.set_appearance_mode("System")       

# Sets the color of the widgets
# Supported themes: green, dark-blue, blue
ctk.set_default_color_theme("green")   

class GUI(ctk.CTk):
    
    def __init__(self, *args, **kwargs):
        '''Layout of the GUI will be written in the init itself'''
        super(GUI, self).__init__(*args, **kwargs)
        
        # Sets the title of our window to "App"
        self.title("Net-New Month to Month")   

        # Dimensions of the window will be 200x200
        self.geometry(f"{appWidth}x{appHeight}")

        #Source system label
        #creating label
        self.SSLabel = ctk.CTkLabel(self, text="Source System")

        #placing label
        self.SSLabel.grid(row=2, column=0,
                                  padx=20, pady=20,
                                  sticky="ew")

        #Source system combo box
        #setting inital value of text to Scotts in the combo box
        self.choice = tk.StringVar(value="Scots")

        #creating combo box and assigning the choice variable to it
        self.SSOptionMenu = ctk.CTkOptionMenu(self,
                                        values=OPTIONS,
                                        variable=self.choice)
        #placing combo box
        self.SSOptionMenu.grid(row=2, column=1,
                                       padx=20, pady=20,
                                       columnspan=2, sticky="ew")
        #Previous month
        #Previous month label
        #creating label for previous month extract
        self.prevMonthLabel = ctk.CTkLabel(self,
                                     text="Upload previous\
                                     month data")

        #placing label for previous month extract
        self.prevMonthLabel.grid(row=3, column=0,
                                padx=20, pady=20,
                                sticky="ew")
        
        #Previous month lookup button, ask user to input file
        self.prevMonthButton = ctk.CTkButton(self,
                                            text="Previous Month",
                                            command=self.open_file)
        
        #placing previous month lookup button
        self.prevMonthButton.grid(row=3,column=1,
                                padx=20, pady=20,
                                sticky="ew")
        
        #current month
        #current month label
        #creating label for previous month extract
        self.currMonthLabel = ctk.CTkLabel(self,
                                     text="Upload current\
                                     month data")

        #placing label for previous month extract
        self.currMonthLabel.grid(row=4, column=0,
                                padx=20, pady=20,
                                sticky="ew")
        
        #creating current month lookup button, ask user to input file
        self.currMonthButton = ctk.CTkButton(self,
                                            text="Current Month",
                                            command=self.open_file)
        
        #placing current month lookup button
        self.currMonthButton.grid(row=4,column=1,
                                padx=20, pady=20,
                                sticky="ew")
        
        # Generate Button, run comparison based on source system 
        self.generateResultsButton = ctk.CTkButton(self,
                                         text="Generate Results", command=self.determine_ss(FILES))
        self.generateResultsButton.grid(row=5, column=0,
                                        columnspan=2,
                                        padx=20, pady=20,
                                        sticky="ew")   
        
    def open_file(self):
        ''' Opens the file explorer for user to enter the files needed for comparison'''
        try:
            self.file=filedialog.askopenfilenames(initialdir="Desktop", title="Select a file",filetypes=[('excel file','*.xlsx'),('csv file','*.csv')])
            FILES.append(self.file)

        except:
            # if there is an error triggered 
            CTkMessagebox(title="Warning", message="File type not valid", icon="warning").grid(padx=20,pady=10,sticky='news')

        else:
            file_lst=[]

            for tup in FILES:

                for file_name in tup:
                    # Apend name of file to file_lst 
                    file_lst.append(str(file_name.split("/")[-1]))

            # prompt user with file name which has been uploaded
            CTkMessagebox(title="File Successfully Uploaded", message="The file "+str(file_lst[-1])+ " has been uploaded")

    def determine_ss(self,FILES):
        ''' Based on the choice of source system from the combobox, this method will create an instance of the source system class to run the comparison on
        Parameters
        ----------
            FILES : lst
                List of file paths
        '''
        if self.SSOptionMenu.get() == "Scots":
            print('here')
            gen_report_sc = SCOTS(FILES)
            
            
            
            

if __name__ == "__main__":
    application = GUI()
    application.mainloop()

Here is the code for the Month_to_Month_Scots:

############################## CODE #####################################

# Import standard built-in Python packages
import re
import os

# Import installable data structure Python packages
import pandas as pd
import numpy as np
from openpyxl import load_workbook
from openpyxl.styles import PatternFill
import import_ipynb
import datetime

# Import installable GUI Python packages
import tkinter as tk
from tkinter import filedialog, messagebox
from CTkMessagebox import CTkMessagebox
import customtkinter as ctk
import Month_Month_GUI 


class SCOTS(Month_Month_GUI.GUI):
    
    def __init__(self, FILES):
        ''' Initalizes variables to run comparision for net new 
        counterparties from one month to another
        
        Parameters
        ----------
            FILES : lst
                List of file paths
        '''
        super(SCOTS,self).__init__(**kwargs)
        self.FILES = FILES
        self.previous_month = ""
        self.previous_month_file = ""
        self.current_month = ""
        self.current_month_file = ""
        
    def show_warning_sc(self):
        '''
        Prompts user with message to enter the correct files for SCOTTS. This is a method for the GUI specific to SCOTTS
        '''
        CTkMessagebox(master=self.master, title='Warning: No or incorrect Files Selected', message="Please select 2 scotts files. One for the previous month and one for the following month.",icon="warning", option_1='Continue')
    
    def find_files_sc(self):
        ''' 
        Assigns user inputted files to initalized variables based on regular naming conventions of files. 
        Prompts warnings if files are not entered as excepted.
        
        Procedure
        ---------
        The variable 'FILES' is looped through to find the files required for the SCOTTS comparison. 
        Once a file is found, check whether the file is a csv or xlsx. 
        
        Assign the file name to corresponding initalized vairable self.*_FILE and assign a newly created dataframe from csv or excel data to self.*_DATA 
        
        If no files are found, too little files are found to run comparison, or the correct files are not found, method show_warning_k2 is run.
        '''
        #Creating list of what the potential dates would be in the files
        date_obj_lst = []
        
        if not self.FILES:
            self.show_warning_sc()
        
        elif len(self.FILES) < 2:
            self.show_warning_sc()
            
        # confirming the files are scots files only
        elif not bool(re.search('SCOTS', file.split("/")[-1])):
            self.show_warning_sc()
            
        else:
            for tup in self.FILES:
                for file in tup:
                    
                    #finding the date in the file name string for later 
                    #note, only 2 files should be uploaded per source system/ generation 
                    date_obj_lst.append(int(re.search(r'\d\d\d\d\d\d\d\d', file.split("/")[-1])[0]))
                    
            #the values in date_obj_lst should be ints to obtain the most nd least recent months.  
            max_date = max(date_obj_lst)
            min_date = min(date_obj_lst)
            
            for tup in self.FILES:
                for file in tup: 
                    
                    # Determines whether the file contains the previous month date
                    if bool(re.search(min_date, file.split("/")[-1])):
                    
                        # Determines whether the file is a csv
                        if bool(re.search(".csv", file.split("/")[-1])):
                            
                            #removes the csv extension to resave as an excel file later
                            self.previous_month_file = file.split("/")[-1].replace('.csv','')
                        
                            #reads csv file as a dataframe
                            self.previous_month = pd.read_csv(file)
                            
                            #save data as excel file to be read as a dataframe 
                            self.previous_month.to_excel(self.previous_month_file+'.xlsx', index=False)
                            self.previous_month = pd.read_excel(self.previous_month_file+'.xlsx', engine='openpyxl')
                            
                        # Determines whether the file is an excel file
                        else:
                            print('here')
                            #saving file path name
                            self.previous_month_file = file
                            
                            #reading least recent month into dataframe
                            self.previous_month = pd.read_excel(file,0)
                        
                            
                    # Determines whether the file contains the current month date
                    elif bool(re.search(max_date, file.split("/")[-1])):
                                  
                        # Determines whether the file is a csv
                        if bool(re.search(".csv", file.split("/")[-1])):

                            #removes the csv extension to resave as an excel file later
                            self.current_month_file = file.split("/")[-1].replace('.csv','')
                        
                            #reads csv file as a dataframe
                            self.current_month = pd.read_csv(file)
                            
                            #save data as excel file to be read as a dataframe 
                            self.current_month.to_excel(self.current_month_file+'.xlsx', index=False)
                            self.current_month = pd.read_excel(self.current_month_file+'.xlsx', engine='openpyxl')
                            
                        # Determines whether the file is an excel file
                        else:
                            #saving file path name
                            self.current_month_file = file
                            
                            #reading least recent month into dataframe
                            self.current_month = pd.read_excel(file,0)
                            
                         
                    # Prompt user with message since correct files were not found      
                    else:
                        CTkMessagebox(title='Please input correct files', message="You have selected to compare ALGO with K2. If this was the incorrect choice, please change the source system")
    
    
    
    def format_prev_month():
        pass
    
    def format_curr_month():
        pass
    
    def generate_report():
        pass
        

The error I am getting is the follwoing in the Month_Month_GUI file:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[28], line 172
    165             gen_report_sc = SCOTS(FILES)
    171 if __name__ == "__main__":
--> 172     application = GUI()
    173     application.mainloop()

Cell In[28], line 128, in GUI.__init__(self, *args, **kwargs)
    122 self.currMonthButton.grid(row=4,column=1,
    123                         padx=20, pady=20,
    124                         sticky="ew")
    126 # Generate Button, run comparison based on source system 
    127 self.generateResultsButton = ctk.CTkButton(self,
--> 128                                  text="Generate Results", command=self.determine_ss(FILES))
    129 self.generateResultsButton.grid(row=5, column=0,
    130                                 columnspan=2,
    131                                 padx=20, pady=20,
    132                                 sticky="ew")

Cell In[28], line 165, in GUI.determine_ss(self, FILES)
    163 if self.SSOptionMenu.get() == "Scots":
    164     print('here')
--> 165     gen_report_sc = SCOTS(FILES)

File <string>:42, in __init__(self, FILES)

TypeError: object.__init__() takes exactly one argument (the instance to initialize)

I have tried to change the super(SCOTS,self).__init__(**kwargs) to super().__init__().

I have tried to not have a super call at all. I run into the problem that I don't know how to pull in the Ctk.CTk object into the SCOTS class from the button command/ the determin_ss function.

I'm not sure what the typeerror means honestly and I'm unsure as to whether the error is in the __init__ of the GUI file or the Scots file as I have read the error may be pointing to a different exception.

Barmar
  • 741,623
  • 53
  • 500
  • 612
mare_g
  • 1
  • 1
    `command=self.determine_ss(FILES)` should be `command=lambda: self.determine_ss(FILES)` – Barmar May 04 '23 at 17:42
  • That made the GUI pop up again but I am still getting this error: TypeError: object.__init__() takes exactly one argument (the instance to initialize). Side question, why does lambda make the GUI show? – mare_g May 04 '23 at 18:54
  • Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\s7259276\AppData\Local\anaconda3\lib\site-packages\customtkinter\windows\widgets\ctk_button.py", line 553, in _clicked self._command() File "C:\Users\s7259276\AppData\Local\Temp\1\ipykernel_8404\2952510113.py", line 128, in text="Generate Results", command=lambda:self.determine_ss(FILES)) File "C:\Users\s7259276\AppData\Local\Temp\1\ipykernel_8404\2952510113.py", line 165, in determine_ss gen_report_sc = SCOTS(FILES) File "", line 42, in __init__ – mare_g May 04 '23 at 18:57
  • The argument to `command` is supposed to be a function to call when the user clicks on the button. You're calling the function immediately when you don't use `lambda`. – Barmar May 04 '23 at 19:01
  • Are you sure you posted the code you're running? In `super(SCOTS,self).__init__(**kwargs)` you're using the undefined variable `kwargs`. – Barmar May 04 '23 at 19:07
  • I'm sure, I got the idea off of https://stackoverflow.com/questions/57672872/typeerror-object-init-takes-exactly-one-argument-the-instance-to-initial – mare_g May 04 '23 at 19:50
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community May 04 '23 at 20:30

0 Answers0