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

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

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

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

Q&A

解決済

1回答

2475閲覧

GASを使用した条件分岐によるプルダウン作成

tkt1964

総合スコア5

Google Apps Script

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

0グッド

0クリップ

投稿2022/05/15 09:37

前提

スプレッドシートに入力した内容から
別シートの対照表を基にプルダウンの選択肢を表示させたい

実現したいこと

・スプレッドシート上でプルダウンを選択、その内容を基に隣の列に新たなプルダウンを作成
・作成されたプルダウンの内容は別シートの対照表を参照
・作成される列は6列(B列で項目選択、C~H列にプルダウン作成)

発生している問題・エラーメッセージ

下記、コードで
基準となる情報を”使用シート”で選択すると
その隣の1列に”設定シート”の対照表を基に”使用シート”上にプルダウンが作成されます。
※ここまでは問題なし

問題は”使用シート”で項目を選択し、隣に6列まで”設定シート”の対照表を参照して
プルダウンを作成したいのですが、上手くいきません。

<使用シート>
B列      C列      D列・・・
データ1    ①
(プルダウン)  (プルダウン)

A列:空白(他データを入れるため)  
B列:このシート上で選択
C列:GASで”設定シート”の対照表のB列を基にプルダウン作成
D列:GASで”設定シート”の対照表のC列を基にプルダウン作成

”設定シート”
A列      B列      C列      D列・・・
データ1    ①       ③       ④
データ1    ②       ④       ④
データ2    ③       ⑤       ⑥ 
データ2    ③       ⑤       ⑦

該当のソースコード

GAS

1/** 2 * ①グローバル変数の定義 3 */ 4const USE_SHEET_NAME = "使用シート"; 5const SETTING_SHEET_NAME = "設定シート"; 6const CATEGORY1_COL_NUM = 2; // B列 7 8/** 9 * ②本体 10 */ 11function onEdit(e) { 12 if (!isTargetCol(e)) return; 13 14 const category1Value = e.value; 15 const changedRow = e.range.getRow(); 16 const changedCol = e.range.getColumn(); 17 const useSheet = e.source.getSheetByName(USE_SHEET_NAME); 18 19 // ③設定シート のデータ(二次元配列) 20 const settingData = e.source.getSheetByName(SETTING_SHEET_NAME).getDataRange().getValues(); 21 22 // ④カテゴリ1に対応するカテゴリ2を入れておくところ 23 let catgory2List = []; 24 25 // ⑤設定シート のデータの中から、「選択されたカテゴリ1」に対応するカテゴリ2を取り出すところ 26 settingData.forEach( row => { 27 if (row[0] === category1Value) { 28 catgory2List.push(row[1]); 29 } 30 }); 31 32 if(catgory2List.length === 0) return; 33 34 // ⑥編集されたセルの右のセルにカテゴリ2のプルダウンをセットする 35 const range = useSheet.getRange(changedRow, changedCol + 1); 36 const rule = SpreadsheetApp.newDataValidation().requireValueInList(catgory2List, true); 37 rule.setAllowInvalid(false).build(); 38 range.setDataValidation(rule); 39} 40 41/** 42 * ⑦プルダウン連動をさせる列かどうかの判断 43 */ 44function isTargetCol(e) { 45 // 値が削除されたときはvalueが undefになるので無視 46 if (!e.range.getValue()) return false; // ※1 47 48 // 関係ないシートのとき 49 if (e.source.getSheetName() !== USE_SHEET_NAME) return false; 50 51 // 列が違うとき 52 if (e.range.getColumn() != CATEGORY1_COL_NUM) return false; 53 54 return true; 55}

補足情報(FW/ツールのバージョンなど)

やりたい事が類似したコードが下記URLにあったので
それを基に変数追加したりと色々試してみたのですが、どうしてもうまくいかず。。
https://qiita.com/sakaimo/items/689e9f3c516bb5a96c19

コードをいじりすぎてわけわからなくなったので
上記のコードはURLのものを貼り付けました。

分かる方お力添えをいただければ幸いです。
何卒宜しくお願いいたします。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2022/05/15 11:12

