質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

940閲覧

カスタムメニューの記述をできるだけ短く記述したい

xu0124

総合スコア31

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2021/01/30 18:22

編集2021/01/31 00:39

スプレッドシートのメニューから各シートに飛ぶGASの記述を書いたのですが、できるだけコードを短く書きたいです。

カスタムメニューから各シートに遷移するスクリプトなのですが、いまのままだとシートを追加するごとに更新する必要があり、できるだけ更新箇所を減らそうと思って、いろいろと分けて書いてみました所、煮詰まった状態になります。

コードの書き方が同じことの繰り返しが多くどうみても悪いのですが、どういった関数の記述方法で短くできるのか調べてみてもわからなかったのでお聞きしてみました。

よろしくお願いいたします。

javascript

1var sheetName1 = "シート1"; 2var sheetName2 = "シート2"; 3var sheetName3 = "シート3"; 4 5var functionName1 = "myFunction1"; 6var functionName2 = "myFunction2"; 7var functionName3 = "myFunction3"; 8 9function onOpen() { 10 var ui = SpreadsheetApp.getUi(); 11 var menu = ui.createMenu("カスタムメニュー"); 12 menu.addItem(sheetName1, functionName1); 13 menu.addItem(sheetName2, functionName2); 14 menu.addItem(sheetName3, functionName3); 15 menu.addToUi(); 16} 17 18function onClickItem(num) { 19 var sheetNum = eval("sheetName" + num); 20 var objSpreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 21 var objSheet = objSpreadsheet.getSheetByName(sheetNum); 22 objSpreadsheet.setActiveSheet(objSheet); 23} 24 25function myFunction1() { 26 var name = arguments.callee.name; 27 var num = name.replace(/[^0-9]/g, ""); 28 onClickItem(num); 29} 30 31function myFunction2() { 32 var name = arguments.callee.name; 33 var num = name.replace(/[^0-9]/g, ""); 34 onClickItem(num); 35} 36 37function myFunction3() { 38 var name = arguments.callee.name; 39 var num = name.replace(/[^0-9]/g, ""); 40 onClickItem(num); 41} 42

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/01/30 22:08

作業依頼でしょうか。
xu0124

2021/01/30 23:29

作業依頼ではないです。 コードの書き方が同じことの繰り返しが多くどうみても悪いのですが、どういった関数の記述方法で短くできるのか調べてみてもわからなかったのでお聞きしてみました。
m.ts10806

2021/01/30 23:32

では、もうちょっと質問の仕方かえたほうがいいです。 具体的にというか。 「スマート」って個人感覚の比率が大きい表現なので、 ゴールが見えない。アンケート要素が強いと非推奨にもなりますし。
m.ts10806

2021/01/30 23:33

あと中身一緒なのにコードわける理由が分からないというか。
xu0124

2021/01/31 00:37

説明不足で失礼いたしました。 カスタムメニューから各シートに遷移するスクリプトなのですが、いまのままだとシートを追加するごとに更新する必要があり、できるだけ更新箇所を減らそうと思って、いろいろと分けて書いてみました所、煮詰まった状態になります。
退会済みユーザー

退会済みユーザー

2021/01/31 03:13 編集

んー、 ① ファイル内のシート名の一覧を列挙して ② ①のシート名の数だけ、カスタムメニューのアイテムを追加して ③ ②カスタムメニューアイテムをクリックしたら、該当シートをアクティブにする ということ? で、これで合っているなら次は①②③をそれぞれ調査すればいい訳だ。頑張って下さい。
xu0124

2021/01/31 03:45

おっしゃるとおりなのはわかっているのですが、メニューのコマンドに変数が入らないので困ってました。
退会済みユーザー

退会済みユーザー

2021/01/31 04:09

最初からそれを質問すれば良かったじゃないですか。。。
xu0124

2021/01/31 06:17

変数に至ったのは自分で考えて導き出した結論で、エンジニアのこなれている方々はもっと良い別の方法があることも想定してしました。カスタムメニューってよく使う事例だと思ってましたので。
guest

回答2

0

イメージ説明

一応できましたが無名関数の追加タイミングにクセがあり苦戦しました。
実装に当たりいくつかポイントを書きます。

質問者さんからもらった情報

カスタムメニューからは引数が取れない
まあ、関数名を文字列で取っているし、リファレンスを見たが引数もないのでまともな方法じゃ無理だわな。

検証ポイント1

カスタムメニューで指定する関数名がグローバルスコープから辿れる事
辿れれば良いのでこんな感じの関数であれば…

js

1// 宣言 2const hoge = { 3 fuga: function() { Browser.msgBox('hello'); }; 4}

こんな感じにドットで繋いでメニューアイテムを入れれば呼び出せる。

js

1// 呼び出しメニューアイテム 2SpreadsheetApp.getActiveSpreadsheet().addMenu('シート名一覧', {[ 3 name: (シート名), 4 functionName: 'hoge.fuga' 5]});

検証ポイント2

グローバルスコープに関数を追加するが、初期化タイミングで追加しておく必要がある
私が検証した範疇ではonOpenより前。
onOpen後は、globalThis等に関数を追加してもメニューからは呼び出せませんでした。
下のようなコードで関数が定義されているかどうかをチェックしてたんですが、
追加処理をした関数内では生きているが、処理を抜けてしまうとglobalThisから消えてしまっていた。

js

1let msg = ''; 2Object.keys(globalThis).filter(key => typeof(globalThis[key] === 'function').forEach(key => { 3 if (msg) { 4 msg += '\n'; 5 } 6 msg += 'key: ' + key + ', funcName: ' + globalThis[key]?.name; 7}); 8Browser.msgBox(msg);

書いたコード

js

1const APP_ACTIVE = SpreadsheetApp.getActive(); 2const SHEETS = APP_ACTIVE.getSheets(); 3const test = (() => { 4 let result = {}; 5 for (let i = 0; i < SHEETS.length; i++) { 6 result['_moveTo' + i] = function() { 7 SHEETS[i].activate(); 8 } 9 } 10 return result; 11})(); 12 13function onOpen() { 14 let userMenus = []; 15 16 // メニューと動的関数を生成する 17 for (let i = 0; i < SHEETS.length; i++) { 18 const customFunctionName = 'test._moveTo' + i; 19 20 // カスタムメニューを追加 21 userMenus.push({ 22 name: SHEETS[i].getSheetName(), 23 functionName: customFunctionName, 24 }); 25 } 26 SpreadsheetApp.getActiveSpreadsheet().addMenu('シート名一覧', userMenus); 27}

普段はこんなに至れり尽くせりにコードを出さないんですが
今回のは色々応用が利きそうで自分の勉強にもなってテンションが上がったので掲載します。
(Qiitaにでもまとめて書こうかな…)

以上。

投稿2021/01/31 11:55

編集2021/01/31 12:03
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xu0124

2021/01/31 12:57

ありがとうございます!!! じつはあれから数時間格闘して、自分でも目次を自動生成して動くものができたのですが、シート名に記号がはいっていると動かなかったので、記号が入っていてもしっかり稼働するこちらのコードがとても素晴らしいので参考にさせていただきます。
sawa

2021/02/01 00:14 編集

こういう書き方で変数を使って動的に関数を生成して、メニューに使えるのですね。横から失礼しますが、とても勉強になったのでコメント入れさせていただきました。 >Qiitaにでもまとめて書こうかな… 需要多いと思いますので、是非お願いしたいです。
guest

0

自己解決

無名関数を使ってみることにしました。

投稿2021/01/31 03:42

xu0124

総合スコア31

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問