1

Google Slides has a option under tools >> Linked Objects called "Update all":

Screenshoot of Linked Objects menu

This option updates all elements in the Presentation. Something similar can be done with Google App Scripts, but unfortunately it does not update tables, it only updates charts. So this solution and other similar workarounds do not work for my project.

I have used Selenium to automate some tasks in other websites, but the elements in Google Slides apparently change their values dynamically. So I could not use something like:

tool_menu = wd.find_element(By.CSS_SELECTOR, 'menu.tool')
tool_menu.click()

Is there a way to navigate to Linked Objects and click on Update all using Selenium?

EDIT:

After some back and forward with a very helpful user, this is the final working code:

# Stuff to make this run on google Colab

!pip install selenium
!apt-get update # to update ubuntu to correctly run apt install
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
import sys
sys.path.insert(0,'/usr/lib/chromium-browser/chromedriver')
from selenium import webdriver
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
wd = webdriver.Chrome('chromedriver',chrome_options=chrome_options)

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
import time

wd.get("https://docs.google.com/presentation/d/[id]/")
from IPython.core.display import Image, display
file_name = "part.png"
wd.set_window_size(1920,1080)
wd.get_screenshot_as_file(file_name)
display(Image(file_name))

# open Tools menu
wd.find_element(By.ID,'docs-tools-menu').click()
time.sleep(1) #this is not optimal, you should use explicit waiters
wd.get_screenshot_as_file(file_name)
display(Image(file_name))

menus = wd.find_elements(By.XPATH, '//div[@role="menu"]')
menu = None
# loop through menus to find the visible one
for m in menus:
    if m.is_displayed():
        menu = m
        break
assert menu

# select the menu item
menu_label = "Linked objects" #change according to you language
item = menu.find_element(By.XPATH,'//span[contains(@aria-label, "%s")]' % menu_label)
item.click()
time.sleep(3) #this is not optimal, you should use explicit waiters

wd.get_screenshot_as_file(file_name)
display(Image(file_name))

# ------- I would use this
refresh_label = "Refresh" # change according to your language (see DOM for the correct label)
refresh_btn = wd.find_element(By.XPATH,'//div[contains(@aria-label, "%s")]' % refresh_label)
# --------
refresh_btn.click()
time.sleep(3)

wd.get_screenshot_as_file(file_name)
display(Image(file_name))


#select update all button
update_all_btn = wd.find_element(By.XPATH,'//div[contains(@class, "update-all-button")]')
update_all_btn.click()
Rubén
  • 34,714
  • 9
  • 70
  • 166
user3347814
  • 1,138
  • 9
  • 28
  • 50

1 Answers1

2

Hy there, I used the following code

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

options = Options()
# I used an already opened Chrome because the signin is not the purpose of this test and I was already signed in on my Google account
options.add_experimental_option("debuggerAddress", "127.0.0.1:1024")
driver = webdriver.Chrome(
    chrome_options=options,
)
driver.get("https://docs.google.com/presentation/d/[...your id...]")
driver.maximize_window()

# open Tools menu
driver.find_element_by_id('docs-tools-menu').click()
time.sleep(1) #this is not optimal, you should use explicit waiters
menus = driver.find_elements_by_xpath('//div[@role="menu"]')
menu = None
# loop through menus to find the visible one
for m in menus:
    if m.is_displayed():
        menu = m
        break
assert menu
# select the menu item
menu_label = "Oggetti collegati" #change according to you language
item = menu.find_element_by_xpath('//span[contains(@aria-label, "%s")]' % menu_label)
item.click()
time.sleep(3) #this is not optimal, you should use explicit waiters

# select update all button
update_all_btn = driver.find_element_by_xpath('//div[contains(@class, "update-all-button")]')
update_all_btn.click()

Here you can see the effect enter image description here

Since something could change due to the different language, please feel free to report any doubt: I will be glad to improve or change my code to help you better.

Mattia Galati
  • 2,415
  • 16
  • 22
  • I've tried your solution, but could not make it work. https://colab.research.google.com/drive/1aIoHejsWIurmz5ox__uJIOJu1WS7SBkN#scrollTo=sxiyQ9pGNhMI Could you give me any more advice, please? – user3347814 Nov 19 '21 at 13:46
  • 1
    @user3347814 I've edited the notebook you linked, and used the document in my demo (I publicly shared it). Corrected some errors and took several screenshots. Please ensure to execute the steps in order since the Tools menu would close after some time, and change menu label according to your language. Also keep in mind that, if the linked documents are unchanged, the "Update All" button will not be present – Mattia Galati Nov 19 '21 at 14:11
  • I have tried adding a step where it clicks on the refresh button before it clicks in update all. But it didn't work (https://colab.research.google.com/drive/1aIoHejsWIurmz5ox__uJIOJu1WS7SBkN#scrollTo=JzhmRTZKhlry) This is the only thing missing. – user3347814 Nov 19 '21 at 14:32
  • 1
    The selector you used is not related to the button you are trying to reach. I've added another selector in your code on colab, check it out. – Mattia Galati Nov 19 '21 at 15:23
  • I'm still getting this error: InvalidSelectorException: Message: invalid selector: Unable to locate an element with the xpath expression //div[@aria-label, "Refesh"] because of the following error: SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//div[@aria-label, "Update"]' is not a valid XPath expression. – user3347814 Nov 19 '21 at 21:20
  • I've tried both refresh_label = "Update" and refresh_label = "Refresh". – user3347814 Nov 19 '21 at 21:21
  • 1
    Changed in "Refresh" and the xpath as well, this way should work. – Mattia Galati Nov 20 '21 at 09:29
  • I worked perfectly. Thank you so much. I've awarded the bounty. I've learn a lot from this, but I still have trouble finding the right element to use. Do you have any tips on how to do this? – user3347814 Nov 20 '21 at 19:15
  • 1
    I'm glad it worked. My suggest is start from [here](https://www.selenium.dev/documentation/webdriver/locating_elements/#tips-on-using-selectors). If you discover Xpath is the right choice among others, install an extension like [this](https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl?hl=en) and check your expressions in realtime before using them in selenium – Mattia Galati Nov 20 '21 at 21:15