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

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

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

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

Q&A

解決済

3回答

1656閲覧

indexOfで検索する文字を、変更したい。

SnowMonkey

総合スコア53

Google Apps Script

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

0グッド

0クリップ

投稿2018/12/26 07:15

編集2018/12/26 09:49

前提・実現したいこと

indexOfで検索する文字を、変更したい。例えば
indexOf(3)と書かずに、例えばindexOf(Key_Word)みたいにして
Key_Wordに代入する形で検索する(具体的には翌週が第何週か示す数字を入れる)ことを実現したい

前提
Spreadsheet上のスケジュールを、毎週、メールに自動で送信することができるよう
Google Apps Scriptを用いてしたいと考えています。

Spreadsheetには、下記の項目を入力済みです
年、月、日、予定、4月1日を基準にその日が第何週か(11列目に記入 月曜始まり)

スプレッドシート

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

例えば、第3週の月曜日を検索しようとしているとしてください。 indexOf(3)なら動作するのですが、 3の代わりに変数を入れると正しく検索できません。何か良 い方法がないでしょうか var row= arrTrans[SEARCH_COL].indexOf(3); //だと10を返す これが正解 var row1= arrTrans[SEARCH_COL].indexOf(Key_Word); //だと3を返す ログは以下の通りです [18-12-26 01:46:45:536 PST] 2.0 //Logger.log(Key_Word); [18-12-26 01:46:45:537 PST] 3//Logger.log(Key); [18-12-26 01:46:45:537 PST] 10.0//Logger.log(row); [18-12-26 01:46:45:537 PST] 3.0//Logger.log(row1);

該当のソースコード

Google

1var MAIL_ADDRESS = "*****@co.jp"; 2var mySheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート53'); 3var Key_Word=3;//検索値 4var SEARCH_COL=10;//検索する列 5 var Key=String(Key_Word); 6function searchSheet(){ 7 var arrData = mySheet.getDataRange().getValues(); 8 /*indexOfで高速検索 ---ライブラリUnderscore for GASを利用して、行列を入れ替え---*/ 9 var _ = Underscore.load(); 10 var arrTrans = _.zip.apply(_, arrData); 11 var row= arrTrans[SEARCH_COL].indexOf(3); //検索値の出てきた最初の行番号-1を返す 12 var row1= arrTrans[SEARCH_COL].indexOf(Key_Word); //検索値の出てきた最初の行番号-1を返す 13 14 //var row= arrTrans[10].indexOf(3); //検索値の出てきた最初の行番号-1を返す 15 16 Logger.log(Key_Word); 17Logger.log(Key); 18 Logger.log(row); 19 Logger.log(row1); 20 /* 21 Logger.log(Object.prototype.toString.call(Key_Word)); 22 Logger.log(Object.prototype.toString.call(Key)); 23 24 Logger.log(row); 25 Logger.log(row1); 26 27 for(var i = row; i <= row+10; i++) { 28 Logger.log(arrData[i][1]+'/'+arrData[i][2]+arrData[i][3]+arrData[i][11]+'\n' ); 29 } 30 */ 31 32} 33

試したこと

Key_Wordが数字型だったので、文字型に変換しても
""や''で囲んでみたが、上手くいきませんでした。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

macaron_xxx

2018/12/26 07:45

再現しません。提示いただいたソースコピーで、正常にrowが取得されました。
SnowMonkey

2018/12/26 08:23 編集

質問の情報が不十分だったようです。 Key_Wordを何にしても同じrowを得るのです。ご確認いただけませんか。 var row= arrTrans[SEARCH_COL].indexOf(3); //正しく10を返す。テストに使っているカレンダーで第3週は11行目始まりです。 var row1= arrTrans[SEARCH_COL].indexOf(Key_Word); //Key_Wordに何を入れても3を返す
macaron_xxx

2018/12/26 08:21

スプレッドシートのデータも提示していただいていいですか?コードを見る限り、変数であろうが生の値であろうが、とれる値に違いが生まれるはずはないのです。
dice142

2018/12/26 08:30

質問文と結構異なるようなので、質問文を適切な形に修正していただけますか?
macaron_xxx

