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

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

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

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

JavaScript

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

Q&A

解決済

2回答

2873閲覧

GASで貸出・返却時刻の自動で出したい(エラーが出て困っています)

jinjinghaiyue

総合スコア13

Google Apps Script

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

JavaScript

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

0グッド

0クリップ

投稿2018/11/06 06:40

編集2018/11/06 07:55

前提・実現したいこと

プログラミング初心者です。

現在、機材の貸出の管理簿としてGoogle App Scriptを用いてスプレッドシートを使用しています。
貸出と返却の時刻を以前までは手入力していたのですが、面倒臭いのでGASで自動入力をしようと思っています。
スプレッドシートのAとBの行にそれぞれ貸出・返却のチェックボックスを作り、そこに貸出・返却の際にチェックを入れることでそれぞれGとHの行にその時刻が出るようにしています。

A:貸出用チェックボックス
B:返却用チェックボックス
C:端末番号
D:(空欄)
E:利用者番号
F:利用者番号からVlookupで導き出した氏名
G:貸出時刻
H:返却時刻

になっています。

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

貸出(A行のチェックボックスにチェックを入れる)をすると時刻が正しく入力されるのですが、返却の際にB行のチェックボックスにチェックを入れると貸出時刻も変わります。つまり貸出・返却時刻共に「返却時刻」に変更されてしまいます。

それぞれトリガーは「変更時」になっていますが、トリガーのエラー(stackdriverのログ)を見ると

エラー 範囲外のセル参照です at logerR(コード:16)

となっています。

Google App Script

function logerB() {//logerBというイベント var ssB = SpreadsheetApp.getActiveSheet(); //現在のスプレッドシートを取得 var RowB = ssB.getActiveCell().getRow(); //現在のスプレッドシートの現在の行を取得 var BCell = ssB.getRange('A' + RowB).getValue(); //現在のスプレッドシートの現在の行のA列 var BTime = ssB.getRange('G' + RowB);//現在のスプレッドシートの現在の行のG列 if(RowB>1){ //Rowが1行目でないとき if(BCell==true) { //現在のスプレッドシートの現在の行のA列の値の変更があったとき BTime.setValue(new Date());//現在時刻を挿入 } } } function logerR() {//logerRというイベント var ssR = SpreadsheetApp.getActiveSheet(); //現在のスプレッドシートを取得 var RowR = ssR.getActiveCell().getRow(); //現在のスプレッドシートの現在の行を取得 var RCell = ssR.getRange('B' + RowR).getValue(); //現在のスプレッドシートの現在の行のB列 var RTime = ssR.getRange('H' + RowR);//現在のスプレッドシートの現在の行のH列 if(RowR>1){ //Rowが1行目でないとき if(RCell==true) { //現在のスプレッドシートの現在の行のA列の値の変更があったとき RTime.setValue(new Date());//現在時刻を挿入 } } }

試したこと

トリガーを変更してみたりしてみました。

初歩的な質問で申し訳ありませんが、どなたかご教授いただけると幸いです。

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

管理簿は一ヶ月ごとにファイルを新しくしていて、全てのシートは日付ごとに分けられています。
例)11/1、11/2・・・とシートが別々
それら全てに適用させたいです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

イベントハンドラーはハードルが高いみたいなんで、↓こうしてください。

const RCell = ssB.getRange('B' + RowB).getValue(); //これif(BCell==true && !RCell)が変更点です。

adhocに考えれば、問題は、「RCell」がオンになった状態なのに、「BCell」がオンになったときの処理が走ってします、だと言えます。つまりRCellがオンである時にBCellがオンになったときの処理が動かなければいい。あるいは、RCellがオフのときだけBCellがオンになった処理が動けばいい、と考えられます。
従って↑の赤字の部分の前者は、BCell処理において、RCellを考慮にいれ、かつ、後者はifにおいて、RCellがfalseであるかを識別すればよい、と考えられます。

javascript

