0

I've built a PySimpleGUI app that selects a CSV,lets you select a Chrome version and then uses Selenium to do form inputs and submits. I now however need to refactor the drop down into a select like how the CSV does but cant get it to work, my code

import csv
import time
import threading
from selenium import webdriver
import PySimpleGUI as sg
import os
import sys


def resource_path(relative_path):

  try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
    base_path = sys._MEIPASS
  except Exception:
    base_path = os.path.abspath(".")

  return os.path.join(base_path, relative_path)



def make_window(theme):

    sg.theme(theme)
    menu_def = [['&Application', ['E&xit']],
                ['&Help', ['&About']] ]
    right_click_menu_def = [[], ['Exit']]

    # Table Data


    input_layout =  [[sg.Menu(menu_def, key='-MENU-')],
                 
                
                [sg.Button("Open File")],
               
                [sg.Text('Chrome Version')],

                [sg.OptionMenu(values=('96', '97', '98'),  k='-OPTION MENU-'),],
               
                [sg.Button('Submit')]]



    
    
    layout = [[sg.Text(' Email Automation', size=(38, 1), justification='center', font=("Helvetica", 16), relief=sg.RELIEF_RIDGE, k='-TEXT HEADING-', enable_events=True)]]
    layout +=[[sg.TabGroup([[  sg.Tab('Setup CSV and Chrome Version', input_layout),
                               
                               ]], key='-TAB GROUP-')]]
              
    return sg.Window('TEST', layout, right_click_menu=right_click_menu_def)


def main():
    window = make_window(sg.theme())
    
    # This is an Event Loop 
    while True:
        event, values = window.read(timeout=100)
        # keep an animation running so show things are happening
       
        if event not in (sg.TIMEOUT_EVENT, sg.WIN_CLOSED):
            print('============ Event = ', event, ' ==============')
            print('-------- Values Dictionary (key=value) --------')
            for key in values:
                print(key, ' = ',values[key])
        if event in (None, 'Exit'):
            print("[LOG] Clicked Exit!")
            break
        elif event == 'About':
            print("[LOG] Clicked About!")
            sg.popup('TEST email automation',
                     'Select CSV file',
                     'Select Chrome Version',
                     'Submit',
                     'Powered By Me')
        elif event == 'Popup':
            print("[LOG] Clicked Popup Button!")
            sg.popup("You pressed a button!")
            print("[LOG] Dismissing Popup!")


        elif event == "Open File":
            print("[LOG] Clicked Open File!")
            csv_file_selected = sg.popup_get_file('Choose your file')
            # sg.popup("You chose: " + str(folder_or_file))
            # print("[LOG] User chose file: " + str(folder_or_file))




def run_selenium(window, file, driver):

    with open(file, 'rt') as csv_file:
        csv_reader = csv.reader(csv_file)
    #-------------------------------------------------------------------------------
    # Web Automation
    driver = webdriver.Chrome(executable_path=driver,service_log_path='/dev/null')
    driver.get('https:/')
  
    
    fname_field = driver.find_element_by_xpath('//*[@id="FIRSTNAME"]')
    lname_field = driver.find_element_by_xpath('//*[@id="LASTNAME"]')
    phone_field = driver.find_element_by_xpath('//*[@id="PHONE"]')
    mail_field = driver.find_element_by_xpath('//*[@id="EMAIL"]')
    deposit_field = driver.find_element_by_xpath('//*[@id="DEPOSIT"]')
    submit = driver.find_element_by_xpath('//*[@id="sib-form"]/div[8]/div/button')

    with open(file, 'rt', encoding='utf-8-sig') as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=';')
        next(csv_reader)
        for line in csv_reader:
            
            time.sleep(2.5)
            
            fname_field.send_keys(line[10])
            lname_field.send_keys(line[11])
            mail_field.send_keys(line[13])
            phone_field.send_keys(line[16])
            deposit_field.send_keys(line[37])
            submit.click()
        
        

    # Not to update GUI in thread, but generate an event which will be processed in event loop.
    window.write_event_value('Done', None)

