вызов удаленного кода из google-apps-script с помощью eval - PullRequest
0 голосов
/ 13 мая 2018

Я сталкиваюсь с проблемой совместного использования сценария с помощью ряда функций, предназначенных для помощи в манипулировании различными копиями одной и той же исходной электронной таблицы Google (у каждого пользователя есть личная копия). Каждая копия электронной таблицы имеет собственную ограниченную копию сценария, поэтому, если я улучшу какую-либо функцию, мне придется обновить каждую копию сценария.

Чтобы преодолеть эту проблему, я увидел, что можно вызвать библиотеку из вашего скриптового проекта и поместить все общие функции в эту библиотеку. Некоторые ссылки, которые я прочитал:

Как я могу вызвать свой автономный скрипт в моей таблице? ; Как использовать скрипт приложений Google в нескольких документах ; Как передать ограниченный скрипт другому пользователю, чтобы он мог добавить его в свои электронные таблицы? ; Распространение скрипта Google Apps и отправка обновлений ; https://issuetracker.google.com/issues/36755072

Там вы можете увидеть несколько проблем использования этого подхода:

  • Чтобы распространять обновления вашей библиотеки (динамически, без необходимости снова прикасаться к пользовательским листам), ее необходимо включить в сценарии с ограниченным листом, используя режим разработки и предоставляя своим пользователям edit доступ к скрипту вашей библиотеки (если у них есть только доступ к просмотру, они используют статическую версию вашей библиотеки).
  • Вам необходимо изменить исходный код, ограниченный листом, чтобы функции вызывались с предшествующим именем, используемым для обозначения вашей библиотеки: libraryname.functionName () - может не быть проблемой, но я упоминаю об этом просто на случай, если кто-то другой получает ошибки из-за этого, как я сделал.
  • Из моих тестов у меня сложилось впечатление, что код работает намного медленнее при использовании библиотеки, по сравнению с тем же кодом, вставленным в ограниченный листом скрипт.

Поэтому мне интересно, возможно ли включить код каким-либо другим способом, и я нашел несколько комментариев о , использующих eval () для включения кода javascript из внешнего URL :

импорт внешнего javascript в скрипт приложений Google ; вставить внешний файл javascript в скрипт приложения Google (Документы Google) ; https://ctrlq.org/code/20380-load-external-javascript-with-eval

По сути, так говорят:

eval(UrlFetchApp.fetch('http://path.to/external/javascript.js').getContentText());

Мои вопросы:

  • Я не совсем понимаю, как eval () должен работать в приведенных выше примерах. Он предназначен для запуска из скрипта, который запускается на сервере приложений Google? (поэтому мой включенный файл будет по-прежнему вызывать функции SpreadsheetApp. или DriveApp.)

  • Если код внутри eval () определяет набор функций, они все еще доступны после завершения eval ()? Можем ли мы вызывать их из событий, управляемых пользователем, например, щелкая пункты меню?

  • А если мы можем их назвать, следует ли обращаться по-особенному? Я не смог этого сделать

Я мог бы просто загрузить новое меню (определенное в remote.js), используя eval (remote.js). НО другие функции, определенные в remote.js, больше не доступны для вызовов меню (нажатие на меню вызывает ошибки, такие как Функция сценария не найдена: f1 ).

  • Должен ли я, возможно, загрузить все функции каким-либо образом до определения меню? Я попытался определить функцию f1 () в начале, но это не имеет значения относительно функции f2 (), которая находится в конце. Я также попробовал 2 отдельных вызова, 1st eval (remote_functions.js), 2nd eval (remote_menuLoader.js), но это тоже не имело значения (поэтому мой код ниже показывает только один вызов eval, который загружает один пульт. JS с определениями обеих функций и меню, которое будет вызывать их).

Мой код:

Ограниченный скрипт Google для электронных таблиц:

var app = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
  app.addMenu("LOAD remote menu", [
    {name: "eval(remote.js) to load new menu", functionName: "evalRemote"}
  ]);
}
function evalRemote() {
  var remotejs_url="https://drive.google.com/uc?authuser=0&id=1wCjewWFTPdH-Luw53zWh_KHX-RhRhFIn&export=view";
  eval(UrlFetchApp.fetch(remotejs_url).getContentText());
  var message=remote_onOpen(app);  
  Browser.msgBox(message);
}

файл remote.js:

function f1() {
    Browser.msgBox("you called f1");
}

function remote_onOpen(app) {
    var menuName="REMOTE-loaded menu";
    app.addMenu(menuName, [
    {name: "FUNCTION 1", functionName: "f1"}
    ,{name: "FUNCTION 2", functionName: "f2"}
    ]);
    return("remote_onOpen(app) function was called;\\n " 
    + "A reference to '" + app.getName() + "' was passed \\n"
    + "in order to create this new menu on it:\\n" 
    + "'" + menuName + "'\\n\\n" 
    + "You should now have 2 new functions available.");
}

function f2() {
    Browser.msgBox("you called f2");
}
...