2018/12/26 08:39 編集

本当に「該当のソースコード」のみを実行してもrowに10が返ってきませんか?私はまったく同じ状況で、Key_Wordを2にすると3が、3にすると10が返ってきますよ。
dice142

2018/12/26 08:45

私も質問文にあるコードをほぼそのまま(ログ出力の追加したくらい)試しましたが 質問文にあるような状況は確認できず、正常に動作しています。 コードは質問文にあるもので全部ですか?他に省略しているものとかないですか?
papinianus

2018/12/26 08:45

まあ、見直しはやっていただくとして、それってこうやらないと求まらないんですかね?https://teratail.com/questions/123633#reply-188348 とかを参照して(gasで使えるmoment.jsのライブラリもあります)計算で求めてはだめなのでしょうか?
macaron_xxx

2018/12/26 08:52 編集

papinianusさん→行番号は求まらないんじゃないですか?
SnowMonkey

2018/12/26 09:28

皆様、ありがとうございます。 メールアドレスなど省略しておりましたので、再度掲載します。このコードだと、 rowは10、row1は3となります。同じじゃないといけないのですが…。 var MAIL_ADDRESS = "*****@****.co.jp"; var mySheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート53'); var Key_Word=3;//検索値 var SEARCH_COL=10;//検索する列 var Key=String(Key_Word); function searchSheet(){ var arrData = mySheet.getDataRange().getValues(); /*indexOfで高速検索 ---ライブラリUnderscore for GASを利用して、行列を入れ替え---*/ var _ = Underscore.load(); var arrTrans = _.zip.apply(_, arrData); var row= arrTrans[SEARCH_COL].indexOf(3); //検索値の出てきた最初の行番号-1を返す var row1= arrTrans[SEARCH_COL].indexOf(Key_Word); //検索値の出てきた最初の行番号-1を返す //var row= arrTrans[10].indexOf(3); //検索値の出てきた最初の行番号-1を返す Logger.log(Key_Word); Logger.log(Key); Logger.log(row); Logger.log(row1); /* Logger.log(Object.prototype.toString.call(Key_Word)); Logger.log(Object.prototype.toString.call(Key)); Logger.log(row); Logger.log(row1); for(var i = row; i <= row+10; i++) { Logger.log(arrData[i][1]+'/'+arrData[i][2]+arrData[i][3]+arrData[i][11]+'\n' ); } */ }
macaron_xxx

2018/12/26 09:30

質問文を編集してください。
papinianus

2018/12/26 09:31

それ本文にかいてくださいませんか
macaron_xxx

2018/12/26 09:32

あと、これを実行したときのログの内容も記入してください。
papinianus

2018/12/26 09:36

質問者様大変失礼します。macaron_xxx様、今これを解決したとして、コメントにある、今回は第3週を検索することにする、ということを実用化しようとしたとき、日付操作が必要になると予期されます。この質問者様がやりたいことにとって行番号を求めることが進むべき道だと考えていないというコメントです。
macaron_xxx

2018/12/26 09:40

papinianusさんがおっしゃる通り、それも必要ですが、結局その週のデータを特定するために、通るべき道です。ただし、それはKey_Wordに値を代入するフェーズで終わっているという認識です。まぁ実現の方法は色々あるのですが、今回の方法は必ずしも間違っていないので。
macaron_xxx

2018/12/26 09:40

行番号(あるいは行データ)がわからないと、予定が取得できない。
macaron_xxx

2018/12/26 09:54

ログをみた限り、Key_Wordが2なんですが…。ほんとうに実行しているスクリプトと提示しているスクリプトは同じですか?
SnowMonkey

2018/12/26 09:54

papinianusさんがおっしゃる通り、その日が第何週かという計算をしなくてはいけないと思います。この問題を解決できたら、取り組む予定でした。ご紹介いただいた質問と回答を参考にさせていただきます。 質問の内容、修正しました。
dice142

2018/12/26 09:58

Key_Wordが2.0なのに、文字列化したKeyが3というわけのわからない状況です。 macaron_xxx様と同意見ですが、実行しているものと提示されているものが同一のものと思えません。
dice142

