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

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

新規登録して質問してみよう
ただいま回答率
85.35%
date

dateは、date型や日付に関する関数や処理についてのタグです

Google Apps Script

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

Q&A

解決済

2回答

1781閲覧

【GAS】日付①と日付②を合体してシート名にする方法

donguriko

総合スコア30

date

dateは、date型や日付に関する関数や処理についてのタグです

Google Apps Script

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

0グッド

0クリップ

投稿2021/06/02 11:47

編集2021/06/02 13:36

前提・実現したいこと

基本的な質問でしたら申し訳ありません。
非エンジニアのGASビギナーです。
独学で「GAS本」引き引き、ネットで調べたりして目下GASと格闘中。
これが2作目のGASです。
GASで以下の作業をさせたいです。

①mySheetnameを生成
YYMMDD(openDate) - YYMMDD(その週の金曜日の日付※<<closeDate)
※IF文で、GAS実行日の曜日に応じて+n日後の日付を
Utilities.formatDateで求めました。

②同じ名前のシートが存在しているか確認
存在している場合⇒Msg表示で処理終了
存在していない場合⇒下記③以降の処理へ進む

③スプレッドシート内の「ひな形シート」をコピー

④上記③の「新シート」を一番左から2番目に移動 

⑤上記③のシート名を①の名称に変更

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

処理①で、
1つ目の「GAS実行日(openDate)」の取得はできました。
また、2つ目の「その週の金曜日の日付(closeDate)」も取得できました。
(console.logで確認済)
ですが、「GAS実行日(openDate)」と「その週の金曜日の日付(closeDate)」の
合体処理がうまくできません。

ちなみに処理⑤で
ss.rename(mySheetName)で(新シート名)で新シート名を変更させようと
思っています。

###エラーメッセージ
ReferenceError: mySheetName is not defined
myFunction2 @ 週次入力シート作成.gs:53

該当のソースコード

長文となりますが、記載したコード全文を記載します。

function myFunction2() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const date = Utilities.formatDate(new Date(), 'Asia/Tokyo','yyyyMMdd');

//「入力シート」の「終了日」指定準備_「開始日」曜日の判定
const openDate = new Date()
const o=Utilities.formatDate(openDate, 'Asia/Tokyo', 'yyyyMMdd');
const openDay = openDate.getDay()
console.log(openDay);
console.log(o);

//(条件1)「開始日」が月曜のとき「終了日」は4日後をセット
if (openDay ==1) {
const closeDate =new Date(openDate.setDate(openDate.getDate() + 4));
const c = Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd');
console.log(c);

//(条件2)火曜のとき「終了日」は3日後をセット
}else if (openDay ==2) {
const closeDate =new Date(openDate.setDate(openDate.getDate() + 3));
const c =Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd');
console.log(c);

//(条件3)水曜のとき「終了日」は2日後をセット
}else if (openDay ==3) {
const closeDate =new Date(openDate.setDate(openDate.getDate() + 2));
const c =Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd');
console.log(c);

//(条件4)木曜のとき「終了日」は1日後をセット
}else if (openDay ==2) {
const closeDate =new Date(openDate.setDate(openDate.getDate() + 1));
const c =Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd');
console.log(c);

//(条件5)金曜のとき
}else if (openDay ==1) {
const closeDate =setDate(openDate.getDate());
const c =Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd');
console.log(c);

//(条件6)それ以外のとき 当日日付をセット
}else {
const closeDate =setDate(openDate)
const c =Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd');
console.log(c);

//★ここで失敗していそうです!! 「実行」クリックしてもここから先の処理は行われていない。
const mySheetName = o + "-" + c
console.log(mySheetName);
}

