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

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

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

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

Q&A

解決済

3回答

2811閲覧

特定のスクリプトを特定のシートにのみ働くようにしたい。

koromo_t

総合スコア60

Google Apps Script

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

1グッド

1クリップ

投稿2018/04/04 04:39

編集2018/04/05 01:11

下記のようなスクリプトを書きました。

下記のスクリプトにおいて、
function onEdit1()はシート「歩数計」のみに働くように、
function onEdit2()はシート「睡眠記録」のみに働くように、
function onEdit3()はシート「10食品群」のみに働くように、
それぞれしたいのですが、
どうも、相互的に?反応してしまうようです。
これを解決するためには、どうすればよいでしょうか。

具体的には、項目ごとにスプレッドシートがあり、
それらの入力用シートだけを集めたスプレッドシートを作ってみたのです。
(IMPORTRANGEを使って、リンクさせている)

よろしくお願いします。

javaScript

1function onEdit(e){ 2 onEdit1(); 3 onEdit2(); 4 onEdit3(); 5} 6 7// シートに変更があった時に実行する関数 8function onEdit1() { 9 // 変更のあったシート 10 var ss = SpreadsheetApp.getActive().getSheetByName("歩数計"); 11 // 変更のあったセル 12 var cell = ss.getActiveRange(); 13 // 変更のあったセルの値 14 var val = cell.getValue(); 15 // 変更のあったセルの文字列がnだった時に 16 if( ( val == "n" ) ) { 17 cell.setValue("バンザイなし") ; 18 } 19 // 変更のあったセルの文字列がaだった時に 20 if( ( val == "a" ) ) { 21 cell.setValue("バンザイあり") ; 22 } 23} 24 25function onEdit2() { 26 // 変更のあったシート 27 var ss = SpreadsheetApp.getActive().getSheetByName("睡眠記録"); 28 // 変更のあったセル 29 var cell = ss.getActiveRange(); 30 Logger.log(cell); 31 // 変更のあったセルの有る行番号 32 var r = cell.getRow(); 33 Logger.log(r); 34 // 変更のあったセルの有る列番号 35 var c = cell.getColumn(); 36 Logger.log(c); 37 // 変更のあったセルの左隣のセル 38 var cellLeft = ss.getRange(r, c - 1); 39 Logger.log(cellLeft); 40 // 変更のあったセルの2つ左隣のセル 41 var cell2Left = ss.getRange(r, c - 2); 42 Logger.log(cell2Left); 43 // 変更のあったセルの値 44 var val = cell.getValue(); 45 Logger.log(val); 46 // 変更のあったセルの左隣のセルの値 47 var val2 = cellLeft.getValue(); 48 Logger.log(val2); 49 // 変更のあったセルの2つ左隣のセルの値 50 var val3 = cell2Left.getValue(); 51 Logger.log(val3); 52 // 変更のあったセルが変更のあったセルの2つ左隣のセルの値よりも小さいか、変更のあったセルの左隣のセルの値が空白ではなく、変更のあったセルの値が変更のあったセルの左隣のセルの値よりも小さかった時に 53 if( ( ( ( val < val3 ) || ( val2 != "" ) ) && val2 > val ) ) { 54 Logger.log( ( ( val < val3 ) || ( val2 != "" ) && val2 > val ) ); 55 // 変更のあったセルの有る行の下の行の2列目を選択 56 var rowRange = ss.getRange(r+1, 2); 57 // 変更のあったセルの有る行の下の行の3列目を選択 58 var rowRangeRight = ss.getRange(r+1, 3); 59 // 変更のあったセルに1を入力 60 cell.setValue(1) ; 61 // 変更のあったセルの有る行の下の行の2列目に0を入力 62 rowRange.setValue(0) ; 63 // 変更のあったセルの有る行の下の行の3列目に変更のあったセルの値を入力して右隣にアクティブセルを移動 64 rowRangeRight.setValue(val).offset(0, 1).activate(); 65 } 66} 67 68// シートに変更があった時に実行する関数 69function onEdit3() { 70 // 変更のあったシート 71 var ss = SpreadsheetApp.getActive().getSheetByName("10食品群"); 72 // 変更のあったセル 73 var cell = ss.getActiveRange(); 74 // 変更のあったセルの値 75 var val = cell.getValue(); 76 // 変更のあったセルの文字列がnだった時に 77 if( ( val == "m" ) ) { 78 cell.setValue("○") ; 79 } 80}

#~解決後のまとめ~
mix-peachさんの回答を参考に解決しましたので、まとめておきます!


