Google Apps Script (V8); почему я не могу использовать экземпляр объекта внутри onOpen? - PullRequest
1 голос
/ 14 февраля 2020

Почему я не могу использовать экземпляр объекта внутри onOpen?

Я экспериментирую со скриптом Google Apps, используя новую среду выполнения V8. Я написал некоторый простой код, который создает экземпляр класса в функции onOpen и пытается связать вызов метода с этим экземпляром, когда я щелкаю по пункту меню.

Когда я щелкаю по связанному меню при входе я получаю сообщение об ошибке «Функция сценария не найдена». Тем не менее, когда я создаю глобальный экземпляр класса или создаю локальный экземпляр в другой функции, все работает нормально.

Я попытался записать значение локального или глобального экземпляра, но он показывает только пустой объект: {}.

Это ошибка или какая-то деталь, которую я упустил, читая документацию?

/** Application Class */
class Application {
    /**
     * ShowUi
     */
    showUi() {
        // const html = HtmlService.createHtmlOutputFromFile('Ui');
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        const ui = SpreadsheetApp.getUi();
        ui.showModalDialog(html, 'User Interface');
    }
}

const global_app = new Application();

/** onOpen */
function onOpen() {
    const app = new Application();
    const ui = SpreadsheetApp.getUi();
    const menu = ui.createMenu('JSClass Example');

    console.log('app, local scope:');
    console.log(app);

    console.log('app, global scope');
    console.log(global_app);

    menu.addItem('Show UI (local)', 'app.showUi');
    menu.addItem('Show UI (global)', 'global_app.showUi');
    menu.addItem('Show UI (global fn)', 'showUi');

    menu.addToUi();
}

/** showUi */
function showUi() {
    const app3 = new Application();
    app3.showUi();
}

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

Ответы [ 2 ]

4 голосов
/ 14 февраля 2020

В вашем примере метод onOpen() выполняется исключительно для заполнения меню, , но не при выборе опции меню.

Когда вы выбираете пункт меню, он выполняется в контексте выполнения fre sh и состояние из функции onOpen() из предыдущего выполнения (т. е. для заполнения меню) не переносится.


Другой подход заключается в использовании stati c метод , который можно вызвать без необходимости создания экземпляра класса.

class Application {
    static showUi() {
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        const ui = SpreadsheetApp.getUi();
        ui.showModalDialog(html, 'User Interface');
    }
}

function onOpen() {
    const app = new Application();
    const ui = SpreadsheetApp.getUi();
    const menu = ui.createMenu('V8 Menu Test');
    menu.addItem('Show UI', 'Application.showUi');
    menu.addToUi();
}
1 голос
/ 14 февраля 2020

Я использовал устанавливаемый триггер onOpen, но он также работает с простым триггером. Я просто не обращал внимания на меню, когда впервые запустил его.

/** Application Class */
class Application {
    /**
     * ShowUi
     */
    showUi() {
        // const html = HtmlService.createHtmlOutputFromFile('Ui');
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        SpreadsheetApp.getUi().showModalDialog(html, 'User Interface');
    }
}

const global_app = new Application();

/** onOpen */
function openForMe() {
    const app = new Application();
    const ui = SpreadsheetApp.getUi();
    const menu = ui.createMenu('JSClass Example')
    .addItem('Show UI (local)', 'app.showUi')//this is still not working
    .addItem('Show UI (global)', 'global_app.showUi')
    .addItem('Show UI (global fn)', 'showUi')
    .addToUi();
}

/** showUi */
function showUi() {
    const app3 = new Application();
    app3.showUi();
}

Кажется, все в порядке:

/** Application Class */
class Application {
     showUi() {
        const html = HtmlService.createHtmlOutput('<h1>Hello World</h1>');
        SpreadsheetApp.getUi().showModalDialog(html, 'User Interface');
    }
}

const global_app = new Application();

/** onOpen */
function onOpen(){
  SpreadsheetApp.getUi().createMenu('JSClass Example')
  .addItem('Show UI (global)', 'global_app.showUi')
  .addItem('Show UI (global fn)', 'showUi')
  .addToUi();
}

/** showUi */
function showUi() {
    const app3 = new Application();
    app3.showUi();
}
...