// すでに「入力シート」が作られていたらメッセージ1を表示し、処理終了
if (ss.getSheetByName(mySheetName) != null) {
Browser.msgBox("今週分のシートはすでに「作成済」です。\n処理を中止します。\nファイル内のシートをもう一度確認してください。");

//存在しない場合は、処理継続
}else{
//「週報ひな形」シートをコピーし(一番右に追加される)新「入力シート」を左から2番目に移動する。(一番左は「ひな形」)
sh_temp1.copyTo(ss).activate();
ss.moveActiveSheet(2);

//「シートA」の氏名(C2)の内容を「入力シート」にコピー
const sh_temp2 = ss.getSheetByName("シートA");
const sh_new = ss.getSheetByName("週報ひな形 のコピー");

//コピー元のシートの中のセルを指定
const copyValue1 = sh_temp2.getRange('C2').getValues();

//コピー先のシートの中のセルを指定して、コピー実行
sh_new.getRange('E4').setValues(copyValue1);

//「シートA」の項目①(C6)の内容を「入力シート」にコピー
//コピー元のシートの中のセルを指定
const copyValue2 = sh_temp2.getRange('C6').getValues();

//コピー先のシートの中のセルを指定して、コピー実行
sh_new.getRange('E6').setValues(copyValue2);

//「シートA」の項目②(C7)の内容を「入力シート」にコピー
//コピー元のシートの中のセルを指定
const copyValue3 = sh_temp2.getRange('C7').getValues();

//コピー先のシートの中のセルを指定して、コピー実行
sh_new.getRange('E7').setValues(copyValue3);

//「シートA」の項目③(C8)の内容を「入力シート」にコピー
//コピー元のシートの中のセルを指定
const copyValue4 = sh_temp2.getRange('C8').getValues();

//コピー先のシートの中のセルを指定して、コピー実行
sh_new.getRange('E8').setValues(copyValue4);

//「入力シート」のシート名編集
const sh_temp1 = ss.getSheetByName("週報ひな形");

const mySheetname = ss.rename(+openDate + "-" + closeDate)
console.log(mySheetName);

//シート追加のメッセージ2を表示
Browser.msgBox("今週分の入力シートを作成しました。内容を入力してください。");
}
}

どこがマズく、どう修正すればよいかアドバイスをいただけないでしょうか?
お忙しいところ申し訳ありませんがGASビギナーでも分かるよう解説いただける
と助かります。

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

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

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/06/02 12:18 編集

エラーメッセージの内容:「ReferenceError: mySheetName is not defined」 は「mySheetNameが定義されていないのに、mySheetNameを参照しようとした」ということです。 ここから察するに「const mySheetName = openDate + "-" + c」の行が実行されていない可能性がありますが、 現状の質問文の一部のコードだけでは判断できません。 なので、可能な限り全部のコードを記載していただけないでしょうか? また、ソースコードは、 ``` と ``` の間に記入していただけると見やすくて助かります。
donguriko

2021/06/02 12:34

お忙しい中、早々のご確認ありがとうございます。 質問の修正をさせていただきました。(コード全文を掲載しました) どうぞよろしくお願いいたします。
guest

回答2

0

ベストアンサー

コード拝見しました。

まず、エラーの直接の原因は、mySheetName という変数が「スコープ」の外で参照されているためです。
「スコープ」とは、簡単にいえば、変数の有効範囲のことです。
{ と }の範囲で囲まれた部分ので、const/letを使って定義された変数は、外から参照する(使う)ことはできません。
(※ varを使って定義した場合は別ですが、ここでは説明を省略します)

簡単な例:

js

