2023年 3月 の投稿一覧

GASでドライブに日毎、月毎のフォルダを一気に作成する方法【コピペでOK】

0.はじめに

ドライブに日毎のフォルダを一気に作成したい!
ということをGASで実現する記事です。

ちまちま作成している人はパパっとコピペして活用しちゃってください!

1.フォルダ作成のコード

//エディタ左からライブラリday.jsを追加してください。スクリプトIDは下記。
//1ShsRhHc8tgPy5wGOzUvgEhOedJUQD53m-gd8lG2MOgs-dXC_aCZn9lFB
function main() {
  //親フォルダを定義
  const rootFolder = DriveApp.getFolderById("親フォルダID");
  let monthFolder = "";

  //開始日と最終日を設定
  let targetDate = dayjs.dayjs("2023/1/1");
  let endDate = dayjs.dayjs("2024/12/31");

  //最終日を超えるまでtargetDateを加算しつつ繰り返し処理
  while(targetDate.isBefore(endDate.add(1,"day"),"day")){
    //日付が1日or月フォルダ未指定の場合はフォルダ作成(root内に当月フォルダが存在するか確認するとよりgood)
    if(targetDate.date()==1 || monthFolder==""){
      //月フォルダを作成
      monthFolder = rootFolder.createFolder(targetDate.format("YYYY/MM"));
    }
    //月フォルダ内に日フォルダを作成
    monthFolder.createFolder(targetDate.format("YYYY/MM/DD"));
    //targetDateに1日加算
    targetDate = targetDate.add(1,"day");
  }
}

コード内にコメントで書いている通り、day.jsを使用するコードになっています。
エディタ左側のライブラリのところから、追加してください。

day.jsのスクリプトIDはこちら
1ShsRhHc8tgPy5wGOzUvgEhOedJUQD53m-gd8lG2MOgs-dXC_aCZn9lFB
day.js公式

実行結果としてはこんな感じになります。
↓↓↓

親フォルダ内に月フォルダが並び・・・

生成済みの月フォルダたち

月フォルダの中には日毎のフォルダが並びます。

月フォルダ内に日毎のフォルダが並ぶ画像

尚、注意点ですが、少し処理時間を要します。
なぜなら1つずつフォルダを順次作成していくからです。

上記の例、丸2年分を私の環境で実行すると、2分15秒かかりました。
手で作成するよりは断然速いですが、あまり大量に作成するとタイムアウトしますので
ある程度は区切って処理していくことをオススメします。

2.当日になったらフォルダを削除したい、そんな時のコード

作って使うだけなら楽ですが、管理上そうもいかない場合が多いです。
そんな時、日次で夜実行のトリガーを設定しておいて当日分を削除するようなコードがあれば便利ですよね。
それがこちらです。月末日の場合は月フォルダも削除します。


//本日のフォルダを削除
function deleteTodayFolder(){
  const rootFolder = DriveApp.getFolderById("親フォルダID");
  const today = dayjs.dayjs();
  const monthFolder = rootFolder.getFoldersByName(today.format("YYYY/MM")).next();
  
  if(monthFolder){
    //月フォルダが見つかったら本日フォルダを検索し、見つかったら削除する
    let todayFolder = monthFolder.getFoldersByName(today.format("YYYY/MM/DD")).next();
    if(todayFolder) todayFolder.removeFolder();

    //翌日が1日だったら月末なので、月フォルダも削除する
    if(today.add(1,"day").date()==1) monthFolder.removeFolder();
  }
}

こちらもday.jsを使いますので事前に追加しておいてくださいね。

3.昨日分を削除したい方へのコード

別に当日分を23時~24時のトリガーで日次削除してもいいけど、
できれば厳密に日が変わってから昨日分を削除したい方はこちらをどうぞ。


//昨日のフォルダを削除
function deleteYesterdayFolder(){
  const rootFolder = DriveApp.getFolderById("親フォルダID");
  const yesterday = dayjs.dayjs().subtract(1,"day");
  const monthFolder = rootFolder.getFoldersByName(yesterday.format("YYYY/MM")).next();
  
  if(monthFolder){
    //月フォルダが見つかったら昨日フォルダを検索し、見つかったら削除する
    let yesterdayFolder = monthFolder.getFoldersByName(yesterday.format("YYYY/MM/DD")).next();
    if(yesterdayFolder) yesterdayFolder.removeFolder();

    //本日が1日であれば先月の月フォルダも削除する
    if(dayjs.dayjs().date()==1) monthFolder.removeFolder();
  }
}

こちらもday.jsです。便利ですね。
私が実務で使っているのも、このパターンです。

4.さいごに

いかかでしたでしょうか。結構シンプルなコードだと思いませんか?
これだけのコードですが、手で作業するとなると莫大な時間を要します。

