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

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

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

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

2842閲覧

【GAS】 配列で取得したデータから特定の条件に合致したデータを除外したい

donguriko

総合スコア30

Google Apps Script

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

2クリップ

投稿2021/12/18 13:23

編集2021/12/18 13:24

前提・実現したいこと

二次元配列でデータ取得しています。
配列内の項目は[日付(B)、予定①~④(D~G),登録処理①~④(H~K),対象判定(L)]の4つです。
「対象判定(ngFlag)==="対象外"」の時、配列からその行データ(配列要素4項目とも)を
削除したいです。

<背景>
配列データを元にGoogleカレンダーに予定登録する際、上記削除処理をしないと、
日付は配列内にデータありのため、土日祝日分は件名なしでカレンダーに予定が
登録されてしまう。これを回避したい。

※類似で、処理開始時点でスプレッドシートH列~K列に「登録済」のフラグが
あるデータも除外したい。
おそらくコレは、「対象判定(ngFlag)==="対象外"」の時の除外と同じやり方で
回避できるのではないかと推測。

<スプレッドシートイメージ:現在のコードで処理後のイメージです>
イメージ説明

困っていること

IF文で「対象判定(ngFlag)==="対象外"」の時で条件指定し、
slice関数で除外 するのか? と考えたのですが、
行インデックスは固定ではなく、可変。(セルC10の数値が変わると変動)
どのようにslice関数で削除する行インデックスを指定すればよいのか、思いつきません。
対象行は可変なので変数を使う???

①どうすれば除外する行インデックスの指定ができるか、
配列から該当行データを除外できるかのアドバイス(ヒント)を
いただけないでしょうか?

②IF文をかませる方法で正解の場合、
IF文とfOR文どちらを先に書けばよいのか、悩みました。
ngFlagはfor文のところでlet指定しているので、FOR文が先が
正解ですか?
コード記載の方法がよく分からないので解説いただけないでしょうか?

