title: A multi-input PySimpleGUI for a working python script
body: <p>I'm using a working script built in python 3 that reads an excel file. Using the input, it figures out which VIP (Virtual IP) subnet I should use and which F5 load balancer the VIP should be matched with, and then spits out the cli commands needed to configure on the load balancer as another file. I want to know if it's possible to add a basic GUI to this using the code I have below. Based on that, it will create a file on my desktop with the commands I need to configure taken from the excel file and input given. If the information is blank within excel it will prompt and ask you. An edited example of a simple working script that runs is shown below:</p>
  
  <pre><code>import pandas as pd
  import datetime
  from netaddr import IPNetwork, IPAddress, IPSet
  import os
  import glob
  import shutil
  
  
  def createfolder(directory):
      try:
          if not os.path.exists(directory):
              os.makedirs(directory)
      except OSError:
          print('Error: Creating directory. ' + directory)
  
  
  global options
  global member
  global lb_mode
  global pool_member1
  global pool_member2
  global pool_member3
  global pool_member4
  global cert
  global iRule1
  global iRule2
  global rules
  global one_connect
  global http_profile
  global primary_persist
  global fallback_persist
  global snat
  global rule_member_1
  global rule_member_2
  global rule_member_3
  global irules
  global profiles
  global loadbalancer
  global subnet
  global ssl_profile_name
  global ssl_config
  
  x = datetime.datetime.now()
  change_order = input("What is the change order for this VIP? ")
  lbarf_file = str(input("Enter the full path of the LBARF form. ").strip('\"'))
  description = "description " + change_order
  df = pd.read_excel(lbarf_file)
  
  # Info pulled from the LBARF
  service_port_input = str(df.iloc[13, 2])
  http_profile_input = df.iloc[33, 2]
  primary_persist_input = df.iloc[34, 2]
  fallback_persist_input = df.iloc[35, 2]
  iRule1_input = df.iloc[42, 2]
  iRule2_input = df.iloc[43, 2]
  snat_input = df.iloc[47, 2]
  one_connect_input = df.iloc[48, 2]
  fqdn = str(df.iloc[12, 2]).lower()
  member1 = str(df.iloc[19, 2])
  member2 = str(df.iloc[20, 2])
  member3 = str(df.iloc[21, 2])
  member4 = str(df.iloc[22, 2])
  pool_port1 = str(df.iloc[19, 4])
  pool_port2 = str(df.iloc[20, 4])
  pool_port3 = str(df.iloc[21, 4])
  pool_port4 = str(df.iloc[22, 4])
  lb_mode_input = df.iloc[32, 2]
  pool_name = str(fqdn + "-" + pool_port1)
  monitor_input = df.iloc[36, 2]
  
  # Pool builder
  if member1 == "nan":
      pool_member1 = ""
  elif member1 != "nan":
      pool_member1 = member1 + ":" + pool_port1 + " "
  else:
      pass
  if member2 == "nan":
      pool_member2 = ""
  elif member2 != "nan":
      pool_member2 = member2 + ":" + pool_port2 + " "
  else:
      pass
  if member3 == "nan":
      pool_member3 = ""
  elif member3 != "nan":
      pool_member3 = member3 + ":" + pool_port3 + " "
  else:
      pass
  if member4 == "nan":
      pool_member4 = ""
  elif member4 != "nan":
      pool_member4 = member4 + ":" + pool_port4 + " "
  else:
      pass
  
  
  if lb_mode_input == "Round Robin":
      lb_mode = "load-balancing-mode round-robin "
  elif lb_mode_input == "Least connections":
      lb_mode = "load-balancing-mode least-connections-node "
  elif lb_mode_input == "Observed":
      lb_mode = "load-balancing-mode observed-node "
  else:
      pass
  
  if monitor_input == "TCP":
      monitor = "monitor tcp "
  elif monitor_input == "TCP 30 seconds":
      monitor = "monitor tcp-30 "
  elif monitor_input == "Self-Service":
      monitor = "monitor self-service "
  elif monitor_input == "None":
      monitor = ""
  else:
      monitor = " monitor " + input("Please enter the health monitor name: ") + " "
  
  member = IPAddress(member1)
  
  # Lists for each LB pair containing the node subnets.
  loadbalancer1_node_IPs = IPSet([IPNetwork('1.1.1.0/22'), IPNetwork('2.2.2.0/22'), IPNetwork('3.3.3.0/22')])
  loadbalancer2_node_IPs = IPSet([IPNetwork('4.4.4.0/23'), IPNetwork('2.2.2.0/23'), IPNetwork('3.3.3.0/23')])
  
  # Provides the LB the VIP is to be built on based on node IP address.
  if IPAddress(member) in loadbalancer1_node_IPs:
      loadbalancer = "The LB pair you need to build this VIP on is loadbalancer1_node_IPs"
      subnet = "You need a VIP ip from subnet 1.1.1.0/22, 2.2.2.0/22, or 3.3.3.0/22"
  elif IPAddress(member) in loadbalancer2_node_IPs:
      loadbalancer = "The LB pair you need to build this VIP on is loadbalancer2_node_IPs"
      subnet = "You need a VIP ip from subnet 4.4.4.0/23, 2.2.2.0/23, or 3.3.3.0/23"
  else:
      pass
  
  print(loadbalancer)
  print(fqdn)
  print(subnet)
  
  vip_ip_input = IPAddress(input("Which VIP IP did you choose? "))
  vip_ip = str(vip_ip_input) + str(":") + str(service_port_input)
  ip = str(vip_ip_input)
  
  if iRule1_input == "_sys_https_redirect":
      iRule1 = "_sys_https_redirect "
  elif iRule1_input == "x-Forwarding":
      iRule1 = "x-forwarding "
  else:
      iRule1 = ""
  if iRule2_input == "_sys_https_redirect":
      iRule2 = "_sys_https_redirect "
  elif iRule2_input == "x-Forwarding":
      iRule2 = "x-forwarding "
  else:
      iRule2 = ""
  
  if snat_input == "Auto Map":
      snat = "snat automap "
  else:
      snat = ""
  
  if one_connect_input == "oneconnect":
      one_connect = "oneconnect "
  else:
      one_connect = ""
  
  if http_profile_input == "http":
      http_profile = "http "
  else:
      http_profile = ""
  
  if primary_persist_input == "Source Addr":
      primary_persist = " persist replace-all-with { source_addr } "
  elif primary_persist_input == "Dest Addr":
      primary_persist = " persist replace-all-with { dest_addr } "
  elif primary_persist_input == "Cookie":
      primary_persist = " persist replace-all-with { cookie } "
  else:
      primary_persist = ""
  
  if fallback_persist_input == "Source Addr":
      fallback_persist = " fallback-persistence source_addr "
  elif fallback_persist_input == "Dest Addr":
      fallback_persist = " fallback-persistence dest_addr "
  elif fallback_persist_input == "Cookie":
      fallback_persist = " fallback-persistence cookie "
  else:
      fallback_persist = ""
  
  folder = r'C:\Users\username\Desktop\LBARF script' + str(change_order)
  
  createfolder(folder)
  
  fh = open(folder + "/" + str(change_order) + ".txt", "w")
  fh.write("This program is a test. I assume no responsibility." + "\r" +
           "Please verify everything looks correct." + "\r" + "\r" + "This script was run on " +
           x.strftime("%x") + " @ " + x.strftime("%I") + ":" + x.strftime("%M") + " " + x.strftime("%p") +
           " for change order " + change_order + "\r" + "\r" + fqdn + "\r" + ip + "\r" + loadbalancer + "\r" + "\r")
  
  fh.write("create ltm pool " + pool_name + " members add { " + pool_member1 + pool_member2 + pool_member3 +
           pool_member4  + " } " + monitor + lb_mode + description + "\r" + "\r")
  
  if service_port_input == "80 and 443":
      service_port_input = "80"
  else:
      pass
  
  if service_port_input == "80":
      if iRule1_input == "_sys_https_redirect":
          port_80_redirect_vip = ("create ltm virtual " + fqdn + "-80 destination " + ip +
                                  ":80 profiles add { http } snat automap rules { _sys_https_redirect } "
                                  + description + "\r" + "\r")
          fh.write(port_80_redirect_vip)
          print("Port 80 VIP is complete, We will now move on to the 443 VIP")
          service_port_input = "443"
          irules = "rules { " + iRule2 + " } "
      elif iRule2_input == "_sys_https_redirect":
          port_80_redirect_vip = ("create ltm virtual " + fqdn + "-80 destination " + ip +
                                  ":80 profiles add { http } snat automap rules { _sys_https_redirect } "
                                  + description + "\r" + "\r")
          fh.write(port_80_redirect_vip)
          print("Port 80 VIP is complete, We will now move on to the 443 VIP")
          service_port_input = "443"
          irules = "rules { " + iRule2 + " } "
      else:
          vip_build = ("create ltm virtual " + fqdn + "-" + service_port_input + " destination " + ip + ":" +
                       service_port_input + " pool " + pool_name + " profiles add { " + http_profile + " } " +
                       primary_persist + fallback_persist + description + "\r" + "\r")
          fh.write(vip_build)
          service_port_input = "443"
  else:
      pass
  
  if iRule1.__contains__("sys"):
      rules = "rules { " + iRule2 + " } "
  elif iRule2.__contains__("sys"):
      rules = "rules { " + iRule1 + " } "
  else:
      rules = "rules { " + iRule1 + iRule2 + " } "
  
  if service_port_input == "443":
      ssl_profile_input = input("Will you be applying an SSL profile? y or n: ").lower()
      if ssl_profile_input.__contains__("y"):
          cert = input("Installing a cert? y or n: ").lower()
          if cert.__contains__("y"):
              ssl_profile_name = fqdn + "-clientssl"
              upload_name = fqdn + "-" + x.strftime("%Y")
              print("**** SSL PROFILE CONFIG *****")
              print("**** Upload Cert/Key to " + loadbalancer + " with the name of " + upload_name)
              ssl_cert = fqdn + "-" + x.strftime("%Y") + ".crt "
              ssl_key = fqdn + "-" + x.strftime("%Y") + ".key "
              chain_input = input("Will a chain be applied? y or n: ").lower()
              if chain_input.__contains__("y"):
                  chain = " chain " + input("What is the name of the chain? ")
              else:
                  chain = ""
              ciphers_input = input("Will ciphers be applied? ").lower()
              if ciphers_input.__contains__("y"):
                  ciphers = "ciphers " + input("Enter Ciphers here: ")
              else:
                  ciphers = ""
              ssl_config = ("create ltm profile client-ssl " + ssl_profile_name + " cert " + ssl_cert + " key " +
                            ssl_key + ciphers + " " + chain + description + "\r" + "\r")
          else:
              ssl_profile_name = input("What is the SSL profile name? ")
      else:
          ssl_profile_name = ""
          cert = ""
          key = ""
          chain = ""
          ciphers = ""
          ssl_config = ""
  else:
      ssl_profile_name = ""
      cert = ""
      key = ""
      chain = ""
      ciphers = ""
      ssl_config = ""
  
  profile = "profiles add { " + one_connect + http_profile + ssl_profile_name + " } "
  if profile == "profiles add {  } ":
      profiles = ""
  else:
      profiles = ("profiles add { " + one_connect + http_profile + ssl_profile_name + " } ")
      options = (profiles + snat + primary_persist + fallback_persist + rules + description)
  
  if cert.__contains__("y"):
      fh.write(ssl_config)
  else:
      pass
  
  fh.write("create ltm virtual " + fqdn + "-" + service_port_input + " destination " + ip + ":" + service_port_input +
           " pool " + pool_name + " " + options + "\r" + "\r")
  fh.close()
  
  key_files = 'C:/Users/username/Downloads/*.key'
  crt_files = 'C:/Users/username/Downloads/*.crt'
  cer_files = 'C:/Users/username/Downloads/*.cer'
  pem_files = 'C:/Users/username/Downloads/*.pem'
  pfx_files = 'C:/Users/username/Downloads/*.pfx'
  filelist = glob.glob(key_files)
  
  for single_file in filelist:
      shutil.move(single_file, folder)
  filelist = glob.glob(crt_files)
  
  for single_file in filelist:
      shutil.move(single_file, folder)
  
  filelist = glob.glob(cer_files)
  for single_file in filelist:
      shutil.move(single_file, folder)
  
  filelist = glob.glob(pem_files)
  for single_file in filelist:
      shutil.move(single_file, folder)
  
  filelist = glob.glob(pfx_files)
  for single_file in filelist:
      shutil.move(single_file, folder)
  
  # os.rename(lbarf_file, 'C:/Users/username/Downloads/' + change_order + ".xlsx")
  shutil.move(lbarf_file, folder)
  print("The CLI commands for this VIP are located at " + folder)
  exit(input("Press Enter to exit."))
  </code></pre>
  
  <p>It was suggested to me to put the script as a function and import it to the code for the GUI which I did and named it vipTest. Next I imported it to PySimpleGUI I am using to create a simple form with here:</p>
  
  <pre><code>import vipTest
  import PySimpleGUI as sg
  
  # Very basic form.  Return values as a list
  form = sg.FlexForm('VIP Builder')  # begin with a blank form
  
  layout = [
            [sg.Text('Please enter the information below')],
            [sg.Text('What is the change order for this VIP?: ', size=(30, 1)), sg.InputText('change #')],
            [sg.Text('Enter the full path of the LBARF form: ', size=(30, 1)), sg.InputText('location path')],
            [sg.Text('Which VIP IP did you choose?: ', size=(30, 1)), sg.InputText('ip address of vip')],
            [sg.Submit(), sg.Cancel()]
           ]
  
  lbarf_file, folder = vipTest.createfolder(directory)
  
  button, values = form.Layout(layout).Read()
  </code></pre>
  
  <p>I am having trouble getting an output from the GUI of the results. When I run this program in PyCharm the GUI does not open and script runs in the console. Even if I can get the GUI to work with a specific example, I am concerned I might need to have the GUI add a text field each time the information in the excel file is blank. I would like to ultimately like to display the config commands from the gui but am not getting anywhere with it as is. Any assistance on this is greatly appreciated. Thank you.</p>