「変更されたシート名を取得すること」、ここがネックだったのですね。
そして、switch文というものに、今回初めて出会いました。条件分岐というのですね。
構造も、知ってしまえばわかりやすくてよいですね! 学習しました。

javaScript

1function onEdit(e){ 2 3 //今変更されたシート名を取得 (どう取得できるかはお調べください^^;) 4 var edit_sheet_name = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetName(); 5 Logger.log(edit_sheet_name); 6 7 switch (edit_sheet_name){ 8 case '歩数計': 9 onEdit1(); 10 break; 11 12 case '睡眠記録': 13 onEdit2(); 14 break; 15 16 case '10食品群': 17 onEdit3(); 18 break; 19 } 20} 21 22// シートに変更があった時に実行する関数 23function onEdit1() { 24 // 変更のあったシート 25 var ss = SpreadsheetApp.getActive().getSheetByName("歩数計"); 26 // 変更のあったセル 27 var cell = ss.getActiveRange(); 28 // 変更のあったセルの値 29 var val = cell.getValue(); 30 // 変更のあったセルの文字列がnだった時に 31 if( ( val == "n" ) ) { 32 cell.setValue("バンザイなし") ; 33 } 34 // 変更のあったセルの文字列がaだった時に 35 if( ( val == "a" ) ) { 36 cell.setValue("バンザイあり") ; 37 } 38} 39 40function onEdit2() { 41 // 変更のあったシート 42 var ss = SpreadsheetApp.getActive().getSheetByName("睡眠記録"); 43 // 変更のあったセル 44 var cell = ss.getActiveRange(); 45 Logger.log(cell); 46 // 変更のあったセルの有る行番号 47 var r = cell.getRow(); 48 Logger.log(r); 49 // 変更のあったセルの有る列番号 50 var c = cell.getColumn(); 51 Logger.log(c); 52 // 変更のあったセルの左隣のセル 53 var cellLeft = ss.getRange(r, c - 1); 54 Logger.log(cellLeft); 55 // 変更のあったセルの2つ左隣のセル 56 var cell2Left = ss.getRange(r, c - 2); 57 Logger.log(cell2Left); 58 // 変更のあったセルの値 59 var val = cell.getValue(); 60 Logger.log(val); 61 // 変更のあったセルの左隣のセルの値 62 var val2 = cellLeft.getValue(); 63 Logger.log(val2); 64 // 変更のあったセルの2つ左隣のセルの値 65 var val3 = cell2Left.getValue(); 66 Logger.log(val3); 67 // 変更のあったセルが変更のあったセルの2つ左隣のセルの値よりも小さいか、変更のあったセルの左隣のセルの値が空白ではなく、変更のあったセルの値が変更のあったセルの左隣のセルの値よりも小さかった時に 68 if( ( ( ( val < val3 ) || ( val2 != "" ) ) && val2 > val ) ) { 69 Logger.log( ( ( val < val3 ) || ( val2 != "" ) && val2 > val ) ); 70 // 変更のあったセルの有る行の下の行の2列目を選択 71 var rowRange = ss.getRange(r+1, 2); 72 // 変更のあったセルの有る行の下の行の3列目を選択 73 var rowRangeRight = ss.getRange(r+1, 3); 74 // 変更のあったセルに1を入力 75 cell.setValue(1) ; 76 // 変更のあったセルの有る行の下の行の2列目に0を入力 77 rowRange.setValue(0) ; 78 // 変更のあったセルの有る行の下の行の3列目に変更のあったセルの値を入力して右隣にアクティブセルを移動 79 rowRangeRight.setValue(val).offset(0, 1).activate(); 80 } 81} 82 83// シートに変更があった時に実行する関数 84function onEdit3() { 85 // 変更のあったシート 86 var ss = SpreadsheetApp.getActive().getSheetByName("10食品群"); 87 // 変更のあったセル 88 var cell = ss.getActiveRange(); 89 // 変更のあったセルの値 90 var val = cell.getValue(); 91 // 変更のあったセルの文字列がnだった時に 92 if( ( val == "m" ) ) { 93 cell.setValue("○") ; 94 } 95}
must👍を押しています

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

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

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

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

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

guest

回答3

0

function onEdit1()はシート「歩数計」のみに働くように、

function onEdit2()はシート「睡眠記録」のみに働くように、
function onEdit3()はシート「10食品群」のみに働くように、

上記だけなら、表面上はmix-peachさんの回答に準じて修正を行えば良いように思えます。

しかし、質問内容から全体の構造をイメージするといろいろと矛盾や疑問が生じます。

スプレッドシートとシート(表現の統一)

経験上、当方がGAS案件を受注する際、クライアント様の要望にて、上記、表現が統一されていないことが多いです。
その際にも前置きしていることですが、以降、スプレッドシート(エクセルで言うブック、以降SS)、シート(同、シート)と明確に区別させて頂きます。

構造と目的の明確化

質問内容から全体構造を解釈すると、以下のようになります。

  • SS_1(「歩数計」シートを含む)
  • SS_2(「睡眠記録」シートを含む)
  • SS_3(「10食品群」シートを含む)
  • SS_4(各SSの入力用シート、3シート)

GASはSS_4に設定され、IMPORTRANGEで読み込んだ各シートに対し、以下の動作を期待している。

  • SS_4.「歩数計」シートを編集→「歩数計」シートのみ反映(SS_1.「歩数計」シートへの反映を期待?)
  • SS_4.「睡眠記録」シートを編集→「睡眠記録」シートのみ反映(SS_2.「睡眠記録」シートへの反映を期待?)
  • SS_4.「10食品群」シートを編集→「10食品群」シートのみ反映(SS_3.「10食品群」シートへの反映を期待?)

矛盾点

上記構造であるなら、IMPORTRANGEで読み込んだデータを編集した場合、そもそも「#REF!」エラーになります。
※読み込み範囲外のセルを編集(この場合は追記)した場合は問題ありません。

期待している処理内容が外部SSへの編集内容反映ならば、そもそもonEditでは外部SSの操作不可です。
従いまして、

相互的に?反応してしまうようです。

という内容に矛盾します。

上記、本来は追記・修正依頼に書くべきですが、細かい説明を要するため回答欄に書きました。
当然、当方の質問内容の誤解もございますので、構造と目的が明確になりましたら、必要に応じて提示されたコードを修正・添削させていただきます。

ちなみにですが、onEdit(e)とされていますので、e.sourceでSSオブジェクト、e.rangeでRangeオブジェクト、e.valueで編集後の値を取得できます。(その他の情報も取得可能)

[参考]
Google Apps Script Event Object > Edit

投稿2018/04/05 00:01

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

koromo_t

2018/04/05 01:02 編集

あ、たぶんおっしゃっていることを私も思ったので(というか、作業のなかで判明した?)、 SS_4内の各「入力用シート」を、SS_1~3内の各「入力用シート」にそれぞれリンクすることで、 そのあたりは解決したと記憶しています。 なので、矛盾はしていません。大丈夫です。 回答ありがとうございます!
退会済みユーザー

退会済みユーザー

2018/04/05 01:41

参照方向が逆でしたね。 > それらの入力用シートだけを集めた 上記からSS_4への集約と誤解しましたが、SS_4からの各SSへの展開ということですね。
koromo_t

2018/04/05 01:51

そうなんです! 私も、最初はそのようにしていたのですが(SS_4への集約)、 なんかエラーが出たような気がするので、方針を変えたところ、うまくいった次第であります。 質問文の書き方が適切ではなかったかもしれません、その点はすみません…。 というか、質問文の「具体的には~」からの、IMPORTRANGEに関する部分は、 誤解を招くだけで、書く必要がなかったような気がしました。。。 状況をなるべく詳しく書こうとして、逆効果になったパターンかもしれません。。
guest

0

ベストアンサー

Google Apps Script は使ったことがありませんので、その前提でお聞きください。

気になるのは、

javascript

1function onEdit(e){ 2 onEdit1(); 3 onEdit2(); 4 onEdit3(); 5}

ここです。

onEditは「どこかのシートのどこかのセルで変更があった時」に呼ばれる処理かと想像していますが、合っていますか?

であれば、
その中でonEdit1 から3まで全て呼んでいるので、いつでも全部が動くのだと思います。

必要なのは、
「今変更されたシート名を識別して、どの関数を呼ぶかを分岐させる」ことでは
ないかな?と思います。

例えば こんな感じ・・・(今適当に書くだけなので、スペルミスなどありましたらご容赦を)

javascript

1function onEdit(e){ 2 3 //今変更されたシート名を取得 (どう取得できるかはお調べください^^;) 4 var edit_sheet_name =???’; 5 6 switch (edit_sheet_name){ 7 case '歩数計': 8  onEdit1(); 9 break; 10 11 case '睡眠記録': 12 onEdit2(); 13 break; 14 15 case '10食品群': 16  onEdit1(); 17 break; 18} 19

投稿2018/04/04 05:23

mix-peach

総合スコア1910

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

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

koromo_t

2018/04/05 01:06 編集

回答ありがとうございます! はい、onEditはそういうイベントハンドラだと思われます! なるほど、「変更されたシート名を取得すること」、ここがネックだったのですね。 そして、switch文というものに、今回初めて出会いました。条件分岐というのですね。 構造も、知ってしまえばわかりやすくてよいですね! 学習しました。 おかげさまで、期待通りの結果を得るスクリプトを書くことができましたので、 回答欄および質問文に追記しようと思います!
guest

0

#~解決後のまとめ~
mix-peachさんの回答を参考に解決しましたので、まとめておきます!


「変更されたシート名を取得すること」、ここがネックだったのですね。
そして、switch文というものに、今回初めて出会いました。条件分岐というのですね。
構造も、知ってしまえばわかりやすくてよいですね! 学習しました。

javaScript

1function onEdit(e){ 2 3 //今変更されたシート名を取得 (どう取得できるかはお調べください^^;) 4 var edit_sheet_name = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetName(); 5 Logger.log(edit_sheet_name); 6 7 switch (edit_sheet_name){ 8 case '歩数計': 9 onEdit1(); 10 break; 11 12 case '睡眠記録': 13 onEdit2(); 14 break; 15 16 case '10食品群': 17 onEdit3(); 18 break; 19 } 20} 21 22// シートに変更があった時に実行する関数 23function onEdit1() { 24 // 変更のあったシート 25 var ss = SpreadsheetApp.getActive().getSheetByName("歩数計"); 26 // 変更のあったセル 27 var cell = ss.getActiveRange(); 28 // 変更のあったセルの値 29 var val = cell.getValue(); 30 // 変更のあったセルの文字列がnだった時に 31 if( ( val == "n" ) ) { 32 cell.setValue("バンザイなし") ; 33 } 34 // 変更のあったセルの文字列がaだった時に 35 if( ( val == "a" ) ) { 36 cell.setValue("バンザイあり") ; 37 } 38} 39 40function onEdit2() { 41 // 変更のあったシート 42 var ss = SpreadsheetApp.getActive().getSheetByName("睡眠記録"); 43 // 変更のあったセル 44 var cell = ss.getActiveRange(); 45 Logger.log(cell); 46 // 変更のあったセルの有る行番号 47 var r = cell.getRow(); 48 Logger.log(r); 49 // 変更のあったセルの有る列番号 50 var c = cell.getColumn(); 51 Logger.log(c); 52 // 変更のあったセルの左隣のセル 53 var cellLeft = ss.getRange(r, c - 1); 54 Logger.log(cellLeft); 55 // 変更のあったセルの2つ左隣のセル 56 var cell2Left = ss.getRange(r, c - 2); 57 Logger.log(cell2Left); 58 // 変更のあったセルの値 59 var val = cell.getValue(); 60 Logger.log(val); 61 // 変更のあったセルの左隣のセルの値 62 var val2 = cellLeft.getValue(); 63 Logger.log(val2); 64 // 変更のあったセルの2つ左隣のセルの値 65 var val3 = cell2Left.getValue(); 66 Logger.log(val3); 67 // 変更のあったセルが変更のあったセルの2つ左隣のセルの値よりも小さいか、変更のあったセルの左隣のセルの値が空白ではなく、変更のあったセルの値が変更のあったセルの左隣のセルの値よりも小さかった時に 68 if( ( ( ( val < val3 ) || ( val2 != "" ) ) && val2 > val ) ) { 69 Logger.log( ( ( val < val3 ) || ( val2 != "" ) && val2 > val ) ); 70 // 変更のあったセルの有る行の下の行の2列目を選択 71 var rowRange = ss.getRange(r+1, 2); 72 // 変更のあったセルの有る行の下の行の3列目を選択 73 var rowRangeRight = ss.getRange(r+1, 3); 74 // 変更のあったセルに1を入力 75 cell.setValue(1) ; 76 // 変更のあったセルの有る行の下の行の2列目に0を入力 77 rowRange.setValue(0) ; 78 // 変更のあったセルの有る行の下の行の3列目に変更のあったセルの値を入力して右隣にアクティブセルを移動 79 rowRangeRight.setValue(val).offset(0, 1).activate(); 80 } 81} 82 83// シートに変更があった時に実行する関数 84function onEdit3() { 85 // 変更のあったシート 86 var ss = SpreadsheetApp.getActive().getSheetByName("10食品群"); 87 // 変更のあったセル 88 var cell = ss.getActiveRange(); 89 // 変更のあったセルの値 90 var val = cell.getValue(); 91 // 変更のあったセルの文字列がnだった時に 92 if( ( val == "m" ) ) { 93 cell.setValue("○") ; 94 } 95}

投稿2018/04/05 01:08

編集2018/04/05 01:13
koromo_t

総合スコア60

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問