Python Forum
Excel isnt working properly after python function is started
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Excel isnt working properly after python function is started
#1
I have a Python application that can create a graph based on input that the user enters into a form(GUI) that is created via Tkinter. This application is actually made as an Excel addin. It works by creating a custom addin via xlwings and creating a custom ribbon with a button via RibbonXEditor. When the user presses this button, the python function show_form is launched via the VBA function, which actually displays the form. And now the problem is that when the form is displayed, then Excel does not work properly, it is not possible to write in the cells, I have to close the form and only then it works normally, is there any way to fix it?Here is for example the VBA code than is launching the python function.
Sub show_form(control As IRibbonControl)
Dim mymodule As String
mymodule = Left(ThisWorkbook.Name, _
        (InStrRev(ThisWorkbook.Name, ".", -1, vbTextCompare) - 1))
RunPython "import " & mymodule & ";" & _
    mymodule & ".show_form()"
And here is the my_show function:
def show_form():
 
    window = tk.Tk()
    window.title("Calculation and Display of p-value")
 
    window.resizable(width=False, height=False)
    frame = tk.Frame(window)
    frame.pack(padx=10, pady=10)
 
 
    # First Section: Distribution Selection
    distribution_frame = tk.LabelFrame(frame, text="Distribution Selection")
    distribution_frame.grid(row=0, column=0, padx=20, pady=10, sticky="news")
    distribution_label = tk.Label(distribution_frame, text="Distribution: ")
    distribution_label.grid(row=0, column=0, padx=20, pady=20)
    distribution_select = ttk.Combobox(distribution_frame, values=["t-distribution", "F-distribution", "chi-square distribution", "z-distribution(0,1)"], state="readonly")
    distribution_select.grid(row=0, column=1, padx=(0,20), pady=10)
 
    # Second Section: Test Statistic Value
    value_frame = tk.LabelFrame(frame, text="Test Statistic Value")
    value_frame.grid(row=2, column=0, padx=20, pady=10, sticky="news")
 
    # Third Section: Test Parameters
    parameters_frame = tk.LabelFrame(frame, text="Statistical Test Parameters")
    parameters_frame.grid(row=1, column=0, padx=20, pady=(0,5), sticky="news")  
 
 
    def update_parameters(event):
        global value_number, parameter1_number, parameter2_number
        # Clearing previous elements
        for widget in parameters_frame.winfo_children():
            widget.destroy()
 
 
        # Creating new elements based on selection in combobox
        if distribution_select.get() == "t-distribution":
            parameter1_label = tk.Label(parameters_frame, text="n₁: ")
            parameter1_label.grid(row=0, column=0, padx=(20,5), pady=10, sticky='w') 
            parameter1_number = tk.Entry(parameters_frame)
            parameter1_number.grid(row=0, column=1, padx=(0,20), pady=10, sticky="e")
            value_label = tk.Label(value_frame, text="t₀: ")
            value_label.grid(row=0, column=0, padx=20, pady=20)
            value_number = tk.Entry(value_frame)
            value_number.grid(row=0, column=1, padx=(0,20), pady=10)
        elif distribution_select.get() == "F-distribution":
            parameter1_label = tk.Label(parameters_frame, text="n₁: ")
            parameter1_label.grid(row=0, column=0, padx=(20,5), pady=10, sticky='w') 
            parameter1_number = tk.Entry(parameters_frame)
            parameter1_number.grid(row=0, column=1, padx=(0,20), pady=10)
            parameter2_label = tk.Label(parameters_frame, text="n₂: ")
            parameter2_label.grid(row=1, column=0, padx=(20,5), pady=10, sticky='w') 
            parameter2_number = tk.Entry(parameters_frame)
            parameter2_number.grid(row=1, column=1, padx=(0,20), pady=10)
            value_label = tk.Label(value_frame, text="F₀: ")
            value_label.grid(row=0, column=0, padx=20, pady=20)
            value_number = tk.Entry(value_frame)
            value_number.grid(row=0, column=1, padx=(0,20), pady=10)
        elif distribution_select.get() == "chi-square distribution":
            parameter1_label = tk.Label(parameters_frame, text="n₁: ")
            parameter1_label.grid(row=0, column=0, padx=(20,5), pady=10, sticky='w') 
            parameter1_number = tk.Entry(parameters_frame)
            parameter1_number.grid(row=0, column=1, padx=(0,20), pady=10)
            value_label = tk.Label(value_frame, text="x²₀: ")
            value_label.grid(row=0, column=0, padx=20, pady=20)
            value_number = tk.Entry(value_frame)
            value_number.grid(row=0, column=1, padx=(0,20), pady=10)
        elif distribution_select.get() == "z-distribution(0,1)":
            value_label = tk.Label(value_frame, text="z₀: ")
            value_label.grid(row=0, column=0, padx=20, pady=20)
            value_number = tk.Entry(value_frame)
            value_number.grid(row=0, column=1, padx=(0,20), pady=10)
 
 
 
 
    # Call the update_parameters function when there is a change in the combobox
    distribution_select.bind("<<ComboboxSelected>>", update_parameters)
 
    # Third Section: Test Type
    type_frame = tk.LabelFrame(frame, text="Test Type")
    type_frame.grid(row=3, column=0, padx=20, pady=(0,5), sticky="news")
 
    left_sided_value = tk.IntVar()
    right_sided_value = tk.IntVar()
    two_sided_value = tk.IntVar()
    alpha_value = tk.IntVar()
    test_type = tk.IntVar()
 
    def set_test_type():
        if test_type.get() == 1:
            left_sided_value.set(1)
            right_sided_value.set(0)
            two_sided_value.set(0)
        elif test_type.get() == 2:
            left_sided_value.set(0)
            right_sided_value.set(1)
            two_sided_value.set(0)
        else:
            left_sided_value.set(0)
            right_sided_value.set(0)
            two_sided_value.set(1)
 
    test_type.set(1)  # Sets the default value to left-sided test
    set_test_type() 
 
    left_sided_button = tk.Radiobutton(type_frame, text="Left-sided", variable=test_type, value=1, command=set_test_type)
    left_sided_button.grid(row=0, column=0, padx=(20, 5), pady=10, sticky='w')
 
    right_sided_button = tk.Radiobutton(type_frame, text="Right-sided", variable=test_type, value=2, command=set_test_type)
    right_sided_button.grid(row=1, column=0, padx=(20, 5), pady=10, sticky='w')
 
    two_sided_button = tk.Radiobutton(type_frame, text="Two-sided", variable=test_type, value=3, command=set_test_type)
    two_sided_button.grid(row=2, column=0, padx=(20, 5), pady=10, sticky='w')
 
 
 
 
    def update_alpha_widgets():
        global alpha_number
        if alpha_value.get() == 1:
            alpha_label = tk.Label(alpha_frame, text="Alpha value: ")
            alpha_label.grid(row=1, column=0, padx=(20,5), pady=10, sticky='w') 
            alpha_number = tk.Entry(alpha_frame)
            alpha_number.grid(row=1, column=1, padx=(0,20), pady=10)
 
 
        else:
            for widget in alpha_frame.winfo_children():
                widget.destroy()
            alpha_button = tk.Checkbutton(alpha_frame, text="Show Alpha", variable=alpha_value, onvalue=1, offvalue=0, command=update_alpha_widgets)
            alpha_button.grid(row=0, column=0, padx=(20,5), pady=10, sticky='w')
 
 
 
    # Fourth Section
    alpha_frame = tk.LabelFrame(frame, text="Alpha")
    alpha_frame.grid(row=4, column=0, padx=20, pady=(0,5), sticky="news")
 
    alpha_button = tk.Checkbutton(alpha_frame, text="Show Alpha", variable=alpha_value, onvalue=1, offvalue=0, command=update_alpha_widgets)
    alpha_button.grid(row=0, column=0, padx=(20,5), pady=10, sticky='w')
    def check_values():
 
        # Checking if all values are defined
 
        if distribution_select.get() == "t-distribution":
                if len(parameter1_number.get()) == 0 or len(value_number.get()) == 0:
                    messagebox.showerror("Error", "Parameter or test value is not provided")
                elif not parameter1_number.get().isnumeric() or not is_float(value_number.get()):
                    messagebox.showerror("Error", "Parameter and test value cannot contain letters")
                else:
                    if alpha_value.get() == 1:
                        if len(alpha_number.get()) == 0:
                            messagebox.showerror("Error","Alpha value must be provided")
                        elif not is_float(alpha_number.get()):
                            messagebox.showerror("Error","Alpha value cannot contain letters")
                        elif float(alpha_number.get()) <= 0 or float(alpha_number.get()) > 1:
                            messagebox.showerror("Error","Alpha value must be between 0 and 1")
                        else:
                            p_from_t(float(value_number.get()),int(parameter1_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),float(alpha_number.get()))
                    else:
                        p_from_t(float(value_number.get()),int(parameter1_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),None)
 
        elif distribution_select.get() == "z-distribution(0,1)":
            if len(value_number.get()) == 0:
                    messagebox.showerror("Error", "Test value is not provided")
            elif not is_float(value_number.get()):
                messagebox.showerror("Error", "Test value cannot contain letters")
            else:
                if alpha_value.get() == 1:
                        if len(alpha_number.get()) == 0:
                            messagebox.showerror("Error","Alpha value must be provided")
                        elif not is_float(alpha_number.get()):
                            messagebox.showerror("Error","Alpha value cannot contain letters")
                        elif float(alpha_number.get()) <= 0 or float(alpha_number.get()) > 1:
                            messagebox.showerror("Error","Alpha value must be between 0 and 1")
                        else:
                            p_from_z(float(value_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),float(alpha_number.get()))
                else:
                    p_from_z(float(value_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),None)
 
        elif distribution_select.get() == "F-distribution":
            if len(parameter1_number.get()) == 0 or len(value_number.get()) == 0 or len(parameter2_number.get()) == 0:
                    messagebox.showerror("Error", "Parameter or test value is not provided")
            elif not parameter1_number.get().isnumeric() or not is_float(value_number.get()) or not parameter2_number.get().isnumeric():
                messagebox.showerror("Error", "Parameter and test value cannot contain letters")
            else:
                if alpha_value.get() == 1:
                        if len(alpha_number.get()) == 0:
                            messagebox.showerror("Error","Alpha value must be provided")
                        elif not is_float(alpha_number.get()):
                            messagebox.showerror("Error","Alpha value cannot contain letters")
                        elif float(alpha_number.get()) <= 0 or float(alpha_number.get()) > 1:
                            messagebox.showerror("Error","Alpha value must be between 0 and 1")
                        else:
                            p_from_f(float(value_number.get()),int(parameter1_number.get()),int(parameter2_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),float(alpha_number.get()))
                else:
                    p_from_f(float(value_number.get()),int(parameter1_number.get()),int(parameter2_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),None)
 
        elif distribution_select.get() == "chi-square distribution":
            if len(parameter1_number.get()) == 0 or len(value_number.get()) == 0:
                    messagebox.showerror("Error", "Parameter or test value is not provided")
            elif not parameter1_number.get().isnumeric() or not is_float(value_number.get()):
                messagebox.showerror("Error", "Parameter and test value cannot contain letters")
            else:
                if alpha_value.get() == 1:
                        if len(alpha_number.get()) == 0:
                            messagebox.showerror("Error","Alpha value must be provided")
                        elif not is_float(alpha_number.get()):
                            messagebox.showerror("Error","Alpha value cannot contain letters")
                        elif float(alpha_number.get()) <= 0 or float(alpha_number.get()) > 1:
                            messagebox.showerror("Error","Alpha value must be between 0 and 1")
                        else:
                            p_from_chi_square(float(value_number.get()),int(parameter1_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),float(alpha_number.get()))
                else:
                    p_from_chi_square(float(value_number.get()),int(parameter1_number.get()),left_sided_value.get(),right_sided_value.get(),two_sided_value.get(),None)
 
 
    button = tk.Button(frame, text="Generate", height=4, width=8, command=check_values)
    button.grid(row=5, column=0, padx=20, pady=20)
 
    window.mainloop()
