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

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

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

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

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Q&A

解決済

1回答

1213閲覧

【GAS】IF 複数分岐時のコード記載方法

donguriko

総合スコア30

Google Apps Script

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

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

0グッド

0クリップ

投稿2022/09/13 11:52

編集2022/09/14 17:33

前提

スプレッドシートファイルの中に以下の2つのシートがあります。

①転記元シート
イメージ説明
②(ひな形)転記先シート
イメージ説明

GASで次の処理をさせたいです。
□処理1:②のシートをコピーし、③当月分シートを作成
□処理2:①の内容を③のシートにコピー
処理が完了したら、処理証跡として③のシートにタイムスタンプを追記

実現したいこと

スプレッドシートファイルの中に当月シートが存在しているか否かで
処理を条件分岐させたいです。

●存在していない
→処理1+2を実行

●存在している
ポップアップMsgを表示
転記処理を「継続」する(OK)か「中止」する(CANCEL)かを
ユーザーに選択させる。

OKクリックの場合
処理2を実行

キャンセルクリックの場合
「処理終了」のポップアップを表示させ、何も行わず、
そのまま処理終了

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

現コードだと「存在している」場合の処理は走る。

しかし、「存在していない」場合がうまくいかない。
「OK」クリックすると処理1は走るが、処理2が行われず終了。

(参考) 存在していない」場合の処理結果
イメージ説明
処理1に続けて、処理2も行わせたいのですが、
どこを、どのように修正すればよいのかがわかりません。

<質問1 >
修正方法のアドバイスが欲しいです。

<質問2>
キャンセルボタンクリック時で処理終了の際、return 
と書きましたが returnの使い方あっていますか?
return、continue、breakの使い分け方がよくわかりません。
(if、forでは、breakは使わない??)
どのように使い分けをすればよいかもレクチャーしてほしいです。     

該当のソースコード

以下、全文記載します。

GAS

