Forum Discussion
Rise 360 - Mass upload of questions into a question bank
I wonder if I can get copilot to generate the code for me?
How do I:
1. Get the format I need for the excel file?
2. Get the access (API?) into my Rise course to point the Python at?
Do you think this is a feasible solution for someone who DOESN'T know Python?
The approach doesn't use API at all. It uses Selenium to automate the browser UI exactly as we would by clicking "Add question," selecting options, tabbing between fields, and pasting text from an Excel file.
The Excel file just needs to be a standard .xlsx with each column mapped to a question field (title, answer choices, feedback, etc.) Python reads the file locally using openpyxl, so no special API access is required.
Copilot can absolutely help generate the script, but you still need PY installed and must run automation locally in a browser session where you log in manually.
NB: The approach isn't future-proof. It relies on the current interface and tab order. If the UI is updated, the automation doesn't work.
- KayneishaW8 days agoCommunity Member
Hi Paul. I literally just used AI to create a python script to turn LearnDash wpProQuiz XML exports into CSV files I could convert to XLS files because I was mistaken that Rise could do the XLS imports. It's a perfect conversion that works in seconds and is now pretty much useless without that last step.
Would you be able to video demo your process on a dummy file and share with the community?- PaulMc18 days agoCommunity Member
I'm happy to leave an example of the excel file and share the proof of concept code here.
- Excel columns with green text are used in the script.
- This automation is for creating questions with feedback by answer choice.
NB: Mentioning again, if the UI changes, this assistive code will not function. On retrying today it did not work, I assume because devs introduced 'Add Audio', thus increasing the tabs needed to navigate.(It has been updated to account for the change)
This tab-order route is brittle, far better options using selectors but even those can change.import time from pathlib import Path from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ----------------------- # CONFIG # ----------------------- EXCEL_PATH = Path(r"C:\Users\USER\ExcelQuestionFile.xlsx") # <- change SHEET_NAME = None # None = active sheet, or set a name like "Sheet1" START_ROW = 2 # row 2 of Excel file # columns referenced: # B=question title, C=?, D=?, E=?, F=?, H=?, I=?, J=?, K=? COL = { "B": "question_title", "C": "col_c", "D": "col_d", "E": "col_e", "F": "col_f", "H": "col_h", "I": "col_i", "J": "col_j", "K": "col_k", } # Timeouts / pacing WAIT_SECS = 20 PAUSE = 0.25 # ----------------------- # HELPERS # ----------------------- def wait_click(driver, css): el = WebDriverWait(driver, WAIT_SECS).until( EC.element_to_be_clickable((By.CSS_SELECTOR, css)) ) el.click() time.sleep(PAUSE) return el def wait_present(driver, css): el = WebDriverWait(driver, WAIT_SECS).until( EC.presence_of_element_located((By.CSS_SELECTOR, css)) ) return el def tab_n(driver, n): active = driver.switch_to.active_element for _ in range(n): active.send_keys(Keys.TAB) time.sleep(0.05) active = driver.switch_to.active_element def clear_active_field(driver): active = driver.switch_to.active_element active.send_keys(Keys.CONTROL, "a") active.send_keys(Keys.BACKSPACE) time.sleep(PAUSE) def type_into_active(driver, text): active = driver.switch_to.active_element # if cell is empty/None, type nothing active.send_keys("" if text is None else str(text)) time.sleep(PAUSE) def triple_click_select_all(driver): active = driver.switch_to.active_element actions = ActionChains(driver) actions.click(active).pause(0.05).click(active).pause(0.05).click(active).perform() time.sleep(0.1) # ----------------------- # MAIN # ----------------------- def main(): if not EXCEL_PATH.exists(): raise FileNotFoundError(f"Excel file not found: {EXCEL_PATH}") wb = load_workbook(EXCEL_PATH) ws = wb[SHEET_NAME] if SHEET_NAME else wb.active # Start Chrome (visible) options = webdriver.ChromeOptions() options.add_argument("--start-maximized") driver = webdriver.Chrome(options=options) wait = WebDriverWait(driver, WAIT_SECS) print("\nOpen Rise in this Chrome window.") print("1) Log in manually") print("2) Navigate manually to the Question Bank screen") input("\nWhen you're on the Question Bank page, press ENTER here to start...") row = START_ROW while True: # Read row data b = ws[f"B{row}"].value c = ws[f"C{row}"].value d = ws[f"D{row}"].value e = ws[f"E{row}"].value f = ws[f"F{row}"].value h = ws[f"H{row}"].value i = ws[f"I{row}"].value j = ws[f"J{row}"].value k = ws[f"K{row}"].value # Stop condition: if B is blank, assume we're done if b is None or str(b).strip() == "": print(f"\nRow {row}: Column B empty. Stopping.") break print(f"\nRow {row}: creating question: {b}") # 1) Click "Add Question" wait_click(driver, "button.sidebar-list__add-question-button") # 2) Click "Multiple choice" menu item # You provided: button[data-menu-item][data-name="MULTIPLE_CHOICE"] wait_click(driver, 'button[data-menu-item][data-name="MULTIPLE_CHOICE"]') # 3) Click "Any Response" trigger button any_response_btn = wait.until(EC.element_to_be_clickable( (By.XPATH, '//button[contains(@class,"menu__trigger")][.//span[contains(normalize-space(.),"Any Response")]]') )) any_response_btn.click() time.sleep(PAUSE) # 4) Select "By Choice" by_choice_li = wait.until(EC.element_to_be_clickable( (By.XPATH, '//li[contains(@class,"menu__item")][.//span[normalize-space(.)="By Choice"]]') )) by_choice_li.click() time.sleep(PAUSE) # 5) Focus question title title_div = wait.until( EC.element_to_be_clickable( ( By.XPATH, '//*[@contenteditable="true" and not(ancestor::li)]' ) ) ) title_div.click() time.sleep(0.2) # Clear existing text clear_active_field(driver) # 6) Paste Column B (question title) title_div.send_keys("" if b is None else str(b)) time.sleep(PAUSE) # 7) Tab 5, delete 8 tab_n(driver, 5) clear_active_field(driver) # 8) Paste C, tab type_into_active(driver, c) tab_n(driver, 1) # 9) Paste H, tab 2 type_into_active(driver, h) tab_n(driver, 2) # 10) delete 8, paste D, tab clear_active_field(driver) type_into_active(driver, d) tab_n(driver, 1) # 11) Paste I, tab 2 type_into_active(driver, i) tab_n(driver, 2) # 12) Paste E, tab type_into_active(driver, e) tab_n(driver, 1) # 13) Paste J, tab 2 type_into_active(driver, j) tab_n(driver, 3) # 14) Paste F, tab type_into_active(driver, f) tab_n(driver, 1) # 15) Paste K type_into_active(driver, k) # Optional: small pause to watch it time.sleep(0.5) row += 1 print("\nDone. Leaving browser open.") input("Press ENTER to close browser...") driver.quit() if __name__ == "__main__": main()
Related Content
- 11 months ago
- 1 year ago