2018/12/26 09:59

それにログの実行時間が現時刻よりもかなり前です。 現在のコードで実行したログを載せていただけますか?
SnowMonkey

2018/12/26 10:10

なぜかアメリカ太平洋時間(PST)ですね。 現在のコードで実行したログも数値に違いはありません。 [18-12-26 02:08:22:389 PST] 2.0 [18-12-26 02:08:22:389 PST] 3 [18-12-26 02:08:22:390 PST] 10.0 [18-12-26 02:08:22:390 PST] 3.0
dice142

2018/12/26 10:13

PSTの部分見逃してました。失礼しました。 実行はsearchSheet()で、関数内他に省略しているところとかはないですか?
SnowMonkey

2018/12/26 10:16

macaron_xxxさん、dice142さん 実行しているものと同一のコードを提示しております。 やっぱり、Key_Word=3とコードしているのに、ログが2.0というのはおかしいんですね。
SnowMonkey

2018/12/26 10:28

dice142さんの「実行はsearchSheet()」で間違いないかとのご指摘で、同じ名前の関数が、別のスクリプトファイル(コピーしたもの)にあることに思い至りました。そのコピーしたスクリプトファイルを削除したところ、正常に動作いたしました。 皆様、本当にありがとうございました。心から感謝申し上げます。 [18-12-26 19:20:30:318 JST] 3.0 [18-12-26 19:20:30:318 JST] 3 [18-12-26 19:20:30:318 JST] 10.0 [18-12-26 19:20:30:319 JST] 10.0
dice142

2018/12/26 10:31

自己解決でいいので解決方法を記述して解決済みにしておいてください。
SnowMonkey

2018/12/26 10:48

身近に詳しいものがおらず、皆様には本当に助けていただきました。ありがとうございます。
papinianus

2018/12/26 13:35

PSTとなる場合、スプレッドシート(カレンダーがあるほう)のファイルメニューの設定あたりから、タイムゾーンを確認してください。
papinianus

2018/12/26 13:51

今更ですし、もう見てないかもしれませんが。 追記されたコード後段がない状態で、"毎週する"という要件とスプレッドシートをみたとき、arrDataをループして、K列が"3"であるものをピックアップすると思いました(暗黙に10日分ループするとは想像できなかったし、週番号をいれているのにそれを見ずに固定回数でループするとは思わなかった)。 いずれにしても、L列を取るためにarrDataのループは不可避であり、その段階でK列(あるいはそれよりもA-C列)を見れば、行番号を一旦得るなどということ、行番号が得られないことに悩むことは全くの遠回りにしか思えませんでした(このとき、今日の週番号となるべき3は今日から計算で求まるため、変数がどうこうという話は無用だと思っていたというのもあります)。 また、固定で10なので回避できていますが、月をまたぐと週はリセットされますし、月またぎの位置が週の開始とあわないも考えると、週番号で動く方式には原理的に無理があると思っておりました。 結果としてグローバル汚染を学べたようなので、安直な提案で混乱させたことについて質問者様含め皆様にお詫びします。
SnowMonkey

2018/12/27 02:50

質問者です。おっしゃる通りですね。 年度初めからの週番号はカレンダー作成時のコードに自分でも組み込めそうだから、それを検索すれば、あとは何とかなるだろうと考えて作り始めました。最初は週番号をピックアップするつもりでしたが、調べたやり方(indexOf)だと最初のデータを検索するようなので、固定回数ループが簡単に思えてそんな仕様にしております。でも、papinianusさんのおっしゃる通り、日付の処理をすれば週番号を記入することは不要な処理なんだということが分かりました。moment.jsなども勉強します。ありがとうございます。
guest

回答3

0

ベストアンサー

たぶん提示外のコードで問題が発生しているとしか考えられないので、
確認すべき事項を列挙しておきます。

  • 実行している関数はsearchSheet()だけなのか
  • Key_Wordという変数を扱っている行が他にないか

