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

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

新規登録して質問してみよう
ただいま回答率
87.20%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

解決済

【GAS】行方向、列方向二重ループ処理について

donguriko
donguriko

総合スコア14

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

1回答

0評価

1クリップ

623閲覧

投稿2022/01/10 07:36

編集2022/01/16 10:20

前提・実現したいこと

以前ご教示いただいた内容から、下のように処理変更をしたいです。
(参考) 前回の質問リンク

<現>
・予定①~④のすべてがブランクの時は列Lに「対象外」のフラグを立て、
配列としてデータ取得の際、該当日付はスキップさせる。

<新>
上記に加え、以下処理も追加
・予定①~④が単体でブランクの時、列H~K(登録処理①~④)に「対象外」のフラグを立て、
配列としてデータ取得の際、該当予定件名の取得はスキップさせる。

※予定③、④は(登録なし)ブランクとなるケースがあることが判明。
予定(登録なし)ブランクとなるケースでカレンダーに「件名なし」で
登録されるのを回避したい。
予定①、②はブランクの想定はないが、オペレーションミスでブランクとなった
ケースを想定し、同処理とする。

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

下のとおりコード修正しました。
列H~列Lまでに「対象外」のフラグを立てる処理はできました。
が、予定①~④のいずれかが単体でブランクの時にもL列に「対象外」フラグが
立ってしまいます。

又、以下の処理も行われずGAS処理が終了となってしまいます。
・カレンダーへの予定登録処理
・スプレッドシート列H(登録処理①)~列K(登録処理④)への「登録済」追記

おそらくループの指定方法に誤りがあると思われるのですが、
どこがマズイのか、どのように修正すればよいのかが分かりません。
アドバイスをいただけないでしょうか?
(ループの範囲の理解がやはりまだ不十分のようです。申し訳ありません。。)

該当のソースコード

以下、コード全文記載します。