1function inport_Test() { 2 const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 const fromSheet = ss.getSheetByName("転記元"); 4 const tempSheet = ss.getSheetByName("[ひな形]転記先"); 5 const mySheetName = "2022年9月分"; 6 const tosheet = ss.getSheetByName(mySheetName); 7 8 //▼条件分岐:当月分シートが作成されているか 9 //(trueの場合)ファイル内に当月分シートがない場合 10 //★うまくいかない★ 処理1しか行われない。処理2もさせたい。 11 if (tosheet === null) { 12 13 //▼処理1:当日分の転記先シートを作成 14 //転記先シートをコピーし、新シートを一番左に作成 15 //新シートのシート名を変更 16 const newSheet = tempSheet.copyTo(ss).activate(); 17 ss.moveActiveSheet(0); 18 newSheet.setName(mySheetName); 19 } 20 //▼ファイル内に当月分シートがある場合(falseの場合) 21 //処理をつつげる(OK) or 処理中止(cancel)のポップアップ表示 22 else { 23 const res = Browser.msgBox("当月分シートは作成済です。\\n 転記処理を続けますか?", Browser.Buttons.OK_CANCEL); 24 25 //▼「OK」ボタンをクリックの場合 26 //処理2から実施 27 if (res === "ok") { 28 //「元シート(fromSheet)」のデータあり最終行取得 29 //C列にデータあり行で判定 30 const fromLastRow = fromSheet.getRange(fromSheet.getMaxRows(), 3).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); //6が正解 31 const fromtargetRows = fromLastRow - 3 32 console.log("fromLastRow " + fromLastRow); // 6が正解 33 console.log("fromtargetRows " + fromtargetRows); // 3が正解 34 35 //▼処理2:データ転記処理 36 //<処理2-1>転記元データの取得 37 //「元シート(fromSheet)」の「項目3(B列)」~「項目2(I列)」の内容を 38 //二次元配列(mydetaRange)として取得 39 //getRange(●行、▲列、■行分、◆列分) 40 const mydetaRange = fromSheet.getRange(4, 2, fromtargetRows, 8).getValues(); 41 console.log("mydetaRange" + mydetaRange); 42 43 for (let r = 0; r <= fromtargetRows - 1; r++) { 44 //配列(mydetaRange)で取得した内容のうち転記したい項目 45 //[行インデックス][列インデックス] 46 let deta3 = mydetaRange[r][0]; 47 let deta4 = mydetaRange[r][1]; 48 let deta5 = mydetaRange[r][2]; 49 let deta6 = mydetaRange[r][3]; 50 let deta7 = mydetaRange[r][4]; 51 let deta8 = mydetaRange[r][5]; 52 let deta1 = mydetaRange[r][6]; 53 let deta2 = mydetaRange[r][7]; 54 console.log(deta3); 55 56 //<処理2-2>「転記先シート(toSheet)」に配列データを転記 57 //getRange(●行、▲列、■行分、◆列分) 58 //B列に項目1(deta1)を転記 59 const mySheet = ss.getSheetByName("転記先"); 60 const copydeta1 = tosheet.getRange(4 + r, 2, 1, 1).setValue(deta1); 61 const copydeta2 = tosheet.getRange(4 + r, 3, 1, 1).setValue(deta2); 62 const copydeta3 = tosheet.getRange(4 + r, 4, 1, 1).setValue(deta3); 63 const copydeta4 = tosheet.getRange(4 + r, 5, 1, 1).setValue(deta4); 64 const copydeta5 = tosheet.getRange(4 + r, 6, 1, 1).setValue(deta5); 65 const copydeta6 = tosheet.getRange(4 + r, 7, 1, 1).setValue(deta6); 66 const copydeta7 = tosheet.getRange(4 + r, 8, 1, 1).setValue(deta7); 67 const copydeta8 = tosheet.getRange(4 + r, 9, 1, 1).setValue(deta8); 68 69 //<処理2-3>タイムスタンプの追記 70 //getRange(●行、▲列、■行分、◆列分) 71 //J列にタイムスタンプを転記 72 const timeStamp = new Date(); 73 const setTimestamp = tosheet.getRange(4 + r, 10, 1, 1).setValue(timeStamp); 74 75 } 76 tosheet.activate(); 77 Browser.msgBox("データ転記処理が完了しました。"); 78 } 79 //「キャンセル」ボタンをクリックの場合 80 //転記処理終了 81 if (res === "cancel") { 82 Browser.msgBox("転記処理を中止します。"); 83 return; 84 } 85 } 86}

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

回答は本日中でなくてもよいです。

非エンジニアビギナーです。
次回から自力解決できるようになりたいので、非エンジニアビギナー
でも理解できるレベルでの解説をいただけると助かります。
お忙しいところ申し訳ありませんが、どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

ポップアップ表示→「OKならば処理をさせる」という流れではなく
ポップアップ表示→ キャンセルならばreturnして終了
という流れに変えればよいのではないでしょうか。

現状は

if (tosheet === null) { 処理1 } else { const res = <ポップアップ表示、OKかキャンセル> if (res === "ok") { 処理2 } } if (res === "cancel") { Browser.msgBox("転記処理を中止します。"); return; } } }

となっています。これを
修正後は

if (tosheet === null) { 処理1 } else { const res = <ポップアップ表示、OKかキャンセル> if (res === "cancel") { Browser.msgBox("転記処理を中止します。"); return; } } 処理2 } }

とします。

もっと単純化すると
現状は

if (tosheet === null) { 処理1 } else { popup表示: if (OKを押したか?) { →OK なら 処理2を実行 } }

となっているため処理1と処理2は少なくともどちらか一方しか実行されません。(もちろん処理2は OK を押したときにしか実行されません)

これを

if (tosheet === null) { 処理1 } else { popup表示: if (キャンセルを押したか?) { → キャンセルなら終了 } } 処理2を実行