1function logerB() {//logerBというイベント 2 var ssB = SpreadsheetApp.getActiveSheet(); //現在のスプレッドシートを取得 3 var RowB = ssB.getActiveCell().getRow(); //現在のスプレッドシートの現在の行を取得 4 var BCell = ssB.getRange('A' + RowB).getValue(); //現在のスプレッドシートの現在の行のA列 5 const RCell = ssB.getRange('B' + RowB).getValue(); //これ 6 var BTime = ssB.getRange('G' + RowB);//現在のスプレッドシートの現在の行のG列 7 8 if(RowB>1){ //Rowが1行目でないとき 9 if(BCell==true && !RCell) { //現在のスプレッドシートの現在の行のA列の値の変更があったとき 10 BTime.setValue(new Date());//現在時刻を挿入 11 } 12 } 13} 14 15function logerR() {//logerRというイベント 16 var ssR = SpreadsheetApp.getActiveSheet(); //現在のスプレッドシートを取得 17 var RowR = ssR.getActiveCell().getRow(); //現在のスプレッドシートの現在の行を取得 18 var RCell = ssR.getRange('B' + RowR).getValue(); //現在のスプレッドシートの現在の行のB列 19 var RTime = ssR.getRange('H' + RowR);//現在のスプレッドシートの現在の行のH列 20 21 if(RowR>1){ //Rowが1行目でないとき 22 if(RCell==true) { //現在のスプレッドシートの現在の行のA列の値の変更があったとき 23 RTime.setValue(new Date());//現在時刻を挿入 24 } 25 } 26}

投稿2018/11/08 06:51

編集2018/11/08 07:02
papinianus

総合スコア12705

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

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

papinianus

2018/11/08 06:52

質問者様以外はマネしないでください
papinianus

2018/11/08 07:03

ちなみにもし今後もコーディングするのであればbooltype == trueと書く習慣は即やめたほうがいいです。とりわけ、jsにおいてbooltype = trueは常にtrueになってしまうので、バグの(分かりづらい)元凶です。
jinjinghaiyue

2018/11/08 07:13

ありがとうございました。
papinianus

2018/11/08 07:14

こっちが動いたってことね
jinjinghaiyue

2018/11/08 07:19

はい。そうです。ありがとうございます。
guest

0

エラーと時間の更新が意図通りいかないのは別問題です。

エラー

変更時トリガーはやめて、編集時にしてください。概略だけいうと、変更時は例えばコメントの追加などのイベントも拾うので、activecellの参照が範囲外になる問題があります。

更新が意図どおりいかない

このコードにはエラーがありません。コード通りの処理がなされます。プログラムとはそういうものです。現在実装しておられるコードは、

  • 「変更時に」
  • 1行目でなく、かつA列がtrueだったら時刻を挿入するという処理
  • 1行目でなく、かつB列がtrueだったら時刻を挿入するという処理

の2つの処理が行われています。ですので、B列にチェックをつけたときの「変更」時に、A列がtrueであればG列に書き込みが起こって当然でしょう。
意図を実装するやり方としては、

  • 編集時に
  • "編集中のセルが"A列であれば、G列に書き込みをし、
  • "編集中のセルが"B列であれば、H列に書き込みをする、

という選択的な動作を1回だけ実行する、という書き方をする必要があります。

javascript

1function onEdit(e) { //onEditという名前ならトリガ設定不要 2 if(e.range.getSheet().getSheetName() !== "シート名") {return;} //シートが違ってたら中断 3 const col = e.range.getColumn(); 4 const row = e.range.getRow(); 5 if(row === 1) {return;} //ヘッダ行だったら中断 6 if(col !== 1 && col !== 2) {return;} //A列でもB列でもなかったら中断 7 if(e.value === "FALSE") {return;} //チェックを外したときは対象外 8 e.range.getSheet().getRange(row,col + 6,1,1).setValue(new Date()); //チェックをつけた場所の6列右に日付を入れる 9}

投稿2018/11/06 07:21

papinianus

総合スコア12705

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

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

papinianus

2018/11/06 07:24

onEditのイベント引数だからなのか分かりませんが、チェックボックスのe.valueが"TRUE"とか"FALSE"とかいった文字列で渡されたので、こういう書き方になりました。boolだと思ったので、(!e.value)としてたのですが…
jinjinghaiyue

2018/11/06 07:43

回答、本当にありがとうございます。いろんなサイトを参考にしてつなぎ合わせただけだったので、特に意味は考えていませんでした。もともと「==true」は入っていなかったのですが、うまくいかなかったため試行のために追加してみました(が機能は向上していないように思えます)。 「undefinedからプロパティ「range」を読み取れません。」とエラーが出たのですが、どうしたら良いかご教授願えますか。
papinianus

2018/11/06 07:45

関数を実行で確認していませんか?チェックを付けたり外したりして確認する必要があります
jinjinghaiyue

2018/11/06 07:51

スクリプトエディタで関数を実行していました。実際にシートでチェックボックスを付けたり外したりしても時刻は入力されませんでした。
papinianus

2018/11/06 08:00

シート名と書いてあるところは正しくなっていますか?
papinianus

2018/11/07 10:20

もう見てないのかな。チェックをつけて、変更をすべて保存しましたと表示がでたら、スクリプト画面に移動して実行トランスクリプトを見たら、なぜ止まっているかわかります。
jinjinghaiyue

2018/11/08 06:43

お返事遅くなり申し訳ありません。 「コピー用」というシートで実行したところ、 if(e.range.getSheet().getSheetName() !== "コピー用") {return;} //シートが違ってたら中断 部分に 「TypeError: undefined からプロパティ「range」を読み取れません。(行 4、ファイル「コード」)」と出てしまいました。
papinianus

2018/11/08 06:47

どうやって実行しましたか?e.rangeはonEditでは必ずセットされるはずのイベントパラメータなので、そのようなエラーが起こるとしたら、googleの仕様から見直さないといけないです。 トリガーは不要ですよ? もしかして、質問者様がセットしたスクリプトを他の人が共有で編集するということですか?
jinjinghaiyue

2018/11/08 06:56

前提となることを言っておらず、申し訳ありません。チームフォルダで数十人と共同編集しています。
papinianus

2018/11/08 06:59

gsuiteですかね。rangeは取得できると思うのですが、状況が分からないのでもう一つの回答をご利用ください
jinjinghaiyue

2018/11/08 07:12

完璧に動きました。ありがとうございます!!
jinjinghaiyue

2018/11/08 07:16

上の回答2で動いたということです。すみません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問