def main():
    # My GUI
    window = make_window(sg.theme())
    folder_or_file = None
    cdriver = resource_path('chromedriver.exe')
    # Using your path for all the drivers of all versions
    paths = {
        #'96': './chromedriver.exe',
        '96': cdriver,
        
    }

    while True:
        event, values = window.read(timeout=100)
        # keep an animation running so show things are happening

        if event not in (sg.TIMEOUT_EVENT, sg.WIN_CLOSED):
            # print('============ Event = ', event, ' ==============')
            # print('-------- Values Dictionary (key=value) --------')
            for key in values:
               print(key, ' = ',values[key])
        if event in (None, 'Exit'):
           # print("[LOG] Clicked Exit!")
            break
        elif event == 'About':
           # print("[LOG] Clicked About!")
            sg.popup('email',
                     'Select CSV file',
                     'Select Chrome Version',
                     'Submit',
                     '')
        elif event == 'Popup':
           # print("[LOG] Clicked Popup Button!")
            sg.popup("You pressed a button!")
           # print("[LOG] Dismissing Popup!")
        elif event == "Open File":
            #print("[LOG] Clicked Open File!")
            folder_or_file = sg.popup_get_file('Choose your file')
            # sg.popup("You chose: " + str(folder_or_file))
            #print("[LOG] User chose file: " + str(folder_or_file))
        elif event == 'Submit':
            version = values['-OPTION MENU-']
            if folder_or_file is None or version not in paths:
              #  print("No CSV file selected or wrong Chrome version selected")
                continue
            # Using thread to avoid long time job will block and cause GUI no response
            threading.Thread(target=run_selenium, args=(window, folder_or_file, paths[version])).start()
            # Disable Submit button to prevent submit again when threading
            window['Submit'].update(disabled=True)
          #  print('[LOG] Run Selenium ...')
        elif event == 'Done':
            # Enable Submit button when thread done
            window['Submit'].update(disabled=False)
           # print('[LOG] End Selenium')

    window.close()

main()

By allowing the chrome version to be picked it will make the whole process much easier instead of consistently rebuilding the app for every new chrome version

RawalD
  • 361
  • 2
  • 14

1 Answers1

1

Here's the suggestion for version of CromeDriver.

from pathlib import Path
from win32com.client import Dispatch

def get_version(file):
    parser = Dispatch("Scripting.FileSystemObject")
    try:
        version = parser.GetFileVersion(file).split(".")[0]
    except Exception:
        version = None
    return version

# It can be read from a json file chromedriver.json for easy update if new version
cromedriver = {
    'explorer': r'C:\Program Files\Google\Chrome\Application\chrome.exe',
    '96': r'.\96\chromedriver.exe',
    '97': r'.\97\chromedriver.exe',
    '98': r'.\98\chromedriver.exe',
}

version = get_version(cromedriver['explorer'])

if version in cromedriver:
    print(Path(cromedriver[version]).absolute())
else:
    print(f'Please download chromedriver.exe for {version} and update chromedriver.json file')
Jason Yang
  • 11,284
  • 2
  • 9
  • 23
  • Thanks so much Jason! Is there anyway you could help me with compiling this to an exe ? https://stackoverflow.com/questions/70941340/add-additional-files-into-one-file-auto-py-2-exe , Ive tried and tried but it simply will not find the files in one file mode – RawalD Feb 05 '22 at 12:20
  • I have no idea about the detail to use AutoPy 2 Exe... – Jason Yang Feb 05 '22 at 12:24
  • Ah shux alright thanks alot, is there any Python to exe way you know of ? – RawalD Feb 05 '22 at 12:30
  • What I know are `py2exe` and `pyinstaller`, but not go to detail, just run py file by python.exe or pyw file by pythonw.exe directly. – Jason Yang Feb 05 '22 at 13:23