という形にすることで、
・当月シートが存在しなければ、処理1と処理2が実行される。
・当月シートが存在する場合は、ポップアップが表示され、キャンセルを押せば終了、OK を押せば処理2が実行される。
というようになります。

全体は下記になります

js

1function inport_Test() { 2 const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 const fromSheet = ss.getSheetByName("転記元"); 4 const tempSheet = ss.getSheetByName("[ひな形]転記先"); 5 const mySheetName = "2022年9月分"; 6 const tosheet = ss.getSheetByName(mySheetName); 7 8 //▼条件分岐:当月分シートが作成されているか 9 //(trueの場合)ファイル内に当月分シートがない場合 10 //★うまくいかない★ 処理1しか行われない。処理2もさせたい。 11 if (tosheet === null) { 12 13 //▼処理1:当日分の転記先シートを作成 14 //転記先シートをコピーし、新シートを一番左に作成 15 //新シートのシート名を変更 16 const newSheet = tempSheet.copyTo(ss).activate(); 17 ss.moveActiveSheet(0); 18 newSheet.setName(mySheetName); 19 } 20 //▼ファイル内に当月分シートがある場合(falseの場合) 21 // ポップアップ表示 22 else { 23 const res = Browser.msgBox("当月分シートは作成済です。\\n 転記処理を続けますか?", Browser.Buttons.OK_CANCEL); 24 //「キャンセル」ボタンをクリックの場合 25 // 転記処理終了 26 if (res === "cancel") { 27 Browser.msgBox("転記処理を中止します。"); 28 return; 29 } 30 } 31 //▼「OK」ボタンをクリックの場合 32 //処理2から実施 33 34 //「元シート(fromSheet)」のデータあり最終行取得 35 //C列にデータあり行で判定 36 const fromLastRow = fromSheet.getRange(fromSheet.getMaxRows(), 3).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); //6が正解 37 const fromtargetRows = fromLastRow - 3 38 console.log("fromLastRow " + fromLastRow); // 6が正解 39 console.log("fromtargetRows " + fromtargetRows); // 3が正解 40 41 //▼処理2:データ転記処理 42 //<処理2-1>転記元データの取得 43 //「元シート(fromSheet)」の「項目3(B列)」~「項目2(I列)」の内容を 44 //二次元配列(mydetaRange)として取得 45 //getRange(●行、▲列、■行分、◆列分) 46 const mydetaRange = fromSheet.getRange(4, 2, fromtargetRows, 8).getValues(); 47 console.log("mydetaRange" + mydetaRange); 48 49 for (let r = 0; r <= fromtargetRows - 1; r++) { 50 //配列(mydetaRange)で取得した内容のうち転記したい項目 51 //[行インデックス][列インデックス] 52 let deta3 = mydetaRange[r][0]; 53 let deta4 = mydetaRange[r][1]; 54 let deta5 = mydetaRange[r][2]; 55 let deta6 = mydetaRange[r][3]; 56 let deta7 = mydetaRange[r][4]; 57 let deta8 = mydetaRange[r][5]; 58 let deta1 = mydetaRange[r][6]; 59 let deta2 = mydetaRange[r][7]; 60 console.log(deta3); 61 62 //<処理2-2>「転記先シート(toSheet)」に配列データを転記 63 //getRange(●行、▲列、■行分、◆列分) 64 //B列に項目1(deta1)を転記 65 const mySheet = ss.getSheetByName("転記先"); 66 const copydeta1 = tosheet.getRange(4 + r, 2, 1, 1).setValue(deta1); 67 const copydeta2 = tosheet.getRange(4 + r, 3, 1, 1).setValue(deta2); 68 const copydeta3 = tosheet.getRange(4 + r, 4, 1, 1).setValue(deta3); 69 const copydeta4 = tosheet.getRange(4 + r, 5, 1, 1).setValue(deta4); 70 const copydeta5 = tosheet.getRange(4 + r, 6, 1, 1).setValue(deta5); 71 const copydeta6 = tosheet.getRange(4 + r, 7, 1, 1).setValue(deta6); 72 const copydeta7 = tosheet.getRange(4 + r, 8, 1, 1).setValue(deta7); 73 const copydeta8 = tosheet.getRange(4 + r, 9, 1, 1).setValue(deta8); 74 75 //<処理2-3>タイムスタンプの追記 76 //getRange(●行、▲列、■行分、◆列分) 77 //J列にタイムスタンプを転記 78 const timeStamp = new Date(); 79 const setTimestamp = tosheet.getRange(4 + r, 10, 1, 1).setValue(timeStamp); 80 81 } 82 tosheet.activate(); 83 Browser.msgBox("データ転記処理が完了しました。"); 84} 85

<質問2>
キャンセルボタンクリック時で処理終了の際、return 
と書きましたが returnの使い方あっていますか?

→特に問題ないと思います。

(if、forでは、breakは使わない??)

if では breakは使いません。

for では途中で直近の内側のループを抜けるときに break を使います。ただし break を使った場合、必ずしも関数を脱出するとは限りません。
一方、for の途中で return すると、直ちに関数を脱出します。

投稿2022/09/13 13:24

編集2022/09/13 14:44
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

donguriko

2022/09/13 13:55

qnoirさま お忙しい中、早々の回答・解説ありがとうございます。 <質問1> 「if (tosheet === null) { 処理1 } ~キャンセルを押したか?→ キャンセルなら終了~ 処理2を実行」 という流れにする発想、全然浮かばなかったです。。。 処理分岐を考える際、何か「考えたのコツ」のようなものはありますか? こうしたひらめきは、(持前のセンス、によるところも大きいかとは 思いますが、、、)経験と場数を重ねて身に着けていくしかないでしょうか? <質問2> ・breakの使い方のレクチャーありがとうございます。 ・forで使用する場合、returnの方が確実にループを抜けられるので  使うなら returnの方がよい、ということですね。  return を使っていきたいと思います。 いつも丁寧な解説本当にありがとうございます。 qnoirさまに教えていただいた内容、自分のモノにしていきたいと思います。 お忙しい中レクチャーありがとうございました。(感謝)
退会済みユーザー

退会済みユーザー

2022/09/13 14:59 編集

1.今回の解決のヒントにしたのは、「条件分岐は早期にreturn したほうがよい」(終了条件/関数から脱出する条件を先に書く)という経験則のようなものです。 「コードをすっきりさせる」とか、「リファクタリング」「リーダブルコード(読みやすいコード)」というキーワードで調べると結構でてきます。 https://zenn.dev/media_engine/articles/early_return https://qiita.com/komekome111/items/af010f60b6da52a7a90c (繰り返しになりますが、今回はコードの可読性というより処理順序そのものが問題なので、上記の経験則は直接当てはまるものではないですが、解決にあたってヒントにはなっています) 他のことも「リファクタリング」「リーダブルコード」などのキーワードでいろいろ検索してみるとよいと思います。 2.複雑な条件分岐になりそうなときは、いきなりコードを書くのではなく、処理の流れを(手描きでいいので)図(フローチャート)を使って書いてみる、というやり方もあります。 フローチャートで、[実行したい内容]と[条件] [分岐] を組み合わせてコードの流れを可視化することで、「どのようなコード(条件分岐)にすればいいのか」が見えやすくなる場合もあります。 ・あとは場数と思います。
donguriko

2022/09/14 08:33

qnoirさま アドバイスありがとうございます。 最初の頃よりは、自分で検索して、前進できるようにはなってきた もののまだまだなので、検索ワード、知識の広げ方のアドバイスを いただけて大変助かります。 GAS本のように、理解が追い付かず途中で心折れそうになってしまう かもしれませんが、少しずつ知識を広げてみようと思います。 条件分岐は頭の中だけで考えていると段々混乱してきて 迷走してしまいがちなので、早速可視化、早速やってみたいと思います。 お忙しい中、具体的なアドバイス本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問