【GAS】스프레드시트의 맞춤 메뉴에서 항목별로 함수를 동적(?)에 할당

개요



이것에 대답했기 때문에.
커스텀 메뉴는 편리합니다만, 함수 지정이 캐릭터 라인만이거나, 함수에 인수를 건네줄 수 없는 느낌이므로, 그것을 타개하고 싶다!

결론부터 말하면!



커스텀 메뉴 아이템마다 별도의 함수를 정의하는 것으로, 인수가 없어도 어떻게든 되도록(듯이) 만들 수 있었다.
이번 샘플이라면 시트 수가 바뀌었을 때, 스프레드 시트를 리로드하지 않으면 정상적으로 움직이지 않기 때문에 동적으로 할당한다고 약간 어폐가 있을지도. . .

완성 된 것의 미리보기



메뉴에서 시트 이름을 선택하면 선택한 시트 이름을 활성화합니다.



출처와 해설



소스 전문


const APP_ACTIVE = SpreadsheetApp.getActive();
const SHEETS = APP_ACTIVE.getSheets();
const ITEM_FUNCTIONS = (function() {
  let result = {};
  for (let i = 0; i < SHEETS.length; i++) {
    // 各メニューアイテムに紐づける関数
    result['_moveTo' + i] = function() {
      SHEETS[i].activate();
      APP_ACTIVE.toast(SHEETS[i].getSheetName() + ' に切り替えた!', 'カスタムメニューさん');
    };
  }
  return result;
})();

/**
 * スプレッドシートを開いた時のハンドラ
 */
function onOpen() {
  let userMenu = [];

  // メニューと動的関数を生成する
  for (let i = 0; i < SHEETS.length; i++) {
    const customFunctionName = 'ITEM_FUNCTIONS._moveTo' + i;

    // カスタムメニューを追加
    userMenu.push({
      name: SHEETS[i].getSheetName(),
      functionName: customFunctionName,
    });
  }
  SpreadsheetApp.getActiveSpreadsheet().addMenu('シート名一覧', userMenu);
}

해설이나 주의점



게재한 소스나 실장에 있어서의 주의점에 대해 쓴다.

커스텀 메뉴로 지정하는 함수명이 글로벌 스코프로부터 추적되는 일



추적하면 좋기 때문에 이런 느낌의 함수라면…
// 宣言
const hoge = {
  fuga: function() { Browser.msgBox('hello'); };
};

이런 식으로 점으로 연결하여 메뉴 아이템을 넣으면 객체 아래에 넣은 함수도 호출할 수 있다.
// 呼び出しメニューアイテム
SpreadsheetApp.getActiveSpreadsheet().addMenu('シート名一覧', {[
  name: 'fugaを呼べ',
  functionName: 'hoge.fuga'
]});

일단, globalThis 를 사용할 수 있으므로 이런 쓰는 방법도 할 수 있었다. 글쎄, 좋아.
// 宣言
globalThis['piyo'] = function() { Browser.msgBox('piyoさんだよ!'); };
// 呼び出しメニューアイテム
SpreadsheetApp.getActiveSpreadsheet().addMenu('シート名一覧', {[
  name: 'piyoを呼べ',
  functionName: 'piyo'
]});

동적 추가 함수는 초기화 시점에 추가되어야 한다.



내가 검증한 범주에서 onOpen 이전.
onOpen 후에는 globalThis 등에 함수를 추가해도 메뉴에서 호출 할 수 없었습니다.
아래와 같은 코드로 함수가 정의되어 있는지 어떤지를 체크하고 있었습니다만,
추가 처리를 한 함수 내에서는 살아 있지만, 처리를 빠져 버리면 globalThis에서 사라져 버렸다.
let msg = '';
Object.keys(globalThis).filter(key => typeof(globalThis[key] === 'function').forEach(key => {
  if (msg) {
    msg += '\\n';
  }
  msg += 'key: ' + key + ', funcName: ' + globalThis[key]?.name;
});
Browser.msgBox(msg);
// こんな感じに書いても、「はーい、testさんだよ!」とは言ってくれずに眠ったまま。
const funcs = {
  'test': function() {
    Browser.msgBox('…zzZ');
  }
};

function onOpen() {
  funcs['test'] = function() {
    Browser.msgBox('はーい、testさんだよ!');
  };
  let userMenu = [{
    name: 'test関数を実行!',
    functionName= 'funcs.test'
  }];
  SpreadsheetApp.getActiveSpreadsheet().addMenu('カスタムメニュー', userMenu);
}


참고


  • Class Spreadsheet - Google App Sxript
  • htps : //에서 ゔぇぺぺrs. 오, ぇ. 코 m / 아 ps-sc 리 pt / 레후 렌세 / sp 라 d ぇ t / sp ㅇ d ぇ t # 아 d 메누 (St 링 g, 오 b ぇ ct)

  • 객체 이니셜라이저 - MDN
  • htps : //에서 ゔぇぺぺr. 어쩌면. 오 rg / 자 / 도 cs / 우 b

  • 좋은 웹페이지 즐겨찾기