<前へ> <次へ>
メール送信順のため,フォーム入力内容が蓄積されたスプレッドシートから必要データを切り出し,別のスプレッドシートとして,mailフォルダに格納する作業を行います。
1. 送信準備のためフォームに入力されたデータをmailフォルダに保存
- 時間指定メール送信フォームが完成し,入力した内容を修正用URLを入力した人に返信できるようになった。フォームに入力した内容は一つのスプレッドシートに蓄積されるので,送信準備のため,入力した内容を切り出して,mailフォルダに格納する。ソフトウェア構成図の④,⑤,⑥を行う。
- フォームで送信が行われた段階で,二重起動を防ぐためのロック等の処理をした後,フォームで作成されたSpreadsheetの最下行のデータを取得する。
- 取得したデータを専用フォルダ「mail」内に用意した新規Spreadsheetに書き込む。
- 一定時間(たとえば1分)ごとに実行するGASプログラムで,現在日時を取得し,保存されたメールファイルの中から,送信日時が現在時刻より古いものを抽出し送信する。
- 送信したファイルは削除する。
今日は,2までを行う。
2.フォーム入力データが格納されたGoogle Spreadsheetの作成
- 時間指定メール送信システムフォームに,データを5件程度入力せよ。過去と未来の両方の送信日時を含むものとする。送信メール内容は適当で構わないが,メールの宛先は必ず自分の公式メールアドレスにすること。
- フォーム編集画面から「回答」をクリック。
- スプレッドシートの作成,をクリック。新しいスプレッドシートを作成する。
- 新しいSpreadsheetが作成され,自動で開かれる。
- Google Driveを見るとSpreadsheetが確認できる。
- 新規にフォルダ「mail」を作成する。
- **SpreadsheetとmailフォルダのIDを確認しておく。**mailフォルダのIDは,そのフォルダに入ってURLで確認する。folders/の後ろの部分がID。
- Spreadsheetのツールメニューからスクリプトエディタを起動し,プロジェクト名を変更。
- デバッグやエラーを出力するファイルを作成。新規,から,Googleドキュメント,を選択し,「log2」というドキュメントを作成する。
- 名前を「log2」に変更する。勝手に保存される。
- log2に実行ログを書き込んだり,エラーを書き込んだりするので,開発中はlog2を開いたままにしておく。
- log2のファイルIDをコピーし,あとで使用するため,エディターに貼り付けておく
- スクリプトエディタで,最初から書かれているGASプログラム,「コード.gs」の4行は全削除する。
- 次の内容をコピーペーストする。「**********」の部分は,エディタに貼り付けたIDに置き換える。
テンプレート
var logID = "**********";//手動でDocument,「log2」を新規作成しIDを調べておく
var ssID1 = "**********";//フォーム入力で作成されたSpreadsheetのID
var ssID2 = ""; //mailフォルダに作成されたSpreadsheetのID
var folderID = "**********"; //mailフォルダのID
function submitForm(){//フォームが送信されたら呼び出される関数,重複処理を避ける
log = new Doc(logID);
log.print('\n'+getDateAndTime(0)+" スクリプト開始\n");
var lock = LockService.getScriptLock();//ロックサービスのオブジェクトを生成
try{
lock.waitLock(30000);//複数のフォーム送信がほぼ同時にあった時,遅い方に最大30秒待ってもらう
log.print("他のスクリプト実行要求をロック完了,最大60秒\n");
main(log);
}catch(err){
log.print("発生したエラー:"+err+'\n');
}finally{
lock.releaseLock();//次の送信のためにロック解除
log.print(getDateAndTime(0)+" ロック解除,次のスクリプト要求を受け付け開始\n");
}
}
function main(log){
var ssSrc = new Ssheet(ssID1);//フォーム入力されたデータが入っているSpreadsheet
var todayNow =getDateAndTime(0);//現在日時の取得
var ssID2 = createSpreadsheetInFolder(folderID, "temp");//新規作成,ファイル名はとりあえずtemp,後で送信日時に変更する
var ssDst = new Ssheet(ssID2); //最後にフォーム入力されたデータだけを記録するSpreadsheet
var maxRow = ssSrc.getLastRow(0);
var maxColumn = ssSrc.getLastColumn(0);
log.print("最後の行"+maxRow+" 最後の列"+maxColumn+"\n");
for(var i=1;i<=maxColumn;i++){
var index = ssSrc.getValue(0, 1, i);
ssDst.setValue(0, 1, i, index);
var data = ssSrc.getValue(0, maxRow, i);
if(index == "date"){
var dateTmp = data;
var date = getDateAndTime(dateTmp).split('_')[0];
log.print(date+"\n");
ssDst.setValue(0, 2, i, date);
}
if(index == "time"){
var timeTmp = data;
var time = getDateAndTime(timeTmp).split('_')[1];
log.print(time+"\n");
ssDst.setValue(0, 2, i, time);
}else{
ssDst.setValue(0, 2, i, data);
}
}
var fn = date + "_" + time;
ssDst.rename(fn);
log.print("最後に入力されたデータを新規Spreadsheetにコピー終了,ファイル名を送信日時に変更\n");
}
//-----------------------日付や時間のための関数群
function getSerial(date,time){//日付と時間からシリアル値をゲット
var serial = new Date(date.toString().slice(0,16)+time.toString().slice(16));
return serial;
}
function getDateAndTime(data){// 引数がゼロなら現在日時そうでなければ指定日時をyyyymmdd_hhmmssで返す
if(data==0) var now = new Date();
else var now = new Date(data);
var year = now.getYear();
var month = now.getMonth() + 1;
var day = now.getDate();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
return (""+year).slice(0,4) + ("0"+month).slice(-2) + ("0"+day).slice(-2) +'_'+
("0"+hour).slice(-2) + ("0"+min).slice(-2) + ("0"+sec).slice(-2);
}
//-----------------------ファイルの新規作成等の関数群
//フォルダID,ファイルID,ファイル名を受け取り,ファイルIDのコピーをフォルダ内に作成して,ファイルのIDを返す
function copyFileInFolder(folderID, srcID, fileName) {
var originalFile = DriveApp.getFileById(srcID);
var folder = DriveApp.getFolderById(folderID);
var copiedFile = originalFile.makeCopy(fileName, folder);
copiedFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);//リンクからアクセスできる人は編集可能にする
var copiedFileId = copiedFile.getId();//コピーのファイルIDをゲット
return copiedFileId;
}
//フォルダID,ファイル名を受け取り,スプレッドシートを指定フォルダ内に新規作成しそのファイルIDを返す
function createSpreadsheetInFolder(folderID, fileName) {
var folder = DriveApp.getFolderById(folderID);
var newSS=SpreadsheetApp.create(fileName);
var originalFile=DriveApp.getFileById(newSS.getId());
var copiedFile = originalFile.makeCopy(fileName, folder);
DriveApp.getRootFolder().removeFile(originalFile);
var copiedFileId = copiedFile.getId();//コピーのファイルIDをゲット
return copiedFileId;
}
//////////Ssheetクラスの定義開始(コンストラクタとメンバ関数で構成)
//Ssheetクラスのコンストラクタの記述
Ssheet = function(id){
this.ssFile = SpreadsheetApp.openById(id);
this.ssFileName = this.ssFile.getName();
SpreadsheetApp.setActiveSpreadsheet(this.ssFile);//値を返さない
this.activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
}
//Ssheetクラスのメンバ関数(メソッド)の定義開始
//spreadsheetのファイル名を返すメソッド
Ssheet.prototype.getFileName = function(){
return this.ssFileName;
}
//spreadsheetのファイル名を変更するメソッド
Ssheet.prototype.rename = function(newName){
this.ssFile.rename(newName);
}
//spreadsheetのsheetでrow行cal列にデータを入れるメソッド
Ssheet.prototype.setValue = function(sheet,row,col,value){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
var cell = this.activeSheet.getRange(row,col);
cell.setValue(value);
}
//spreadsheetのsheetでrow行cal列をクリアするメソッド
Ssheet.prototype.clear = function(sheet,row,col,value){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
var cell = this.activeSheet.getRange(row,col);
cell.clear(value);
}
//spreadsheetのsheetからrow行のcal列のデータをもらってくるメソッド
Ssheet.prototype.getValue = function(sheet,row,col) {
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
var value = this.activeSheet.getRange(row, col).getValue();
return value;
}
//背景の色を設定するメソッド
Ssheet.prototype.setBackgroundColor = function(sheet,row,col, r,g,b) {
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
var cell = this.activeSheet.getRange(row,col);
cell.setBackgroundRGB(r,g,b);
}
//spreadsheetのsheet数を指定の数増やすメソッド
Ssheet.prototype.insertSheet = function(num){
var sheetNum = this.activeSpreadsheet.getNumSheets();
while(num>sheetNum){
this.activeSpreadsheet.insertSheet();
sheetNum++;
}
}
//spreadsheetの指定sheetを削除
Ssheet.prototype.deleteSheet = function(sheet){
this.activeSpreadsheet.deleteSheet(this.activeSpreadsheet.getSheets()[sheet])
}
//spreadsheetのsheetの名前をセットするメソッド
Ssheet.prototype.renameSheet = function(sheet,newName){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
this.activeSheet.setName(newName);
}
//spreadsheetの指定sheetの全データを取得
Ssheet.prototype.getValues = function(sheet){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
return this.activeSheet.getDataRange().getValues();//シートの全データを取得
}
//spreadsheetの指定sheetを取得
Ssheet.prototype.getSheet = function(sheet){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
return this.activeSheet;//シートを返す
}
//spreadsheetの指定sheetの最後の行番号を取得
Ssheet.prototype.getLastRow = function(sheet){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
return this.activeSheet.getLastRow();//最後の行番号を取得
}
//spreadsheetの指定sheetの最後の列番号を取得
Ssheet.prototype.getLastColumn = function(sheet){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
return this.activeSheet.getLastColumn();//最後の列番号を取得
}
//spreadsheetの指定行rowを削除
Ssheet.prototype.deleteRow = function(sheet,row){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
this.activeSheet.deleteRow(row);//行を削除
}
//spreadsheetの指定行rowを挿入
Ssheet.prototype.insertRow = function(sheet,row){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
this.activeSheet.insertRows(row);//行を挿入
}
//spreadsheetの指定列colを削除
Ssheet.prototype.deleteColumn = function(sheet,col){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
this.activeSheet.deleteColumn(col);//列を削除
}
//spreadsheetの指定列colを挿入
Ssheet.prototype.insertColumn = function(sheet,col){
this.activeSheet = this.activeSpreadsheet.getSheets()[sheet];
this.activeSheet.insertColumns(col);//列を挿入
}
//////////Ssheetクラスの定義終了
//////////Docクラスの定義開始(コンストラクタとメンバ関数で構成)
//Docクラスのコンストラクタの記述
Doc = function(id){
this.ID = id;
this.doc = DocumentApp.openById(this.ID);
this.body = this.doc.getBody();
this.docText = this.body.editAsText();
}
//Docクラスのメンバ関数の定義開始
//メソッドprintの定義,テキスト追加
Doc.prototype.print = function(str){
this.docText.appendText(str);
}
//メソッドreplaceの定義,文字列置き換え
Doc.prototype.replace = function(src,dst){
this.body.replaceText(src,dst);
}
//メソッドclearの定義,全消去
Doc.prototype.clear = function(){
this.body.clear();
}
//メソッドgetIDの定義,ファイルIDを返す
Doc.prototype.getID = function(){
return this.ID;
}
//指定秒数のウェイト,表示動作を遅らせたい時などに使用
Doc.prototype.waitSec = function(sec){
var start = new Date().getSeconds();
while((new Date().getSeconds()-start) < sec);
}
//指定ミリ秒のウェイト,表示動作を遅らせたい時などに使用
Doc.prototype.waitMiliSec = function(msec){
var start = new Date(); //new Date()は,「1970年1月1日午前0時」からの通算ミリ秒を返す
while((new Date()-start) < msec);
}
//今現在の日時を表示
Doc.prototype.printTodayNow = function(){
var now = new Date();
var year = now.getYear();
var month = now.getMonth() + 1;
var day = now.getDate();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
this.docText.appendText(year +'_'+ ("0"+month).slice(-2) +'_'+ ("0"+day).slice(-2) +' '+
("0"+hour).slice(-2) +'-'+ ("0"+min).slice(-2) +'-'+ ("0"+sec).slice(-2));
}
/////////Docクラスの定義終了
- 現在のプロジェクトのトリガーを設定する。
- 承認の許可を求められるので,内容を確認して許可する。
- log2を見えるようにした状態で,フォームに入力して送信する。間違っても人に迷惑をかけないため,送信先アドレスは自分のアドレスにする。
- log2で動作チェックを行う。フォーム入力で作成されたSpreadsheetの最下行に追加されたデータが,mailフォルダに新規作成され,送信日時のファイル名となっているSpreadsheetの内容になっていることを確認する。
次は,タイムベース実行する関数を作成し,1分ごとに実行し,メール送信時間になったら,メール送信を行います。
<前へ> <次へ>