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

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

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

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

Q&A

解決済

2回答

2839閲覧

毎月の最初の日に日報を自動的に生成し、日付を自動的に入力したい

koroaisu

総合スコア8

Google Apps Script

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

0グッド

0クリップ

投稿2019/08/30 01:47

編集2019/09/03 16:40

前提・実現したいこと

日報の作成コード及び日付の記入コード自体は作成しましたが、トリガーを使って毎月に日報を作成する際に、作成された日報の方で日付の記入コードを実行しなければなりません。
そのため、2つのコードを1つにまとめて、毎月の初日に1回のみ実行する形を取りたいです。
しかし、新しく作成したファイルが上手く取得できず、困っています。

該当のソースコード

日報の作成コード

GAS

1var FOLDER_ID = '日報の作成先フォルダ'; 2 3function creatSS() { 4 var templateFileId = '日報のテンプレ'; 5 var date = new Date 6 var year = date.getFullYear(); 7 var month = date.getMonth(); 8 var month = month+1 //1月は0のため、+1 9 var sheetName = '日報_' +year+"年"+ month + '月'; //日報の名前を年月で作成 10 11 var filename = SpreadsheetApp.openById(templateFileId).copy(sheetName).getId() 12 var fileSS = DriveApp.getFileById(filename) 13 var folderTarget = DriveApp.getFolderById(FOLDER_ID); 14 folderTarget.addFile(fileSS) 15 DriveApp.getRootFolder().removeFile(fileSS); //ファイルをコピーする際に、マイドライブの方にもコピーが作成されるため、それを削除 16 17}

自動的に日付を記入するコード

GAS

1function setdate() { 2 3var sheet = SpreadsheetApp.getActiveSheet(); 4var lastC = sheet.getLastColumn(); 5 6var d = new Date(); 7//var year = d.getFullYear(); 8var month = d.getMonth() + 1; 9var day = d.getDate(); 10var day = 1 11var newD = month+"月"+day+"日" 12 13for(var i = 3; i <= lastC; i++) { //C行から最終行まで日付を記入 14 sheet.getRange(1, i).setValue(newD); 15 var day = day+1 16 var newD = month+"月"+day+"日" 17 } 18}

試したこと

GAS

1folderTarget.addFile(fileSS) 

このコードを実行する際に、folderTarget.addFile(fileSS).getId()をして、SpreadsheetApp.openById(id)で日付を記入するコードを実行するように書き換えてみましたが、idが上手く取得できませんでした。

回答を頂いた後にアレンジしたコード

GAS

1var FOLDER_ID = 'コピーするフォルダ'; 2function creatSS() { 3 var templateFileId = 'テンプレのリンク'; 4 var newdate = Utilities.formatDate(new Date(), "Asia/Tokyo", 'yyyy/MM'); 5 var sheetName = '日報'+newdate; 6var ss = SpreadsheetApp.openById(templateFileId).copy(sheetName); //スプレッドシート 7var file = DriveApp.getFileById(ss.getId()); //idを取得するタイミングを変更 8DriveApp.getFolderById(FOLDER_ID).addFile(file); //ファイルを移動 9DriveApp.getRootFolder().removeFile(file); //ルートフォルダのファイルを削除 10setdate(ss); //自動的に日付を記入するコードを実行 11 12} 13 14function setdate(ss) { 15 16 var sheet = ss.getActiveSheet(); //新しく作ったスプレッドシート 17 var month = new Date().getMonth()+1; 18 var newdays=[]; 19 if(month==2){ 20 var numofday=29 //numofdayは月の日数及び実行回数を設定するための変数、2月分はうるう年に対応して手動で設定 21 } 22 else if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){ // 23 var numofday=31  24 25 } 26 else if(month==2||month==4||month==6||month==9||month==11){ 27 var numofday=30 28 29 } 30 var day =1 31 for(var i=1;i<=numofday;i++){ 32 var newD=month+'月'+day+'日'; // Utilities.formatDate(new Date()+i, "Asia/Tokyo", 'MM月dd日')を試してみましたが、エラーが出たため、このような書き方にしました。 33 newdays.push(newD); 34day=day+1; 35 } 36 for(var V = 1; V <= numofday; V++) { 37var lastC = sheet.getLastColumn(); 38sheet.getRange(3,1,newdays,1).setValues(newdays[V]); //setValuesの際にクラスを変換できないエラーが出ました。 39} 40}

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

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

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

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

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

guest

回答2

0

ベストアンサー

そのため、2つのコードを1つにまとめて、毎月の初日に1回のみ実行する形を取りたいです。

関数を1つにしたいってことですか?
トリガーを1つにするだけならば、creatSS()からsetdate()を呼べばいいのです。

以下、合計3つのステップがあります。

1. まず、**creatSS()**内のvar filenameから続く5行を次のように変更してください。

var ss = SpreadsheetApp.openById(templateFileId).copy(sheetName); //スプレッドシート var file = DriveApp.getFileById(ss.getId()); //idを取得するタイミングを変更 DriveApp.getFolderById(FOLDER_ID).addFile(file); //ファイルを移動 DriveApp.getRootFolder().removeFile(file); //ルートフォルダのファイルを削除 setdate(ss); //自動的に日付を記入するコードを実行

2. 次に、function setdate()function setdate(ss)に変えてください。

3. 最後に、**setdate(ss)**内の最初のvar sheetの1行を次のように変更してください。

var sheet = ss.getActiveSheet(); //新しく作ったスプレッドシート

蛇足
0. getFullYearとか使わなくてもUtilities.formatDate(date, timeZone, format)を使ったほうが見やすくなると思います。

  1. 31日がない日はAG列に翌月の日付が入るので、条件分岐を使うことをオススメします。
  2. 少ないデータなのでいいですが、getRange(row, col).getValue()を使うより、getRange(row, col, numRow. numCol).setValues()を使うほうが処理時間が短くなります。

##サンプルコード

///実行する月の日付を返します。前月にやる場合は2行目を編集 function main(ss) { const d = new Date(); //d.setMonth(d.getMonth() - 1); //前月にやる場合(例:8/31に9月分を作成するとき) const m = d.getMonth(); const sheet = ss.getActiveSheet(); const lastCol = sheet.getLastColumn() - 1; //最終列 //月末まで繰り返し //月末が31日以外の時は最終列まで削除 const arr = []; for(var i = 1; i < 32; i++){ d.setDate(i); if(d.getMonth() == m){ //Utilities.formatDateの第一引数はnew Date()のまま入れます。 //わざわざ、getMonthやgetDateをしなくていいメリットがあります。 arr.push(Utilities.formatDate(d, 'Asia/Tokyo', 'M月d日')); } //月末が31日以外の場合 else{ sheet.deleteColumns(i + 2, lastCol - i); //AG列までないとエラー break; } } sheet.getRange(1, 3, 1, arr.length).setValues([arr]); //C列から月末までまとめて挿入 }

投稿2019/08/31 13:49

編集2019/09/04 04:48
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

koroaisu

2019/09/02 03:17

丁寧なご説明及びご教授、誠にありがとうございます。 また、アドバイスまで頂いて、本当にありがとうございます。
koroaisu

2019/09/03 04:46 編集

一つ質問ががざいまして、大変恐縮ですが、ご教授頂ければ幸いです。 「getRange(row, col).getValue()」を「getRange(row, col, numRow. numCol).setValues()」に変更したいのですが、現在はセール数を使って、ループ数に応じて日付が増やす書き方にしていますが、setValuesの場合、一気に指定して行に同じ値を設定してしまい、どのように書き換えればよいのか分からないです... また、当月に31日が存在しない場合、最終列を削除するように書き換えを行いたいのです。 最初は月が偶数かどうかで判定しようとしましたが、7月と8月とも31日ですので、月ごとに判定を行わなければいけませんでしょうか。
退会済みユーザー

退会済みユーザー

2019/09/03 04:55

setValues()というものは、配列をセットします。横1行の時は[[9月1日, 9月2日, …, 9月30日]]みたいな形をとる必要があります。 当月に31日が存在しない場合は、月ごとに判定するのが無難でしょう。2月はうるう年の関係もありますので。まず、当月の月を変数mに格納しといて、ループしてる時にnew Date()を使って、月同士比較したらいいと思います。
koroaisu

2019/09/03 16:47

いつもご丁寧に回答頂き、誠に感謝致します! 本当に大変お世話になっております。 ご教授頂いた内容に沿って、自分なりにアレンジしましたが、setValuesの方で「クラス変換できない」エラーが発生しました。 コードを質問欄「回答を頂いた後にアレンジしたコード」にて記載させていただきました。 ご教授頂ければ幸いです。 また、現在は3行目から最終行までちょうど31行ありますが、30日の月の際に、31日目の列を削除したいのですが、「deleteColumn(34)」(最初の3行は日付ではないため),2月の場合は29日のため、「deleteColumn(34,2)」で書き方で大丈夫でしょうか。
退会済みユーザー

退会済みユーザー

2019/09/04 04:49

setValues()の時はfor文で繰り返さなくてもいいです(なので処理が速くなります) >>現在は3行目から最終行までちょうど31行ありますが >>最初の3行は日付ではないため 3列目(C列)は日付とした前提だと、列の削除方法は33列目ですので「deleteColumn(33)」でいいですが、2月の場合は「deleteColumns(32, 2)」とします。(複数形の場合「s」をお忘れなく。第一引数は削除する列の開始位置、第二引数は列数を表します。) 私もサンプルコードを記載しました。
koroaisu

2019/09/04 10:21 編集

この度は最後までご丁寧に説明して頂き、サンプルコードまでご教授頂き、誠に感謝致します。 本当に大変お世話になりました。 ありがとうございます!
退会済みユーザー

退会済みユーザー

2019/09/04 23:31

追記ですが、サンプルコードはcreateSSとsetDateの2つを合わせたコードです。
koroaisu

2019/09/06 15:00

サンプルコード自体が、日報のテンプレファイルをコピー可能でことでしょうか? 自分はcreateSSと組み合わせて使っています...
退会済みユーザー

退会済みユーザー

2019/09/07 01:33

失礼しました。私の間違いです。createSSと組み合わせてお使いください。
guest

0

SpreadsheetApp.openByIdの引数にとるidfilenameでよいのでは?

投稿2019/08/30 01:59

macaron_xxx

総合スコア3191

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問