function createEvent() { //▼予定を追記するGoogleカレンダーIDを取得する <<セルC9(行9,列3) const ss = SpreadsheetApp.getActiveSpreadsheet(); const mysheet1 = ss.getSheetByName("カレンダー転記用");  const calId = mysheet1.getRange(9,3).getValue(); const cal = CalendarApp.getCalendarById(calId); const targetRows = mysheet1.getRange('C13').getValue(); console.log("targetRows " + targetRows); //予定①~予定④に予定なし分(土、日、祝日)はL列にフラグ立て const endRow = targetRows + 15 console.log("endRow " + endRow); for (let Row = 16; Row < endRow + 1; Row++) { for (let col = 4; col < 8 + 1; col++) { const myRange1 = mysheet1.getRange(Row, col, 1, 1); const myRange2 = mysheet1.getRange(Row, 4, 1, 4); //▼予定①~④がブランクの時のフラグ立て if (myRange1.isBlank()) { mysheet1.getRange(Row, col + 4, 1, 1).setValue("対象外"); } else if (myRange2.isBlank()) mysheet1.getRange(Row, 12, 1, 1).setValue("対象外"); //getRange(行目,列目,●行分,●列分) } } //▼データ取得範囲の指定 //各種予定のデータ取得範囲の指定  //getRange(行目,列目,●行分,●列分) //予定配列>>セルB16(行16,列2)~L列まで  const eventRange = mysheet1.getRange(16, 2, targetRows, 11); console.log("eventRange " + eventRange.getA1Notation()); //▼各予定データを配列(myEvent)として取得する const myEvent = eventRange.getValues(); Logger.log(myEvent); //▼各日付ごとに処理する for (let i = 0; i < targetRows; i++) { let myDate = myEvent[i][0]; //「日付」は起点B16から下にi行、右に0 let ngFlag = myEvent[i][10]; //「対象外フラグ」は起点B16から下にi行、右に10  // 「対象外」であればスキップして次の行へ。 if (ngFlag === "対象外") { continue; } //▼「①~④予定」を一列ずつ処理(column:0~3までループ) for (let column = 0; column < 4; column++) { let flag = myEvent[i][6 + column]; //「①~④登録済フラグ」は起点B16から下にi行、右に6+column // 「登録済」であればスキップして隣の列へ。 if (flag === "登録済" || flag === "対象外") { continue; } //「予定名(title)」を取得 let title = myEvent[i][2 + column]; //「①~④予定名」は起点0(B16)から下にi行、右に2+column //▼カレンダーへの予定登録 cal.createAllDayEvent(title, new Date(myDate)); //▼スプレッドシートへの「登録済」フラグ記載 mysheet1.getRange(16 + i, 8 + column, 1, 1).setValue("登録済"); //スプシH列に「登録済」と追記 } } //▼ダイアログMsgの表示 Browser.msgBox("Googleカレンダーへの転記作業が完了しました。登録内容は「カレンダー転記用」シートで確認してください。", Browser.Buttons.OK) }

試したこと

今回の処理変更に伴い、
予定①~④がブランクか否かの判定を横方向のループ処理で判定させる
のがよいのではないかと考え、行方向、列方向の二重ループ処理に変更すべく、
以下を試みました。

●変更1:17行目以降
(現)endRowまで1行ずつ下に処理していくループ処理
(新)上のループに加え、
列D~Gまで1列ずつ右に処理していくループ処理 を追加。

for (let Row = 16; Row < endRow + 1; Row++) { for (let col = 4; col < 8 + 1; col++) {

●変更2:56行目以降
(現) flag==="登録済" の時処理スキップ
(新) (flag === "登録済" || flag === "対象外") に変更

if (flag === "登録済" || flag === "対象外") { continue; }

33行目以降の処理が行われていない原因は
括弧のくくり方(閉じ括弧の位置)が間違えているからですか?
列方向のループ処理を追加する位置が違うからですか?

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

回答は本日中でなくても大丈夫です。
お忙しいところ何度も質問してしまい本当に申し訳ありません。
次回から自力で解決できるよう、非エンジニア、ビギナーでも分かるレベルでの
アドバイス、解説をいただけると助かります。
お手数をおかけいたしまして申し訳ありません。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

qnoir

2022/01/10 08:20

L列に「対象外」という文字を入れる条件について確認なのですが、 ①D列~G列4つとも空白の場合は、H~K列に「対象外」を入力し、L列にも「対象外」を入力する、という理解でよろしいでしょうか。 ②たとえば、D列だけに予定が入っていて、E~G列3つが空欄の場合は、 H列は空欄、I列~K列に「対象外」を入力し、L列には「対象外」を入力しない という理解でよろしいでしょうか。
donguriko

2022/01/10 09:49 編集

qnoirさま 確認が遅くなり申し訳ありません。以下、回答します。 ①はい、重複感はありますが、4つとも空白の場合は、H~K列に「対象外」かつ、  L列にも「対象外」と返す想定でいます。 ②はい、ご認識のとおりの想定です。  L列「対象外」の時は配列に日付取得しない。<<件名なしの予定が4個登録されるのを回避したい。  H~K列「対象外」の時は、日付は取得するが、予定件名のみ取得しないとしたい。  修正前のコードだと、予定③、④がブランクの場合、該当日に件名なしの予定が2個登録  されてしまう。<<これを回避したいです。※  ※もし、上記フラグ立てでは、予定③、④がブランク時の件名ブランク登録が   回避できない場合は、可能であればどのようなやり方なら回避できそうかアドバイスを   いただけると幸いです。
donguriko

2022/01/15 15:43 編集

qnoirさま 返信が遅くなり申し訳ありません。 お忙しい中、回答ありがとうございます。 ループ処理の際の参照範囲の指定誤りが原因だったのですね。 又、処理が遅い部分についても改善策提示ありがとうございます。 私のコードだと、my Range2で同じ範囲を4回チェックすることに なってしまっていたのですね。時間がかかる筈ですね。 いつも困った時に、助けていただき本当にありがとうございます。 今回の回答も今後に生かせるよう読み返し、お勉強させていただきます。 ありがとうございました。 ★追伸・・・修正いただいたコードで格段に処理が早くなりました。本当にありがとうございました。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します