1function test1(){ 2 // myNameという変数を、外で定義。 3 const myName = "soto"; 4 5 const a = 0; 6 if (a == 0){ 7 // 外で定義した変数を中で呼び出してみる。 8 Logger.log(myName +" Hi!") // 正常に表示できる。 9 } 10} 11 12function test2(){ 13 const a = 0; 14 15 if (a == 0){ 16 // myNameという変数を、{ }の中で定義。 17 const yourName = "naka"; 18 } 19 // 定義した部分の外で呼び出してみる 20 Logger.log(yourName+" Hi!") // エラーになる。 21} 22

 
上のtest1 を実行すると、「soto Hi!」と表示され正常終了しますが、
下のtest2を実行すると ReferenceError: myName is not defined.と言われてエラーになります。

これは、test2では、if文の {} ので yourNameという変数を定義し、
if文の{}のでyourName使おうとしたからです。

if文の{}の中で const/let 定義した yourNameという変数は、その{}の中でしか使えません。
(逆にif文の{}の外で定義した変数は、中から呼び出せます:test1)

以上を踏まえて質問者さんのコードを見ると、

} else { const closeDate =setDate(openDate) const c =Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd'); console.log(c); //★ここで失敗していそうです!! 「実行」クリックしてもここから先の処理は行われていない。 const mySheetName = o + "-" + c console.log(mySheetName); }

のように、else { }の中で、mySheetName を定義しており
その直後に

// すでに「入力シート」が作られていたらメッセージ1を表示し、処理終了 if (ss.getSheetByName(mySheetName) != null) { Browser.msgBox( "今週分のシートはすでに「作成済」です。\n処理を中止します。\nファイル内のシートをもう一度確認してください。" );

というようにelse {}の外で mySheetNameを使おうとしています
このためReferenceErrorが発生しています。

ではどのように直すか。

1つのやり方として、mySheetNameという変数を、dateやopendateと同じ場所で定義することが考えられます。

ただし constで定義してしまうと、変更(+を使って文字列連結)できなくなるので、letで定義しましょう。
使うときは、既に定義済みなので、「const」は不要です。
・closeDateも同様に、先頭で定義し、それ以降のすべてのconstを削除します。

diff

1function myFunction2() { 2 const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 const date = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyyMMdd"); 4+ // openDate と同じ場所に定義する。文字列を変更できるように、constではなくletで定義する。 5+ let mySheetName = ""; 6+ let closeDate = ""; 7 //「入力シート」の「終了日」指定準備_「開始日」曜日の判定 8 const openDate = new Date(); 9 const o = Utilities.formatDate(openDate, "Asia/Tokyo", "yyyyMMdd"); 10 const openDay = openDate.getDay(); 11 console.log(openDay); 12 console.log(o); 13 //(条件1)「開始日」が月曜のとき「終了日」は4日後をセット 14 if (openDay == 1) { 15+ //以降 すべてのcloseDateの前にあるconstは削除する。 16- const closeDate = new Date(openDate.setDate(openDate.getDate() + 4)); 17+ closeDate = new Date(openDate.setDate(openDate.getDate() + 4)); 18(略) 19 //(条件2)火曜のとき「終了日」は3日後をセット 20 } else if (openDay == 2) { 21(略) 22 console.log(c); 23 24 //★ここで失敗していそうです!! 「実行」クリックしてもここから先の処理は行われていない。 25- // mySheetNameは既に定義済みなので、使うときに「const」は不要。 26- const mySheetName = o + "-" + c; 27+ mySheetName = o + "-" + c; 28 console.log(mySheetName); 29 } 30 31 // すでに「入力シート」が作られていたらメッセージ1を表示し、処理終了 32 if (ss.getSheetByName(mySheetName) != null) {

その他

**1.**sh_temp1(週報ひな形シート)が初期化前に参照されてしまっているため、
ReferenceError: Cannot access 'sh_temp1' before initialization エラーが発生します。
sh_temp1 の定義は、下記のようにcopyToの前に持ってくる必要があります。

diff

1 //存在しない場合は、処理継続 2 } else { 3+ //「入力シート」のシート名編集 4+ const sh_temp1 = ss.getSheetByName("週報ひな形"); 5 //「週報ひな形」シートをコピーし(一番右に追加される)新「入力シート」を左から2番目に移動する。(一番左は「ひな形」) 6 sh_temp1.copyTo(ss).activate(); 7 ss.moveActiveSheet(2); 8~~ 9(略) 10~~ 11 //コピー先のシートの中のセルを指定して、コピー実行 12 sh_new.getRange("E8").setValues(copyValue4); 13 14- ↓は、sh_temp1.copyToの前に移動する必要あり。 15- //「入力シート」のシート名編集 16- const sh_temp1 = ss.getSheetByName("週報ひな形"); 17 const mySheetname = ss.rename(+openDate + "-" + closeDate); 18 console.log(mySheetName); 19

 

2.
Yoshi88さんご指摘の通り、現状、スプレッドシートの名前をリネームする部分で、closeDateという日付型(Date型)の変数をそのまま文字連結しようとしているため、意図した通りの結果になっていないと思われます。

したがって、下記のように日付型の変数を文字列に変換してから連結する必要があります。

diff

1(略) 2 3- const mySheetname = ss.rename(+openDate + "-" + closeDate); 4+ // closeDateを文字列にしてから連結。 5+ const c = Utilities.formatDate(closeDate, "Asia/Tokyo", "yyyyMMdd"); 6+ mySheetname = ss.rename(o + "-" + c); 7 8 console.log(mySheetName); 9 10 //シート追加のメッセージ2を表示 11 Browser.msgBox( 12 "今週分の入力シートを作成しました。内容を入力してください。" 13 );

投稿2021/06/02 14:00

編集2021/06/02 14:27
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

donguriko

2021/06/02 14:22

qnoirさま、丁寧に解説いただきありがとうございます!! 知識が追いつかず、まだすぐにはピンと来ない状態ですが(あと何回か読み返さないと ダメそうです)、アドバイスいただいた内容をしっかり読み込んで、コード修正すると 共に自分のモノにしたいと思います。 コードを1つ書いて、思った通りに動くかを試して、動いたら次を書き足して、、、と なかなか前に進めず苦戦中ですが、GASの「使い手」になれるよう引き続き 頑張りたいと思います。 お忙しい中、迅速に回答を返していただきありがとうございました!! 大変助かりました。
退会済みユーザー

退会済みユーザー

2021/06/02 14:25

ご丁寧にどうもです。頑張ってください。
donguriko

2021/06/06 10:13

qnoirさま、先日は丁寧に解説ありがとうございました。 教えていただいた内容をもとに今日コード修正し、無事やりたかった動きにたどりつくことができました。お忙しい中レクチャーありがとうございました!!
guest

0

ここがマズいところでしょう

const mySheetName = openDate + "-" + c

openDate の中身は、文字列(string)ではなく Date型のままになっているようです。

文字列として連結させる(合体させる)場合は、

const c = Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMd');

の様に、変換してやるといいです。

追記

ソースコードを全部記載されたので回答を修正しますね。

結論から申し上げますと 

原因1:変数の”スコープ”の外で値を利用しようとしているため、変数の中に「値が無い」自状態になっています。

例えば
const C・・・ を if のブロックの中に記述している。→ if ブロックの外に出ると、変数の値は無くなります

原因2:ファイル名を生成する変数の場所が、IFの判定条件の中に記述しているため、ほとんどの場合、実行されない。(おそらくミスタイプ)

つまり 「//(条件6)それ以外のとき 当日日付をセット」 の { } の中に書かれているから、月曜から金曜日以外のタイミングでしか、変数は結合されません(合体)

コメントには 失敗していそう!と書いてあるので、ほぼ、正解だったのに惜しかったですね (^^)

//★ここで失敗していそうです!! 「実行」クリックしてもここから先の処理は行われていない。 const mySheetName = o + "-" + c console.log(mySheetName);

変数のスコープの違いについては、このページなんかいかがでしょうか?

【GAS入門】変数/定数を宣言するvar・const・letの違い

投稿2021/06/02 12:29

編集2021/06/02 14:02
Yoshi88

総合スコア623

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

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

donguriko

2021/06/02 12:52

Yoshi88さま、早々の回答ありがとうございます。 知識が乏しく恐縮です。以下の理解であっていますか? (qnoirさまからのコメントを受け、質問を修正し、記載したコード全文を再掲しました。) <誤> const c = Utilities.formatDate(closeDate, 'Asia/Tokyo', 'yyyyMMdd'); <修正> ( )内の一番最後の部分のdを一つ減らすことでDate型⇒文字列に変換される
Yoshi88

2021/06/02 14:04

回答を追記しましたよ。 でも、qnoir さんの解説のほうが、より詳しいですね。あちらを参考されてみてはいかがでしょうか。
donguriko

2021/06/02 14:31 編集

Yoshi88さま、ビギナーに優しい解説ありがとうございます。大変助かりました。 また、リンクのご案内もありがとうございます。勉強させていただきます。 非エンジニアにはGASは手強くて、なかなか前に進めず苦戦していますが、 思った通りに動くとまるで「魔法使い」になれた気分なので、引き続き実際に手を動かして 知識を増やしたいと思います。回答ありがとうございました。
donguriko

2021/06/06 10:13

Yoshi88さま、先日は丁寧に解説ありがとうございました。 変数、定数、、、独りで本で読んでいても今ひとつしっくり来なかったのですが、改めてリンク先を拝見したら少し前進した気がします。 スコープ外では使えない、基礎中の基礎をおさえられてませんでしたね。 勉強になりました。ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問