ぜひGASを活用して効率化、高速化を実現してきましょう!
ご活用いただけると幸いです。それではまた。

GASで契約管理! 管理シートを自動参照&通知日に自動メール通知!

0.はじめに

期日管理、自動化していますか?

「期日の〇ヶ月前になったら通知する」等は定型的で非常に自動化しやすい部分です。
その一例としてシート例とコード例をご紹介します。
もし業務の補助になるなら、ぜひチャレンジしてみてください。

1.スプレッドシート

こんな構成にしました。

契約管理更新シートのサンプル画像

E2セルにはこんな関数が入っています。

=ARRAYFORMULA(IF((D2:D=””)+(F2:F=””)+(F2:F=”-“),””,EDATE(D2:D,F2:F*-1)))

IF文でD列が空白orF列が空白orF列が-の場合は空に、
それ以外の場合はD列からF列の月数をマイナスした日付が入ります。

GASを学ぶとつい全てコードでやってしまいそうになりますが、
関数を適切に活用することでコードがシンプルになり可読性や保守性が向上します。

2.コード

//最初にライブラリdayjsを追加しておくこと
//スクリプトIDは1ShsRhHc8tgPy5wGOzUvgEhOedJUQD53m-gd8lG2MOgs-dXC_aCZn9lFB
//メイン処理
function alertContractMain() {
  const targets = getAlertTargets();
  if(targets.length == 0) return;

  for(let t of targets){
    let body = getHtmlBody(t);
    alert(t,body);
  }
}

//アラートメール送信
function alert(target,body){
  let mailArgs = {htmlBody : body};
  GmailApp.sendEmail(target.AlertTo, `契約更新通知 ${target.Title}`,"",mailArgs);
}

//HTMLメール本文を作成する
function getHtmlBody(target){
  const body = `下記、契約更新通知の時期となりましたため通知いたします。<br>
                <br>
                対象:${target.Title}<br>
                カテゴリ:${target.Type}<br>
                契約満了日:${dayjs.dayjs(target.EndDate).format("YYYY/MM/DD")}<br>
                自動更新有無:${target.AutoUpdate}<br>
                コメント:${target.Detail}<br>
                <br>
                必要に応じて更新検討および更新手続きをお願いします。`;
  return body;
}

//本日アラート日のものを返す
function getAlertTargets(){
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheetByName("契約管理");
  const vals = sh.getRange("A2:H").getValues().filter(x => x[0]);
  const obj = vals.map(x => new Contract(x));

  return obj.filter(x => dayjs.dayjs(x.AlertDate).isSame(dayjs.dayjs(),"day"));
}

//SS情報をオブジェクト化するためのクラス
class Contract{
  constructor(row){
    this.Title      = row[0]; //項目名
    this.Type       = row[1]; //カテゴリ
    this.AutoUpdate = row[2]; //自動更新
    this.EndDate    = row[3]; //契約満了日
    this.AlertDate  = row[4]; //通知日
    this.AlertTiming= row[5]; //通知時期
    this.AlertTo    = row[6]; //通知先
    this.Detail     = row[7]; //詳細
  }
}

 

3.ポイント

3-1.day.js

ライブラリ、day.jsを使っています。
使わなくても日付比較はできますが、使うと非常に楽ですので使用をオススメします。

使い方は、エディタ左側のライブラリのところで「+」を押し
下記のスクリプトIDを入力、追加してください。

1ShsRhHc8tgPy5wGOzUvgEhOedJUQD53m-gd8lG2MOgs-dXC_aCZn9lFB
day.js公式

3-2.トリガー設定

通知日=本日のデータがないかチェックしてメール送信する仕組みですので、
毎日起動する必要があります。

業務都合に合うお好きな時間帯を日次設定してください。

3-3.テンプレートリテラルについて

htmlBodyを作成する際、変数の値と文字列を組み合わせて作成しています。
文字列と変数を+で結合しても問題ありません。
ただ、当コードで使用しているテンプレートリテラルを活用すると
途中で柔軟に改行できることから可読性と保守性が増す場合が多いです。

使用方法としては、まず文字列を ` で囲います。
変数や定数の値を使用したい場合は`の中で${変数名}と書くと展開されます。

今回のような長めの文字列を扱う場合、有効ですので是非この機会に慣れておいてください。

4.さいごに

結構シンプルですぐ作れる内容でありながら、
業務にはバッチリ貢献してくれそうな例だと思います。

期日管理系ですと類似のものでこんな記事もありますので興味があれば参照してみてください。
GASでシートの入社日や退職日に合わせて自動でメールを送信する事例

ご活用いただけますと幸いです。ありがとうございました。