0

I want that when the button is clicked (which is just an image within the cell), the function to translate the text is fired:

screenshot with self-explanatory arrows

When using onSelectionChange, the following error is output:

Exception: You do not have permission to call UrlFetchApp.fetch. Required permissions: https://www.googleapis.com/auth/script.external_request

I've also tried with onSelectionChangeHandler, but nothing happens in that case (it doesn't seem to executed at all)

Please note I've on appscript.json that: https://www.googleapis.com/auth/script.external_request:

{
  "timeZone": "Europe/Warsaw",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": ["https://www.googleapis.com/auth/script.scriptapp", "https://www.googleapis.com/auth/spreadsheets.currentonly", "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/script.container.ui", "https://www.googleapis.com/auth/script.external_request"],
  "runtimeVersion": "V8"
}

Please note I've tried both by naming the function with onSelectionChangeHandler and onSelectionChange, adding the trigger manually:

Owned by Last run Deployment Event Function Error rate
Me May 24, 2023, 2:57:16 PM Head From spreadsheet - On change onSelectionChange 100%
Me May 24, 2023, 2:57:16 PM Head From spreadsheet - On edit onEditHandler 8%

And also in the code:

function installTriggers() {
  var sheet = SpreadsheetApp.getActive();
  ScriptApp.newTrigger("onEditHandler")
    .forSpreadsheet(sheet)
    .onEdit()
    .create();
  ScriptApp.newTrigger("onSelectionChange")
    .forSpreadsheet(sheet)
    .onChange()
    .create();
}

function onOpen(e) {
  SpreadsheetApp.getUi()
    .createMenu('install menu')
    .addItem('Install script (1/2): Give permissions', 'installTriggers')
    .addToUi();
}

This is the function that is working:

function onEditHandler(e) {
  if (!e) {
    throw new Error(
      'Please do not run the onEdit(e) function in the script editor window. '
      + 'It runs automatically when you hand edit the spreadsheet.'
    );
  }

  var r = e.source.getActiveRange();

  // To translate with DeepL the column C (column 3):
  if (r.getColumn() == 3 && r.getRow() > 4 && r.getRow() < 75) {
    var toLang = SpreadsheetApp.getActiveSheet().getName();
    if (toLang == "ES" || toLang == "IT" || toLang == "FR" || toLang == "DE") {
      r.offset(0, -2).setValue(DEEPL2(e.value, toLang, "en"));
    }
  }

}

But the following fails with the mentioned Exception:

function onSelectionChange(e) {
  var sheet = e.source.getActiveSheet();
  var range = e.range;

 range = e.source.getActiveRange();


  // Check if the selected range intersects with column B
  if (range.getColumn() == 2) {
    var row = range.getRow();
    var text = sheet.getRange(row, 3).getValue();

    var toLang = sheet.getName();
    if (toLang == "ES" || toLang == "IT" || toLang == "FR" || toLang == "DE") {
      var translatedText = DEEPL2(text, toLang, "en");
      var targetRange = range.offset(0, -1);
      targetRange.setValue(translatedText);
    }
  }
}

Intuitively, I think the reason of why it's not working may be related to the following affirmation I found in the official documentation:

To activate this trigger, you must refresh the spreadsheet once the trigger is added and every time the spreadsheet is opened.

I've refreshed the spreadsheet, but I got that exception over and over:

screenshot of the error

No error is shown in the logs:

logs screenshot