「”使用シート”で項目を選択し、隣に6列まで”設定シート”の対照表を参照してプルダウンを作成」するとのことなので、 ”設定シート"のB列~G列までの6列分(固定)のデータをプルダウンの元データとして持ってくればよい、という理解でよろしいでしょうか?
tkt1964

2022/05/15 12:35

回答遅くなり申し訳ございません。 はい、そうです。 回答も早速試してみます。 誠にありがとうございます!
tkt1964

2022/05/15 12:45

gnoirさん 出来ました、誠にありがとうございました!
guest

回答1

0

ベストアンサー

下記のような形ではいかがでしょうか。

js

1/** 2 * ①グローバル変数の定義 3 */ 4const USE_SHEET_NAME = "使用シート"; 5const SETTING_SHEET_NAME = "設定シート"; 6const CATEGORY1_COL_NUM = 2; // B列 7 8/** 9 * ②本体 10 */ 11function onEdit(e) { 12 if (!isTargetCol(e)) return; 13 14 const category1Value = e.value; 15 const changedRow = e.range.getRow(); 16 const changedCol = e.range.getColumn(); 17 const useSheet = e.source.getSheetByName(USE_SHEET_NAME); 18 19 // 設定シート のデータ(二次元配列) 20 const settingData = e.source.getSheetByName(SETTING_SHEET_NAME).getDataRange().getValues(); 21 22 // 編集されたセルの右のセルにカテゴリ2のプルダウンをセットする 23 for (let i = 1; i <= 6; i++) { 24 const range = useSheet.getRange(changedRow, changedCol + i); 25 const rule = getRule(category1Value, settingData, i); 26 if (rule == null) continue; 27 range.setDataValidation(rule); 28 } 29} 30 31function getRule(category1Value, settingData, column) { 32 // カテゴリ1に対応するカテゴリ2を入れておくところ 33 let catgory2List = []; 34 35 // 設定シート のデータの中から、「選択されたカテゴリ1」に対応するカテゴリ2を取り出すところ 36 settingData.forEach(row => { 37 if (row[0] === category1Value) { 38 catgory2List.push(row[column]); 39 } 40 }); 41 42 const rule = SpreadsheetApp.newDataValidation().requireValueInList(catgory2List, true); 43 rule.setAllowInvalid(false).build(); 44 return rule; 45} 46 47/** 48 * ⑦プルダウン連動をさせる列かどうかの判断 49 */ 50function isTargetCol(e) { 51 // 値が削除されたときはvalueが undefになるので無視 52 if (!e.range.getValue()) return false; // ※1 53 54 // 関係ないシートのとき 55 if (e.source.getSheetName() !== USE_SHEET_NAME) return false; 56 57 // 列が違うとき 58 if (e.range.getColumn() != CATEGORY1_COL_NUM) return false; 59 60 return true; 61}

説明

元のコードだと1列しか作っていないプルダウンを作る部分を、関数として切り出しています。
引数columnが、プルダウンの元データを読み込む設定シートの列(1ならばB列)となります。

js

1function getRule(category1Value, settingData, column) { 2 // カテゴリ1に対応するカテゴリ2を入れておくところ 3 let catgory2List = []; 4 5 // 設定シート のデータの中から、「選択されたカテゴリ1」に対応するカテゴリ2を取り出すところ 6 settingData.forEach(row => { 7 if (row[0] === category1Value) { 8 catgory2List.push(row[column]); 9 } 10 }); 11 12 const rule = SpreadsheetApp.newDataValidation().requireValueInList(catgory2List, true); 13 rule.setAllowInvalid(false).build(); 14 return rule; 15}

呼び出し元では、ループを使って列を切りかえて、上記の getRule 関数を呼び出し、読み込んだプルダウンの情報を各列に設定するようにします。

js

1function onEdit(e) { 2(略) 3 // 編集されたセルの右のセルにカテゴリ2のプルダウンをセットする 4 for (let i = 1; i <= 6; i++) { 5 const range = useSheet.getRange(changedRow, changedCol + i); 6 const rule = getRule(category1Value, settingData, i); 7 if (rule == null) continue; 8 range.setDataValidation(rule); 9 } 10}

投稿2022/05/15 12:05

編集2022/05/15 13:51
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問