該当のソースコード

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

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 i=16; i < endRow+1; i++){
const myRange = mysheet1.getRange(i,4,1,4);
if(myRange.isBlank()){
mysheet1.getRange(i,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);

//各配列のデータ取得取得位置の指定
//▼「①予定」の取得
//取得する項目は「予定名(title1)」「日付(myDate1)」「登録済フラグ(flag1_1)」「対象外フラグ(ngFlag)」の4つ
for(let i=0; i < targetRows; i++){
let title1 = myEvent[i][2]; //「①予定名」は起点0(B16)から下にi行、右に2
let myDate1 = myEvent[i][0]; //「日付」は起点B16から下にi行、右に0
let flag1_1 = myEvent[i][6]; //「①登録済フラグ」は起点B16から下にi行、右に6
let ngFlag = myEvent[i][6]; //「対象外フラグ」は起点B16から下にi行、右に10

//★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外
//if (ngFlag !== "対象外"){ ????
//★うまくできない★ 「登録済フラグ(flag1_1)行インデックスを配列から除外

//▼カレンダーへの予定登録
//cal.createAllDayEvent(title1,new Date(myDate1)); 

//▼スプレッドシートへの「登録済」フラグ記載
//getRange(行目,列目,●行分,●列分) >>セルH16以降に転記
mysheet1.getRange(16,8,targetRows,1).setValue("登録済"); //スプシH列に「登録済」と追記
}

//▼「②予定」の取得
//取得する項目は「予定名(title2)」「日付(myDate2)」「登録済フラグ(flag2)」「対象外フラグ(ngFlag)」の4つ
for(let i=0; i < targetRows; i++){
let title2 = myEvent[i][3]; //「②予定名」は起点0(B16)から下にi行、右に3
let myDate2 = myEvent[i][0];  //「日付」は起点0(B16)から下にi行、右に0
let flag2 = myEvent[i][7]; //「②登録済フラグ」は起点0(B16)から下にi行、右に7
let ngFlag = myEvent[i][6]; //「対象外フラグ」は起点B16から下にi行、右に10

//★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外
//★うまくできない★ 「登録済フラグ(flag2)行インデックスを配列から除外

//▼カレンダーへの予定登録
//cal.createAllDayEvent(title2,new Date(myDate2)); 

//▼スプレッドシートへの「登録済」フラグ記載
//getRange(行目,列目,●行分,●列分) >>セルI16以降に転記
mysheet1.getRange(16,9,targetRows,1).setValue("登録済"); //スプシI列に「登録済」と追記
}

//▼「③予定」の取得
//配列内の項目は「予定名(title3)」「日付(myDate3)」「登録済フラグ(flag3)」「対象外フラグ(flag1_2)」の4つ
//「登録済フラグ(flag3)」に「登録済」の表示がある時は、処理しない
for(let i=0; i < targetRows; i++){
let title3  = myEvent[i][4]; //「③予定名」は起点0(B16)から下にi行、右に4
let myDate3 = myEvent[i][0];  //「日付」は起点0(B16)から下にi行、右に0
let flag3  = myEvent[i][8]; //「③登録済フラグ」は起点0(B16)から下にi行、右に8列

//★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外
//★うまくできない★ 「登録済フラグ(flag3)行インデックスを配列から除外

//▼カレンダーへの予定登録
//cal.createAllDayEvent(title3,new Date(myDate1)); 

//▼スプレッドシートへの「登録済」フラグ記載
//getRange(行目,列目,●行分,●列分) >>セルJ16以降に転記
mysheet1.getRange(16,10,targetRows,1).setValue("登録済"); //スプシJ列に「登録済」と追記
}

//▼「④予定」の取得
//配列内の項目は「予定名(title4)」「日付(myDate4)」「登録済フラグ(flag4)」「対象外フラグ(flag1_2)」の4つ
//「登録済フラグ(flag4)」に「登録済」の表示がある時は、処理しない
for(let i=0; i < targetRows; i++){
let myDate4 = myEvent[i][0];  //「日付」は起点0(B16)から下にi行、右に0
let title4  = myEvent[i][5];  //「④予定名」は起点0(B16)から下にi行、右に5
let flag4 = myEvent[i][9]; //「④登録済フラグ」は起点0(B16)から下にi行、右に9列

//★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外
//★うまくできない★ 「登録済フラグ(flag4)行インデックスを配列から除外

//▼カレンダーへの予定登録
//cal.createAllDayEvent(title4,new Date(myDate4)); 

//▼スプレッドシートへの「登録済」フラグ記載
//getRange(行目,列目,●行分,●列分1) >>セルK16以降に転記
mysheet1.getRange(16,11,targetRows,1).setValue("登録済"); //スプシK列に「登録済」と追記
}

//▼ダイアログMsgの表示
Browser.msgBox("Googleカレンダーへの転記作業が完了しました。\n登録内容はカレンダー転記シートで確認してください。",Browser.Buttons.OK);
}

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

前回の質問の続きです。
(リンク内容)

回答は、本日中でなくて大丈夫です。
非エンジニア、ビギナーでも理解できるレベルのアドバイスまたはヒントを
いただけると助かります。

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

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

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

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

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

guest

回答1

0

ベストアンサー

直すとすれば下記のようになるでしょうか

diff

1function createEvent() { 2 //▼予定を追記するGoogleカレンダーIDを取得する <<セルC9(行9,列3) 3 const ss = SpreadsheetApp.getActiveSpreadsheet(); 4 const mysheet1 = ss.getSheetByName("カレンダー転記用"); 5 const calId = mysheet1.getRange(9, 3).getValue(); 6 const cal = CalendarApp.getCalendarById(calId); 7 const targetRows = mysheet1.getRange('C13').getValue(); 8 console.log("targetRows " + targetRows); 9 10 //予定①~予定④に予定なし分(土、日、祝日)はL列にフラグ立て 11 const endRow = targetRows + 15 12 console.log("endRow " + endRow); 13 14 for (let i = 16; i < endRow + 1; i++) { 15 const myRange = mysheet1.getRange(i, 4, 1, 4); 16 if (myRange.isBlank()) { 17 mysheet1.getRange(i, 12, 1, 1).setValue("対象外"); 18 //getRange(行目,列目,●行分,●列分) 19 } 20 } 21 22 //▼データ取得範囲の指定 23 //各種予定のデータ取得範囲の指定  24 //getRange(行目,列目,●行分,●列分) 25 //予定配列>>セルB16(行16,列2)~L列まで  26 const eventRange = mysheet1.getRange(16, 2, targetRows, 11); 27 console.log("eventRange " + eventRange.getA1Notation()); 28 29 //▼各予定データを配列(myEvent)として取得する 30 const myEvent = eventRange.getValues(); 31 Logger.log(myEvent); 32 33 //各配列のデータ取得取得位置の指定 34 //▼「①予定」の取得 35 //取得する項目は「予定名(title1)」「日付(myDate1)」「登録済フラグ(flag1_1)」「対象外フラグ(ngFlag)」の4つ 36 for (let i = 0; i < targetRows; i++) { 37 let title1 = myEvent[i][2]; //「①予定名」は起点0(B16)から下にi行、右に2 38 let myDate1 = myEvent[i][0]; //「日付」は起点B16から下にi行、右に0 39 let flag1_1 = myEvent[i][6]; //「①登録済フラグ」は起点B16から下にi行、右に6 40- let ngFlag = myEvent[i][6]; //「対象外フラグ」は起点B16から下にi行、右に10 41+ let ngFlag = myEvent[i][10]; //「対象外フラグ」は起点B16から下にi行、右に10  42 //★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外 43- if (ngFlag !== "対象外"){ ???? 44+ if (ngFlag === "対象外" || flag1_1 === "登録済") { // 「対象外」または「登録済」であれば、処理をスキップ 45+ continue; 46+ } 47 48 //★うまくできない★ 「登録済フラグ(flag1_1)行インデックスを配列から除外 49 50 //▼カレンダーへの予定登録 51- //cal.createAllDayEvent(title1,new Date(myDate1));  52+ cal.createAllDayEvent(title1,new Date(myDate1));  53 //▼スプレッドシートへの「登録済」フラグ記載 54 //getRange(行目,列目,●行分,●列分) >>セルH16以降に転記 55- //mysheet1.getRange(16, 8, targetRows, 1).setValue("登録済"); //スプシH列に「登録済」と追記 56+ mysheet1.getRange(16 + i, 8, 1, 1).setValue("登録済"); //スプシH列に「登録済」と追記 57 } 58 59 //▼「②予定」の取得 60 //取得する項目は「予定名(title2)」「日付(myDate2)」「登録済フラグ(flag2)」「対象外フラグ(ngFlag)」の4つ 61 for (let i = 0; i < targetRows; i++) { 62 let title2 = myEvent[i][3]; //「②予定名」は起点0(B16)から下にi行、右に3 63 let myDate2 = myEvent[i][0];  //「日付」は起点0(B16)から下にi行、右に0 64 let flag2 = myEvent[i][7]; //「②登録済フラグ」は起点0(B16)から下にi行、右に7 65- let ngFlag = myEvent[i][6]; //「対象外フラグ」は起点B16から下にi行、右に10 66+ let ngFlag = myEvent[i][10]; //「対象外フラグ」は起点B16から下にi行、右に10 67 //★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外 68 //★うまくできない★ 「登録済フラグ(flag2)行インデックスを配列から除外 69+ if (ngFlag === "対象外" || flag2 === "登録済") { 70+ continue; 71+ } 72 73 //▼カレンダーへの予定登録 74 //cal.createAllDayEvent(title2,new Date(myDate2));  75 76 //▼スプレッドシートへの「登録済」フラグ記載 77 //getRange(行目,列目,●行分,●列分) >>セルI16以降に転記 78- mysheet1.getRange(16, 9, targetRows, 1).setValue("登録済"); //スプシI列に「登録済」と追記 79+ mysheet1.getRange(16 + i, 9, 1, 1).setValue("登録済"); //スプシI列に「登録済」と追記 80 } 81 82 //▼「③予定」の取得 83 //配列内の項目は「予定名(title3)」「日付(myDate3)」「登録済フラグ(flag3)」「対象外フラグ(flag1_2)」の4つ 84 //「登録済フラグ(flag3)」に「登録済」の表示がある時は、処理しない 85 for (let i = 0; i < targetRows; i++) { 86 let title3 = myEvent[i][4]; //「③予定名」は起点0(B16)から下にi行、右に4 87 let myDate3 = myEvent[i][0];  //「日付」は起点0(B16)から下にi行、右に0 88 let flag3 = myEvent[i][8]; //「③登録済フラグ」は起点0(B16)から下にi行、右に8列 89+ let ngFlag = myEvent[i][10]; //「対象外フラグ」は起点B16から下にi行、右に10  90 //★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外 91 //★うまくできない★ 「登録済フラグ(flag3)行インデックスを配列から除外 92 93+ if (ngFlag === "対象外" || flag3 === "登録済") {){ 94+ continue; 95+ } 96 97 //▼カレンダーへの予定登録 98- //cal.createAllDayEvent(title3,new Date(myDate1));  99+ cal.createAllDayEvent(title3,new Date(myDate3)); // myDate1 -> myDate3 に修正  100 //▼スプレッドシートへの「登録済」フラグ記載 101 //getRange(行目,列目,●行分,●列分) >>セルJ16以降に転記 102- mysheet1.getRange(16, 10, targetRows, 1).setValue("登録済"); //スプシJ列に「登録済」と追記 103+ mysheet1.getRange(16 + i, 10, 1, 1).setValue("登録済"); //スプシJ列に「登録済」と追記 104 } 105 106 //▼「④予定」の取得 107 //配列内の項目は「予定名(title4)」「日付(myDate4)」「登録済フラグ(flag4)」「対象外フラグ(flag1_2)」の4つ 108 //「登録済フラグ(flag4)」に「登録済」の表示がある時は、処理しない 109 for (let i = 0; i < targetRows; i++) { 110 let myDate4 = myEvent[i][0];  //「日付」は起点0(B16)から下にi行、右に0 111 let title4 = myEvent[i][5];  //「④予定名」は起点0(B16)から下にi行、右に5 112 let flag4 = myEvent[i][9]; //「④登録済フラグ」は起点0(B16)から下にi行、右に9列 113+ let ngFlag = myEvent[i][10]; //「対象外フラグ」は起点B16から下にi行、右に10  114 //★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外 115 //★うまくできない★ 「登録済フラグ(flag4)行インデックスを配列から除外 116+ if (ngFlag === "対象外" || flag4 === "登録済") {){ 117+ continue; 118+ } 119 120 121 //▼カレンダーへの予定登録 122- //cal.createAllDayEvent(title4,new Date(myDate4));  123+ cal.createAllDayEvent(title4,new Date(myDate4));  124 //▼スプレッドシートへの「登録済」フラグ記載 125 //getRange(行目,列目,●行分,●列分1) >>セルK16以降に転記 126- mysheet1.getRange(16, 11, targetRows, 1).setValue("登録済"); //スプシK列に「登録済」と追記 127+ mysheet1.getRange(16 + i, 11, 1, 1).setValue("登録済"); //スプシK列に「登録済」と追記 128 } 129 130 //▼ダイアログMsgの表示 131 Browser.msgBox("Googleカレンダーへの転記作業が完了しました。\n登録内容はカレンダー転記シートで確認してください。", Browser.Buttons.OK); 132}

説明

(1)行を除外する

①どうすれば除外する行インデックスの指定ができるか、
配列から該当行データを除外できるかのアドバイス(ヒント)を
いただけないでしょうか?

ここではsliceを使って配列をいじる必要はありません。

・if文を使って、対象行が「対象外」または「登録済」かどうかを判定する。
->「対象外」または「登録済」であれば、continue でその行の処理をスキップする

という形にすればよいです。

回答の下記の部分になります。

diff

1+ let ngFlag = myEvent[i][10]; //「対象外フラグ」は起点B16から下にi行、右に10  2 //★うまくできない★ 「対象外フラグ(ngFlag)」対象外フラグあり行インデックスを配列から除外 3- if (ngFlag !== "対象外"){ ???? 4+ if (ngFlag === "対象外" || flag1_1 === "登録済") { // 「対象外」または「登録済」であれば、処理をスキップ 5+ continue; 6+ }

「||」は難しい言葉で「論理和演算子」と呼ばれるものです。
ごく簡単に言えば、if文で「A || B」という形で使うと、AまたはBのどちらかが正の場合、文が実行されます。
参照:MDN:||(論理和)


(2)IF文とfOR文どちらを先に書けばよいのか

②IF文をかませる方法で正解の場合、
IF文とfOR文どちらを先に書けばよいのか、悩みました。
ngFlagはfor文のところでlet指定しているので、FOR文が先が
正解ですか?

今回の場合はforループの中で1行ずつ条件判定しているので、for文が先で正解です。

(3)「登録済」フラグの書き込み
元の質問文では、カレンダーに登録した行についてH列~K列に「登録済」という値を設定しようとされていますが、
実際は常に16行目~最後の行まで書き込むようになってしまっています。
ここは、カレンダーを登録した行だけに書き込むようにする必要があります(下記)

diff

1 //▼スプレッドシートへの「登録済」フラグ記載 2 //getRange(行目,列目,●行分,●列分) >>セルH16以降に転記 3- //mysheet1.getRange(16, 8, targetRows, 1).setValue("登録済"); //スプシH列に「登録済」と追記 4+ mysheet1.getRange(16 + i, 8, 1, 1).setValue("登録済"); //スプシH列に「登録済」と追記

改善案

元々のコードですが、同じ処理について列を変えて繰り返すコードを追加する過程で
列の指定を誤って修正してしまっていると思われる部分がところどころにあります。
注意深くデバッグして正しく動けば問題ないのですが、現状のアプローチでは下記のような問題があります。

・仮に登録処理の列が増えたり減ったりした場合に、4つのブロックそれぞれを変更しなければならなくなる。
・その際にチェックが不足していると、同じような列指定ミスが発生する可能性が高くなる。

2つ前の御質問と同様に、規則性を見出してまとめられるところはまとめた方が、変更に強く、バグを出しにくいコードになります。

たとえば今回で言えば、「各日付の4つの処理件名列と、登録済フラグを書き込む列はそれぞれ4列ずつ離れている」という規則性があります。
イメージ説明

そこで、「件名の取得とカレンダーへの登録、及び登録済フラグの書き込み」を1つの処理としてまとめ、
列を1つずつ移動させればすっきりしたコードになります。

下記では、もともとのforループ(targetRowを動かすループ)の中に、もう1つforループを加えています。
この追加したforループの中で、column という変数を0~3までループさせています。
各処理対象に対して column 変数が示す値を加算することで、1列ずつ移動して処理を行っています。

js

1// 4列分の処理をまとめたコード 2 3 4function createEvent2() { 5 //▼予定を追記するGoogleカレンダーIDを取得する <<セルC9(行9,列3) 6 const ss = SpreadsheetApp.getActiveSpreadsheet(); 7 const mysheet1 = ss.getSheetByName("カレンダー転記用"); 8 const calId = mysheet1.getRange(9, 3).getValue(); 9 const cal = CalendarApp.getCalendarById(calId); 10 const targetRows = mysheet1.getRange('C13').getValue(); 11 console.log("targetRows " + targetRows); 12 13 //予定①~予定④に予定なし分(土、日、祝日)はL列にフラグ立て 14 const endRow = targetRows + 15 15 console.log("endRow " + endRow); 16 17 for (let i = 16; i < endRow + 1; i++) { 18 const myRange = mysheet1.getRange(i, 4, 1, 4); 19 if (myRange.isBlank()) { 20 mysheet1.getRange(i, 12, 1, 1).setValue("対象外"); 21 //getRange(行目,列目,●行分,●列分) 22 } 23 } 24 25 //▼データ取得範囲の指定 26 //各種予定のデータ取得範囲の指定  27 //getRange(行目,列目,●行分,●列分) 28 //予定配列>>セルB16(行16,列2)~L列まで  29 const eventRange = mysheet1.getRange(16, 2, targetRows, 11); 30 console.log("eventRange " + eventRange.getA1Notation()); 31 32 //▼各予定データを配列(myEvent)として取得する 33 const myEvent = eventRange.getValues(); 34 Logger.log(myEvent); 35 36 //▼各日付ごとに処理する 37 for (let i = 0; i < targetRows; i++) { 38 let myDate = myEvent[i][0]; //「日付」は起点B16から下にi行、右に0 39 let ngFlag = myEvent[i][10]; //「対象外フラグ」は起点B16から下にi行、右に10  40 // 「対象外」であればスキップして次の行へ。 41 if (ngFlag === "対象外") { 42 continue; 43 } 44 //▼「①~④予定」を一列ずつ処理(column:0~3までループ) 45 for (let column = 0; column < 4; column++) { 46 let flag = myEvent[i][6 + column]; //「①~④登録済フラグ」は起点B16から下にi行、右に6+column 47 // 「登録済」であればスキップして隣の列へ。 48 if (flag === "登録済") { 49 continue; 50 } 51 //「予定名(title)」を取得 52 let title = myEvent[i][2 + column]; //「①~④予定名」は起点0(B16)から下にi行、右に2+column 53 54 //▼カレンダーへの予定登録 55 cal.createAllDayEvent(title, new Date(myDate)); 56 //▼スプレッドシートへの「登録済」フラグ記載 57 mysheet1.getRange(16 + i, 8 + column, 1, 1).setValue("登録済"); //スプシH列に「登録済」と追記 58 } 59 } 60 //▼ダイアログMsgの表示 61 Browser.msgBox("Googleカレンダーへの転記作業が完了しました。\n登録内容はカレンダー転記シートで確認してください。", Browser.Buttons.OK); 62}

その他

本件の質問とは直接関係ありませんが、スクリプトのタイムゾーン設定が日本時間になっていない場合、日時がずれてGoogleカレンダーに登録されることがあります。

もし日時がずれて登録される場合は、下記の手順で、スクリプトのタイムゾーン設定が日本時間になっているか確認してください。(特に登録日時がズレていない場合は不要です)

1.左端の歯車マークをクリックして、“「appsscriptjson」マニフェストファイルをエディタで表示する”にチェックを入れます。
イメージ説明

2.コードエディタ画面に戻ると、「appsscriptjson」というファイルが表示されているはずなので、そこをクリックし、timeZoneが「Asia/Tokyo」になっているか確認します。
(「Asia/Tokyo」になっていない場合は、「Asia/Tokyo」に直して保存)
イメージ説明


参考に、配列から要素を除外する方法(splice関数)について書こうとしましたが、書くと文字数制限を超えるためここでは割愛します。必要があればコメントに記載します。

投稿2021/12/19 01:12

編集2021/12/19 03:19
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

donguriko

2021/12/19 09:05 編集

qnoirさま お忙しい中、丁寧な解説ありがとうございます。 ●規則性を見出してまとめるところはまとめるべし 解説を拝見し、こんなにすっきりできるのかと目から鱗です。 前回もご指摘いただいていたのに改善できておらず申し訳ありません。 1つ1つの処理をどう書けばいいのかに必死で、全体を俯瞰してみる 視点が全然持てていませんでした。 不慣れな素人ほどミス連発ですし、チェックする目も甘い。 こうまとめればいいという視点なかったです。とても勉強になります。 (そして、誤修正している箇所連発にも関わらず丁寧な添削、心から感謝です) ●for文ループ処理 continueでスキップ判定された時に次にどの処理に進むのかが まだちょっと消化不良気味です。 以下のイメージで理解あっていますか? <1個目のループ> 配列(myEvent)内に日付を取り込むか否かを判定し、取込み処理。 取込みOK判定→ループ2へ スキップ判定→for文の一番外の閉じかっこ の外の処理へ <2個目のループ> 配列(myEvent)内に予定件名を取り込むか否かを判定し、 a)取込 b)カレンダー登録 c)登録済追記 の3つを処理。 取込みOK判定→3つ処理後、for文の一番外の閉じかっこ の外の処理へ スキップ判定→for文の一番外の閉じかっこ の外の処理へ 基礎中の基礎で本当に恐縮ですが、コードを記載している時や解説 いただいているコードをおさらいしている時など、どこからどこまでが 括弧でくくられている範囲(ブロック?)なのか段々と分からなくなり、 コード記載している時に閉じ括弧を忘れてエラーが立ちがちです。 (全部黒一色なので、この閉じ括弧はどの開始括弧の相対??? と迷子に) ここは慣れと注意力をあげるしかないでしょうか? ●登録済の追記処理 ループ2の中にいれることで、対象外を除外できるのですね。勉強になりました。 そして、getRangeの行目は16+iで可変、何行分書くかは1。 可変させる箇所間違えてましたね。 getRangeの指定方法も、配列同様まだまだ復習が必要ですね。 回答コードを読み込むとなるほど、となんとなく分かった気になっていても、 では「いざ自分でどうぞ」となるとまだ身についていないと痛感します。 もっと勉強したいと思います。 ●タイムゾーン設定 解説ありがとうございます!! 実はちょうど別処理の祝日の取得処理が自宅環境でできていたのが、別環境で コード等移植して動かしてみたら日時がずれてしまい、どうしてだろう、、、 と思っていた所でした。 かゆいところに手が届くご指導、本当にありがとうございます。 ●splice関数 今後のためにぜひ、教えてください。 が、お忙しいと思いますので、急ぎません。qnoirさまのお時間のある時で大丈夫です。 自分でネットを見たり、GAS本も読んでみましたが、私にはまだレベルが高い記載で もう少しかみ砕いた解説がいたただけるととても助かります。 いつもqnoirさまからの解説を読んでからGAS本に戻ると、そういうことか、、、と 前より少しだけ理解できるようになります。
退会済みユーザー