chelder
  • 3,819
  • 6
  • 56
  • 90
  • onSelectionChange is a simple trigger so it cannot perform operations that require permission. – Cooper May 24 '23 at 19:46
  • Why do you need `onSelectionChange` trigger? You said you want to execute when clicked, not when changed. To simplify, an easy workaround would be to write a custom formula that call your API – Waxim Corp May 25 '23 at 12:01
  • @WaximCorp may you give an example? **I've not found** a way to write **custom formula that call an API when a cell is clicked** (eg when `B5` is clicked, it gets the data of `C5` and output the text at `A5`. Same of `B6`, `B7`...). Please note that when an **image is over cell**, I can click on the 3 dots and `Assign script`. But when the **image is in cell**, I didn't find a way. How to call a function when a cell is clicked or an image in a cell is clicked? – chelder May 25 '23 at 14:40
  • @Cooper that's good to know to reduce my level of craziness! haha If you know any way to do it, please share :) – chelder May 25 '23 at 14:42

2 Answers2

1

I understand that the function DEEPL2 contains a UrlFetchApp.fetch() call. I was able to reproduce the issue and it is occurring because Google Apps Script is recognizing the function onSelectionChange() as a simple trigger.

Based on Google Reference related to simple triggers Restrictions:

Cannot access services that require authorization.

The approach to create Installable Triggers instead is appropriate but you'll need to make sure that the functions are not named the same as simple triggers, otherwise Google Apps Script will attempt to run those as well. You could try resetting the application by:

  1. Deleting all installed triggers at Triggers -> Delete trigger
  2. Change the name of the function back to onSelectionChangeHandler()
function onSelectionChangeHandler(e) {
  var sheet = e.source.getActiveSheet();
  var range = e.range;

 range = e.source.getActiveRange();
...
  1. Update the installTriggers() funtion to include the new function name:
...
  ScriptApp.newTrigger("onSelectionChangeHandler")
    .forSpreadsheet(sheet)
    .onChange()
    .create();
...
  1. Install the triggers via menu one more time.

References:

Bryan Monterrosa
  • 1,385
  • 1
  • 3
  • 13
  • Thanks for your reply! Unfortunately, nothing seem to be executed. On the Execution section, the latest function shown is `installTriggers`, I also reloaded the sheet. The trigger is there after the installation by clicking on the menu, but the function is not executed at all no idea of why. I also try with double click instead single click. I'm out of ideas. – chelder May 24 '23 at 19:07
1

Problems:

  • You can't execute UrlFetch with simple trigger
  • By inserting an image inside a cell, and attaching an Apps Script function on it, you can't access the env (row/column/...).
  • clicking on image does not trigger onEdit/onChange event

Regarding what you are trying to do, here two workarounds I'm suggesting :

  1. custom Apps Script function: This method will execute the translate in (almost) realtime everytime you modify the source cell.

Open Apps Script Editor from Google Spreadsheet and add the following function

function customTranslate(value, langue) {

  const options = {
    "method" : "post",
    "payload" : {
      "content_to_translate": value,
      "langue": langue
    }
  }

  const r = UrlFetchApp.fetch(<<YOUR_ENDPOINT>>, options);
  return r.getContentText();
}

//for testing:
//function customTranslate(value, langue) {
//  return value + " (translated)";
//}

Add the function as a formula with the parameters in the Google Spreadsheet enter image description here

--

  1. Trigger with checkboxes: replacing the image with a checkboxes in order to trigger onChange event

enter image description here

Add a custom onEdit function :

function onEditCustom(e) {

  //console.log(e);

  const column = e.range.getColumn();
  const row = e.range.getRow();

  if (e.value === "TRUE") {
    //get the value (with col and row)
    //call api
    //write the return
  }

}

Then, add the trigger manually in the project section:

  • Create new trigger
  • Select the function
  • Select onChange
  • Confirm

Each time the checkboxe is checked, it will execute the function

Waxim Corp
  • 657
  • 4
  • 16
  • The first workaround (**-1- custom Apps Script function**) doesn't work well to me because the function is called several times each time the Google Sheet is opened, so the API usage limit is consumed really quick. But the second idea is perfect to me (**-2- Trigger with checkboxes**). At the end of the function, I've included: `range.setValue(false);` to untick back the checkbox once the translation is done. It's just more elegant to me. Thanks sir! – chelder May 27 '23 at 16:06