Sorry for messy code
Reply
#2
When excel executes a Python script, it waits for the script to complete. Your script doesn't complete until the window is closed. This blocks excel from running. There are multiple ways to solve this problem. but the easiest might be to run the window script as a subprocess.

This is my window file (window.py)
import tkinter as tk

root = tk.Tk()
tk.Button(root, text="Close", command=root.destroy).pack(padx=100, pady=100)
root.mainloop()
I can do that by running the window as a subprocess.

This is a python script that runs window.py as a subprocess.
import subprocess

subprocess.Popen(["python", "window.py"])
print("I am done")
Your spreadsheet calls the launch script. The lauch script starts a process to run the window.py script. Because the launch script uses Popen withou a wait(), it doesn't wait for the window to close, and doesn't block the spreadsheet.
You'll need to use absolute paths for python.exe and window.py.
IchNar likes this post
Reply
#3
Thanks it works well, but i have one question. In the launch_script is it possible to use relative path? I used it with os but it didnt work well.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  File Handling not working properly TheLummen 8 904 Feb-17-2024, 07:47 PM
Last Post: TheLummen
Shocked kindly support with this dropna function not working gheevarpaulosejobs 2 735 Jul-24-2023, 03:41 PM
Last Post: deanhystad
  How do I properly implement restarting a multithreaded python application? MrFentazis 1 662 Jul-17-2023, 09:10 PM
Last Post: JamesSmith
  Cannot get started standenman 4 1,258 Feb-22-2023, 05:25 PM
Last Post: standenman
  Working with Excel and Word, Several Questions Regarding Find and Replace Brandon_Pickert 4 1,641 Feb-11-2023, 03:59 PM
Last Post: Brandon_Pickert
  How to properly format rows and columns in excel data from parsed .txt blocks jh67 7 1,989 Dec-12-2022, 08:22 PM
Last Post: jh67
  [Solved]Help Displaying Emails properly via Python Extra 5 1,238 Sep-28-2022, 09:28 PM
Last Post: deanhystad
Exclamation Function Not Working Alivegamer 7 1,945 Jul-19-2022, 01:03 PM
Last Post: deanhystad
  try function working on PC but not raspberry pi AnotherSam 1 1,577 Oct-11-2021, 04:51 AM
Last Post: bowlofred
  Working with excel files arsouzaesilva 6 3,275 Sep-17-2021, 06:52 PM
Last Post: arsouzaesilva

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020