コーディング部分の指摘をすると、なるべく関数外で変数宣言はしない方がいいです。
特にKey_WordとかSEARCH_COLとか検索用の関数でしか使わないので、
関数内部で宣言しておいた方が他でいじってしまう危険が少ないです。
他の関数で設定した値をsearchSheet()で使うのであれば引数として渡してあげれば済みます。

まあ後は変数の命名規則を統一したほうが見やすいです。
大文字だけとか頭大文字でアンダースコア付けてたりバラバラ過ぎるので、見直したときに把握しにくいです。

投稿2018/12/26 10:30

dice142

総合スコア5158

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

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

SnowMonkey

2018/12/27 08:21

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

0

回答の前提

この前提を信じています

前提
Spreadsheet上のスケジュールを、毎週、メールに自動で送信することができるよう
Google Apps Scriptを用いてしたいと考えています。

回答の趣旨

質問者様にとって行番号が取れた解決が良かったと思いません。

週番号はほんとうに必要なデータなのでしょうか?このプログラムは(おそらくトリガによってでしょうが)いつどういうタイミングで動くのでしょう?
月曜に動くなら、A、B、C列が今日であるようなものを判定すればよかったのではないでしょうか?例にあげられた2017/4は偶然月末に週が終わりますが、2018/12であったとき31日が月曜なのですが、2019/1/1の予定は12/31に通知されますよね?2019/1/1から数日が第1週であるというデータは本当に意味のあるデータなのでしょうか?
(手で書くと思っているのですが、そのような利用もされないデータを手で埋めるのは無駄ではないですか?)

カレンダーをどうこう、という時点で覚えるべきは、日付のハンドリングであって、配列の縦横を転置する方法ではないと考えます

サンプルコード

  • 今日を含む7日間をつくります→daysInThisWeek。比較の簡便のため文字列にしています("2017411"など)

提示された例では10日分のようですが、であれば[0,1,2,3,4,5,6,7,8,9]とすればよい。

  • シートのデータのA-C列を利用して、上記7日間に含まれる日付の行を抽出→arrData
  • L列のみをピックアップ(イベントの行だと想定した)→columnLs

提示された例ではA列から組んでいるため、この処理は不要かもしれない

  • 本文にする→body

まあ、ここは適宜

function sendSchedules() { const today = Moment.moment(); if(today.day() !== 1) { return; } //月曜以外は中止 //トリガを時間主導で、週ベース、毎週月曜日とすればこの行は不要 const daysInThisWeek = [0,1,2,3,4,5,6].map(function(e) { return today.clone().add(e, 'days').format("YYYYMD"); }); const arrData = SpreadsheetApp.getActiveSheet().getDataRange().getValues().filter(function(e){ return daysInThisWeek.indexOf(e[0]+""+e[1]+""+e[2]) !== -1;}); const columnLs = arrData.map(function(e) { return e[11];}); const body = "月曜からの予定を1行ずつ\n"+columnLs.join("\n"); MailApp.sendEmail("***@gmail.com", "今週の予定", body) }

投稿2018/12/26 13:30

papinianus

総合スコア12705

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

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

papinianus

2018/12/27 00:47 編集

結果としてグローバル汚染を学べたようなので、安直な提案で混乱させたことについて質問者様含め皆様にお詫びします。 自分ではできないのでマイナス評価してください QAプラットフォームにおけるこの質問についての理解の相違だと思いますが、この質問の答えってなんだったんでしょう
guest

0

質問者です。スクリプトファイルのコピーをとっていたのですが、それを削除しました(同名の関数があった)。そうするとなぜか正常に動作しました。

投稿2018/12/26 10:43

編集2018/12/26 10:45
SnowMonkey

総合スコア53

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

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

papinianus

2018/12/26 13:32

同じ名前の変数は1つしか定義できません。同じ名前の変数が複数あった場合、後に定義されたものが採用されます。複数のファイルがある場合、おそらくファイル名でソートしてプログラムが読み込まれると思います。今回は、後からコピー分が読み込まれそちらの変数が採用されたのでしょう。 どちらの変数が採用されるかは、制御したり指定したりできないと思ったほうがいいと思います
SnowMonkey

2018/12/27 01:28

ありがとうございます。勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問