Problem - I have a Python function that reads values from an Excel sheet, performs some calculations, and writes back the data to the Excel sheet. Let's say this entire function takes 1 minute to complete. Now, I have converted my Python file to an .exe file and I am calling this .exe file through a VBA macro, and it is running.
Need Help - Once my code starts running, I need a stop button on the sg window (which I have created) that will stop my running code immediately. Is it possible to stop the Python code externally?
# Create GUI window
window = sg.Window("Peak Shave Simualtion", layout ,icon="C:\Env\Profit_calculator\Tricera-logo.ico") # main window configuration
progress_bar = window['-PROGRESS-']
# Event loop
while True:
event, values = window.read()
if event == sg.WIN_CLOSED: # if closed or click on cancel button window will close
break
elif event == 'Process':
file_path = sys.argv[1]
start_time = time.time()
Python_profitcalculator_simulation(file_path)
end_time = time.time()
sg.popup(f"Processing complete!\nSimulation total time: {(f'{((end_time - start_time)/60):.2f} minutes' if (end_time - start_time) >= 60 else f'{(end_time - start_time):.2f} seconds')}")
break
elif event == 'Stop':
exit()
break
# Close GUI window
window.close()
In above code - I tried to create a stop button and when I click on 'Process' my sg.window is freeze and i can not press on button until it completes. So, basically stop button is useless.
Updated - I tried to used flag
import time
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
from peak_shave.peak_shave_reader import Peakshave_Reader
from Seb.profit_calculator_dataclass_neu import *
from peak_shave.raw_data_setup_profit_calculator import Raw_data_from_Peak_shave, peak_shave_final_data
import PySimpleGUI as sg
from tkinter.filedialog import askopenfilename
import sys
import threading
import pythoncom
# Define a flag to indicate whether the function should stop running or not
stop_flag = False
def Python_profitcalculator_simulation(excel_path):
global stop_flag
progress_bar.update(10) # 10% of progress for funtion loads
excel_workbook = Peakshave_Reader(excel_path)
progress_bar.update(20) # 20% of progress for excel sheet load
# Reading Peak_shave excel
Pv_Profile_Raw = Raw_data_from_Peak_shave.PV_profile_raw(excel_workbook)
Load_Profile_raw = Raw_data_from_Peak_shave.Load_profile_raw(excel_workbook)
Investtabelle_Raw = Raw_data_from_Peak_shave.Investtabelle_raw_data(excel_workbook)
battery_raw_Eingabe_Übersicht_sheet = Raw_data_from_Peak_shave.Raw_data_from_Eingabe_Übersicht_sheet(excel_workbook)
battery_raw_Simulation_sheet = Raw_data_from_Peak_shave.Raw_data_from_Simulation_sheet(excel_workbook)
battery_raw_AdvanceSettingsDatabase_sheet = Raw_data_from_Peak_shave.Raw_data_from_AdvanceSettingsDatabase_sheet(excel_workbook)
battery_raw_Wirtschaftlichkeitsmatrix_sheet = Raw_data_from_Peak_shave.Raw_data_from_Wirtschaftlichkeitsmatrix_sheet(excel_workbook)
Wirtschaftlichkeitsmatrix_Raw = Raw_data_from_Peak_shave.wirtschaftlichkeitsmatrix_sheet_battery_configuration_values(excel_workbook)
# Convertion of values in SI unit
PV_Profile = peak_shave_final_data.PVprofile_conversion_setup(Pv_Profile_Raw)
Load_Profile = peak_shave_final_data.Loadprofile_conversion_setup(Load_Profile_raw)
Eingabe_Übersicht_sheet = peak_shave_final_data.Eingabe_Übersicht_conversion(battery_raw_Eingabe_Übersicht_sheet)
Simulation_sheet = peak_shave_final_data.Simulation_convertsion(battery_raw_Simulation_sheet)
AdvanceSettingsDatabase_sheet = peak_shave_final_data.AdvanceSettingsDatabase_conversion(battery_raw_AdvanceSettingsDatabase_sheet)
Wirtschaftlichkeitsmatrix_sheet = peak_shave_final_data.Wirtschaftlichkeitsmatrix_conversion(battery_raw_Wirtschaftlichkeitsmatrix_sheet)
Wirtschaftlichkeitsmatrix_battery_configuration = peak_shave_final_data.Wirtschaftlichkeitsmatrix_battery_configuration_values(Wirtschaftlichkeitsmatrix_Raw)
#profile setup for simulation
p_pv = np.array(PV_Profile['PV_profile'])
p_load = np.array(Load_Profile['Load_profile'])*-1
#general input
technical_input = dict(
p_cut_consumption_W = Eingabe_Übersicht_sheet.P_cut_consumption_W,
PV_W_peak = Eingabe_Übersicht_sheet.PV_Pinstall,
cp_rate = Eingabe_Übersicht_sheet.Cp_rate,
bat_capacity_E_Wh = Eingabe_Übersicht_sheet.Battery_energy_nominal,
DoD_pu = Simulation_sheet.DoD,
p_reserve_W = Eingabe_Übersicht_sheet.Battery_Pmax_reserve,
efficiency = Eingabe_Übersicht_sheet.Battery_efficiency,
SOC_target_pu = Eingabe_Übersicht_sheet.Battery_soll_soc_1,
SOC_reserve_pu = Eingabe_Übersicht_sheet.Battery_reserve_soc_1
)
eco_input = dict(
cost_pv_per_kWp = Eingabe_Übersicht_sheet.Investment_cost_PV,
cost_bat = Eingabe_Übersicht_sheet.Investment_cost_battery,
equity = Eingabe_Übersicht_sheet.Equity_share,
duration_funding_years = Eingabe_Übersicht_sheet.Financing_period,
duration_operation_years = Eingabe_Übersicht_sheet.Observation_period
)
general = {
'technical_input' : technical_input,
'eco_input' : eco_input
}
#advanced input
tech_param = dict(
SOC_start_pu= AdvanceSettingsDatabase_sheet.Battery_soc_start,
degradation = AdvanceSettingsDatabase_sheet.Degredation,
pv_deg_per_year = AdvanceSettingsDatabase_sheet.PV_degradation_per_year, #/a
bat_deg_per_year = AdvanceSettingsDatabase_sheet.Battery_degradation
)
maintanance_spare = dict(
maintained = AdvanceSettingsDatabase_sheet.Maintained,
pv_maintain_per_akWp = AdvanceSettingsDatabase_sheet.Maintenance_cost_PV,
bat_maintain_per_akWh = AdvanceSettingsDatabase_sheet.Maintenance_cost_battery,
pv_spare_per_akWp = AdvanceSettingsDatabase_sheet.PV_spare_per_kWp,
bat_spare_per_akWh = AdvanceSettingsDatabase_sheet.Bat_spare_per_kWh
)
insurance = dict(
pv_insured = AdvanceSettingsDatabase_sheet.Consider_insurance_PV,
pv_insurance_per_akWp = AdvanceSettingsDatabase_sheet.PV_insurance, #/kWp * a
bat_insured = AdvanceSettingsDatabase_sheet.Consider_insurance_bat,
bat_insurance_per_akWh = AdvanceSettingsDatabase_sheet.Battery_insurance #/kWp * a
)
finance = dict(
borrowed_interest = AdvanceSettingsDatabase_sheet.Borrowing_rate
)
tax = dict(
corporate_tax = AdvanceSettingsDatabase_sheet.Corporate_tax,
trade_tax = AdvanceSettingsDatabase_sheet.Trade_tax
)
discount = dict(
discounted = AdvanceSettingsDatabase_sheet.Consider_discounting,
discounting = AdvanceSettingsDatabase_sheet.Discount
)
price_per_unit = dict(
cost_current_jbd_below_per_kWh = AdvanceSettingsDatabase_sheet.Electricity_price_jbd_above_per_kWp,
cost_current_jbd_above_per_kWh = AdvanceSettingsDatabase_sheet.Electricity_price_jbd_below_per_kWp,
cost_power_jbd_below_per_kW = Eingabe_Übersicht_sheet.Power_price_jbd_above_per_kWp,
cost_power_jbd_above_per_kW = Eingabe_Übersicht_sheet.Power_price_jbd_below_per_kWp,
revenue_injected_current_per_kWh = Eingabe_Übersicht_sheet.Feedin_with_PPA_Direct_feedin_PV,
staggering_current_per_year = AdvanceSettingsDatabase_sheet.Electricity_price_increase_rate
)
lease = dict(
leased = AdvanceSettingsDatabase_sheet.Consider_lease,
needed_space_pv_ha_per_MWp = AdvanceSettingsDatabase_sheet.PV_space_requirement,
needed_space_bat_ha_per_MWh = AdvanceSettingsDatabase_sheet.Battery_space_requirement,
lease_pv_per_ha = AdvanceSettingsDatabase_sheet.PV_lease,
lease_bat_per_ha = AdvanceSettingsDatabase_sheet.Battery_lease
)
advanced = {
'tech_param': tech_param,
'maintanance_spare' : maintanance_spare,
'insurance' : insurance,
'finance' : finance,
'tax' : tax,
'discount' : discount,
'price_per_unit' : price_per_unit,
'lease' : lease
}
#other input not important
other_input = dict(
abschreibung_pv = 25_000,
abschreibung_bat = 13_750.66
)
profit_calc_params = {
'general' : general,
'advanced' : advanced,
'other_input' : other_input
}
W_matrix = {'energy_column_1': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_1,
'energy_column_2' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_2,
'energy_column_3': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_3,
'energy_column_4' :Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_4,
'energy_column_5': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_5,
'energy_column_6': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_6,
'energy_column_7' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_7,
'energy_column_8' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_8,
'energy_column_9' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_9,
'energy_column_10' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_10}
W_matrix_bool = {'energy_column_1': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_1_bool,
'energy_column_2' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_2_bool,
'energy_column_3': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_3_bool,
'energy_column_4' :Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_4_bool,
'energy_column_5': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_5_bool,
'energy_column_6': Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_6_bool,
'energy_column_7' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_7_bool,
'energy_column_8' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_8_bool,
'energy_column_9' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_9_bool,
'energy_column_10' : Wirtschaftlichkeitsmatrix_battery_configuration.energy_column_10_bool}
W_matrix_C_rate = {'C_Rate_row_1' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_1,
'C_Rate_row_2' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_2,
'C_Rate_row_3' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_3,
'C_Rate_row_4' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_4,
'C_Rate_row_5' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_5}
W_matrix_C_rate_bool = {'C_Rate_row_1' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_1_bool,
'C_Rate_row_2' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_2_bool,
'C_Rate_row_3' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_3_bool,
'C_Rate_row_4' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_4_bool,
'C_Rate_row_5' : Wirtschaftlichkeitsmatrix_battery_configuration.C_Rate_row_5_bool}
# Investtabelle battery cost setup
bats = []
for key in W_matrix:
if W_matrix_bool[key] == 'berechnen':
bats.append(W_matrix[key])
rates = []
for key in W_matrix_C_rate:
if W_matrix_C_rate_bool[key] == 'berechnen':
rates.append(W_matrix_C_rate[key])
investtable = pd.DataFrame(index = rates, columns = bats)
for bat in bats:
for rate in rates:
if Eingabe_Übersicht_sheet.Battery_type == 'Generisch':
battery_type_key = 'PB300'
else:
battery_type_key = Eingabe_Übersicht_sheet.Battery_type
try:
investtable[bat][rate] = Investtabelle_Raw[Eingabe_Übersicht_sheet.Battery_module][battery_type_key][Eingabe_Übersicht_sheet.Installation_site]['energy'+'_'+str(int(bat/1000))+'_C_rate_'+str(rate)]
except KeyError:
investtable[bat][rate]= 0
print("KeyError:", rate)
battery_type = Eingabe_Übersicht_sheet.Battery_type
SOC_res1 = Eingabe_Übersicht_sheet.Battery_reserve_soc_1
SOC_res2 = Eingabe_Übersicht_sheet.Battery_reserve_soc_2
SOC1_max = Wirtschaftlichkeitsmatrix_sheet.Soll_soc_1_max
SOC1_min = Wirtschaftlichkeitsmatrix_sheet.Soll_soc_1_min
SOC2_max = Wirtschaftlichkeitsmatrix_sheet.Soll_soc_2_max
SOC2_min = Wirtschaftlichkeitsmatrix_sheet.Soll_soc_2_min
SOC_step_percent = Wirtschaftlichkeitsmatrix_sheet.Step_size_soc
accuracy = Wirtschaftlichkeitsmatrix_sheet.Break_off_precision_peakshaving
finanzierung = Wirtschaftlichkeitsmatrix_sheet.Financing
SOC_start = AdvanceSettingsDatabase_sheet.Battery_soc_start
year_list = get_year_list(Eingabe_Übersicht_sheet.Battery_soll_soc_2_start,Eingabe_Übersicht_sheet.Battery_soll_soc_2_end)
timestep =0.25 #=15min
progress_bar.update(50) # 50% of progress for pre process done and simulation is starting
# Simulation
amount_SOCs = Wirtschaftlichkeitsmatrix_sheet.Number_of_SOCs
algorithm = Wirtschaftlichkeitsmatrix_sheet.Algorithm_for_12_SOCs
simulation = Wirtschaftlichkeitsmatrix_sheet.Year_simulation_of_the_best_system
if amount_SOCs == 2:
w_matrix, wartung = w_matrix_modular_excel(p_load, p_pv,0,SOC_res1, SOC_res2, SOC_start, SOC1_min, SOC1_max, SOC2_min, SOC2_max,SOC_step_percent, accuracy, Wirtschaftlichkeitsmatrix_sheet.Consideration_case,finanzierung,bats,rates, profit_calc_params, investtable, battery_type,year_list, timestep)
else:
if algorithm == 'dispatcher':
algo = 1
elif algorithm == 'brute-force':
algo = 2
else:
algo = 3
w_matrix = w_matrix_modular_monthly(algo, p_load, p_pv, SOC_start, SOC1_min, SOC1_max, SOC_step_percent, Wirtschaftlichkeitsmatrix_sheet.Consideration_case,finanzierung,bats,rates, profit_calc_params, investtable, battery_type, timestep)
system,bat_capacity_E,c_rate = get_most_profitable_system(w_matrix)
progress_bar.update(80) # 80% of progress for Simulation done and writing results
if simulation == 'EXCEL' and amount_SOCs == 2:
Peakshave_Reader.write_Best_system_to_excel(excel_workbook,number_of_SOCs=amount_SOCs,matrix_data=system,bat_energie=bat,c_rate=c_rate)
Peakshave_Reader.write_matrixdata_SOCs_to_excel(excel_workbook,number_of_SOCs=amount_SOCs,Profit_calculator_matrix_result=w_matrix)
##just write the data back, no simulatioon
elif simulation == 'BETSI':
pass
#results = GlobalFactory
#write it back
else:
results = do_simulation_with_numba(p_load, p_pv, system, bat_capacity_E, c_rate, battery_type, SOC_start, year_list)
Peakshave_Reader.write_Best_system_to_excel(excel_workbook,number_of_SOCs=amount_SOCs,matrix_data=system,bat_energie=bat,c_rate=c_rate)
Peakshave_Reader.write_data_to_excel(excel_workbook,data=results)
Peakshave_Reader.write_matrixdata_SOCs_to_excel(excel_workbook,number_of_SOCs=amount_SOCs,Profit_calculator_matrix_result=w_matrix)
#write it back
progress_bar.update(100) # 100% process completed
while True:
# Check the stop flag and break out of the loop if it's set to True
if stop_flag:
break
def run_simulation(excel_path):
global stop_flag
start_time = time.time()
# Create a new thread to run the simulation function
simulation_thread = threading.Thread(target=Python_profitcalculator_simulation, args=(excel_path,))
simulation_thread.start()
# Wait for the simulation to complete or for the stop button to be pressed
while simulation_thread.is_alive():
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel':
break
elif event == 'Stop':
stop_flag = True
break
# Calculate the simulation time and show a message
end_time = time.time()
if not stop_flag:
sg.popup(f"Processing complete!\nSimulation total time: {(f'{((end_time - start_time)/60):.2f} minutes' if (end_time - start_time) >= 60 else f'{(end_time - start_time):.2f} seconds')}")
# Define GUI layout
layout = [[sg.Text("Python Peak Shave Simulation:")], # For title
[sg.ProgressBar(100, orientation='h', size=(20, 20), key='-PROGRESS-')], # progress bar configuration
[sg.Button("Process"), sg.Button("Stop")]] # Stop button configuration
# Create GUI window
window = sg.Window("Peak Shave Simulation", layout, icon="C:\Env\Profit_calculator\Tricera-logo.ico") # main window configuration
progress_bar = window['-PROGRESS-']
# Event loop
event, values = window.read()
if event == sg.WIN_CLOSED : # if closed or click on cancel button window will close
window.close()
elif event == 'Process':
excel_path = sys.argv[1]
if excel_path == '':
sg.popup('Please select an Excel file.')
else:
run_simulation(excel_path)
elif event == 'Stop':
# This event will only be triggered if the simulation is running
stop_flag = True
window.close()
exit()
I added thread and flag but, i dont know what i am doing wrong. I am getting this error
File "C:\Python395\lib\threading.py", line 980, in _bootstrap_inner
self.run()
File "C:\Python395\lib\threading.py", line 917, in run
self._target(*self._args, **self._kwargs)
File "C:\Env\profit_calculator_2.py", line 257, in Python_profitcalculator_simulation
Peakshave_Reader.write_Best_system_to_excel(excel_workbook,number_of_SOCs=amount_SOCs,matrix_data=system,bat_energie=bat,c_rate=c_rate)
File "C:\Env\peak_shave\peak_shave_reader.py", line 151, in write_Best_system_to_excel
app = xw.App(visible=False)
File "C:\Env\Profit_Calculator_env\lib\site-packages\xlwings\main.py", line 294, in __init__
self.impl = engines.active.apps.add(
File "C:\Env\Profit_Calculator_env\lib\site-packages\xlwings\main.py", line 203, in add
return App(impl=self.impl.add(**kwargs))
File "C:\Env\Profit_Calculator_env\lib\site-packages\xlwings\_xlwindows.py", line 497, in add
return App(spec=spec, add_book=add_book, xl=xl, visible=visible)
File "C:\Env\Profit_Calculator_env\lib\site-packages\xlwings\_xlwindows.py", line 521, in __init__
self._xl = COMRetryObjectWrapper(DispatchEx("Excel.Application"))
File "C:\Env\Profit_Calculator_env\lib\site-packages\win32com\client\__init__.py", line 145, in DispatchEx
dispatch = pythoncom.CoCreateInstanceEx(
pywintypes.com_error: (-2147221008, 'CoInitialize wurde nicht aufgerufen.', None, None)