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

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

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

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

Q&A

解決済

1回答

954閲覧

GASでループ処理を実装したい

ytm.

総合スコア1

Google Apps Script

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

0グッド

0クリップ

投稿2021/12/01 00:51

前提・実現したいこと

Google Apps Scriptで
シートAを参照してシートBに文字列を記載するスクリプトを制作しています。

ネットで調べた情報を参考に、スクリプト自体は理想の動作で
なんとか動かすことができたのですが、処理をループさせる方法で悩んでいます。

シートA、K列最終行の次の行から処理を開始して、
処理の最後に、シートA、K列に日付を記載するまでを1セットで、
処理をループさせたいです。

該当のスプレッドシート

https://docs.google.com/spreadsheets/d/1Ba21o6hwndBd7QeC1tGdzmJ34GG9XngGRDVqTlh_xD4/edit#gid=796635446

該当のソースコード

GoogleAppScript

1function myFunction() { 2// ① [ sheetA ] [ sheetB ] を取得 3 var ss = SpreadsheetApp.getActiveSpreadsheet(); 4 var csv = ss.getSheetByName('sheetA') 5 var prc = ss.getSheetByName('sheetB') 6 7//② シートの最終行を取得 8 const LastRow = csv.getLastRow();   //シートのデータが入力されている最終行を取得 9 10//③ K列 最終行を取得 11 const kLastRow = csv.getRange(1,11).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow(); 12 13//④A列 > K列の場合処理を行う 14var remRow = LastRow - kLastRow; 15 16//処理を行う行 kLastRow+1 17var prcRow = kLastRow + 1; 18//⑤ kLastRow+1のF列を参照、セルの情報を取得 [ 文字列 ] 19var fCol = csv.getRange(prcRow,6).getValue(); 20 21//⑥ prcRowのA列を参照、セルの情報を取得 [ 年月 ] 22var aCol = csv.getRange(prcRow,1).getValue(); 23var aColD = new Date(aCol); 24var aColY = Utilities.formatDate(aColD,"JST","yy年MM月"); 25 26//⑦ prcRowのC列を参照、セルの情報を取得 [ 文字列 ] 27var cCol = csv.getRange(prcRow,3).getValue(); 28 29//⑧ 2行目の特定名の列を検索して返す関数を定義 30 function colSearch(label) { 31 for (i = 1; i <= prc.getLastColumn(); i++) { 32 if (prc.getRange(2, i).getValue() == label) { 33 return i; 34 } 35 } 36 } 37//⑨ 行を検索して返す関数を定義 38 function rowSearch(label) { 39 for (i = 1; i <= prc.getLastRow(); i++) { 40 if (prc.getRange(i, 1).getValue() == label) { 41 return i; 42 } 43 } 44 } 45//⑩ colSearchでaColを元に[ sheetB ]の列を検索して返す(yy/MMの一致:日付は一致不要) 46var refCol = colSearch(aColY); 47//⑪ rowSearchでfColを元に[ sheetB ]の行を検索して返す 48var refRow = rowSearch(fCol); 49 50//⑫ ⑩⑪で取得したrefCol、refRowを元にセルを指定し、決定した処理内容を反映 51 if ( cCol == "AAAA") { 52  prc.getRange(refRow,refCol).setValue("処理A") 53 } else if ( cCol == "BBBB") { 54 prc.getRange(refRow,refCol).setValue("処理A") 55 } else if ( cCol == "CCCC") { 56 prc.getRange(refRow,refCol).setValue("処理B") 57 } 58 59//⑬ 処理完了後、[ sheetA ] K列 に反映日時を記載 60const today = new Date(); 61var setDate = Utilities.formatDate(today,"JST","MM/dd"); 62csv.getRange(prcRow,11).setValue(setDate) 63}

試したこと

for(i=1,i>=LastLow,i++){
if(remRow>0){
var prcRow = kLastRow + i;
・・・
}else{break;
}

ネットでループ処理について調べて、
上記のような形で実装を試みましたが、
remRowの値が大きくなりすぎたり、
1行を処理するだけで終わってしまったり
未だにうまく実装できていません。

GASどころか、コーディング初心者で
意味不明な書き方をしている部分もあるかと思いますので、
大変恐縮なのですが、自分だけで解決できそうになかったので質問させていただきました。
何卒、ご教授いただけますと幸いです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

変更をなるべく最小限にするならば下記のようなコードになるかと思います。
(下記先頭が「+」となっている行は追加、「-」となっている行は削除)

diff

1 2function myFunction() { 3 // ① [ sheetA ] [ sheetB ] を取得 4 var ss = SpreadsheetApp.getActiveSpreadsheet(); 5 var csv = ss.getSheetByName('sheetA') 6 var prc = ss.getSheetByName('sheetB') 7 8 //② シートの最終行を取得 9 const LastRow = csv.getLastRow();   //シートのデータが入力されている最終行を取得 10 11 //③ K列 最終行を取得 12- const kLastRow = csv.getRange(1,11).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow(); 13+ const kLastRow = csv.getRange(csv.getMaxRows(), 11).getNextDataCell(SpreadsheetApp.Direction.UP).getRow() 14 //④A列 > K列の場合処理を行う 15 var remRow = LastRow - kLastRow; // remRowを使っていない場合は不要 16 17 //処理を行う行 kLastRow+1 18- //var prcRow = kLastRow + 1; // 削除 19+ for (var prcRow = kLastRow + 1; prcRow <= LastRow; prcRow++) { // 追加 20 //⑤ kLastRow+1のF列を参照、セルの情報を取得 [ 文字列 ] 21 var fCol = csv.getRange(prcRow, 6).getValue(); 22 23 //⑥ prcRowのA列を参照、セルの情報を取得 [ 年月 ] 24 var aCol = csv.getRange(prcRow, 1).getValue(); 25 var aColD = new Date(aCol); 26 var aColY = Utilities.formatDate(aColD, "JST", "yy年MM月"); 27 28 //⑦ prcRowのC列を参照、セルの情報を取得 [ 文字列 ] 29 var cCol = csv.getRange(prcRow, 3).getValue(); 30 31 //⑧ 2行目の特定名の列を検索して返す関数を定義 32 function colSearch(label) { 33 for (i = 1; i <= prc.getLastColumn(); i++) { 34 if (prc.getRange(2, i).getValue() == label) { 35 return i; 36 } 37 } 38+ Logger.log("colSearch:ラベル「" + label + "」はシートBの2行目に存在しません。"); 39+ return null; 40 41 } 42 //⑨ 行を検索して返す関数を定義 43 function rowSearch(label) { 44 for (i = 1; i <= prc.getLastRow(); i++) { 45 if (prc.getRange(i, 1).getValue() == label) { 46 return i; 47 } 48 } 49+ Logger.log("rowSearch:ラベル「" + label + "」がシートBのA列に存在しません。"); 50+ return null; 51 } 52 //⑩ colSearchでaColを元に[ sheetB ]の列を検索して返す(yy/MMの一致:日付は一致不要) 53 var refCol = colSearch(aColY); 54 //⑪ rowSearchでfColを元に[ sheetB ]の行を検索して返す 55 var refRow = rowSearch(fCol); 56 57+ // sheetBに検索値が見つからなかった場合は終了 58+ if (refCol == null || refRow == null) return; 59 60 //⑫ ⑩⑪で取得したrefCol、refRowを元にセルを指定し、決定した処理内容を反映 61 if (cCol == "AAAA") { 62 prc.getRange(refRow, refCol).setValue("処理A") 63 } else if (cCol == "BBBB") { 64 prc.getRange(refRow, refCol).setValue("処理A") 65 } else if (cCol == "CCCC") { 66 prc.getRange(refRow, refCol).setValue("処理B") 67 } 68 69 //⑬ 処理完了後、[ sheetA ] K列 に反映日時を記載 70 const today = new Date(); 71 var setDate = Utilities.formatDate(today, "JST", "MM/dd"); 72 csv.getRange(prcRow, 11).setValue(setDate) 73+ } // 追加 74}

・ループ処理

for (var prcRow = kLastRow + 1; prcRow <= LastRow; prcRow++) { ・・・ }

の部分で、K列の次の行から、A列の最終データがある行まで処理を繰り返すようにしています。

・「③ K列 最終行を取得」
csv.getRange(1,11).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() だと、1行目しかデータがない場合、正しく次の行を取得できません(表示範囲が1000行の場合、1000が返ってくる)
したがって、
csv.getRange(csv.getMaxRows(), 11).getNextDataCell(SpreadsheetApp.Direction.UP).getRow()
としています。

・2行目の特定名の列を検索して返す関数を定義/ ⑨ 行を検索して返す関数を定義
検索値が見つからなかった場合は終了するように修正しています
(現状でも検索値が見つからない場合エラーで強制終了しますが、ここでは、どういう値が見つからなかったのかを表示するようにしています)

投稿2021/12/01 04:03

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

退会済みユーザー

総合スコア0

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

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

ytm.

2021/12/01 04:07

回答ありがとうございます! また、詳細な説明も頂きありがとうございます。 for文の書き方が一番迷っていた部分だったのですが、 変数をiで置くことに固執しており、思いつかなかった部分でしたので とても参考になりました! 自分のコードと比較して勉強させていただきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問