退会済みユーザー

2021/12/23 12:50 編集

●for文ループ処理 continueは、その属しているブロック内のループ部分に戻ります。 たとえば for(let x=0; x<5; i++) {   …(a)  ***(a)ループブロック内の処理***  if(~){   continue; …① →(a)に戻る  }   for(let y=0; y<10; ++) {  …(b)   ***(b)ループブロック内の処理***   if(~){    continue;  …② →(b)に戻る   }  } } ①のcontinueは(a)のブロック内に属している為、(a)に戻ります。 ②のcontinueは(b)のブロック内に属している為、(b)に戻ります。 【画像で説明】 ◎ブロックの区分は下の図のようになります https://teratail-v2.storage.googleapis.com/uploads/contributed_images/9e9e0dd25f199aec8d7929ddfb3271ca.png ◎2つのcontinueと戻り先の関係は下の図のようになります。 https://teratail-v2.storage.googleapis.com/uploads/contributed_images/3c98c90cc8496a479f56e64b8c7494ee.png        ●splice関数 配列から既存の要素を取り除くには、splice()という関数 ( https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/splice )を使います(sliceではありません。s*p*liceです) ☆つかいかた 「配列.splice(取り除く要素の先頭の位置(0始まりのindex), 取り除く個数)」 ------------------------------------------------------ 例1) const nums = [7,8,9,10,11] nums.splice(0,1) // 配列の0番目(=1始まり換算で1番目)から、1個取り除く // => 「7」が除去される。 console.log(nums); 出力結果:[8,9,10,11] 例2) const chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']; chars.splice(5, 2); // 配列の(0始まりindexの)5番目(=1始まり換算で6番目)から、2個取り除く // => 「f」と「g」が除去される。 console.log(chars); 出力結果: ["a", "b", "c", "d", "e", "h", "i"] ------------------------------------------------------ sliceとspliceの違いは、簡単に言えば sliceは、配列の中から一部を取り出す関数、spliceは配列から一部を取り除く関数、といったイメージです。 今回sliceやspliceを使わなかったのは、書き込み先が連続しているからです。 たとえば「対象外のデータを取り除いたリストを、”別のシート"に張り付ける」といった用途であれば、spliceを使う余地があります。 しかし今回は、平日土日関係なく、 全部の日付を調べて、対象外であればスキップし 用件があればカレンダーに登録して「登録済」を書き込まなければならないため spliceを使って配列から要素を取り除いたところであまり意味がありません。       ●閉じ括弧の対応の確認方法 GASの新しいエディタを使っているのであれば、 括弧にカーソルをあてると薄いグレーの四角で括弧が囲まれます。 このとき、対応する閉じ括弧(閉じ括弧をカーソルに充てているときは開き括弧)もグレーの四角で囲まれるので、これによって対応関係を知ることができます。 (下の図参照) https://teratail-v2.storage.googleapis.com/uploads/contributed_images/0ee068808f947aff120dc0da56037097.png ※見にくいのですが、括弧にカーソルを当てた時、その括弧のある行の行頭から下方向に延びているグレーの線が強調表示されます。この線をたどっていくと、閉じ括弧(開き括弧)に到達することができます。 https://teratail-v2.storage.googleapis.com/uploads/contributed_images/1031daf4822981defac1dd83d6c5edb1.png また、エディタ上で右クリックして「ドキュメントのフォーマット」をクリックすると、ソースコードを整形(インデント)してくれます。 これにより括弧で作られたブロックごとにきれいに整列表示されるので、対応関係が分かりやすくなります。 図: https://teratail-v2.storage.googleapis.com/uploads/contributed_images/857204334bccf30a152a61e592587be0.png
donguriko

