Google Sheets
I would like to create a macro to highlight text or cells in Google Sheets with a Streamdeck button. How would I program the ability to select the browser window "fill color: yellow" menu item in Google Sheets and have that be a button on my Streamdeck? I was able to make it fairly easily in Keyboard Maestro using a keyboard trigger but am lost on Soundflow or how to access my Streamdeck.
Cheers!
Lij
PS Here is an XML of my KM macro:
Actions ActionUID 54800 KeyCode 44 MacroActionType SimulateKeystroke Modifiers 2048 ReleaseAll TargetApplication TargetingType Front ActionUID 54802 IsActive MacroActionType Pause Time .5 TimeOutAbortsMacro Action ByPasting ActionUID 54798 MacroActionType InsertText Text fill color: yellow ActionUID 54801 IsActive MacroActionType Pause Time 1 TimeOutAbortsMacro ActionUID 54797 KeyCode 76 MacroActionType SimulateKeystroke Modifiers 65536 ReleaseAll TargetApplication TargetingType Front CreationDate 696807648.76429796 CustomIconData KMEP-MultiAction ModificationDate 696808574.22742999 Name Highlight Color Triggers FireType Pressed KeyCode 4 MacroTriggerType HotKey Modifiers 768 UID D73C195A-B8F9-4EE9-8496-D9415BDA710D- Raphael Sepulveda @raphaelsepulveda2023-02-03 00:44:18.995Z2023-02-03 00:53:17.897Z
Hey @Lij_Shaw !
Here's a translation from your Keyboard Maestro macro to a SoundFlow script. You can create a new script command and paste the following in there:
// Bring up the search menu toolbar from the Help menu sf.keyboard.press({ keys: "alt+slash" }); sf.wait({ intervalMs: 500 }); sf.keyboard.type({ text: "fill color: yellow" }); sf.wait({ intervalMs: 1000 }); sf.keyboard.press({ keys: "numpad enter" });
Then add this script to be triggered with one of your Stream Deck buttons, as shown at the end of this video: https://youtu.be/KugAJId1WBQ?t=469
With SoundFlow, we usually recommend using UI automation instead of keystrokes and replacing fixed wait times with dynamic ones. In this case, it's a little more complex since we're dealing with a webpage containing dozens of elements nested within each other, so it's okay to use the simpler approach. But in case you're curious here's how that would go—assuming your using Chrome:
/** * @param {object} obj * @param {AxElement} obj.element - Element to search * @param {string} obj.role - ie. AXPopUpButton, AXButton * @param {string} obj.description - Element description to look for * @returns {AxElement} */ function getElement({ element, role, description }) { if (element.role === role && element.getString("AXDescription") === description) { return element; } if (element.children.count) { let targetElement; element.children.some(child => { targetElement = getElement({ element: child, role, description }); return !!targetElement; }); return targetElement; } } function googleSheetsFillColor({ color }) { const chrome = sf.ui.app("com.google.Chrome"); const toolbar = chrome.mainWindow.groups.first.groups.first.groups.first.groups.first .children.whoseRole.is("AXWebArea").first; const fillColor = toolbar.groups.first.groups.whoseDescription.is("Menu bar").first .groups.allItems[4].groups.allItems[1].groups.first .children.whoseRole.is("AXToolbar").whoseDescription.is("Main").first .popupButtons.whoseDescription.is("Fill color").first .groups.first.groups.first.groups.first.groups.first.groups.first; const colorPalette = toolbar.groups.first.children.whoseRole.is("AXMenu").first; chrome.appActivateMainWindow(); fillColor.elementClick(); colorPalette.elementWaitFor(); const colorButton = getElement({ element: colorPalette, role: "AXGroup", description: color }); colorButton.elementClick(); colorPalette.elementWaitFor({ waitType: "Disappear" }); } googleSheetsFillColor({ color: "yellow" });
Hope that helps!
- LLij Shaw @Lij_Shaw
Thanks dude!