2022/01/09 08:46

qnoirさま 返信が遅くなり申し訳ありません。 そして、お忙しい中 親切・丁寧な解説 本当にありがとうございます!! ●for文ループ処理 continueでの戻り方イメージ とてもわかりやすい解説感謝です。イメージつかめた気がします。 ●splice関数 sliceとspliceの違いまで解説いただき感謝です。 また、何故「sliceやspliceを使わなかったのか」の解説(考え方)もとても勉強になりました。 今までqnoirさまの回答は、My「参考書」として大切に保管し、つまづいた都度、立ち返って 読み返させています。 今回の分も大切に読み込ませていただきます!! ●閉じ括弧の対応の確認方法 今までなんとなくエディタ上でうすグレーのアミがかかっていたり、 縦の線が出ているな、とは思っていましたが、コードの「書き手」にお知らせ してくれていたのですね。 「ドキュメントのフォーマット」すごいですね!!  こんな技があるとは。。。教えていただき感謝です。 (再質問) ソースコードはあとで、自分または他の人が見返した際にわかりやすく書くことが 大切かと。 プロのみなさんはコードの字下げ処理等はどのタイミングで整えていらっしゃいますか? ある程度コード記載し終えたタイミングで、最後に「ドキュメントのフォーマット」で 整えていらっしゃるのですか? (特段意識しなくてもすでに身についているので、記載の都度 自然と手作業でできている?)
退会済みユーザー

退会済みユーザー

2022/01/09 09:29

> コードの字下げ処理等はどのタイミングで整えていらっしゃいますか? →個人的には、1行書くたびに、ほぼ常に無意識的に手でインデントしています。 他のページから塊でコピーしたり、書いてあるコードのブロックを塊で移動させたときなどに「ドキュメントのフォーマット」メニューを使っています。 VSCodeというエディタでは、保存時に自動でフォーマットしてくれるアドオンもあります。
donguriko

2022/01/09 10:04

qnoirさま 早々の回答ありがとうございます。 コードをコピー使用する場合に「ドキュメントのフォーマット」メニューを利用 しているのですね。 私も意識しなくても、自然にインデント処理ができるよう、まずは数をこなして 「お作法」をカラダに覚えさせていきたいと思います。 コメントありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問